// Orderaddrtemp ensures that n is okay to pass by address to runtime routines.
// If the original argument n is not okay, orderaddrtemp creates a tmp, emits
// tmp = n, and then returns tmp.
+// The result of orderaddrtemp MUST be assigned back to n, e.g.
+// n.Left = orderaddrtemp(n.Left, order)
func orderaddrtemp(n *Node, order *Order) *Node {
+ if consttype(n) >= 0 {
+ // TODO: expand this to all static composite literal nodes?
+ n = defaultlit(n, nil)
+ dowidth(n.Type)
+ vstat := staticname(n.Type)
+ vstat.Name.Readonly = true
+ var out []*Node
+ staticassign(vstat, n, &out)
+ if out != nil {
+ Fatalf("staticassign of const generated code: %+v", n)
+ }
+ vstat = typecheck(vstat, Erv)
+ return vstat
+ }
if isaddrokay(n) {
return n
}
n = l
break
}
- // Optimize convT2{E,I} when T is not pointer-shaped.
- // We make the interface by initializing a stack temporary to
- // the value we want to put in the interface, then using the address of
- // that stack temporary for the interface data word.
- if !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024 {
- tmp := temp(n.Left.Type)
- init.Append(typecheck(nod(OAS, tmp, n.Left), Etop))
+
+ // Optimize convT2{E,I} when T is not pointer-shaped,
+ // but the value does not escape or is a readonly global.
+ var value *Node
+ switch {
+ case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024:
+ // Initializing a stack temporary to the value we want to put in the interface,
+ // then using the address of that stack temporary for the interface data word.
+ value = temp(n.Left.Type)
+ init.Append(typecheck(nod(OAS, value, n.Left), Etop))
+ case n.Left.Class == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly:
+ // readonly global; use directly.
+ value = n.Left
+ }
+
+ if value != nil {
var t *Node
if n.Type.IsEmptyInterface() {
t = typename(n.Left.Type)
} else {
t = itabname(n.Left.Type, n.Type)
}
- l := nod(OEFACE, t, typecheck(nod(OADDR, tmp, nil), Erv))
+ l := nod(OEFACE, t, typecheck(nod(OADDR, value, nil), Erv))
l.Type = n.Type
l.Typecheck = n.Typecheck
n = l
func f9() bool {
g8()
x := i9
- y := interface{}(99.0i) // ERROR "live at call to convT2E: x.data x.type$"
+ y := interface{}(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+ x.data x.type$" "live at call to str: x.data x.type$"
i9 = y // make y escape so the line above has to call convT2E
return x != y
}
var m map[string]int
+// str is used to ensure that a temp is required for runtime calls below.
+func str() string
+
func f16() {
if b {
- delete(m, "hi") // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
+ delete(m, str()) // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
}
- delete(m, "hi") // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
- delete(m, "hi") // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
+ delete(m, str()) // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
+ delete(m, str()) // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
}
var m2s map[string]*byte
func f17b(p *byte) { // ERROR "live at entry to f17b: p$"
// key temporary
if b {
- m2s["x"] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$"
+ m2s[str()] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$" "live at call to str: p$"
}
- m2s["x"] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$"
- m2s["x"] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$"
+ m2s[str()] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$" "live at call to str: p$"
+ m2s[str()] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$" "live at call to str: p$"
}
func f17c() {
// key and value temporaries
if b {
- m2s["x"] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
+ m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
}
- m2s["x"] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
- m2s["x"] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
+ m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
+ m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
}
func f17d() *byte
var ch chan *byte
+// byteptr is used to ensure that a temp is required for runtime calls below.
+func byteptr() *byte
+
func f19() {
// dest temporary for channel receive.
var z *byte
func f20() {
// src temporary for channel send
if b {
- ch <- nil // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
+ ch <- byteptr() // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
}
- ch <- nil // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
- ch <- nil // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
+ ch <- byteptr() // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
+ ch <- byteptr() // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
}
func f21() {
func f31(b1, b2, b3 bool) {
if b1 {
- g31("a") // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to g31: .autotmp_[0-9]+$"
+ g31(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to g31: .autotmp_[0-9]+$"
}
if b2 {
- h31("b") // ERROR "live at call to convT2E: .autotmp_[0-9]+ .autotmp_[0-9]+$" "live at call to h31: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
+ h31(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+ .autotmp_[0-9]+$" "live at call to h31: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
}
if b3 {
- panic("asdf") // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to gopanic: .autotmp_[0-9]+$"
+ panic(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to gopanic: .autotmp_[0-9]+$"
}
print(b3)
}
var m33 map[interface{}]int
func f33() {
- if m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
printnl()
return
} else {
}
func f34() {
- if m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
printnl()
return
}
}
func f35() {
- if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if m33[byteptr()] == 0 && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
printnl()
return
}
}
func f36() {
- if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if m33[byteptr()] == 0 || m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
printnl()
return
}
}
func f37() {
- if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if (m33[byteptr()] == 0 || m33[byteptr()] == 0) && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
printnl()
return
}