Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/noder/irgen.go

Documentation: cmd/compile/internal/noder

     1  // Copyright 2021 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 noder
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  
    11  	"cmd/compile/internal/base"
    12  	"cmd/compile/internal/dwarfgen"
    13  	"cmd/compile/internal/ir"
    14  	"cmd/compile/internal/syntax"
    15  	"cmd/compile/internal/typecheck"
    16  	"cmd/compile/internal/types"
    17  	"cmd/compile/internal/types2"
    18  	"cmd/internal/src"
    19  )
    20  
    21  // check2 type checks a Go package using types2, and then generates IR
    22  // using the results.
    23  func check2(noders []*noder) {
    24  	if base.SyntaxErrors() != 0 {
    25  		base.ErrorExit()
    26  	}
    27  
    28  	// setup and syntax error reporting
    29  	var m posMap
    30  	files := make([]*syntax.File, len(noders))
    31  	for i, p := range noders {
    32  		m.join(&p.posMap)
    33  		files[i] = p.file
    34  	}
    35  
    36  	// typechecking
    37  	conf := types2.Config{
    38  		GoVersion:             base.Flag.Lang,
    39  		IgnoreLabels:          true, // parser already checked via syntax.CheckBranches mode
    40  		CompilerErrorMessages: true, // use error strings matching existing compiler errors
    41  		Error: func(err error) {
    42  			terr := err.(types2.Error)
    43  			base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg)
    44  		},
    45  		Importer: &gcimports{
    46  			packages: make(map[string]*types2.Package),
    47  		},
    48  		Sizes: &gcSizes{},
    49  	}
    50  	info := types2.Info{
    51  		Types:      make(map[syntax.Expr]types2.TypeAndValue),
    52  		Defs:       make(map[*syntax.Name]types2.Object),
    53  		Uses:       make(map[*syntax.Name]types2.Object),
    54  		Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
    55  		Implicits:  make(map[syntax.Node]types2.Object),
    56  		Scopes:     make(map[syntax.Node]*types2.Scope),
    57  		Inferred:   make(map[syntax.Expr]types2.Inferred),
    58  		// expand as needed
    59  	}
    60  	pkg, err := conf.Check(base.Ctxt.Pkgpath, files, &info)
    61  	files = nil
    62  	base.ExitIfErrors()
    63  	if err != nil {
    64  		base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
    65  	}
    66  	if base.Flag.G < 2 {
    67  		os.Exit(0)
    68  	}
    69  
    70  	g := irgen{
    71  		target: typecheck.Target,
    72  		self:   pkg,
    73  		info:   &info,
    74  		posMap: m,
    75  		objs:   make(map[types2.Object]*ir.Name),
    76  		typs:   make(map[types2.Type]*types.Type),
    77  	}
    78  	g.generate(noders)
    79  
    80  	if base.Flag.G < 3 {
    81  		os.Exit(0)
    82  	}
    83  }
    84  
    85  type irgen struct {
    86  	target *ir.Package
    87  	self   *types2.Package
    88  	info   *types2.Info
    89  
    90  	posMap
    91  	objs   map[types2.Object]*ir.Name
    92  	typs   map[types2.Type]*types.Type
    93  	marker dwarfgen.ScopeMarker
    94  
    95  	// Fully-instantiated generic types whose methods should be instantiated
    96  	instTypeList []*types.Type
    97  }
    98  
    99  func (g *irgen) generate(noders []*noder) {
   100  	types.LocalPkg.Name = g.self.Name()
   101  	typecheck.TypecheckAllowed = true
   102  
   103  	// Prevent size calculations until we set the underlying type
   104  	// for all package-block defined types.
   105  	types.DeferCheckSize()
   106  
   107  	// At this point, types2 has already handled name resolution and
   108  	// type checking. We just need to map from its object and type
   109  	// representations to those currently used by the rest of the
   110  	// compiler. This happens mostly in 3 passes.
   111  
   112  	// 1. Process all import declarations. We use the compiler's own
   113  	// importer for this, rather than types2's gcimporter-derived one,
   114  	// to handle extensions and inline function bodies correctly.
   115  	//
   116  	// Also, we need to do this in a separate pass, because mappings are
   117  	// instantiated on demand. If we interleaved processing import
   118  	// declarations with other declarations, it's likely we'd end up
   119  	// wanting to map an object/type from another source file, but not
   120  	// yet have the import data it relies on.
   121  	declLists := make([][]syntax.Decl, len(noders))
   122  Outer:
   123  	for i, p := range noders {
   124  		g.pragmaFlags(p.file.Pragma, ir.GoBuildPragma)
   125  		for j, decl := range p.file.DeclList {
   126  			switch decl := decl.(type) {
   127  			case *syntax.ImportDecl:
   128  				g.importDecl(p, decl)
   129  			default:
   130  				declLists[i] = p.file.DeclList[j:]
   131  				continue Outer // no more ImportDecls
   132  			}
   133  		}
   134  	}
   135  	types.LocalPkg.Height = myheight
   136  
   137  	// 2. Process all package-block type declarations. As with imports,
   138  	// we need to make sure all types are properly instantiated before
   139  	// trying to map any expressions that utilize them. In particular,
   140  	// we need to make sure type pragmas are already known (see comment
   141  	// in irgen.typeDecl).
   142  	//
   143  	// We could perhaps instead defer processing of package-block
   144  	// variable initializers and function bodies, like noder does, but
   145  	// special-casing just package-block type declarations minimizes the
   146  	// differences between processing package-block and function-scoped
   147  	// declarations.
   148  	for _, declList := range declLists {
   149  		for _, decl := range declList {
   150  			switch decl := decl.(type) {
   151  			case *syntax.TypeDecl:
   152  				g.typeDecl((*ir.Nodes)(&g.target.Decls), decl)
   153  			}
   154  		}
   155  	}
   156  	types.ResumeCheckSize()
   157  
   158  	// 3. Process all remaining declarations.
   159  	for _, declList := range declLists {
   160  		g.target.Decls = append(g.target.Decls, g.decls(declList)...)
   161  	}
   162  
   163  	if base.Flag.W > 1 {
   164  		for _, n := range g.target.Decls {
   165  			s := fmt.Sprintf("\nafter noder2 %v", n)
   166  			ir.Dump(s, n)
   167  		}
   168  	}
   169  
   170  	typecheck.DeclareUniverse()
   171  
   172  	for _, p := range noders {
   173  		// Process linkname and cgo pragmas.
   174  		p.processPragmas()
   175  
   176  		// Double check for any type-checking inconsistencies. This can be
   177  		// removed once we're confident in IR generation results.
   178  		syntax.Walk(p.file, func(n syntax.Node) bool {
   179  			g.validate(n)
   180  			return false
   181  		})
   182  	}
   183  
   184  	// Create any needed stencils of generic functions
   185  	g.stencil()
   186  
   187  	// For now, remove all generic functions from g.target.Decl, since they
   188  	// have been used for stenciling, but don't compile. TODO: We will
   189  	// eventually export any exportable generic functions.
   190  	j := 0
   191  	for i, decl := range g.target.Decls {
   192  		if decl.Op() != ir.ODCLFUNC || !decl.Type().HasTParam() {
   193  			g.target.Decls[j] = g.target.Decls[i]
   194  			j++
   195  		}
   196  	}
   197  	g.target.Decls = g.target.Decls[:j]
   198  }
   199  
   200  func (g *irgen) unhandled(what string, p poser) {
   201  	base.FatalfAt(g.pos(p), "unhandled %s: %T", what, p)
   202  	panic("unreachable")
   203  }
   204  

View as plain text