go/ssa: make Builtin capable of representing non-spec-defined intrinsics.
Also, define ssa:wrapnilchk intrinsic to check and gracefully
fail when a T method is dynamically invoked via a nil *T receiver.
+ Test.
A follow-up CL will add another intrinsic, ssa:memclr.
+ minor cleanups.
LGTM=gri
R=gri
CC=golang-codereviews
https://golang.org/cl/101170044
diff --git a/go/ssa/ssa.go b/go/ssa/ssa.go
index 404bf92..b1e582f 100644
--- a/go/ssa/ssa.go
+++ b/go/ssa/ssa.go
@@ -440,14 +440,23 @@
// Builtins are immutable values. Builtins do not have addresses.
// Builtins can only appear in CallCommon.Func.
//
-// Object() returns a *types.Builtin.
+// Name() indicates the function: one of the built-in functions from the
+// Go spec (excluding "make" and "new") or one of these ssa-defined
+// intrinsics:
+//
+// // wrapnilchk returns ptr if non-nil, panics otherwise.
+// // (For use in indirection wrappers.)
+// func ssa:wrapnilchk(ptr *T, recvType, methodName string) *T
+//
+// Object() returns a *types.Builtin for built-ins defined by the spec,
+// nil for others.
//
// Type() returns a *types.Signature representing the effective
// signature of the built-in for this call.
//
type Builtin struct {
- object *types.Builtin // canonical types.Universe object for this built-in
- sig *types.Signature
+ name string
+ sig *types.Signature
}
// Value-defining instructions ----------------------------------------
@@ -1382,10 +1391,10 @@
func (s *Go) Value() *Call { return nil }
func (v *Builtin) Type() types.Type { return v.sig }
-func (v *Builtin) Name() string { return v.object.Name() }
+func (v *Builtin) Name() string { return v.name }
func (*Builtin) Referrers() *[]Instruction { return nil }
func (v *Builtin) Pos() token.Pos { return token.NoPos }
-func (v *Builtin) Object() types.Object { return v.object }
+func (v *Builtin) Object() types.Object { return types.Universe.Lookup(v.name) }
func (v *Builtin) Parent() *Function { return nil }
func (v *FreeVar) Type() types.Type { return v.typ }