src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

buildir.go (2566B)


      1 // Copyright 2018 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Package buildir defines an Analyzer that constructs the IR
      6 // of an error-free package and returns the set of all
      7 // functions within it. It does not report any diagnostics itself but
      8 // may be used as an input to other analyzers.
      9 //
     10 // THIS INTERFACE IS EXPERIMENTAL AND MAY BE SUBJECT TO INCOMPATIBLE CHANGE.
     11 package buildir
     12 
     13 import (
     14 	"reflect"
     15 
     16 	"honnef.co/go/tools/go/ir"
     17 
     18 	"golang.org/x/tools/go/analysis"
     19 	"golang.org/x/tools/go/analysis/passes/ctrlflow"
     20 )
     21 
     22 var Debug = struct {
     23 	Mode ir.BuilderMode
     24 }{}
     25 
     26 var Analyzer = &analysis.Analyzer{
     27 	Name:       "buildir",
     28 	Doc:        "build IR for later passes",
     29 	Run:        run,
     30 	ResultType: reflect.TypeFor[*IR](),
     31 	Requires:   []*analysis.Analyzer{ctrlflow.Analyzer},
     32 }
     33 
     34 // IR provides intermediate representation for all the
     35 // source functions in the current package.
     36 type IR struct {
     37 	Pkg      *ir.Package
     38 	SrcFuncs []*ir.Function
     39 }
     40 
     41 func run(pass *analysis.Pass) (any, error) {
     42 	cfgs := pass.ResultOf[ctrlflow.Analyzer].(*ctrlflow.CFGs)
     43 
     44 	// Plundered from ssautil.BuildPackage.
     45 
     46 	// We must create a new Program for each Package because the
     47 	// analysis API provides no place to hang a Program shared by
     48 	// all Packages. Consequently, IR Packages and Functions do not
     49 	// have a canonical representation across an analysis session of
     50 	// multiple packages. This is unlikely to be a problem in
     51 	// practice because the analysis API essentially forces all
     52 	// packages to be analysed independently, so any given call to
     53 	// Analysis.Run on a package will see only IR objects belonging
     54 	// to a single Program.
     55 
     56 	mode := ir.GlobalDebug
     57 	if Debug.Mode != 0 {
     58 		mode = Debug.Mode
     59 	}
     60 
     61 	prog := ir.NewProgram(pass.Fset, mode)
     62 
     63 	prog.SetNoReturn(cfgs.NoReturn)
     64 
     65 	// Create IR packages for direct imports.
     66 	for _, p := range pass.Pkg.Imports() {
     67 		prog.CreatePackage(p, nil, nil, true)
     68 	}
     69 
     70 	// Create and build the primary package.
     71 	irpkg := prog.CreatePackage(pass.Pkg, pass.Files, pass.TypesInfo, false)
     72 	irpkg.Build()
     73 
     74 	// Compute list of source functions, including literals,
     75 	// in source order.
     76 	var addAnons func(f *ir.Function)
     77 	funcs := make([]*ir.Function, len(irpkg.Functions))
     78 	copy(funcs, irpkg.Functions)
     79 	addAnons = func(f *ir.Function) {
     80 		for _, anon := range f.AnonFuncs {
     81 			funcs = append(funcs, anon)
     82 			addAnons(anon)
     83 		}
     84 	}
     85 	for _, fn := range irpkg.Functions {
     86 		addAnons(fn)
     87 	}
     88 
     89 	return &IR{Pkg: irpkg, SrcFuncs: funcs}, nil
     90 }