return n
}
+ isInteger := fromType.IsInteger()
+ isBool := fromType.IsBoolean()
+ if sc := fromType.SoleComponent(); sc != nil {
+ isInteger = sc.IsInteger()
+ isBool = sc.IsBoolean()
+ }
// Try a bunch of cases to avoid an allocation.
var value ir.Node
switch {
// n is zero-sized. Use zerobase.
cheapExpr(n, init) // Evaluate n for side-effects. See issue 19246.
value = ir.NewLinksymExpr(base.Pos, ir.Syms.Zerobase, types.Types[types.TUINTPTR])
- case fromType.IsBoolean() || (fromType.Size() == 1 && fromType.IsInteger()):
+ case isBool || fromType.Size() == 1 && isInteger:
// n is a bool/byte. Use staticuint64s[n * 8] on little-endian
// and staticuint64s[n * 8 + 7] on big-endian.
n = cheapExpr(n, init)
+ n = soleComponent(init, n)
// byteindex widens n so that the multiplication doesn't overflow.
index := ir.NewBinaryExpr(base.Pos, ir.OLSH, byteindex(n), ir.NewInt(3))
if ssagen.Arch.LinkArch.ByteOrder == binary.BigEndian {
return types.Txxx, types.Txxx
}
+func soleComponent(init *ir.Nodes, n ir.Node) ir.Node {
+ if n.Type().SoleComponent() == nil {
+ return n
+ }
+ // Keep in sync with cmd/compile/internal/types/type.go:Type.SoleComponent.
+ for {
+ switch {
+ case n.Type().IsStruct():
+ if n.Type().Field(0).Sym.IsBlank() {
+ // Treat blank fields as the zero value as the Go language requires.
+ n = typecheck.Temp(n.Type().Field(0).Type)
+ appendWalkStmt(init, ir.NewAssignStmt(base.Pos, n, nil))
+ return n
+ }
+ n = typecheck.Expr(ir.NewSelectorExpr(n.Pos(), ir.OXDOT, n, n.Type().Field(0).Sym))
+ case n.Type().IsArray():
+ n = typecheck.Expr(ir.NewIndexExpr(n.Pos(), n, ir.NewInt(0)))
+ default:
+ return n
+ }
+ }
+}
+
// byteindex converts n, which is byte-sized, to an int used to index into an array.
// We cannot use conv, because we allow converting bool to int here,
// which is forbidden in user code.