From c8396b51888e4d6ab8b4675b111f329eb23408f6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 12 Sep 2023 04:51:16 -0700 Subject: [PATCH] cmd/compile/internal/ir: add NewZero This constructs a zero value of any type, which helps address some corner case scenarios. It should also eventually handle the predeclared "zero" value, at least as currently implemented in go.dev/cl/520336. For #61372. Change-Id: I3a86a94fd8fa388c9c6bf281da8aa532b3da00fc Reviewed-on: https://go-review.googlesource.com/c/go/+/527696 Auto-Submit: Matthew Dempsky Reviewed-by: Robert Griesemer Reviewed-by: Than McIntosh LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/ir/const.go | 30 +++++++++++++++++++++++ src/cmd/compile/internal/noder/codes.go | 2 +- src/cmd/compile/internal/noder/helpers.go | 4 --- src/cmd/compile/internal/noder/reader.go | 15 +++--------- src/cmd/compile/internal/noder/writer.go | 2 +- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/cmd/compile/internal/ir/const.go b/src/cmd/compile/internal/ir/const.go index e297671449..0efd1137fe 100644 --- a/src/cmd/compile/internal/ir/const.go +++ b/src/cmd/compile/internal/ir/const.go @@ -34,6 +34,36 @@ func NewUintptr(pos src.XPos, v int64) Node { return NewBasicLit(pos, types.Types[types.TUINTPTR], constant.MakeInt64(v)) } +// NewZero returns a zero value of the given type. +func NewZero(pos src.XPos, typ *types.Type) Node { + switch { + case typ.HasNil(): + return NewNilExpr(pos, typ) + case typ.IsInteger(): + return NewBasicLit(pos, typ, intZero) + case typ.IsFloat(): + return NewBasicLit(pos, typ, floatZero) + case typ.IsComplex(): + return NewBasicLit(pos, typ, complexZero) + case typ.IsBoolean(): + return NewBasicLit(pos, typ, constant.MakeBool(false)) + case typ.IsString(): + return NewBasicLit(pos, typ, constant.MakeString("")) + case typ.IsArray() || typ.IsStruct(): + // TODO(mdempsky): Return a typechecked expression instead. + return NewCompLitExpr(pos, OCOMPLIT, typ, nil) + } + + base.FatalfAt(pos, "unexpected type: %v", typ) + panic("unreachable") +} + +var ( + intZero = constant.MakeInt64(0) + floatZero = constant.ToFloat(intZero) + complexZero = constant.ToComplex(intZero) +) + // NewOne returns an OLITERAL representing 1 with the given type. func NewOne(pos src.XPos, typ *types.Type) Node { var val constant.Value diff --git a/src/cmd/compile/internal/noder/codes.go b/src/cmd/compile/internal/noder/codes.go index 764d53e9c5..88c10a74e7 100644 --- a/src/cmd/compile/internal/noder/codes.go +++ b/src/cmd/compile/internal/noder/codes.go @@ -58,7 +58,7 @@ const ( exprSizeof exprAlignof exprOffsetof - exprNil + exprZero exprFuncInst exprRecv exprReshape diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 05a57d07f0..117abe603d 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -59,10 +59,6 @@ func FixValue(typ *types.Type, val constant.Value) constant.Value { return val } -func Nil(pos src.XPos, typ *types.Type) ir.Node { - return ir.NewNilExpr(pos, typ) -} - // Expressions func Addr(pos src.XPos, x ir.Node) *ir.AddrExpr { diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 2fe593c8e3..760170ddfc 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1340,16 +1340,9 @@ func (r *reader) syntheticArgs(pos src.XPos) (recvs, params ir.Nodes) { // For anonymous and blank parameters, we don't have an *ir.Name // to use as the argument. However, since we know the shaped // function won't use the value either, we can just pass the - // zero value. (Also unfortunately, we don't have an easy - // zero-value IR node; so we use a default-initialized temporary - // variable.) + // zero value. if arg == nil { - tmp := typecheck.TempAt(pos, r.curfn, param.Type) - r.curfn.Body.Append( - typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)), - typecheck.Stmt(ir.NewAssignStmt(pos, tmp, nil)), - ) - arg = tmp + arg = ir.NewZero(pos, param.Type) } out.Append(arg) @@ -2177,10 +2170,10 @@ func (r *reader) expr() (res ir.Node) { val := FixValue(typ, r.Value()) return ir.NewBasicLit(pos, typ, val) - case exprNil: + case exprZero: pos := r.pos() typ := r.typ() - return Nil(pos, typ) + return ir.NewZero(pos, typ) case exprCompLit: return r.compLit() diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index c9162e880a..76c8bb8f2d 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1752,7 +1752,7 @@ func (w *writer) expr(expr syntax.Expr) { } if _, isNil := obj.(*types2.Nil); isNil { - w.Code(exprNil) + w.Code(exprZero) w.pos(expr) w.typ(tv.Type) return