mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:10 -07:00
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 <mdempsky@google.com> Reviewed-by: Robert Griesemer <gri@google.com> Reviewed-by: Than McIntosh <thanm@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
661e3be497
commit
c8396b5188
@ -34,6 +34,36 @@ func NewUintptr(pos src.XPos, v int64) Node {
|
|||||||
return NewBasicLit(pos, types.Types[types.TUINTPTR], constant.MakeInt64(v))
|
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.
|
// NewOne returns an OLITERAL representing 1 with the given type.
|
||||||
func NewOne(pos src.XPos, typ *types.Type) Node {
|
func NewOne(pos src.XPos, typ *types.Type) Node {
|
||||||
var val constant.Value
|
var val constant.Value
|
||||||
|
@ -58,7 +58,7 @@ const (
|
|||||||
exprSizeof
|
exprSizeof
|
||||||
exprAlignof
|
exprAlignof
|
||||||
exprOffsetof
|
exprOffsetof
|
||||||
exprNil
|
exprZero
|
||||||
exprFuncInst
|
exprFuncInst
|
||||||
exprRecv
|
exprRecv
|
||||||
exprReshape
|
exprReshape
|
||||||
|
@ -59,10 +59,6 @@ func FixValue(typ *types.Type, val constant.Value) constant.Value {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func Nil(pos src.XPos, typ *types.Type) ir.Node {
|
|
||||||
return ir.NewNilExpr(pos, typ)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expressions
|
// Expressions
|
||||||
|
|
||||||
func Addr(pos src.XPos, x ir.Node) *ir.AddrExpr {
|
func Addr(pos src.XPos, x ir.Node) *ir.AddrExpr {
|
||||||
|
@ -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
|
// For anonymous and blank parameters, we don't have an *ir.Name
|
||||||
// to use as the argument. However, since we know the shaped
|
// to use as the argument. However, since we know the shaped
|
||||||
// function won't use the value either, we can just pass the
|
// function won't use the value either, we can just pass the
|
||||||
// zero value. (Also unfortunately, we don't have an easy
|
// zero value.
|
||||||
// zero-value IR node; so we use a default-initialized temporary
|
|
||||||
// variable.)
|
|
||||||
if arg == nil {
|
if arg == nil {
|
||||||
tmp := typecheck.TempAt(pos, r.curfn, param.Type)
|
arg = ir.NewZero(pos, param.Type)
|
||||||
r.curfn.Body.Append(
|
|
||||||
typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)),
|
|
||||||
typecheck.Stmt(ir.NewAssignStmt(pos, tmp, nil)),
|
|
||||||
)
|
|
||||||
arg = tmp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Append(arg)
|
out.Append(arg)
|
||||||
@ -2177,10 +2170,10 @@ func (r *reader) expr() (res ir.Node) {
|
|||||||
val := FixValue(typ, r.Value())
|
val := FixValue(typ, r.Value())
|
||||||
return ir.NewBasicLit(pos, typ, val)
|
return ir.NewBasicLit(pos, typ, val)
|
||||||
|
|
||||||
case exprNil:
|
case exprZero:
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
typ := r.typ()
|
typ := r.typ()
|
||||||
return Nil(pos, typ)
|
return ir.NewZero(pos, typ)
|
||||||
|
|
||||||
case exprCompLit:
|
case exprCompLit:
|
||||||
return r.compLit()
|
return r.compLit()
|
||||||
|
@ -1752,7 +1752,7 @@ func (w *writer) expr(expr syntax.Expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, isNil := obj.(*types2.Nil); isNil {
|
if _, isNil := obj.(*types2.Nil); isNil {
|
||||||
w.Code(exprNil)
|
w.Code(exprZero)
|
||||||
w.pos(expr)
|
w.pos(expr)
|
||||||
w.typ(tv.Type)
|
w.typ(tv.Type)
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user