mirror of
https://github.com/golang/go
synced 2024-11-18 19:44:46 -07:00
go.tools/ssa: some refactorings
ssa: - Prog.CreatePackages inlined into all callers. - Prog.CreatePackage is now exposed; idempotent; and checks for errors. - '*address' not 'address' now implements lvalue (since it's 6 words). - removed types.Method case from createMemberFromObject. importer: - added importer.PackageInfo.String method. - simplifed importer.PackageInfo by putting types.Info in it. - removed obsolete precondition from IsType. R=gri CC=golang-dev https://golang.org/cl/11408045
This commit is contained in:
parent
6d85cc17dd
commit
69ce87a6c1
@ -131,7 +131,11 @@ func (imp *Importer) LoadPackage(importPath string) (*PackageInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return imp.CreateSourcePackage(importPath, files)
|
||||
info := imp.CreateSourcePackage(importPath, files)
|
||||
if info.Err != nil {
|
||||
return nil, info.Err
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// CreateSourcePackage invokes the type-checker on files and returns a
|
||||
@ -146,33 +150,20 @@ func (imp *Importer) LoadPackage(importPath string) (*PackageInfo, error) {
|
||||
// The ParseFiles utility may be helpful for parsing a set of Go
|
||||
// source files.
|
||||
//
|
||||
func (imp *Importer) CreateSourcePackage(importPath string, files []*ast.File) (*PackageInfo, error) {
|
||||
// The result is always non-nil; the presence of errors is indicated
|
||||
// by the PackageInfo.Err field.
|
||||
//
|
||||
func (imp *Importer) CreateSourcePackage(importPath string, files []*ast.File) *PackageInfo {
|
||||
pkgInfo := &PackageInfo{
|
||||
Files: files,
|
||||
types: make(map[ast.Expr]types.Type),
|
||||
idents: make(map[*ast.Ident]types.Object),
|
||||
constants: make(map[ast.Expr]exact.Value),
|
||||
typecases: make(map[*ast.CaseClause]*types.Var),
|
||||
}
|
||||
|
||||
info := &types.Info{
|
||||
Types: pkgInfo.types,
|
||||
Values: pkgInfo.constants,
|
||||
Objects: pkgInfo.idents,
|
||||
Info: types.Info{
|
||||
Types: make(map[ast.Expr]types.Type),
|
||||
Values: make(map[ast.Expr]exact.Value),
|
||||
Objects: make(map[*ast.Ident]types.Object),
|
||||
Implicits: make(map[ast.Node]types.Object),
|
||||
},
|
||||
}
|
||||
var firstErr error
|
||||
pkgInfo.Pkg, firstErr = imp.context.TypeChecker.Check(importPath, imp.Fset, files, info)
|
||||
if firstErr != nil {
|
||||
return nil, firstErr
|
||||
}
|
||||
|
||||
for node, obj := range info.Implicits {
|
||||
if cc, ok := node.(*ast.CaseClause); ok {
|
||||
pkgInfo.typecases[cc] = obj.(*types.Var)
|
||||
}
|
||||
}
|
||||
|
||||
pkgInfo.Pkg, pkgInfo.Err = imp.context.TypeChecker.Check(importPath, imp.Fset, files, &pkgInfo.Info)
|
||||
imp.Packages[importPath] = pkgInfo
|
||||
return pkgInfo, nil
|
||||
return pkgInfo
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ package importer
|
||||
// TODO(gri): absorb this into go/types.
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.tools/go/exact"
|
||||
"code.google.com/p/go.tools/go/types"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strconv"
|
||||
|
||||
"code.google.com/p/go.tools/go/exact"
|
||||
"code.google.com/p/go.tools/go/types"
|
||||
)
|
||||
|
||||
// PackageInfo holds the ASTs and facts derived by the type-checker
|
||||
@ -17,13 +19,13 @@ import (
|
||||
//
|
||||
type PackageInfo struct {
|
||||
Pkg *types.Package
|
||||
Err error // non-nil if the package had static errors
|
||||
Files []*ast.File // abstract syntax for the package's files
|
||||
types.Info // type-checker deductions.
|
||||
}
|
||||
|
||||
// Type-checker deductions.
|
||||
types map[ast.Expr]types.Type // inferred types of expressions
|
||||
constants map[ast.Expr]exact.Value // values of constant expressions
|
||||
idents map[*ast.Ident]types.Object // resolved objects for named entities
|
||||
typecases map[*ast.CaseClause]*types.Var // implicit vars for single-type typecases
|
||||
func (info *PackageInfo) String() string {
|
||||
return fmt.Sprintf("PackageInfo(%s)", info.Pkg.Path())
|
||||
}
|
||||
|
||||
// Imports returns the set of packages imported by this one, in source
|
||||
@ -57,7 +59,7 @@ func (info *PackageInfo) Imports() []*types.Package {
|
||||
// Precondition: e belongs to the package's ASTs.
|
||||
//
|
||||
func (info *PackageInfo) TypeOf(e ast.Expr) types.Type {
|
||||
if t, ok := info.types[e]; ok {
|
||||
if t, ok := info.Types[e]; ok {
|
||||
return t
|
||||
}
|
||||
// Defining ast.Idents (id := expr) get only Ident callbacks
|
||||
@ -73,20 +75,18 @@ func (info *PackageInfo) TypeOf(e ast.Expr) types.Type {
|
||||
// Precondition: e belongs to the package's ASTs.
|
||||
//
|
||||
func (info *PackageInfo) ValueOf(e ast.Expr) exact.Value {
|
||||
return info.constants[e]
|
||||
return info.Values[e]
|
||||
}
|
||||
|
||||
// ObjectOf returns the typechecker object denoted by the specified id.
|
||||
// Precondition: id belongs to the package's ASTs.
|
||||
//
|
||||
func (info *PackageInfo) ObjectOf(id *ast.Ident) types.Object {
|
||||
return info.idents[id]
|
||||
return info.Objects[id]
|
||||
}
|
||||
|
||||
// IsType returns true iff expression e denotes a type.
|
||||
// Precondition: e belongs to the package's ASTs.
|
||||
// e must be a true expression, not a KeyValueExpr, or an Ident
|
||||
// appearing in a SelectorExpr or declaration.
|
||||
//
|
||||
func (info *PackageInfo) IsType(e ast.Expr) bool {
|
||||
switch e := e.(type) {
|
||||
@ -126,7 +126,10 @@ func (info *PackageInfo) IsPackageRef(sel *ast.SelectorExpr) types.Object {
|
||||
// case clause in a type switch, or nil if not found.
|
||||
//
|
||||
func (info *PackageInfo) TypeCaseVar(cc *ast.CaseClause) *types.Var {
|
||||
return info.typecases[cc]
|
||||
if v := info.Implicits[cc]; v != nil {
|
||||
return v.(*types.Var)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
@ -146,9 +149,6 @@ var (
|
||||
// be moved there and made accessible via an additional types.Context
|
||||
// callback.
|
||||
//
|
||||
// The returned Signature is degenerate and only intended for use by
|
||||
// emitCallArgs.
|
||||
//
|
||||
func (info *PackageInfo) BuiltinCallSignature(e *ast.CallExpr) *types.Signature {
|
||||
var params []*types.Var
|
||||
var isVariadic bool
|
||||
|
@ -245,14 +245,16 @@ func TestEnclosingFunction(t *testing.T) {
|
||||
t.Errorf("EnclosingFunction(%q) not exact", test.substr)
|
||||
continue
|
||||
}
|
||||
info, err := imp.CreateSourcePackage("main", []*ast.File{f})
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
info := imp.CreateSourcePackage("main", []*ast.File{f})
|
||||
if info.Err != nil {
|
||||
t.Error(info.Err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
prog := ssa.NewProgram(imp.Fset, 0)
|
||||
prog.CreatePackages(imp)
|
||||
for _, info := range imp.Packages {
|
||||
prog.CreatePackage(info)
|
||||
}
|
||||
pkg := prog.Package(info.Pkg)
|
||||
pkg.Build()
|
||||
|
||||
|
@ -38,7 +38,8 @@ func CreatePackageFromArgs(imp *Importer, args []string) (info *PackageInfo, res
|
||||
files, err = ParseFiles(imp.Fset, ".", args[:i]...)
|
||||
rest = args[i:]
|
||||
if err == nil {
|
||||
info, err = imp.CreateSourcePackage("main", files)
|
||||
info = imp.CreateSourcePackage("main", files)
|
||||
err = info.Err
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -7,7 +7,7 @@ package ssa
|
||||
// definitions of all package members are created, method-sets are
|
||||
// computed, and wrapper methods are synthesized. The create phase
|
||||
// proceeds in topological order over the import dependency graph,
|
||||
// initiated by client calls to CreatePackages.
|
||||
// initiated by client calls to Program.CreatePackage.
|
||||
//
|
||||
// In the BUILD phase (builder.go), the builder traverses the AST of
|
||||
// each Go source function and generates SSA instructions for the
|
||||
@ -447,7 +447,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||
if v == nil {
|
||||
v = fn.lookup(obj, escaping)
|
||||
}
|
||||
return address{addr: v, id: e, object: obj}
|
||||
return &address{addr: v, id: e, object: obj}
|
||||
|
||||
case *ast.CompositeLit:
|
||||
t := deref(fn.Pkg.typeOf(e))
|
||||
@ -458,7 +458,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||
v = fn.addLocal(t, e.Lbrace)
|
||||
}
|
||||
b.compLit(fn, v, e, t) // initialize in place
|
||||
return address{addr: v}
|
||||
return &address{addr: v}
|
||||
|
||||
case *ast.ParenExpr:
|
||||
return b.addr(fn, e.X, escaping)
|
||||
@ -467,13 +467,13 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||
// p.M where p is a package.
|
||||
if obj := fn.Pkg.info.IsPackageRef(e); obj != nil {
|
||||
if v := b.lookup(fn.Pkg, obj); v != nil {
|
||||
return address{addr: v}
|
||||
return &address{addr: v}
|
||||
}
|
||||
panic("undefined package-qualified name: " + obj.Name())
|
||||
}
|
||||
|
||||
// e.f where e is an expression.
|
||||
return address{addr: b.selectField(fn, e, true, escaping)}
|
||||
return &address{addr: b.selectField(fn, e, true, escaping)}
|
||||
|
||||
case *ast.IndexExpr:
|
||||
var x Value
|
||||
@ -502,10 +502,10 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||
Index: emitConv(fn, b.expr(fn, e.Index), tInt),
|
||||
}
|
||||
v.setType(et)
|
||||
return address{addr: fn.emit(v)}
|
||||
return &address{addr: fn.emit(v)}
|
||||
|
||||
case *ast.StarExpr:
|
||||
return address{addr: b.expr(fn, e.X), starPos: e.Star}
|
||||
return &address{addr: b.expr(fn, e.X), starPos: e.Star}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unexpected address expression: %T", e))
|
||||
@ -519,7 +519,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||
// in an addressable location.
|
||||
//
|
||||
func (b *builder) exprInPlace(fn *Function, loc lvalue, e ast.Expr) {
|
||||
if _, ok := loc.(address); ok {
|
||||
if _, ok := loc.(*address); ok {
|
||||
if e, ok := e.(*ast.CompositeLit); ok {
|
||||
typ := loc.typ()
|
||||
switch typ.Underlying().(type) {
|
||||
@ -1047,7 +1047,7 @@ func (b *builder) globalValueSpec(init *Function, spec *ast.ValueSpec, g *Global
|
||||
continue
|
||||
}
|
||||
g.spec = nil
|
||||
lval = address{addr: g}
|
||||
lval = &address{addr: g}
|
||||
} else {
|
||||
// Mode B: initialize all globals.
|
||||
if !isBlankIdent(id) {
|
||||
@ -1056,7 +1056,7 @@ func (b *builder) globalValueSpec(init *Function, spec *ast.ValueSpec, g *Global
|
||||
continue // already done
|
||||
}
|
||||
g2.spec = nil
|
||||
lval = address{addr: g2}
|
||||
lval = &address{addr: g2}
|
||||
}
|
||||
}
|
||||
if init.Prog.mode&LogSource != 0 {
|
||||
@ -1241,7 +1241,7 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ
|
||||
}
|
||||
faddr.setType(types.NewPointer(sf.Type()))
|
||||
fn.emit(faddr)
|
||||
b.exprInPlace(fn, address{addr: faddr}, e)
|
||||
b.exprInPlace(fn, &address{addr: faddr}, e)
|
||||
}
|
||||
|
||||
case *types.Array, *types.Slice:
|
||||
@ -1274,7 +1274,7 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ
|
||||
}
|
||||
iaddr.setType(types.NewPointer(at.Elem()))
|
||||
fn.emit(iaddr)
|
||||
b.exprInPlace(fn, address{addr: iaddr}, e)
|
||||
b.exprInPlace(fn, &address{addr: iaddr}, e)
|
||||
}
|
||||
if t != at { // slice
|
||||
s := &Slice{X: array}
|
||||
|
@ -42,14 +42,16 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
info, err := imp.CreateSourcePackage("main", []*ast.File{f})
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
info := imp.CreateSourcePackage("main", []*ast.File{f})
|
||||
if info.Err != nil {
|
||||
t.Error(info.Err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
|
||||
prog.CreatePackages(imp)
|
||||
for _, info := range imp.Packages {
|
||||
prog.CreatePackage(info)
|
||||
}
|
||||
mainPkg := prog.Package(info.Pkg)
|
||||
mainPkg.Build()
|
||||
|
||||
|
@ -57,24 +57,6 @@ func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
|
||||
return prog
|
||||
}
|
||||
|
||||
// CreatePackages creates an SSA Package for each type-checker package
|
||||
// held by imp. All such packages must be error-free.
|
||||
//
|
||||
// The created packages may be accessed via the Program.Packages field.
|
||||
//
|
||||
// A package in the 'created' state has its Members mapping populated,
|
||||
// but a subsequent call to Package.Build() or Program.BuildAll() is
|
||||
// required to build SSA code for the bodies of its functions.
|
||||
//
|
||||
func (prog *Program) CreatePackages(imp *importer.Importer) {
|
||||
// TODO(adonovan): make this idempotent, so that a second call
|
||||
// to CreatePackages creates only the packages that appeared
|
||||
// in imp since the first.
|
||||
for path, info := range imp.Packages {
|
||||
createPackage(prog, path, info)
|
||||
}
|
||||
}
|
||||
|
||||
// memberFromObject populates package pkg with a member for the
|
||||
// typechecker object obj.
|
||||
//
|
||||
@ -143,10 +125,6 @@ func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
|
||||
pkg.Prog.concreteMethods[method] = fn
|
||||
}
|
||||
|
||||
case *types.Method:
|
||||
// TODO(adonovan): do something more sensible here?
|
||||
memberFromObject(pkg, obj.Func, syntax)
|
||||
|
||||
default: // (incl. *types.Package)
|
||||
panic(fmt.Sprintf("unexpected Object type: %T", obj))
|
||||
}
|
||||
@ -202,13 +180,23 @@ func membersFromDecl(pkg *Package, decl ast.Decl) {
|
||||
}
|
||||
}
|
||||
|
||||
// createPackage constructs an SSA Package from an error-free
|
||||
// package described by info, and populates its Members mapping.
|
||||
// CreatePackage constructs and returns an SSA Package from an
|
||||
// error-free package described by info, and populates its Members
|
||||
// mapping.
|
||||
//
|
||||
// Repeated calls with the same info returns the same Package.
|
||||
//
|
||||
// The real work of building SSA form for each function is not done
|
||||
// until a subsequent call to Package.Build().
|
||||
//
|
||||
func createPackage(prog *Program, importPath string, info *importer.PackageInfo) {
|
||||
func (prog *Program) CreatePackage(info *importer.PackageInfo) *Package {
|
||||
if info.Err != nil {
|
||||
panic(fmt.Sprintf("package %s has errors: %s", info, info.Err))
|
||||
}
|
||||
if p := prog.packages[info.Pkg]; p != nil {
|
||||
return p // already loaded
|
||||
}
|
||||
|
||||
p := &Package{
|
||||
Prog: prog,
|
||||
Members: make(map[string]Member),
|
||||
@ -246,11 +234,11 @@ func createPackage(prog *Program, importPath string, info *importer.PackageInfo)
|
||||
if obj, ok := obj.(*types.TypeName); ok {
|
||||
mset := types.NewMethodSet(obj.Type())
|
||||
for i, n := 0, mset.Len(); i < n; i++ {
|
||||
memberFromObject(p, mset.At(i), nil)
|
||||
memberFromObject(p, mset.At(i).Func, nil)
|
||||
}
|
||||
mset = types.NewMethodSet(types.NewPointer(obj.Type()))
|
||||
for i, n := 0, mset.Len(); i < n; i++ {
|
||||
memberFromObject(p, mset.At(i), nil)
|
||||
memberFromObject(p, mset.At(i).Func, nil)
|
||||
}
|
||||
}
|
||||
memberFromObject(p, obj, nil)
|
||||
@ -269,10 +257,12 @@ func createPackage(prog *Program, importPath string, info *importer.PackageInfo)
|
||||
p.DumpTo(os.Stderr)
|
||||
}
|
||||
|
||||
prog.PackagesByPath[importPath] = p
|
||||
prog.PackagesByPath[info.Pkg.Path()] = p
|
||||
prog.packages[p.Object] = p
|
||||
|
||||
if prog.mode&SanityCheckFunctions != 0 {
|
||||
sanityCheckPackage(p)
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
@ -47,16 +47,18 @@ func main() {
|
||||
}
|
||||
|
||||
// Create a "main" package containing one file.
|
||||
info, err := imp.CreateSourcePackage("main", []*ast.File{file})
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error()) // type error
|
||||
info := imp.CreateSourcePackage("main", []*ast.File{file})
|
||||
if info.Err != nil {
|
||||
fmt.Printf(info.Err.Error()) // type error
|
||||
return
|
||||
}
|
||||
|
||||
// Create SSA-form program representation.
|
||||
var mode ssa.BuilderMode
|
||||
prog := ssa.NewProgram(imp.Fset, mode)
|
||||
prog.CreatePackages(imp)
|
||||
for _, info := range imp.Packages {
|
||||
prog.CreatePackage(info)
|
||||
}
|
||||
mainPkg := prog.Package(info.Pkg)
|
||||
|
||||
// Print out the package.
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.google.com/p/go.tools/importer"
|
||||
"code.google.com/p/go.tools/ssa"
|
||||
@ -79,22 +80,22 @@ var gorootTests = []string{
|
||||
"ddd.go",
|
||||
"blank.go", // partly disabled; TODO(adonovan): skip blank fields in struct{_} equivalence.
|
||||
"map.go",
|
||||
"bom.go",
|
||||
"closedchan.go",
|
||||
"divide.go",
|
||||
"rename.go",
|
||||
"const3.go",
|
||||
"nil.go",
|
||||
"recover.go", // partly disabled; TODO(adonovan): fix.
|
||||
// Slow tests follow.
|
||||
"cmplxdivide.go cmplxdivide1.go",
|
||||
"append.go",
|
||||
"crlf.go", // doesn't actually assert anything
|
||||
"typeswitch1.go",
|
||||
"floatcmp.go",
|
||||
"gc1.go",
|
||||
"crlf.go", // doesn't actually assert anything
|
||||
// Slow tests follow.
|
||||
"bom.go", // ~1.7s
|
||||
"gc1.go", // ~1.7s
|
||||
"cmplxdivide.go cmplxdivide1.go", // ~2.4s
|
||||
|
||||
// Working, but not worth enabling:
|
||||
// "append.go", // works, but slow (15s).
|
||||
// "gc2.go", // works, but slow, and cheats on the memory check.
|
||||
// "sigchld.go", // works, but only on POSIX.
|
||||
// "peano.go", // works only up to n=9, and slow even then.
|
||||
@ -111,7 +112,6 @@ var gorootTests = []string{
|
||||
|
||||
// Typechecker failures:
|
||||
// "switch.go", // https://code.google.com/p/go/issues/detail?id=5505
|
||||
// "rune.go", // https://code.google.com/p/go/issues/detail?id=5895
|
||||
|
||||
// Broken. TODO(adonovan): fix.
|
||||
// copy.go // very slow; but with N=4 quickly crashes, slice index out of range.
|
||||
@ -139,6 +139,8 @@ var testdataTests = []string{
|
||||
func run(t *testing.T, dir, input string) bool {
|
||||
fmt.Printf("Input: %s\n", input)
|
||||
|
||||
start := time.Now()
|
||||
|
||||
var inputs []string
|
||||
for _, i := range strings.Split(input, " ") {
|
||||
inputs = append(inputs, dir+i)
|
||||
@ -166,14 +168,16 @@ func run(t *testing.T, dir, input string) bool {
|
||||
}()
|
||||
|
||||
hint = fmt.Sprintf("To dump SSA representation, run:\n%% go run src/code.google.com/p/go.tools/ssa/ssadump.go -build=CFP %s\n", input)
|
||||
info, err := imp.CreateSourcePackage("main", files)
|
||||
if err != nil {
|
||||
t.Errorf("ssa.Builder.CreatePackage(%s) failed: %s", inputs, err.Error())
|
||||
info := imp.CreateSourcePackage("main", files)
|
||||
if info.Err != nil {
|
||||
t.Errorf("importer.CreateSourcePackage(%s) failed: %s", inputs, info.Err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
|
||||
prog.CreatePackages(imp)
|
||||
for _, info := range imp.Packages {
|
||||
prog.CreatePackage(info)
|
||||
}
|
||||
prog.BuildAll()
|
||||
|
||||
hint = fmt.Sprintf("To trace execution, run:\n%% go run src/code.google.com/p/go.tools/ssa/ssadump.go -build=C -run --interp=T %s\n", input)
|
||||
@ -183,6 +187,11 @@ func run(t *testing.T, dir, input string) bool {
|
||||
}
|
||||
|
||||
hint = "" // call off the hounds
|
||||
|
||||
if false {
|
||||
fmt.Println(input, time.Since(start)) // test profiling
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -29,13 +29,13 @@ type address struct {
|
||||
object types.Object // source var, if from *ast.Ident
|
||||
}
|
||||
|
||||
func (a address) load(fn *Function) Value {
|
||||
func (a *address) load(fn *Function) Value {
|
||||
load := emitLoad(fn, a.addr)
|
||||
load.pos = a.starPos
|
||||
return load
|
||||
}
|
||||
|
||||
func (a address) store(fn *Function, v Value) {
|
||||
func (a *address) store(fn *Function, v Value) {
|
||||
store := emitStore(fn, a.addr, v)
|
||||
store.pos = a.starPos
|
||||
if a.id != nil {
|
||||
@ -44,7 +44,7 @@ func (a address) store(fn *Function, v Value) {
|
||||
}
|
||||
}
|
||||
|
||||
func (a address) address(fn *Function) Value {
|
||||
func (a *address) address(fn *Function) Value {
|
||||
if a.id != nil {
|
||||
// NB: this kind of DebugRef yields the object's address.
|
||||
emitDebugRef(fn, a.id, a.addr)
|
||||
@ -52,7 +52,7 @@ func (a address) address(fn *Function) Value {
|
||||
return a.addr
|
||||
}
|
||||
|
||||
func (a address) typ() types.Type {
|
||||
func (a *address) typ() types.Type {
|
||||
return deref(a.addr.Type())
|
||||
}
|
||||
|
||||
|
@ -40,14 +40,16 @@ func TestObjValueLookup(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
info, err := imp.CreateSourcePackage("main", []*ast.File{f})
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
info := imp.CreateSourcePackage("main", []*ast.File{f})
|
||||
if info.Err != nil {
|
||||
t.Error(info.Err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
prog := ssa.NewProgram(imp.Fset, ssa.DebugInfo /*|ssa.LogFunctions*/)
|
||||
prog.CreatePackages(imp)
|
||||
for _, info := range imp.Packages {
|
||||
prog.CreatePackage(info)
|
||||
}
|
||||
pkg := prog.Package(info.Pkg)
|
||||
pkg.Build()
|
||||
|
||||
|
@ -114,7 +114,9 @@ func main() {
|
||||
|
||||
// Create and build SSA-form program representation.
|
||||
prog := ssa.NewProgram(imp.Fset, mode)
|
||||
prog.CreatePackages(imp)
|
||||
for _, info := range imp.Packages {
|
||||
prog.CreatePackage(info)
|
||||
}
|
||||
prog.BuildAll()
|
||||
|
||||
// Run the interpreter.
|
||||
|
Loading…
Reference in New Issue
Block a user