go.tools/ssa: SSA fixes for *types.Builtin becoming an object (CL 13813043)

R=gri
CC=golang-dev
https://golang.org/cl/13848043
This commit is contained in:
Alan Donovan 2013-09-23 18:18:35 -04:00
parent a05da76c7b
commit 318b83e376
6 changed files with 31 additions and 42 deletions

View File

@ -41,9 +41,11 @@ func callees(o *Oracle, qpos *QueryPos) (queryResult, error) {
}
// Reject calls to built-ins.
if b, ok := qpos.info.TypeOf(call.Fun).(*types.Builtin); ok {
if id, ok := unparen(call.Fun).(*ast.Ident); ok {
if b, ok := qpos.info.ObjectOf(id).(*types.Builtin); ok {
return nil, o.errorf(call, "this is a call to the built-in '%s' operator", b.Name())
}
}
buildSSA(o)

View File

@ -265,15 +265,15 @@ func (b *builder) exprN(fn *Function, e ast.Expr) Value {
}
// builtin emits to fn SSA instructions to implement a call to the
// built-in function called name with the specified arguments
// built-in function obj with the specified arguments
// and return type. It returns the value defined by the result.
//
// The result is nil if no special handling was required; in this case
// the caller should treat this like an ordinary library function
// call.
//
func (b *builder) builtin(fn *Function, name string, args []ast.Expr, typ types.Type, pos token.Pos) Value {
switch name {
func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
switch obj.Name() {
case "make":
switch typ.Underlying().(type) {
case *types.Slice:
@ -554,9 +554,8 @@ func (b *builder) expr0(fn *Function, e ast.Expr) Value {
}
// Call to "intrinsic" built-ins, e.g. new, make, panic.
if id, ok := e.Fun.(*ast.Ident); ok {
obj := fn.Pkg.objectOf(id)
if _, ok := fn.Prog.builtins[obj]; ok {
if v := b.builtin(fn, id.Name, e.Args, typ, e.Lparen); v != nil {
if obj, ok := fn.Pkg.objectOf(id).(*types.Builtin); ok {
if v := b.builtin(fn, obj, e.Args, typ, e.Lparen); v != nil {
return v
}
}
@ -639,7 +638,7 @@ func (b *builder) expr0(fn *Function, e ast.Expr) Value {
case *ast.Ident:
obj := fn.Pkg.objectOf(e)
// Universal built-in?
if obj.Pkg() == nil {
if obj, ok := obj.(*types.Builtin); ok {
return fn.Prog.builtins[obj]
}
// Package-level func or var?
@ -1750,7 +1749,7 @@ func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type) (k, v Value
} else {
// length = len(x).
var c Call
c.Call.Value = fn.Prog.builtins[types.Universe.Lookup("len")]
c.Call.Value = fn.Prog.builtins[types.Universe.Lookup("len").(*types.Builtin)]
c.Call.Args = []Value{x}
c.setType(tInt)
length = fn.emit(&c)

View File

@ -43,7 +43,7 @@ func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
Fset: fset,
imported: make(map[string]*Package),
packages: make(map[*types.Package]*Package),
builtins: make(map[types.Object]*Builtin),
builtins: make(map[*types.Builtin]*Builtin),
boundMethodWrappers: make(map[*types.Func]*Function),
ifaceMethodWrappers: make(map[*types.Func]*Function),
mode: mode,
@ -51,7 +51,7 @@ func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
// Create Values for built-in functions.
for _, name := range types.Universe.Names() {
if obj, ok := types.Universe.Lookup(name).(*types.Func); ok {
if obj, ok := types.Universe.Lookup(name).(*types.Builtin); ok {
prog.builtins[obj] = &Builtin{obj}
}
}

View File

@ -178,18 +178,13 @@ func (prog *Program) packageLevelValue(obj types.Object) Value {
return nil
}
// FuncValue returns the SSA Value denoted by the source-level named
// function obj. The result may be a *Function or a *Builtin, or nil
// if not found.
// FuncValue returns the Function denoted by the source-level named
// function obj.
//
func (prog *Program) FuncValue(obj *types.Func) Value {
// Universal built-in?
if v, ok := prog.builtins[obj]; ok {
return v
}
func (prog *Program) FuncValue(obj *types.Func) *Function {
// Package-level function or declared method?
if v := prog.packageLevelValue(obj); v != nil {
return v
return v.(*Function)
}
// Interface method wrapper?
meth := recvType(obj).MethodSet().Lookup(obj.Pkg(), obj.Name())

View File

@ -103,28 +103,19 @@ func TestObjValueLookup(t *testing.T) {
}
func checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) {
v := prog.FuncValue(obj)
// fmt.Printf("FuncValue(%s) = %s\n", obj, v) // debugging
if v == nil {
fn := prog.FuncValue(obj)
// fmt.Printf("FuncValue(%s) = %s\n", obj, fn) // debugging
if fn == nil {
t.Errorf("FuncValue(%s) == nil", obj)
return
}
// v must be an *ssa.Function or *ssa.Builtin.
v2, _ := v.(interface {
Object() types.Object
})
if v2 == nil {
t.Errorf("FuncValue(%s) = %s %T; has no Object() method",
obj, v.Name(), v)
return
}
if vobj := v2.Object(); vobj != obj {
if fnobj := fn.Object(); fnobj != obj {
t.Errorf("FuncValue(%s).Object() == %s; value was %s",
obj, vobj, v.Name())
obj, fnobj, fn.Name())
return
}
if !types.IsIdentical(v.Type(), obj.Type()) {
t.Errorf("FuncValue(%s).Type() == %s", obj, v.Type())
if !types.IsIdentical(fn.Type(), obj.Type()) {
t.Errorf("FuncValue(%s).Type() == %s", obj, fn.Type())
return
}
}

View File

@ -25,7 +25,7 @@ type Program struct {
Fset *token.FileSet // position information for the files of this Program
imported map[string]*Package // all importable Packages, keyed by import path
packages map[*types.Package]*Package // all loaded Packages, keyed by object
builtins map[types.Object]*Builtin // all built-in functions, keyed by typechecker objects.
builtins map[*types.Builtin]*Builtin // all built-in functions, keyed by typechecker objects.
mode BuilderMode // set of mode bits for SSA construction
methodsMu sync.Mutex // guards the following maps:
@ -401,12 +401,14 @@ type Global struct {
// Builtins are immutable values. Builtins do not have addresses.
// Builtins can only appear in CallCommon.Func.
//
// Type() returns a *types.Builtin.
// Built-in functions may have polymorphic or variadic types that are
// not expressible in Go's type system.
// Object() returns a *types.Builtin.
//
// Type() returns types.Typ[types.Invalid], since built-in functions
// may have polymorphic or variadic types that are not expressible in
// Go's type system.
//
type Builtin struct {
object *types.Func // canonical types.Universe object for this built-in
object *types.Builtin // canonical types.Universe object for this built-in
}
// Value-defining instructions ----------------------------------------