summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hubbs <williamh@gentoo.org>2017-03-22 09:37:30 -0500
committerWilliam Hubbs <williamh@gentoo.org>2017-03-22 09:38:36 -0500
commit8f8a61e7f5f6b446db1bc6331e948345f4fcd94d (patch)
tree7fb78ca1d21a84ba01ccbe413b5548f611ce029b
parentmedia-plugins/qmmp-plugin-pack: amd64 stable wrt bug #613436 (diff)
downloadgentoo-8f8a61e7f5f6b446db1bc6331e948345f4fcd94d.tar.gz
gentoo-8f8a61e7f5f6b446db1bc6331e948345f4fcd94d.tar.bz2
gentoo-8f8a61e7f5f6b446db1bc6331e948345f4fcd94d.zip
dev-lang/go: 1.8-r1 revision bump
This fixes #19182 upstream [1]. [1] https://github.com/golang/go/issues/19182 Package-Manager: Portage-2.3.3, Repoman-2.3.2
-rw-r--r--dev-lang/go/files/1.8-cmd-compile-add-opcode-flag-hasSideEffects-for-do-no.patch738
-rw-r--r--dev-lang/go/go-1.8-r1.ebuild231
2 files changed, 969 insertions, 0 deletions
diff --git a/dev-lang/go/files/1.8-cmd-compile-add-opcode-flag-hasSideEffects-for-do-no.patch b/dev-lang/go/files/1.8-cmd-compile-add-opcode-flag-hasSideEffects-for-do-no.patch
new file mode 100644
index 00000000000..c8ebf376f45
--- /dev/null
+++ b/dev-lang/go/files/1.8-cmd-compile-add-opcode-flag-hasSideEffects-for-do-no.patch
@@ -0,0 +1,738 @@
+From 11b283092a29a9d402ce05706fd3a85683576218 Mon Sep 17 00:00:00 2001
+From: David Chase <drchase@google.com>
+Date: Tue, 21 Feb 2017 15:22:52 -0500
+Subject: [PATCH] cmd/compile: add opcode flag hasSideEffects for do-not-remove
+
+Added a flag to generic and various architectures' atomic
+operations that are judged to have observable side effects
+and thus cannot be dead-code-eliminated.
+
+Test requires GOMAXPROCS > 1 without preemption in loop.
+
+Fixes #19182.
+
+Change-Id: Id2230031abd2cca0bbb32fd68fc8a58fb912070f
+Reviewed-on: https://go-review.googlesource.com/37333
+Run-TryBot: David Chase <drchase@google.com>
+TryBot-Result: Gobot Gobot <gobot@golang.org>
+Reviewed-by: Cherry Zhang <cherryyz@google.com>
+---
+ src/cmd/compile/internal/ssa/deadcode.go | 2 +-
+ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 16 ++--
+ src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 20 ++---
+ src/cmd/compile/internal/ssa/gen/MIPSOps.go | 16 ++--
+ src/cmd/compile/internal/ssa/gen/S390XOps.go | 16 ++--
+ src/cmd/compile/internal/ssa/gen/genericOps.go | 28 +++----
+ src/cmd/compile/internal/ssa/gen/main.go | 4 +
+ src/cmd/compile/internal/ssa/op.go | 1 +
+ src/cmd/compile/internal/ssa/opGen.go | 111 +++++++++++++++++--------
+ test/fixedbugs/issue19182.go | 36 ++++++++
+ 10 files changed, 168 insertions(+), 82 deletions(-)
+ create mode 100644 test/fixedbugs/issue19182.go
+
+diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go
+index d75d2d5..ce786a9 100644
+--- a/src/cmd/compile/internal/ssa/deadcode.go
++++ b/src/cmd/compile/internal/ssa/deadcode.go
+@@ -64,7 +64,7 @@ func liveValues(f *Func, reachable []bool) []bool {
+ q = append(q, v)
+ }
+ for _, v := range b.Values {
+- if opcodeTable[v.Op].call && !live[v.ID] {
++ if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects) && !live[v.ID] {
+ live[v.ID] = true
+ q = append(q, v)
+ }
+diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+index cdd5539..1b73ac1 100644
+--- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
++++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+@@ -548,15 +548,15 @@ func init() {
+ // store arg0 to arg1+auxint+aux, arg2=mem.
+ // These ops return a tuple of <old contents of *(arg1+auxint+aux), memory>.
+ // Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)!
+- {name: "XCHGL", argLength: 3, reg: gpstorexchg, asm: "XCHGL", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true},
+- {name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true},
++ {name: "XCHGL", argLength: 3, reg: gpstorexchg, asm: "XCHGL", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true},
++ {name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true},
+
+ // Atomic adds.
+ // *(arg1+auxint+aux) += arg0. arg2=mem.
+ // Returns a tuple of <old contents of *(arg1+auxint+aux), memory>.
+ // Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)!
+- {name: "XADDLlock", argLength: 3, reg: gpstorexchg, asm: "XADDL", typ: "(UInt32,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true},
+- {name: "XADDQlock", argLength: 3, reg: gpstorexchg, asm: "XADDQ", typ: "(UInt64,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true},
++ {name: "XADDLlock", argLength: 3, reg: gpstorexchg, asm: "XADDL", typ: "(UInt32,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, hasSideEffects: true},
++ {name: "XADDQlock", argLength: 3, reg: gpstorexchg, asm: "XADDQ", typ: "(UInt64,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, hasSideEffects: true},
+ {name: "AddTupleFirst32", argLength: 2}, // arg0=tuple <x,y>. Returns <x+arg1,y>.
+ {name: "AddTupleFirst64", argLength: 2}, // arg0=tuple <x,y>. Returns <x+arg1,y>.
+
+@@ -579,12 +579,12 @@ func init() {
+ // JEQ ...
+ // but we can't do that because memory-using ops can't generate flags yet
+ // (flagalloc wants to move flag-generating instructions around).
+- {name: "CMPXCHGLlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
+- {name: "CMPXCHGQlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGQ", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
++ {name: "CMPXCHGLlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "CMPXCHGQlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGQ", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // Atomic memory updates.
+- {name: "ANDBlock", argLength: 3, reg: gpstore, asm: "ANDB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true}, // *(arg0+auxint+aux) &= arg1
+- {name: "ORBlock", argLength: 3, reg: gpstore, asm: "ORB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true}, // *(arg0+auxint+aux) |= arg1
++ {name: "ANDBlock", argLength: 3, reg: gpstore, asm: "ANDB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true}, // *(arg0+auxint+aux) &= arg1
++ {name: "ORBlock", argLength: 3, reg: gpstore, asm: "ORB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true}, // *(arg0+auxint+aux) |= arg1
+ }
+
+ var AMD64blocks = []blockData{
+diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
+index e8d5be2..0986ac6 100644
+--- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
++++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
+@@ -456,16 +456,16 @@ func init() {
+
+ // atomic stores.
+ // store arg1 to arg0. arg2=mem. returns memory. auxint must be zero.
+- {name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true},
+- {name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true},
++ {name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true},
++ {name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic exchange.
+ // store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>. auxint must be zero.
+ // LDAXR (Rarg0), Rout
+ // STLXR Rarg1, (Rarg0), Rtmp
+ // CBNZ Rtmp, -2(PC)
+- {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
+- {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic add.
+ // *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
+@@ -473,8 +473,8 @@ func init() {
+ // ADD Rarg1, Rout
+ // STLXR Rout, (Rarg0), Rtmp
+ // CBNZ Rtmp, -3(PC)
+- {name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
+- {name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero.
+@@ -490,8 +490,8 @@ func init() {
+ // STLXR Rarg2, (Rarg0), Rtmp
+ // CBNZ Rtmp, -4(PC)
+ // CSET EQ, Rout
+- {name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true},
+- {name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic and/or.
+ // *arg0 &= (|=) arg1. arg2=mem. returns memory. auxint must be zero.
+@@ -499,8 +499,8 @@ func init() {
+ // AND/OR Rarg1, Rtmp
+ // STLXRB Rtmp, (Rarg0), Rtmp
+ // CBNZ Rtmp, -3(PC)
+- {name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true},
+- {name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "ORR", faultOnNilArg0: true},
++ {name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "ORR", faultOnNilArg0: true, hasSideEffects: true},
+ }
+
+ blocks := []blockData{
+diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go
+index 78b961f..3d88b71 100644
+--- a/src/cmd/compile/internal/ssa/gen/MIPSOps.go
++++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go
+@@ -267,8 +267,8 @@ func init() {
+ // SYNC
+ // MOVW Rarg1, (Rarg0)
+ // SYNC
+- {name: "LoweredAtomicStore", argLength: 3, reg: gpstore, faultOnNilArg0: true},
+- {name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true},
++ {name: "LoweredAtomicStore", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic exchange.
+ // store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>.
+@@ -278,7 +278,7 @@ func init() {
+ // SC Rtmp, (Rarg0)
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+- {name: "LoweredAtomicExchange", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicExchange", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic add.
+ // *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>.
+@@ -289,8 +289,8 @@ func init() {
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+ // ADDU Rarg1, Rout
+- {name: "LoweredAtomicAdd", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
+- {name: "LoweredAtomicAddconst", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int32", resultNotInArgs: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicAdd", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicAddconst", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int32", resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
+@@ -308,7 +308,7 @@ func init() {
+ // SC Rout, (Rarg0)
+ // BEQ Rout, -4(PC)
+ // SYNC
+- {name: "LoweredAtomicCas", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicCas", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic and/or.
+ // *arg0 &= (|=) arg1. arg2=mem. returns memory.
+@@ -318,8 +318,8 @@ func init() {
+ // SC Rtmp, (Rarg0)
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+- {name: "LoweredAtomicAnd", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true},
+- {name: "LoweredAtomicOr", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true},
++ {name: "LoweredAtomicAnd", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicOr", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true, hasSideEffects: true},
+
+ // large or unaligned zeroing
+ // arg0 = address of memory to zero (in R1, changed as side effect)
+diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go
+index 4c5f070..40ba252 100644
+--- a/src/cmd/compile/internal/ssa/gen/S390XOps.go
++++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go
+@@ -429,14 +429,14 @@ func init() {
+
+ // Atomic stores. These are just normal stores.
+ // store arg1 to arg0+auxint+aux. arg2=mem.
+- {name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true},
+- {name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true},
++ {name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // Atomic adds.
+ // *(arg0+auxint+aux) += arg1. arg2=mem.
+ // Returns a tuple of <old contents of *(arg0+auxint+aux), memory>.
+- {name: "LAA", argLength: 3, reg: gpstorelaa, asm: "LAA", typ: "(UInt32,Mem)", aux: "SymOff", faultOnNilArg0: true},
+- {name: "LAAG", argLength: 3, reg: gpstorelaa, asm: "LAAG", typ: "(UInt64,Mem)", aux: "SymOff", faultOnNilArg0: true},
++ {name: "LAA", argLength: 3, reg: gpstorelaa, asm: "LAA", typ: "(UInt32,Mem)", aux: "SymOff", faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LAAG", argLength: 3, reg: gpstorelaa, asm: "LAAG", typ: "(UInt64,Mem)", aux: "SymOff", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "AddTupleFirst32", argLength: 2}, // arg0=tuple <x,y>. Returns <x+arg1,y>.
+ {name: "AddTupleFirst64", argLength: 2}, // arg0=tuple <x,y>. Returns <x+arg1,y>.
+
+@@ -461,13 +461,13 @@ func init() {
+ // BEQ ...
+ // but we can't do that because memory-using ops can't generate flags yet
+ // (flagalloc wants to move flag-generating instructions around).
+- {name: "LoweredAtomicCas32", argLength: 4, reg: cas, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
+- {name: "LoweredAtomicCas64", argLength: 4, reg: cas, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicCas32", argLength: 4, reg: cas, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicCas64", argLength: 4, reg: cas, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // Lowered atomic swaps, emulated using compare-and-swap.
+ // store arg1 to arg0+auxint+aux, arg2=mem.
+- {name: "LoweredAtomicExchange32", argLength: 3, reg: exchange, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
+- {name: "LoweredAtomicExchange64", argLength: 3, reg: exchange, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
++ {name: "LoweredAtomicExchange32", argLength: 3, reg: exchange, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
++ {name: "LoweredAtomicExchange64", argLength: 3, reg: exchange, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // find leftmost one
+ {
+diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go
+index f39598e..3854a39 100644
+--- a/src/cmd/compile/internal/ssa/gen/genericOps.go
++++ b/src/cmd/compile/internal/ssa/gen/genericOps.go
+@@ -441,20 +441,20 @@ var genericOps = []opData{
+ // Atomic loads return a new memory so that the loads are properly ordered
+ // with respect to other loads and stores.
+ // TODO: use for sync/atomic at some point.
+- {name: "AtomicLoad32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
+- {name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
+- {name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
+- {name: "AtomicStore32", argLength: 3, typ: "Mem"}, // Store arg1 to *arg0. arg2=memory. Returns memory.
+- {name: "AtomicStore64", argLength: 3, typ: "Mem"}, // Store arg1 to *arg0. arg2=memory. Returns memory.
+- {name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem"}, // Store arg1 to *arg0. arg2=memory. Returns memory.
+- {name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)"}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
+- {name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)"}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
+- {name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)"}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
+- {name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)"}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
+- {name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)"}, // if *arg0==arg1, then set *arg0=arg2. Returns true iff store happens and new memory.
+- {name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)"}, // if *arg0==arg1, then set *arg0=arg2. Returns true iff store happens and new memory.
+- {name: "AtomicAnd8", argLength: 3, typ: "Mem"}, // *arg0 &= arg1. arg2=memory. Returns memory.
+- {name: "AtomicOr8", argLength: 3, typ: "Mem"}, // *arg0 |= arg1. arg2=memory. Returns memory.
++ {name: "AtomicLoad32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
++ {name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
++ {name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
++ {name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
++ {name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
++ {name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
++ {name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
++ {name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
++ {name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
++ {name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
++ {name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true iff store happens and new memory.
++ {name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true iff store happens and new memory.
++ {name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
++ {name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
+ }
+
+ // kind control successors implicit exit
+diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go
+index 41199f7..19b904a 100644
+--- a/src/cmd/compile/internal/ssa/gen/main.go
++++ b/src/cmd/compile/internal/ssa/gen/main.go
+@@ -52,6 +52,7 @@ type opData struct {
+ faultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset)
+ faultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset)
+ usesScratch bool // this op requires scratch memory space
++ hasSideEffects bool // for "reasons", not to be eliminated. E.g., atomic store, #19182.
+ }
+
+ type blockData struct {
+@@ -208,6 +209,9 @@ func genOp() {
+ if v.usesScratch {
+ fmt.Fprintln(w, "usesScratch: true,")
+ }
++ if v.hasSideEffects {
++ fmt.Fprintln(w, "hasSideEffects: true,")
++ }
+ if a.name == "generic" {
+ fmt.Fprintln(w, "generic:true,")
+ fmt.Fprintln(w, "},") // close op
+diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go
+index 4c3164f..37b2f74 100644
+--- a/src/cmd/compile/internal/ssa/op.go
++++ b/src/cmd/compile/internal/ssa/op.go
+@@ -34,6 +34,7 @@ type opInfo struct {
+ faultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset)
+ faultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset)
+ usesScratch bool // this op requires scratch memory space
++ hasSideEffects bool // for "reasons", not to be eliminated. E.g., atomic store, #19182.
+ }
+
+ type inputInfo struct {
+diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
+index 26bcbe0..7a96216 100644
+--- a/src/cmd/compile/internal/ssa/opGen.go
++++ b/src/cmd/compile/internal/ssa/opGen.go
+@@ -7632,6 +7632,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
++ hasSideEffects: true,
+ asm: x86.AXCHGL,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -7649,6 +7650,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
++ hasSideEffects: true,
+ asm: x86.AXCHGQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -7667,6 +7669,7 @@ var opcodeTable = [...]opInfo{
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
++ hasSideEffects: true,
+ asm: x86.AXADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -7685,6 +7688,7 @@ var opcodeTable = [...]opInfo{
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
++ hasSideEffects: true,
+ asm: x86.AXADDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -7712,6 +7716,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: x86.ACMPXCHGL,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -7732,6 +7737,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: x86.ACMPXCHGQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -7752,6 +7758,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: x86.AANDB,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -7766,6 +7773,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: x86.AORB,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -12982,6 +12990,7 @@ var opcodeTable = [...]opInfo{
+ name: "STLR",
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: arm64.ASTLR,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -12994,6 +13003,7 @@ var opcodeTable = [...]opInfo{
+ name: "STLRW",
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: arm64.ASTLRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -13007,6 +13017,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+@@ -13022,6 +13033,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+@@ -13037,6 +13049,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+@@ -13052,6 +13065,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+@@ -13068,6 +13082,7 @@ var opcodeTable = [...]opInfo{
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+@@ -13085,6 +13100,7 @@ var opcodeTable = [...]opInfo{
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+@@ -13100,6 +13116,7 @@ var opcodeTable = [...]opInfo{
+ name: "LoweredAtomicAnd8",
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -13112,6 +13129,7 @@ var opcodeTable = [...]opInfo{
+ name: "LoweredAtomicOr8",
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -14302,6 +14320,7 @@ var opcodeTable = [...]opInfo{
+ name: "LoweredAtomicStore",
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+@@ -14313,6 +14332,7 @@ var opcodeTable = [...]opInfo{
+ name: "LoweredAtomicStorezero",
+ argLen: 2,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+@@ -14324,6 +14344,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+@@ -14339,6 +14360,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+@@ -14355,6 +14377,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 2,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+@@ -14369,6 +14392,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 4,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+@@ -14384,6 +14408,7 @@ var opcodeTable = [...]opInfo{
+ name: "LoweredAtomicAnd",
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: mips.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -14396,6 +14421,7 @@ var opcodeTable = [...]opInfo{
+ name: "LoweredAtomicOr",
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: mips.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19839,6 +19865,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19853,6 +19880,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19866,6 +19894,7 @@ var opcodeTable = [...]opInfo{
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.ALAA,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19882,6 +19911,7 @@ var opcodeTable = [...]opInfo{
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.ALAAG,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19909,6 +19939,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.ACS,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19929,6 +19960,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.ACSG,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19949,6 +19981,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.ACS,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -19967,6 +20000,7 @@ var opcodeTable = [...]opInfo{
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
++ hasSideEffects: true,
+ asm: s390x.ACSG,
+ reg: regInfo{
+ inputs: []inputInfo{
+@@ -21738,59 +21772,70 @@ var opcodeTable = [...]opInfo{
+ generic: true,
+ },
+ {
+- name: "AtomicStore32",
+- argLen: 3,
+- generic: true,
++ name: "AtomicStore32",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicStore64",
+- argLen: 3,
+- generic: true,
++ name: "AtomicStore64",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicStorePtrNoWB",
+- argLen: 3,
+- generic: true,
++ name: "AtomicStorePtrNoWB",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicExchange32",
+- argLen: 3,
+- generic: true,
++ name: "AtomicExchange32",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicExchange64",
+- argLen: 3,
+- generic: true,
++ name: "AtomicExchange64",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicAdd32",
+- argLen: 3,
+- generic: true,
++ name: "AtomicAdd32",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicAdd64",
+- argLen: 3,
+- generic: true,
++ name: "AtomicAdd64",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicCompareAndSwap32",
+- argLen: 4,
+- generic: true,
++ name: "AtomicCompareAndSwap32",
++ argLen: 4,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicCompareAndSwap64",
+- argLen: 4,
+- generic: true,
++ name: "AtomicCompareAndSwap64",
++ argLen: 4,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicAnd8",
+- argLen: 3,
+- generic: true,
++ name: "AtomicAnd8",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ {
+- name: "AtomicOr8",
+- argLen: 3,
+- generic: true,
++ name: "AtomicOr8",
++ argLen: 3,
++ hasSideEffects: true,
++ generic: true,
+ },
+ }
+
+diff --git a/test/fixedbugs/issue19182.go b/test/fixedbugs/issue19182.go
+new file mode 100644
+index 0000000..3a90ff4
+--- /dev/null
++++ b/test/fixedbugs/issue19182.go
+@@ -0,0 +1,36 @@
++// run
++
++// Copyright 2017 The Go Authors. 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"
++ "runtime"
++ "sync/atomic"
++ "time"
++)
++
++var a uint64 = 0
++
++func main() {
++ runtime.GOMAXPROCS(2) // With just 1, infinite loop never yields
++
++ go func() {
++ for {
++ atomic.AddUint64(&a, uint64(1))
++ }
++ }()
++
++ time.Sleep(10 * time.Millisecond) // Short sleep is enough in passing case
++ i, val := 0, atomic.LoadUint64(&a)
++ for ; val == 0 && i < 100; val, i = atomic.LoadUint64(&a), i+1 {
++ time.Sleep(100 * time.Millisecond)
++ }
++ if val == 0 {
++ fmt.Printf("Failed to observe atomic increment after %d tries\n", i)
++ }
++
++}
+--
+2.10.2
+
diff --git a/dev-lang/go/go-1.8-r1.ebuild b/dev-lang/go/go-1.8-r1.ebuild
new file mode 100644
index 00000000000..b86d8f90242
--- /dev/null
+++ b/dev-lang/go/go-1.8-r1.ebuild
@@ -0,0 +1,231 @@
+# Copyright 1999-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+
+export CBUILD=${CBUILD:-${CHOST}}
+export CTARGET=${CTARGET:-${CHOST}}
+
+MY_PV=${PV/_/}
+
+inherit toolchain-funcs
+
+BOOTSTRAP_DIST="https://dev.gentoo.org/~williamh/dist"
+BOOTSTRAP_VERSION="bootstrap-1.8"
+BOOTSTRAP_URI="
+amd64? ( ${BOOTSTRAP_DIST}/go-linux-amd64-${BOOTSTRAP_VERSION}.tbz )
+arm? ( ${BOOTSTRAP_DIST}/go-linux-arm-${BOOTSTRAP_VERSION}.tbz )
+arm64? ( ${BOOTSTRAP_DIST}/go-linux-arm64-${BOOTSTRAP_VERSION}.tbz )
+ppc64? (
+ ${BOOTSTRAP_DIST}/go-linux-ppc64-${BOOTSTRAP_VERSION}.tbz
+ ${BOOTSTRAP_DIST}/go-linux-ppc64le-${BOOTSTRAP_VERSION}.tbz
+)
+s390? ( ${BOOTSTRAP_DIST}/go-linux-s390x-${BOOTSTRAP_VERSION}.tbz )
+x86? ( ${BOOTSTRAP_DIST}/go-linux-386-${BOOTSTRAP_VERSION}.tbz )
+amd64-fbsd? ( ${BOOTSTRAP_DIST}/go-freebsd-amd64-${BOOTSTRAP_VERSION}.tbz )
+x86-fbsd? ( ${BOOTSTRAP_DIST}/go-freebsd-386-${BOOTSTRAP_VERSION}.tbz )
+x64-macos? ( ${BOOTSTRAP_DIST}/go-darwin-amd64-${BOOTSTRAP_VERSION}.tbz )
+x64-solaris? ( ${BOOTSTRAP_DIST}/go-solaris-amd64-${BOOTSTRAP_VERSION}.tbz )
+"
+
+case ${PV} in
+*9999*)
+ EGIT_REPO_URI="git://github.com/golang/go.git"
+ inherit git-r3
+ ;;
+*)
+ SRC_URI="https://storage.googleapis.com/golang/go${MY_PV}.src.tar.gz "
+ S="${WORKDIR}"/go
+ case ${PV} in
+ *_beta*|*_rc*) ;;
+ *)
+ KEYWORDS="-* ~amd64 ~arm ~arm64 ~ppc64 ~x86 ~amd64-fbsd ~x86-fbsd ~x64-macos ~x64-solaris"
+ # The upstream tests fail under portage but pass if the build is
+ # run according to their documentation [1].
+ # I am restricting the tests on released versions until this is
+ # solved.
+ # [1] https://golang.org/issues/18442
+ RESTRICT="test"
+ ;;
+ esac
+esac
+SRC_URI+="!gccgo? ( ${BOOTSTRAP_URI} )"
+
+DESCRIPTION="A concurrent garbage collected and typesafe programming language"
+HOMEPAGE="http://www.golang.org"
+
+LICENSE="BSD"
+SLOT="0/${PV}"
+IUSE="gccgo"
+
+DEPEND="gccgo? ( >=sys-devel/gcc-5[go] )"
+RDEPEND="!<dev-go/go-tools-0_pre20150902"
+
+# These test data objects have writable/executable stacks.
+QA_EXECSTACK="
+ usr/lib/go/src/debug/elf/testdata/*.obj
+ usr/lib/go/src/go/internal/gccgoimporter/testdata/unicode.gox
+ usr/lib/go/src/go/internal/gccgoimporter/testdata/time.gox
+ "
+
+# Do not complain about CFLAGS, etc, since Go doesn't use them.
+QA_FLAGS_IGNORED='.*'
+
+REQUIRES_EXCLUDE="/usr/lib/go/src/debug/elf/testdata/*"
+
+# The tools in /usr/lib/go should not cause the multilib-strict check to fail.
+QA_MULTILIB_PATHS="usr/lib/go/pkg/tool/.*/.*"
+
+# Do not strip this package. Stripping is unsupported upstream and may
+# fail.
+RESTRICT+=" strip"
+
+DOCS=(
+AUTHORS
+CONTRIBUTING.md
+CONTRIBUTORS
+PATENTS
+README.md
+)
+
+PATCHES=(
+"${FILESDIR}"/${PV}-cmd-compile-add-opcode-flag-hasSideEffects-for-do-no.patch
+)
+
+go_arch()
+{
+ # By chance most portage arch names match Go
+ local portage_arch=$(tc-arch $@)
+ case "${portage_arch}" in
+ x86) echo 386;;
+ x64-*) echo amd64;;
+ ppc64) [[ $(tc-endian $@) = big ]] && echo ppc64 || echo ppc64le ;;
+ s390) echo s390x ;;
+ *) echo "${portage_arch}";;
+ esac
+}
+
+go_arm()
+{
+ case "${1:-${CHOST}}" in
+ armv5*) echo 5;;
+ armv6*) echo 6;;
+ armv7*) echo 7;;
+ *)
+ die "unknown GOARM for ${1:-${CHOST}}"
+ ;;
+ esac
+}
+
+go_os()
+{
+ case "${1:-${CHOST}}" in
+ *-linux*) echo linux;;
+ *-darwin*) echo darwin;;
+ *-freebsd*) echo freebsd;;
+ *-netbsd*) echo netbsd;;
+ *-openbsd*) echo openbsd;;
+ *-solaris*) echo solaris;;
+ *-cygwin*|*-interix*|*-winnt*)
+ echo windows
+ ;;
+ *)
+ die "unknown GOOS for ${1:-${CHOST}}"
+ ;;
+ esac
+}
+
+go_tuple()
+{
+ echo "$(go_os $@)_$(go_arch $@)"
+}
+
+go_cross_compile()
+{
+ [[ $(go_tuple ${CBUILD}) != $(go_tuple) ]]
+}
+
+pkg_pretend()
+{
+ # make.bash does not understand cross-compiling a cross-compiler
+ if [[ $(go_tuple) != $(go_tuple ${CTARGET}) ]]; then
+ die "CHOST CTARGET pair unsupported: CHOST=${CHOST} CTARGET=${CTARGET}"
+ fi
+}
+
+src_unpack()
+{
+ if [[ ${PV} = 9999 ]]; then
+ git-r3_src_unpack
+ fi
+ default
+}
+
+src_compile()
+{
+ export GOROOT_BOOTSTRAP="${WORKDIR}"/go-$(go_os)-$(go_arch)-bootstrap
+ if use gccgo; then
+ mkdir -p "${GOROOT_BOOTSTRAP}/bin" || die
+ local go_binary=$(gcc-config --get-bin-path)/go-$(gcc-major-version)
+ [[ -x ${go_binary} ]] || go_binary=$(
+ find "${EPREFIX}"/usr/${CHOST}/gcc-bin/*/go-$(gcc-major-version) |
+ sort -V | tail -n1)
+ [[ -x ${go_binary} ]] ||
+ die "go-$(gcc-major-version): command not found"
+ ln -s "${go_binary}" "${GOROOT_BOOTSTRAP}/bin/go" || die
+ fi
+ export GOROOT_FINAL="${EPREFIX}"/usr/lib/go
+ export GOROOT="$(pwd)"
+ export GOBIN="${GOROOT}/bin"
+
+ # Go's build script does not use BUILD/HOST/TARGET consistently. :(
+ export GOHOSTARCH=$(go_arch ${CBUILD})
+ export GOHOSTOS=$(go_os ${CBUILD})
+ export CC=$(tc-getBUILD_CC)
+
+ export GOARCH=$(go_arch)
+ export GOOS=$(go_os)
+ export CC_FOR_TARGET=$(tc-getCC)
+ export CXX_FOR_TARGET=$(tc-getCXX)
+ if [[ ${ARCH} == arm ]]; then
+ export GOARM=$(go_arm)
+ fi
+ elog "GOROOT_BOOTSTRAP is ${GOROOT_BOOTSTRAP}"
+
+ cd src
+ ./make.bash || die "build failed"
+}
+
+src_test()
+{
+ go_cross_compile && return 0
+
+ cd src
+ PATH="${GOBIN}:${PATH}" \
+ ./run.bash -no-rebuild || die "tests failed"
+}
+
+src_install()
+{
+ local bin_path f x
+
+ dodir /usr/lib/go
+
+ # There is a known issue which requires the source tree to be installed [1].
+ # Once this is fixed, we can consider using the doc use flag to control
+ # installing the doc and src directories.
+ # [1] https://golang.org/issue/2775
+ #
+ # deliberately use cp to retain permissions
+ cp -R api bin doc lib pkg misc src test "${ED}"/usr/lib/go
+ if go_cross_compile; then
+ bin_path="bin/$(go_tuple)"
+ else
+ bin_path=bin
+ fi
+ for x in ${bin_path}/*; do
+ f=${x##*/}
+ dosym ../lib/go/${bin_path}/${f} /usr/bin/${f}
+ done
+ einstalldocs
+}