Skip to content

Commit

Permalink
updating info lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
grantnelson-wf committed Nov 18, 2024
1 parent 22fb425 commit a35ce9c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 52 deletions.
32 changes: 16 additions & 16 deletions compiler/decls.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ func (d *Decl) Dce() *dce.Info {
// importDeclFullName returns a unique name for an import declaration.
// This import name may be duplicated in different packages if they both
// import the same package.
func (fc *funcContext) importDeclFullName(importedPkg *types.Package) string {
func importDeclFullName(fc *funcContext, importedPkg *types.Package) string {
return `import:` + fc.importedPkgVar(importedPkg)
}

// varDeclFullName returns a unique name for a package-level variable declaration.
// This var name only references one of the variables in a single assignment.
func (fc *funcContext) varDeclFullName(init *types.Initializer) string {
func varDeclFullName(init *types.Initializer) string {
// TODO: Check what happens when Lhs is blank.
return `var:` + symbol.New(init.Lhs[0]).String()
}
Expand All @@ -94,39 +94,39 @@ func (fc *funcContext) varDeclFullName(init *types.Initializer) string {
// that is used for a function (without a receiver) declaration.
// If the function is generic, this declaration name is also for the list
// of instantiations of the function.
func (fc *funcContext) funcVarDeclFullName(o *types.Func) string {
func funcVarDeclFullName(fc *funcContext, o *types.Func) string {
return `funcVar:` + o.Pkg().Path() + `.` + fc.objectName(o)
}

// mainFuncFullName returns the name for the declaration used to invoke the
// main function of the program.
func (fc *funcContext) mainFuncDeclFullName() string {
func mainFuncDeclFullName() string {
return `init:main`
}

// funcDeclFullName returns a unique name for a package-level function
// declaration for the given instance of a function.
func (fc *funcContext) funcDeclFullName(inst typeparams.Instance) string {
func funcDeclFullName(inst typeparams.Instance) string {
return `func:` + inst.String()
}

// typeVarDeclFullName returns a unique name for a package-level variable
// that is used for a named type declaration.
// If the type is generic, this declaration name is also for the list
// of instantiations of the type.
func (fc *funcContext) typeVarDeclFullName(o *types.TypeName) string {
func typeVarDeclFullName(o *types.TypeName) string {
return `typeVar:` + symbol.New(o).String()
}

// typeDeclFullName returns a unique name for a package-level type declaration
// for the given instance of a type.
func (fc *funcContext) typeDeclFullName(inst typeparams.Instance) string {
func typeDeclFullName(inst typeparams.Instance) string {
return `type:` + inst.String()
}

// anonTypeDeclFullName returns a unique name for a package-level type
// declaration for an anonymous type.
func (fc *funcContext) anonTypeDeclFullName(o types.Object) string {
func anonTypeDeclFullName(o types.Object) string {
return `anonType:` + symbol.New(o).String()
}

Expand Down Expand Up @@ -214,7 +214,7 @@ func (fc *funcContext) importDecls() (importedPaths []string, importDecls []*Dec
func (fc *funcContext) newImportDecl(importedPkg *types.Package) *Decl {
pkgVar := fc.importedPkgVar(importedPkg)
d := &Decl{
FullName: fc.importDeclFullName(importedPkg),
FullName: importDeclFullName(fc, importedPkg),
Vars: []string{pkgVar},
DeclCode: []byte(fmt.Sprintf("\t%s = $packages[\"%s\"];\n", pkgVar, importedPkg.Path())),
InitCode: fc.CatchOutput(1, func() { fc.translateStmt(fc.importInitializer(importedPkg.Path()), nil) }),
Expand Down Expand Up @@ -280,7 +280,7 @@ func (fc *funcContext) varDecls(vars []*types.Var) []*Decl {
// initializer.
func (fc *funcContext) newVarDecl(init *types.Initializer) *Decl {
d := &Decl{
FullName: fc.varDeclFullName(init),
FullName: varDeclFullName(init),
}

assignLHS := []ast.Expr{}
Expand Down Expand Up @@ -338,7 +338,7 @@ func (fc *funcContext) funcDecls(functions []*ast.FuncDecl) ([]*Decl, error) {
// package-level variable by which they all are referenced.
objName := fc.objectName(o)
varDecl := &Decl{
FullName: fc.funcVarDeclFullName(o),
FullName: funcVarDeclFullName(fc, o),
Vars: []string{objName},
}
varDecl.Dce().SetName(o)
Expand Down Expand Up @@ -366,7 +366,7 @@ func (fc *funcContext) funcDecls(functions []*ast.FuncDecl) ([]*Decl, error) {
// been initialized. It must come after all other functions, especially all
// init() functions, otherwise main() will be invoked too early.
funcDecls = append(funcDecls, &Decl{
FullName: fc.mainFuncDeclFullName(),
FullName: mainFuncDeclFullName(),
InitCode: fc.CatchOutput(1, func() { fc.translateStmt(fc.callMainFunc(mainFunc), nil) }),
})
}
Expand All @@ -377,7 +377,7 @@ func (fc *funcContext) funcDecls(functions []*ast.FuncDecl) ([]*Decl, error) {
func (fc *funcContext) newFuncDecl(fun *ast.FuncDecl, inst typeparams.Instance) *Decl {
o := fc.pkgCtx.Defs[fun.Name].(*types.Func)
d := &Decl{
FullName: fc.funcDeclFullName(inst),
FullName: funcDeclFullName(inst),
Blocking: fc.pkgCtx.IsBlocking(inst),
LinkingName: symbol.New(o),
}
Expand Down Expand Up @@ -480,7 +480,7 @@ func (fc *funcContext) namedTypeDecls(typeNames typesutil.TypeNames) ([]*Decl, e
func (fc *funcContext) newNamedTypeVarDecl(obj *types.TypeName) *Decl {
name := fc.objectName(obj)
varDecl := &Decl{
FullName: fc.typeVarDeclFullName(obj),
FullName: typeVarDeclFullName(obj),
Vars: []string{name},
}
if typeparams.HasTypeParams(obj.Type()) {
Expand Down Expand Up @@ -515,7 +515,7 @@ func (fc *funcContext) newNamedTypeInstDecl(inst typeparams.Instance) (*Decl, er

underlying := instanceType.Underlying()
d := &Decl{
FullName: fc.typeDeclFullName(inst),
FullName: typeDeclFullName(inst),
}
d.Dce().SetName(inst.Object, inst.TArgs...)
fc.pkgCtx.CollectDCEDeps(d, func() {
Expand Down Expand Up @@ -638,7 +638,7 @@ func (fc *funcContext) anonTypeDecls(anonTypes []*types.TypeName) []*Decl {
decls := []*Decl{}
for _, t := range anonTypes {
d := &Decl{
FullName: fc.anonTypeDeclFullName(t),
FullName: anonTypeDeclFullName(t),
Vars: []string{t.Name()},
}
d.Dce().SetName(t)
Expand Down
56 changes: 25 additions & 31 deletions compiler/internal/analysis/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ type Info struct {
funcInstInfos *typeparams.InstanceMap[*FuncInfo]
funcLitInfos map[*ast.FuncLit]*FuncInfo
InitFuncInfo *FuncInfo // Context for package variable initialization.

isImportedBlocking func(typeparams.Instance) bool // For functions from other packages.
allInfos []*FuncInfo
allInfos []*FuncInfo
}

func (info *Info) newFuncInfo(n ast.Node, inst *typeparams.Instance) *FuncInfo {
Expand All @@ -69,7 +67,7 @@ func (info *Info) newFuncInfo(n ast.Node, inst *typeparams.Instance) *FuncInfo {
Blocking: make(map[ast.Node]bool),
GotoLabel: make(map[*types.Label]bool),
loopReturnIndex: -1,
localInstCallees: new(typeparams.InstanceMap[[]astPath]),
instCallees: new(typeparams.InstanceMap[[]astPath]),
literalFuncCallees: make(map[*ast.FuncLit]astPath),
}

Expand Down Expand Up @@ -153,14 +151,13 @@ func (info *Info) VarsWithInitializers() map[*types.Var]bool {

func AnalyzePkg(files []*ast.File, fileSet *token.FileSet, typesInfo *types.Info, typeCtx *types.Context, typesPkg *types.Package, instanceSets *typeparams.PackageInstanceSets, isBlocking func(typeparams.Instance) bool) *Info {
info := &Info{
Info: typesInfo,
Pkg: typesPkg,
typeCtx: typeCtx,
instanceSets: instanceSets,
HasPointer: make(map[*types.Var]bool),
isImportedBlocking: isBlocking,
funcInstInfos: new(typeparams.InstanceMap[*FuncInfo]),
funcLitInfos: make(map[*ast.FuncLit]*FuncInfo),
Info: typesInfo,
Pkg: typesPkg,
typeCtx: typeCtx,
instanceSets: instanceSets,
HasPointer: make(map[*types.Var]bool),
funcInstInfos: new(typeparams.InstanceMap[*FuncInfo]),
funcLitInfos: make(map[*ast.FuncLit]*FuncInfo),
}
info.InitFuncInfo = info.newFuncInfo(nil, nil)

Expand All @@ -172,7 +169,7 @@ func AnalyzePkg(files []*ast.File, fileSet *token.FileSet, typesInfo *types.Info

done := false
for !done {
done = info.propagateFunctionBlocking()
done = info.propagateFunctionBlocking(isBlocking)
}

info.propagateControlStatementBlocking()
Expand All @@ -186,16 +183,22 @@ func AnalyzePkg(files []*ast.File, fileSet *token.FileSet, typesInfo *types.Info
// For each function we check all other functions it may call and if any of
// them are blocking, we mark the caller blocking as well. The process is
// repeated until no new blocking functions is detected.
func (info *Info) propagateFunctionBlocking() bool {
func (info *Info) propagateFunctionBlocking(isBlocking func(typeparams.Instance) bool) bool {
done := true
for _, caller := range info.allInfos {
// Check calls to named functions and function-typed variables.
caller.localInstCallees.Iterate(func(callee typeparams.Instance, callSites []astPath) {
if info.FuncInfo(callee).IsBlocking() {
caller.instCallees.Iterate(func(callee typeparams.Instance, callSites []astPath) {
blocking := false
if callee.Object.Pkg() != info.Pkg {
blocking = isBlocking(callee)
} else {
blocking = info.FuncInfo(callee).IsBlocking()
}
if blocking {
for _, callSite := range callSites {
caller.markBlocking(callSite)
}
caller.localInstCallees.Delete(callee)
caller.instCallees.Delete(callee)
done = false
}
})
Expand Down Expand Up @@ -250,9 +253,10 @@ type FuncInfo struct {
// returns defined before any defers in a loop may still be affected by
// those defers because of the loop. See comment on [deferStmt].
loopReturnIndex int
// List of other named functions from the current package this function calls.
// List of other named functions in the current package or another package
// that this function calls.
// If any of them are blocking, this function will become blocking too.
localInstCallees *typeparams.InstanceMap[[]astPath]
instCallees *typeparams.InstanceMap[[]astPath]
// List of function literals directly called from this function (for example:
// `func() { /* do stuff */ }()`). This is distinct from function literals
// assigned to named variables (for example: `doStuff := func() {};
Expand Down Expand Up @@ -610,21 +614,11 @@ func (fi *FuncInfo) callToNamedFunc(callee typeparams.Instance, deferredCall boo
}
}

if o.Pkg() != fi.pkgInfo.Pkg {
if fi.pkgInfo.isImportedBlocking(callee) {
fi.markBlocking(fi.visitorStack)
if deferredCall {
fi.deferStmts = append(fi.deferStmts, newBlockingDefer())
}
}
return
}

// We probably don't know yet whether the callee function is blocking.
// Record the calls site for the later stage.
paths := fi.localInstCallees.Get(callee)
paths := fi.instCallees.Get(callee)
paths = append(paths, fi.visitorStack.copy())
fi.localInstCallees.Set(callee, paths)
fi.instCallees.Set(callee, paths)
if deferredCall {
fi.deferStmts = append(fi.deferStmts, newInstDefer(callee))
}
Expand Down
7 changes: 2 additions & 5 deletions compiler/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,9 @@ func (ic *ImportContext) isBlocking(inst typeparams.Instance) bool {
panic(err)
}

// TODO(grantnelson-wf): f.FullName() does not differentiate between
// different instantiations of the same generic function. This needs to be
// fixed when the declaration names are updated to better support instances.
fullName := f.FullName()
fullName := funcDeclFullName(inst)
for _, d := range archive.Declarations {
if string(d.FullName) == fullName {
if d.FullName == fullName {
return d.Blocking
}
}
Expand Down

0 comments on commit a35ce9c

Please sign in to comment.