From f71f32e5e155ae5b7f60005c939746637086f30e Mon Sep 17 00:00:00 2001 From: Alexander Menzhinsky Date: Mon, 17 Apr 2017 22:06:46 -0500 Subject: [PATCH] cmd/cgo: read source files once Now cgo reads source files twice: for c prefix generation and parsing go code to an ast node. It can be narrowed down to single loop. Change-Id: Ie05452a3a12106aaab863244727390037e69e8e6 Reviewed-on: https://go-review.googlesource.com/40939 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor --- src/cmd/cgo/ast.go | 14 +++++++------- src/cmd/cgo/main.go | 24 +++++++++++------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index 8ce824196d..7122a9dbbe 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -17,8 +17,8 @@ import ( "strings" ) -func parse(name string, flags parser.Mode) *ast.File { - ast1, err := parser.ParseFile(fset, name, nil, flags) +func parse(name string, src []byte, flags parser.Mode) *ast.File { + ast1, err := parser.ParseFile(fset, name, src, flags) if err != nil { if list, ok := err.(scanner.ErrorList); ok { // If err is a scanner.ErrorList, its String will print just @@ -39,12 +39,12 @@ func sourceLine(n ast.Node) int { return fset.Position(n.Pos()).Line } -// ReadGo populates f with information learned from reading the -// Go source file with the given file name. It gathers the C preamble +// ParseGo populates f with information learned from the Go source code +// which was read from the named file. It gathers the C preamble // attached to the import "C" comment, a list of references to C.xxx, // a list of exported functions, and the actual AST, to be rewritten and // printed. -func (f *File) ReadGo(name string) { +func (f *File) ParseGo(name string, src []byte) { // Create absolute path for file, so that it will be used in error // messages and recorded in debug line number information. // This matches the rest of the toolchain. See golang.org/issue/5122. @@ -58,8 +58,8 @@ func (f *File) ReadGo(name string) { // so we use ast1 to look for the doc comments on import "C" // and on exported functions, and we use ast2 for translating // and reprinting. - ast1 := parse(name, parser.ParseComments) - ast2 := parse(name, 0) + ast1 := parse(name, src, parser.ParseComments) + ast2 := parse(name, src, 0) f.Package = ast1.Name.Name f.Name = make(map[string]*Name) diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 505d25551d..4a60ac5f6e 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -17,7 +17,7 @@ import ( "go/ast" "go/printer" "go/token" - "io" + "io/ioutil" "os" "path/filepath" "reflect" @@ -265,30 +265,28 @@ func main() { // concern is other cgo wrappers for the same functions. // Use the beginning of the md5 of the input to disambiguate. h := md5.New() - for _, input := range goFiles { + fs := make([]*File, len(goFiles)) + for i, input := range goFiles { if *srcDir != "" { input = filepath.Join(*srcDir, input) } - f, err := os.Open(input) + + b, err := ioutil.ReadFile(input) if err != nil { fatalf("%s", err) } - io.Copy(h, f) - f.Close() - } - cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6]) - - fs := make([]*File, len(goFiles)) - for i, input := range goFiles { - if *srcDir != "" { - input = filepath.Join(*srcDir, input) + if _, err = h.Write(b); err != nil { + fatalf("%s", err) } + f := new(File) - f.ReadGo(input) + f.ParseGo(input, b) f.DiscardCgoDirectives() fs[i] = f } + cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6]) + if *objDir == "" { // make sure that _obj directory exists, so that we can write // all the output files there. -- 2.48.1