2016-03-11 14:28:16 -08:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
//go:generate go run mkbuiltin.go
|
|
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bufio"
|
2016-06-24 15:03:04 -07:00
|
|
|
"bytes"
|
2016-03-11 14:28:16 -08:00
|
|
|
"cmd/compile/internal/ssa"
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
"cmd/compile/internal/types"
|
2016-03-11 14:28:16 -08:00
|
|
|
"cmd/internal/obj"
|
2016-12-06 17:08:06 -08:00
|
|
|
"cmd/internal/src"
|
2016-04-06 12:01:40 -07:00
|
|
|
"cmd/internal/sys"
|
2016-03-11 14:28:16 -08:00
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
|
|
|
|
"path"
|
2016-03-21 14:37:57 +11:00
|
|
|
"runtime"
|
2016-03-11 14:28:16 -08:00
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var imported_unsafe bool
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
buildid string
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
2017-01-11 13:53:34 -08:00
|
|
|
Debug_append int
|
2017-03-20 15:01:20 -07:00
|
|
|
Debug_asm bool
|
2017-01-11 13:53:34 -08:00
|
|
|
Debug_closure int
|
|
|
|
|
debug_dclstack int
|
|
|
|
|
Debug_panic int
|
|
|
|
|
Debug_slice int
|
2017-03-20 15:01:20 -07:00
|
|
|
Debug_vlog bool
|
2017-01-11 13:53:34 -08:00
|
|
|
Debug_wb int
|
2017-02-17 16:55:40 -05:00
|
|
|
Debug_pctab string
|
2016-03-11 14:28:16 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Debug arguments.
|
|
|
|
|
// These can be specified with the -d flag, as in "-d nil"
|
2017-02-22 16:13:06 -05:00
|
|
|
// to set the debug_checknil variable.
|
|
|
|
|
// Multiple options can be comma-separated.
|
|
|
|
|
// Each option accepts an optional argument, as in "gcprog=2"
|
2016-03-11 14:28:16 -08:00
|
|
|
var debugtab = []struct {
|
|
|
|
|
name string
|
2017-02-22 16:13:06 -05:00
|
|
|
val interface{} // must be *int or *string
|
2016-03-11 14:28:16 -08:00
|
|
|
}{
|
|
|
|
|
{"append", &Debug_append}, // print information about append compilation
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
{"closure", &Debug_closure}, // print information about closure compilation
|
2016-09-16 00:33:29 +10:00
|
|
|
{"disablenil", &disable_checknil}, // disable nil checks
|
2017-01-11 13:53:34 -08:00
|
|
|
{"dclstack", &debug_dclstack}, // run internal dclstack checks
|
2016-03-11 14:28:16 -08:00
|
|
|
{"gcprog", &Debug_gcprog}, // print dump of GC programs
|
|
|
|
|
{"nil", &Debug_checknil}, // print information about nil checks
|
|
|
|
|
{"panic", &Debug_panic}, // do not hide any compiler panic
|
|
|
|
|
{"slice", &Debug_slice}, // print information about slice compilation
|
|
|
|
|
{"typeassert", &Debug_typeassert}, // print information about type assertion inlining
|
|
|
|
|
{"wb", &Debug_wb}, // print information about write barriers
|
|
|
|
|
{"export", &Debug_export}, // print export data
|
2017-02-17 16:55:40 -05:00
|
|
|
{"pctab", &Debug_pctab}, // print named pc-value table
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func usage() {
|
|
|
|
|
fmt.Printf("usage: compile [options] file.go...\n")
|
|
|
|
|
obj.Flagprint(1)
|
|
|
|
|
Exit(2)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func hidePanic() {
|
|
|
|
|
if Debug_panic == 0 && nsavederrors+nerrors > 0 {
|
|
|
|
|
// If we've already complained about things
|
|
|
|
|
// in the program, don't bother complaining
|
|
|
|
|
// about a panic too; let the user clean up
|
|
|
|
|
// the code and try again.
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func doversion() {
|
|
|
|
|
p := obj.Expstring()
|
|
|
|
|
if p == "X:none" {
|
|
|
|
|
p = ""
|
|
|
|
|
}
|
|
|
|
|
sep := ""
|
|
|
|
|
if p != "" {
|
|
|
|
|
sep = " "
|
|
|
|
|
}
|
2016-09-09 08:13:16 -04:00
|
|
|
fmt.Printf("compile version %s%s%s\n", obj.Version, sep, p)
|
2016-03-11 14:28:16 -08:00
|
|
|
os.Exit(0)
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 15:31:49 -04:00
|
|
|
// supportsDynlink reports whether or not the code generator for the given
|
|
|
|
|
// architecture supports the -shared and -dynlink flags.
|
|
|
|
|
func supportsDynlink(arch *sys.Arch) bool {
|
|
|
|
|
return arch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.I386, sys.PPC64, sys.S390X)
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-24 15:03:04 -07:00
|
|
|
// timing data for compiler phases
|
|
|
|
|
var timings Timings
|
|
|
|
|
var benchfile string
|
|
|
|
|
|
2016-11-11 16:56:07 -08:00
|
|
|
// Main parses flags and Go source files specified in the command-line
|
|
|
|
|
// arguments, type-checks the parsed Go package, compiles functions to machine
|
|
|
|
|
// code, and finally writes the compiled package definition to disk.
|
2017-03-17 13:35:31 -07:00
|
|
|
func Main(archInit func(*Arch)) {
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "init")
|
|
|
|
|
|
2016-03-11 14:28:16 -08:00
|
|
|
defer hidePanic()
|
|
|
|
|
|
2017-03-17 13:35:36 -07:00
|
|
|
archInit(&thearch)
|
2017-03-17 13:35:31 -07:00
|
|
|
|
2017-03-17 13:35:36 -07:00
|
|
|
Ctxt = obj.Linknew(thearch.LinkArch)
|
2017-03-06 07:32:37 -08:00
|
|
|
Ctxt.DebugInfo = debuginfo
|
2016-09-15 15:45:10 +10:00
|
|
|
Ctxt.DiagFunc = yyerror
|
2016-09-13 14:05:14 -07:00
|
|
|
Ctxt.Bso = bufio.NewWriter(os.Stdout)
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
localpkg = mkpkg("")
|
|
|
|
|
localpkg.Prefix = "\"\""
|
|
|
|
|
|
|
|
|
|
// pseudo-package, for scoping
|
|
|
|
|
builtinpkg = mkpkg("go.builtin")
|
|
|
|
|
builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin
|
|
|
|
|
|
|
|
|
|
// pseudo-package, accessed by import "unsafe"
|
|
|
|
|
unsafepkg = mkpkg("unsafe")
|
|
|
|
|
unsafepkg.Name = "unsafe"
|
|
|
|
|
|
2017-02-28 15:51:29 -08:00
|
|
|
// Pseudo-package that contains the compiler's builtin
|
|
|
|
|
// declarations for package runtime. These are declared in a
|
|
|
|
|
// separate package to avoid conflicts with package runtime's
|
|
|
|
|
// actual declarations, which may differ intentionally but
|
|
|
|
|
// insignificantly.
|
|
|
|
|
Runtimepkg = mkpkg("go.runtime")
|
2016-03-11 14:28:16 -08:00
|
|
|
Runtimepkg.Name = "runtime"
|
2017-02-28 15:51:29 -08:00
|
|
|
Runtimepkg.Prefix = "runtime"
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
// pseudo-packages used in symbol tables
|
|
|
|
|
itabpkg = mkpkg("go.itab")
|
|
|
|
|
itabpkg.Name = "go.itab"
|
|
|
|
|
itabpkg.Prefix = "go.itab" // not go%2eitab
|
|
|
|
|
|
2016-03-17 06:18:13 -07:00
|
|
|
itablinkpkg = mkpkg("go.itablink")
|
|
|
|
|
itablinkpkg.Name = "go.itablink"
|
|
|
|
|
itablinkpkg.Prefix = "go.itablink" // not go%2eitablink
|
|
|
|
|
|
2016-03-11 14:28:16 -08:00
|
|
|
trackpkg = mkpkg("go.track")
|
|
|
|
|
trackpkg.Name = "go.track"
|
|
|
|
|
trackpkg.Prefix = "go.track" // not go%2etrack
|
|
|
|
|
|
|
|
|
|
typepkg = mkpkg("type")
|
|
|
|
|
typepkg.Name = "type"
|
|
|
|
|
|
2016-04-19 08:31:04 -07:00
|
|
|
// pseudo-package used for map zero values
|
|
|
|
|
mappkg = mkpkg("go.map")
|
|
|
|
|
mappkg.Name = "go.map"
|
|
|
|
|
mappkg.Prefix = "go.map"
|
|
|
|
|
|
2016-09-09 08:13:16 -04:00
|
|
|
Nacl = obj.GOOS == "nacl"
|
2016-03-11 14:28:16 -08:00
|
|
|
if Nacl {
|
2016-04-13 18:37:18 -07:00
|
|
|
flag_largemodel = true
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&compiling_runtime, "+", false, "compiling runtime")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("%", "debug non-static initializers", &Debug['%'])
|
|
|
|
|
obj.Flagcount("B", "disable bounds checking", &Debug['B'])
|
2017-03-08 14:26:23 -08:00
|
|
|
obj.Flagcount("C", "disable printing of columns in error messages", &Debug['C']) // TODO(gri) remove eventually
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.StringVar(&localimport, "D", "", "set relative `path` for local imports")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("E", "debug symbol export", &Debug['E'])
|
|
|
|
|
obj.Flagfn1("I", "add `directory` to import search path", addidir)
|
|
|
|
|
obj.Flagcount("K", "debug missing line numbers", &Debug['K'])
|
|
|
|
|
obj.Flagcount("N", "disable optimizations", &Debug['N'])
|
2017-03-20 15:01:20 -07:00
|
|
|
flag.BoolVar(&Debug_asm, "S", false, "print assembly listing")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagfn0("V", "print compiler version", doversion)
|
|
|
|
|
obj.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
|
|
|
|
|
flag.StringVar(&buildid, "buildid", "", "record `id` as the build id in the export metadata")
|
|
|
|
|
flag.BoolVar(&pure_go, "complete", false, "compiling complete package (no C or assembly)")
|
|
|
|
|
flag.StringVar(&debugstr, "d", "", "print debug information about items in `list`")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("e", "no limit on number of errors reported", &Debug['e'])
|
|
|
|
|
obj.Flagcount("f", "debug stack frames", &Debug['f'])
|
|
|
|
|
obj.Flagcount("h", "halt on error", &Debug['h'])
|
|
|
|
|
obj.Flagcount("i", "debug line number stack", &Debug['i'])
|
|
|
|
|
obj.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
|
|
|
|
|
obj.Flagcount("l", "disable inlining", &Debug['l'])
|
2016-04-26 21:50:59 -04:00
|
|
|
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("live", "debug liveness analysis", &debuglive)
|
|
|
|
|
obj.Flagcount("m", "print optimization decisions", &Debug['m'])
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
|
cmd/compile: add -dolinkobj flag
When set to false, the -dolinkobj flag instructs the compiler
not to generate or emit linker information.
This is handy when you need the compiler's export data,
e.g. for use with go/importer,
but you want to avoid the cost of full compilation.
This must be used with care, since the resulting
files are unusable for linking.
This CL interacts with #18369,
where adding gcflags and ldflags to buildid has been mooted.
On the one hand, adding gcflags would make safe use of this
flag easier, since if the full object files were needed,
a simple 'go install' would fix it.
On the other hand, this would mean that
'go install -gcflags=-dolinkobj=false' would rebuild the object files,
although any existing object files would probably suffice.
Change-Id: I8dc75ab5a40095c785c1a4d2260aeb63c4d10f73
Reviewed-on: https://go-review.googlesource.com/37384
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-22 00:05:18 -08:00
|
|
|
flag.BoolVar(&dolinkobj, "dolinkobj", true, "generate linker-specific objects; if false, some invalid code may compile")
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&nolocalimports, "nolocalimports", false, "reject local (relative) imports")
|
|
|
|
|
flag.StringVar(&outfile, "o", "", "write output to `file`")
|
|
|
|
|
flag.StringVar(&myimportpath, "p", "", "set expected package import `path`")
|
|
|
|
|
flag.BoolVar(&writearchive, "pack", false, "write package file instead of object file")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("r", "debug generated wrappers", &Debug['r'])
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&flag_race, "race", false, "enable race detector")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s'])
|
2016-12-09 17:15:05 -08:00
|
|
|
flag.StringVar(&pathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&safemode, "u", false, "reject unsafe code")
|
2017-03-20 15:01:20 -07:00
|
|
|
flag.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagcount("w", "debug type checking", &Debug['w'])
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&use_writebarrier, "wb", true, "enable write barrier")
|
|
|
|
|
var flag_shared bool
|
2016-03-11 14:28:16 -08:00
|
|
|
var flag_dynlink bool
|
2017-03-17 13:35:36 -07:00
|
|
|
if supportsDynlink(thearch.LinkArch.Arch) {
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&flag_shared, "shared", false, "generate code that can be linked into a shared library")
|
2016-04-07 15:31:49 -04:00
|
|
|
flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2017-03-17 13:35:36 -07:00
|
|
|
if thearch.LinkArch.Family == sys.AMD64 {
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.BoolVar(&flag_largemodel, "largemodel", false, "generate code that assumes a large memory model")
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2016-04-13 18:37:18 -07:00
|
|
|
flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to `file`")
|
|
|
|
|
flag.StringVar(&memprofile, "memprofile", "", "write memory profile to `file`")
|
|
|
|
|
flag.Int64Var(&memprofilerate, "memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
|
2016-08-01 20:34:12 +10:00
|
|
|
flag.StringVar(&traceprofile, "traceprofile", "", "write an execution trace to `file`")
|
2017-04-02 18:37:04 -07:00
|
|
|
flag.StringVar(&blockprofile, "blockprofile", "", "write block profile to `file`")
|
2017-04-05 08:01:33 -07:00
|
|
|
flag.StringVar(&mutexprofile, "mutexprofile", "", "write mutex profile to `file`")
|
2016-06-24 15:03:04 -07:00
|
|
|
flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
|
2016-03-11 14:28:16 -08:00
|
|
|
obj.Flagparse(usage)
|
|
|
|
|
|
2016-04-13 18:41:59 -07:00
|
|
|
Ctxt.Flag_shared = flag_dynlink || flag_shared
|
2016-03-11 14:28:16 -08:00
|
|
|
Ctxt.Flag_dynlink = flag_dynlink
|
|
|
|
|
Ctxt.Flag_optimize = Debug['N'] == 0
|
|
|
|
|
|
2017-03-20 15:01:20 -07:00
|
|
|
Ctxt.Debugasm = Debug_asm
|
|
|
|
|
Ctxt.Debugvlog = Debug_vlog
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
if flag.NArg() < 1 {
|
|
|
|
|
usage()
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-06 13:42:31 -07:00
|
|
|
thearch.LinkArch.Init(Ctxt)
|
|
|
|
|
|
2017-01-11 15:20:38 -08:00
|
|
|
if outfile == "" {
|
|
|
|
|
p := flag.Arg(0)
|
|
|
|
|
if i := strings.LastIndex(p, "/"); i >= 0 {
|
|
|
|
|
p = p[i+1:]
|
|
|
|
|
}
|
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
|
if i := strings.LastIndex(p, `\`); i >= 0 {
|
|
|
|
|
p = p[i+1:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if i := strings.LastIndex(p, "."); i >= 0 {
|
|
|
|
|
p = p[:i]
|
|
|
|
|
}
|
|
|
|
|
suffix := ".o"
|
|
|
|
|
if writearchive {
|
|
|
|
|
suffix = ".a"
|
|
|
|
|
}
|
|
|
|
|
outfile = p + suffix
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 14:28:16 -08:00
|
|
|
startProfile()
|
|
|
|
|
|
2016-04-13 18:37:18 -07:00
|
|
|
if flag_race {
|
2016-03-11 14:28:16 -08:00
|
|
|
racepkg = mkpkg("runtime/race")
|
|
|
|
|
racepkg.Name = "race"
|
|
|
|
|
}
|
2016-04-13 18:37:18 -07:00
|
|
|
if flag_msan {
|
2016-03-11 14:28:16 -08:00
|
|
|
msanpkg = mkpkg("runtime/msan")
|
|
|
|
|
msanpkg.Name = "msan"
|
|
|
|
|
}
|
2016-04-13 18:37:18 -07:00
|
|
|
if flag_race && flag_msan {
|
2016-03-11 14:28:16 -08:00
|
|
|
log.Fatal("cannot use both -race and -msan")
|
2016-04-13 18:37:18 -07:00
|
|
|
} else if flag_race || flag_msan {
|
2016-03-11 14:28:16 -08:00
|
|
|
instrumenting = true
|
|
|
|
|
}
|
2017-03-20 09:56:50 -07:00
|
|
|
if compiling_runtime && Debug['N'] != 0 {
|
|
|
|
|
log.Fatal("cannot disable optimizations while compiling runtime")
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
// parse -d argument
|
|
|
|
|
if debugstr != "" {
|
|
|
|
|
Split:
|
|
|
|
|
for _, name := range strings.Split(debugstr, ",") {
|
|
|
|
|
if name == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2017-02-22 16:13:06 -05:00
|
|
|
val, valstring, haveInt := 1, "", true
|
|
|
|
|
if i := strings.IndexAny(name, "=:"); i >= 0 {
|
2016-03-11 14:28:16 -08:00
|
|
|
var err error
|
2017-02-22 16:13:06 -05:00
|
|
|
name, valstring = name[:i], name[i+1:]
|
|
|
|
|
val, err = strconv.Atoi(valstring)
|
2016-03-11 14:28:16 -08:00
|
|
|
if err != nil {
|
2017-02-22 16:13:06 -05:00
|
|
|
val, haveInt = 1, false
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, t := range debugtab {
|
2017-02-22 16:13:06 -05:00
|
|
|
if t.name != name {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
switch vp := t.val.(type) {
|
|
|
|
|
case nil:
|
|
|
|
|
// Ignore
|
|
|
|
|
case *string:
|
|
|
|
|
*vp = valstring
|
|
|
|
|
case *int:
|
|
|
|
|
if !haveInt {
|
|
|
|
|
log.Fatalf("invalid debug value %v", name)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2017-02-22 16:13:06 -05:00
|
|
|
*vp = val
|
|
|
|
|
default:
|
|
|
|
|
panic("bad debugtab type")
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2017-02-22 16:13:06 -05:00
|
|
|
continue Split
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
// special case for ssa for now
|
|
|
|
|
if strings.HasPrefix(name, "ssa/") {
|
|
|
|
|
// expect form ssa/phase/flag
|
|
|
|
|
// e.g. -d=ssa/generic_cse/time
|
|
|
|
|
// _ in phase name also matches space
|
|
|
|
|
phase := name[4:]
|
|
|
|
|
flag := "debug" // default flag is debug
|
|
|
|
|
if i := strings.Index(phase, "/"); i >= 0 {
|
|
|
|
|
flag = phase[i+1:]
|
|
|
|
|
phase = phase[:i]
|
|
|
|
|
}
|
2016-05-11 15:25:17 -04:00
|
|
|
err := ssa.PhaseOption(phase, flag, val, valstring)
|
2016-03-11 14:28:16 -08:00
|
|
|
if err != "" {
|
|
|
|
|
log.Fatalf(err)
|
|
|
|
|
}
|
|
|
|
|
continue Split
|
|
|
|
|
}
|
|
|
|
|
log.Fatalf("unknown debug key -d %s\n", name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-17 16:55:40 -05:00
|
|
|
// set via a -d flag
|
|
|
|
|
Ctxt.Debugpcln = Debug_pctab
|
|
|
|
|
|
2016-03-11 14:28:16 -08:00
|
|
|
// enable inlining. for now:
|
|
|
|
|
// default: inlining on. (debug['l'] == 1)
|
|
|
|
|
// -l: inlining off (debug['l'] == 0)
|
|
|
|
|
// -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1)
|
|
|
|
|
if Debug['l'] <= 1 {
|
|
|
|
|
Debug['l'] = 1 - Debug['l']
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-17 13:35:36 -07:00
|
|
|
Widthint = thearch.LinkArch.IntSize
|
|
|
|
|
Widthptr = thearch.LinkArch.PtrSize
|
|
|
|
|
Widthreg = thearch.LinkArch.RegSize
|
2016-03-11 14:28:16 -08:00
|
|
|
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
// initialize types package
|
|
|
|
|
// (we need to do this to break dependencies that otherwise
|
|
|
|
|
// would lead to import cycles)
|
|
|
|
|
types.Widthptr = Widthptr
|
|
|
|
|
types.Dowidth = dowidth
|
|
|
|
|
types.Fatalf = Fatalf
|
|
|
|
|
types.Sconv = func(s *types.Sym, flag, mode int) string {
|
|
|
|
|
return sconv(s, FmtFlag(flag), fmtMode(mode))
|
|
|
|
|
}
|
|
|
|
|
types.Tconv = func(t *types.Type, flag, mode, depth int) string {
|
|
|
|
|
return tconv(t, FmtFlag(flag), fmtMode(mode), depth)
|
|
|
|
|
}
|
|
|
|
|
types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
|
|
|
|
|
symFormat(sym, s, verb, fmtMode(mode))
|
|
|
|
|
}
|
|
|
|
|
types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) {
|
|
|
|
|
typeFormat(t, s, verb, fmtMode(mode))
|
|
|
|
|
}
|
|
|
|
|
types.Cmptyp = cmptyp
|
|
|
|
|
types.FieldName = func(f *types.Field) string {
|
|
|
|
|
return f.Sym.Name
|
|
|
|
|
}
|
|
|
|
|
types.TypeLinkSym = func(t *types.Type) *obj.LSym {
|
|
|
|
|
return Linksym(typenamesym(t))
|
|
|
|
|
}
|
|
|
|
|
types.FmtLeft = int(FmtLeft)
|
|
|
|
|
types.FmtUnsigned = int(FmtUnsigned)
|
|
|
|
|
types.FErr = FErr
|
|
|
|
|
|
2016-03-11 15:22:21 -08:00
|
|
|
initUniverse()
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
blockgen = 1
|
|
|
|
|
dclcontext = PEXTERN
|
|
|
|
|
nerrors = 0
|
|
|
|
|
|
2017-03-28 13:52:14 -07:00
|
|
|
autogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
|
|
|
|
|
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "loadsys")
|
2016-03-11 14:28:16 -08:00
|
|
|
loadsys()
|
|
|
|
|
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "parse")
|
2017-01-11 15:31:48 -08:00
|
|
|
lines := parseFiles(flag.Args())
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Stop()
|
2016-12-09 17:15:05 -08:00
|
|
|
timings.AddEvent(int64(lines), "lines")
|
2016-03-11 14:28:16 -08:00
|
|
|
|
2016-03-11 15:22:21 -08:00
|
|
|
finishUniverse()
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
typecheckok = true
|
|
|
|
|
if Debug['f'] != 0 {
|
|
|
|
|
frame(1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process top-level declarations in phases.
|
|
|
|
|
|
|
|
|
|
// Phase 1: const, type, and names and types of funcs.
|
|
|
|
|
// This will gather all the information about types
|
|
|
|
|
// and methods but doesn't depend on any of it.
|
2017-01-26 09:00:56 -08:00
|
|
|
// We also defer type alias declarations until phase 2
|
|
|
|
|
// to avoid cycles like #18640.
|
2016-03-11 14:28:16 -08:00
|
|
|
defercheckwidth()
|
|
|
|
|
|
|
|
|
|
// Don't use range--typecheck can add closures to xtop.
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "typecheck", "top1")
|
2016-03-11 14:28:16 -08:00
|
|
|
for i := 0; i < len(xtop); i++ {
|
2016-12-29 15:49:01 -08:00
|
|
|
n := xtop[i]
|
2017-01-26 09:00:56 -08:00
|
|
|
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
|
2016-12-29 15:49:01 -08:00
|
|
|
xtop[i] = typecheck(n, Etop)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 2: Variable assignments.
|
|
|
|
|
// To check interface assignments, depends on phase 1.
|
|
|
|
|
|
|
|
|
|
// Don't use range--typecheck can add closures to xtop.
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "typecheck", "top2")
|
2016-03-11 14:28:16 -08:00
|
|
|
for i := 0; i < len(xtop); i++ {
|
2016-12-29 15:49:01 -08:00
|
|
|
n := xtop[i]
|
2017-01-26 09:00:56 -08:00
|
|
|
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
|
2016-12-29 15:49:01 -08:00
|
|
|
xtop[i] = typecheck(n, Etop)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
resumecheckwidth()
|
|
|
|
|
|
|
|
|
|
// Phase 3: Type check function bodies.
|
|
|
|
|
// Don't use range--typecheck can add closures to xtop.
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "typecheck", "func")
|
|
|
|
|
var fcount int64
|
2016-03-11 14:28:16 -08:00
|
|
|
for i := 0; i < len(xtop); i++ {
|
2016-12-29 15:49:01 -08:00
|
|
|
n := xtop[i]
|
|
|
|
|
if op := n.Op; op == ODCLFUNC || op == OCLOSURE {
|
|
|
|
|
Curfn = n
|
2016-03-11 14:28:16 -08:00
|
|
|
decldepth = 1
|
|
|
|
|
saveerrors()
|
2016-03-19 17:02:01 -07:00
|
|
|
typecheckslice(Curfn.Nbody.Slice(), Etop)
|
2016-03-11 14:28:16 -08:00
|
|
|
checkreturn(Curfn)
|
|
|
|
|
if nerrors != 0 {
|
|
|
|
|
Curfn.Nbody.Set(nil) // type errors; do not compile
|
|
|
|
|
}
|
2016-06-24 15:03:04 -07:00
|
|
|
fcount++
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
}
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.AddEvent(fcount, "funcs")
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
// Phase 4: Decide how to capture closed variables.
|
|
|
|
|
// This needs to run before escape analysis,
|
|
|
|
|
// because variables captured by value do not escape.
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "capturevars")
|
2016-03-11 14:28:16 -08:00
|
|
|
for _, n := range xtop {
|
|
|
|
|
if n.Op == ODCLFUNC && n.Func.Closure != nil {
|
|
|
|
|
Curfn = n
|
|
|
|
|
capturevars(n)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Curfn = nil
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 5: Inlining
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "inlining")
|
2016-03-11 14:28:16 -08:00
|
|
|
if Debug['l'] > 1 {
|
|
|
|
|
// Typecheck imported function bodies if debug['l'] > 1,
|
|
|
|
|
// otherwise lazily when used or re-exported.
|
|
|
|
|
for _, n := range importlist {
|
2016-04-24 13:50:26 -07:00
|
|
|
if n.Func.Inl.Len() != 0 {
|
2016-03-11 14:28:16 -08:00
|
|
|
saveerrors()
|
|
|
|
|
typecheckinl(n)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if Debug['l'] != 0 {
|
|
|
|
|
// Find functions that can be inlined and clone them before walk expands them.
|
|
|
|
|
visitBottomUp(xtop, func(list []*Node, recursive bool) {
|
2016-03-23 16:35:50 +01:00
|
|
|
for _, n := range list {
|
2016-05-05 11:45:27 -07:00
|
|
|
if !recursive {
|
2016-03-11 14:28:16 -08:00
|
|
|
caninl(n)
|
2016-05-03 17:21:32 -07:00
|
|
|
} else {
|
|
|
|
|
if Debug['m'] > 1 {
|
|
|
|
|
fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2016-05-05 11:45:27 -07:00
|
|
|
inlcalls(n)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 6: Escape analysis.
|
|
|
|
|
// Required for moving heap allocations onto stack,
|
|
|
|
|
// which in turn is required by the closure implementation,
|
|
|
|
|
// which stores the addresses of stack variables into the closure.
|
|
|
|
|
// If the closure does not escape, it needs to be on the stack
|
|
|
|
|
// or else the stack copier will not update it.
|
|
|
|
|
// Large values are also moved off stack in escape analysis;
|
|
|
|
|
// because large values may contain pointers, it must happen early.
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("fe", "escapes")
|
2016-03-11 14:28:16 -08:00
|
|
|
escapes(xtop)
|
|
|
|
|
|
cmd/compile: add -dolinkobj flag
When set to false, the -dolinkobj flag instructs the compiler
not to generate or emit linker information.
This is handy when you need the compiler's export data,
e.g. for use with go/importer,
but you want to avoid the cost of full compilation.
This must be used with care, since the resulting
files are unusable for linking.
This CL interacts with #18369,
where adding gcflags and ldflags to buildid has been mooted.
On the one hand, adding gcflags would make safe use of this
flag easier, since if the full object files were needed,
a simple 'go install' would fix it.
On the other hand, this would mean that
'go install -gcflags=-dolinkobj=false' would rebuild the object files,
although any existing object files would probably suffice.
Change-Id: I8dc75ab5a40095c785c1a4d2260aeb63c4d10f73
Reviewed-on: https://go-review.googlesource.com/37384
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-22 00:05:18 -08:00
|
|
|
if dolinkobj {
|
|
|
|
|
// Phase 7: Transform closure bodies to properly reference captured variables.
|
|
|
|
|
// This needs to happen before walk, because closures must be transformed
|
|
|
|
|
// before walk reaches a call of a closure.
|
|
|
|
|
timings.Start("fe", "xclosures")
|
|
|
|
|
for _, n := range xtop {
|
|
|
|
|
if n.Op == ODCLFUNC && n.Func.Closure != nil {
|
|
|
|
|
Curfn = n
|
|
|
|
|
transformclosure(n)
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: rearrange fields between ssa.Func, ssa.Cache, and ssa.Config
This makes ssa.Func, ssa.Cache, and ssa.Config fulfill
the roles laid out for them in CL 38160.
The only non-trivial change in this CL is how cached
values and blocks get IDs. Prior to this CL, their IDs were
assigned as part of resetting the cache, and only modified
IDs were reset. This required knowing how many values and
blocks were modified, which required a tight coupling between
ssa.Func and ssa.Config. To eliminate that coupling,
we now zero values and blocks during reset,
and assign their IDs when they are used.
Since unused values and blocks have ID == 0,
we can efficiently find the last used value/block,
to avoid zeroing everything.
Bulk zeroing is efficient, but not efficient enough
to obviate the need to avoid zeroing everything every time.
As a happy side-effect, ssa.Func.Free is no longer necessary.
DebugHashMatch and friends now belong in func.go.
They have been left in place for clarity and review.
I will move them in a subsequent CL.
Passes toolstash -cmp. No compiler performance impact.
No change in 'go test cmd/compile/internal/ssa' execution time.
Change-Id: I2eb7af58da067ef6a36e815a6f386cfe8634d098
Reviewed-on: https://go-review.googlesource.com/38167
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2017-03-15 11:15:13 -07:00
|
|
|
// Prepare for SSA compilation.
|
|
|
|
|
// This must be before peekitabs, because peekitabs
|
|
|
|
|
// can trigger function compilation.
|
|
|
|
|
initssaconfig()
|
|
|
|
|
|
cmd/compile: de-virtualize interface calls
With this change, code like
h := sha1.New()
h.Write(buf)
sum := h.Sum()
gets compiled into static calls rather than
interface calls, because the compiler is able
to prove that 'h' is really a *sha1.digest.
The InterCall re-write rule hits a few dozen times
during make.bash, and hundreds of times during all.bash.
The most common pattern identified by the compiler
is a constructor like
func New() Interface { return &impl{...} }
where the constructor gets inlined into the caller,
and the result is used immediately. Examples include
{sha1,md5,crc32,crc64,...}.New, base64.NewEncoder,
base64.NewDecoder, errors.New, net.Pipe, and so on.
Some existing benchmarks that change on darwin/amd64:
Crc64/ISO4KB-8 2.67µs ± 1% 2.66µs ± 0% -0.36% (p=0.015 n=10+10)
Crc64/ISO1KB-8 694ns ± 0% 690ns ± 1% -0.59% (p=0.001 n=10+10)
Adler32KB-8 473ns ± 1% 471ns ± 0% -0.39% (p=0.010 n=10+9)
On architectures like amd64, the reduction in code size
appears to contribute more to benchmark improvements than just
removing the indirect call, since that branch gets predicted
accurately when called in a loop.
Updates #19361
Change-Id: I57d4dc21ef40a05ec0fbd55a9bb0eb74cdc67a3d
Reviewed-on: https://go-review.googlesource.com/38139
Run-TryBot: Philip Hofer <phofer@umich.edu>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2017-03-13 15:03:17 -07:00
|
|
|
// Just before compilation, compile itabs found on
|
|
|
|
|
// the right side of OCONVIFACE so that methods
|
|
|
|
|
// can be de-virtualized during compilation.
|
cmd/compile: add -dolinkobj flag
When set to false, the -dolinkobj flag instructs the compiler
not to generate or emit linker information.
This is handy when you need the compiler's export data,
e.g. for use with go/importer,
but you want to avoid the cost of full compilation.
This must be used with care, since the resulting
files are unusable for linking.
This CL interacts with #18369,
where adding gcflags and ldflags to buildid has been mooted.
On the one hand, adding gcflags would make safe use of this
flag easier, since if the full object files were needed,
a simple 'go install' would fix it.
On the other hand, this would mean that
'go install -gcflags=-dolinkobj=false' would rebuild the object files,
although any existing object files would probably suffice.
Change-Id: I8dc75ab5a40095c785c1a4d2260aeb63c4d10f73
Reviewed-on: https://go-review.googlesource.com/37384
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-22 00:05:18 -08:00
|
|
|
Curfn = nil
|
cmd/compile: de-virtualize interface calls
With this change, code like
h := sha1.New()
h.Write(buf)
sum := h.Sum()
gets compiled into static calls rather than
interface calls, because the compiler is able
to prove that 'h' is really a *sha1.digest.
The InterCall re-write rule hits a few dozen times
during make.bash, and hundreds of times during all.bash.
The most common pattern identified by the compiler
is a constructor like
func New() Interface { return &impl{...} }
where the constructor gets inlined into the caller,
and the result is used immediately. Examples include
{sha1,md5,crc32,crc64,...}.New, base64.NewEncoder,
base64.NewDecoder, errors.New, net.Pipe, and so on.
Some existing benchmarks that change on darwin/amd64:
Crc64/ISO4KB-8 2.67µs ± 1% 2.66µs ± 0% -0.36% (p=0.015 n=10+10)
Crc64/ISO1KB-8 694ns ± 0% 690ns ± 1% -0.59% (p=0.001 n=10+10)
Adler32KB-8 473ns ± 1% 471ns ± 0% -0.39% (p=0.010 n=10+9)
On architectures like amd64, the reduction in code size
appears to contribute more to benchmark improvements than just
removing the indirect call, since that branch gets predicted
accurately when called in a loop.
Updates #19361
Change-Id: I57d4dc21ef40a05ec0fbd55a9bb0eb74cdc67a3d
Reviewed-on: https://go-review.googlesource.com/38139
Run-TryBot: Philip Hofer <phofer@umich.edu>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2017-03-13 15:03:17 -07:00
|
|
|
peekitabs()
|
cmd/compile: add -dolinkobj flag
When set to false, the -dolinkobj flag instructs the compiler
not to generate or emit linker information.
This is handy when you need the compiler's export data,
e.g. for use with go/importer,
but you want to avoid the cost of full compilation.
This must be used with care, since the resulting
files are unusable for linking.
This CL interacts with #18369,
where adding gcflags and ldflags to buildid has been mooted.
On the one hand, adding gcflags would make safe use of this
flag easier, since if the full object files were needed,
a simple 'go install' would fix it.
On the other hand, this would mean that
'go install -gcflags=-dolinkobj=false' would rebuild the object files,
although any existing object files would probably suffice.
Change-Id: I8dc75ab5a40095c785c1a4d2260aeb63c4d10f73
Reviewed-on: https://go-review.googlesource.com/37384
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-22 00:05:18 -08:00
|
|
|
|
|
|
|
|
// Phase 8: Compile top level functions.
|
|
|
|
|
// Don't use range--walk can add functions to xtop.
|
|
|
|
|
timings.Start("be", "compilefuncs")
|
|
|
|
|
fcount = 0
|
|
|
|
|
for i := 0; i < len(xtop); i++ {
|
|
|
|
|
n := xtop[i]
|
|
|
|
|
if n.Op == ODCLFUNC {
|
|
|
|
|
funccompile(n)
|
|
|
|
|
fcount++
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
cmd/compile: add -dolinkobj flag
When set to false, the -dolinkobj flag instructs the compiler
not to generate or emit linker information.
This is handy when you need the compiler's export data,
e.g. for use with go/importer,
but you want to avoid the cost of full compilation.
This must be used with care, since the resulting
files are unusable for linking.
This CL interacts with #18369,
where adding gcflags and ldflags to buildid has been mooted.
On the one hand, adding gcflags would make safe use of this
flag easier, since if the full object files were needed,
a simple 'go install' would fix it.
On the other hand, this would mean that
'go install -gcflags=-dolinkobj=false' would rebuild the object files,
although any existing object files would probably suffice.
Change-Id: I8dc75ab5a40095c785c1a4d2260aeb63c4d10f73
Reviewed-on: https://go-review.googlesource.com/37384
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-22 00:05:18 -08:00
|
|
|
timings.AddEvent(fcount, "funcs")
|
2016-03-11 14:28:16 -08:00
|
|
|
|
cmd/compile: add -dolinkobj flag
When set to false, the -dolinkobj flag instructs the compiler
not to generate or emit linker information.
This is handy when you need the compiler's export data,
e.g. for use with go/importer,
but you want to avoid the cost of full compilation.
This must be used with care, since the resulting
files are unusable for linking.
This CL interacts with #18369,
where adding gcflags and ldflags to buildid has been mooted.
On the one hand, adding gcflags would make safe use of this
flag easier, since if the full object files were needed,
a simple 'go install' would fix it.
On the other hand, this would mean that
'go install -gcflags=-dolinkobj=false' would rebuild the object files,
although any existing object files would probably suffice.
Change-Id: I8dc75ab5a40095c785c1a4d2260aeb63c4d10f73
Reviewed-on: https://go-review.googlesource.com/37384
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-22 00:05:18 -08:00
|
|
|
if nsavederrors+nerrors == 0 {
|
|
|
|
|
fninit(xtop)
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
|
cmd/compile: add -dolinkobj flag
When set to false, the -dolinkobj flag instructs the compiler
not to generate or emit linker information.
This is handy when you need the compiler's export data,
e.g. for use with go/importer,
but you want to avoid the cost of full compilation.
This must be used with care, since the resulting
files are unusable for linking.
This CL interacts with #18369,
where adding gcflags and ldflags to buildid has been mooted.
On the one hand, adding gcflags would make safe use of this
flag easier, since if the full object files were needed,
a simple 'go install' would fix it.
On the other hand, this would mean that
'go install -gcflags=-dolinkobj=false' would rebuild the object files,
although any existing object files would probably suffice.
Change-Id: I8dc75ab5a40095c785c1a4d2260aeb63c4d10f73
Reviewed-on: https://go-review.googlesource.com/37384
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-22 00:05:18 -08:00
|
|
|
if compiling_runtime {
|
|
|
|
|
checknowritebarrierrec()
|
|
|
|
|
}
|
cmd/compile: rework reporting of oversized stack frames
We don't support stack frames over 2GB.
Rather than detect this during backend compilation,
check for it at the end of compilation.
This is arguably a more accurate check anyway,
since it takes into account the full frame,
including local stack, arguments, and arch-specific
rounding, although it's unlikely anyone would ever notice.
Also, rather than reporting the error right away,
take note of it and report it later, at the top level.
This is not relevant now, but it will help with making
the backend concurrent, as the append to the list of
oversized functions can be cheaply protected by a plain mutex.
Updates #15756
Updates #19250
Change-Id: Id3fa21906616d62e9dc66e27a17fd5f83304e96e
Reviewed-on: https://go-review.googlesource.com/38972
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2017-03-30 11:46:45 -07:00
|
|
|
for _, largePos := range largeStackFrames {
|
|
|
|
|
yyerrorl(largePos, "stack frame too large (>2GB)")
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 9: Check external declarations.
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("be", "externaldcls")
|
2016-03-11 14:28:16 -08:00
|
|
|
for i, n := range externdcl {
|
|
|
|
|
if n.Op == ONAME {
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
externdcl[i] = typecheck(externdcl[i], Erv)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nerrors+nsavederrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-11 16:56:07 -08:00
|
|
|
// Write object data to disk.
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Start("be", "dumpobj")
|
2016-03-11 14:28:16 -08:00
|
|
|
dumpobj()
|
|
|
|
|
if asmhdr != "" {
|
|
|
|
|
dumpasmhdr()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nerrors+nsavederrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-15 15:45:10 +10:00
|
|
|
flusherrors()
|
2016-06-24 15:03:04 -07:00
|
|
|
timings.Stop()
|
|
|
|
|
|
|
|
|
|
if benchfile != "" {
|
|
|
|
|
if err := writebench(benchfile); err != nil {
|
|
|
|
|
log.Fatalf("cannot write benchmark data: %v", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func writebench(filename string) error {
|
|
|
|
|
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var buf bytes.Buffer
|
2016-09-09 08:13:16 -04:00
|
|
|
fmt.Fprintln(&buf, "commit:", obj.Version)
|
2016-06-24 15:03:04 -07:00
|
|
|
fmt.Fprintln(&buf, "goos:", runtime.GOOS)
|
|
|
|
|
fmt.Fprintln(&buf, "goarch:", runtime.GOARCH)
|
|
|
|
|
timings.Write(&buf, "BenchmarkCompile:"+myimportpath+":")
|
|
|
|
|
|
|
|
|
|
n, err := f.Write(buf.Bytes())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if n != buf.Len() {
|
|
|
|
|
panic("bad writer")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return f.Close()
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var importMap = map[string]string{}
|
|
|
|
|
|
|
|
|
|
func addImportMap(s string) {
|
|
|
|
|
if strings.Count(s, "=") != 1 {
|
|
|
|
|
log.Fatal("-importmap argument must be of the form source=actual")
|
|
|
|
|
}
|
|
|
|
|
i := strings.Index(s, "=")
|
|
|
|
|
source, actual := s[:i], s[i+1:]
|
|
|
|
|
if source == "" || actual == "" {
|
|
|
|
|
log.Fatal("-importmap argument must be of the form source=actual; source and actual must be non-empty")
|
|
|
|
|
}
|
|
|
|
|
importMap[source] = actual
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func saveerrors() {
|
|
|
|
|
nsavederrors += nerrors
|
|
|
|
|
nerrors = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func arsize(b *bufio.Reader, name string) int {
|
|
|
|
|
var buf [ArhdrSize]byte
|
|
|
|
|
if _, err := io.ReadFull(b, buf[:]); err != nil {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
aname := strings.Trim(string(buf[0:16]), " ")
|
|
|
|
|
if !strings.HasPrefix(aname, name) {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
asize := strings.Trim(string(buf[48:58]), " ")
|
|
|
|
|
i, _ := strconv.Atoi(asize)
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func skiptopkgdef(b *bufio.Reader) bool {
|
|
|
|
|
// archive header
|
|
|
|
|
p, err := b.ReadString('\n')
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("reading input: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if p != "!<arch>\n" {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// package export block should be first
|
|
|
|
|
sz := arsize(b, "__.PKGDEF")
|
|
|
|
|
return sz > 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var idirs []string
|
|
|
|
|
|
|
|
|
|
func addidir(dir string) {
|
|
|
|
|
if dir != "" {
|
|
|
|
|
idirs = append(idirs, dir)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isDriveLetter(b byte) bool {
|
|
|
|
|
return 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// is this path a local name? begins with ./ or ../ or /
|
|
|
|
|
func islocalname(name string) bool {
|
|
|
|
|
return strings.HasPrefix(name, "/") ||
|
2016-03-21 14:37:57 +11:00
|
|
|
runtime.GOOS == "windows" && len(name) >= 3 && isDriveLetter(name[0]) && name[1] == ':' && name[2] == '/' ||
|
2016-03-11 14:28:16 -08:00
|
|
|
strings.HasPrefix(name, "./") || name == "." ||
|
|
|
|
|
strings.HasPrefix(name, "../") || name == ".."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func findpkg(name string) (file string, ok bool) {
|
|
|
|
|
if islocalname(name) {
|
2016-04-13 18:37:18 -07:00
|
|
|
if safemode || nolocalimports {
|
2016-03-11 14:28:16 -08:00
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// try .a before .6. important for building libraries:
|
|
|
|
|
// if there is an array.6 in the array.a library,
|
|
|
|
|
// want to find all of array.a, not just array.6.
|
|
|
|
|
file = fmt.Sprintf("%s.a", name)
|
|
|
|
|
if _, err := os.Stat(file); err == nil {
|
|
|
|
|
return file, true
|
|
|
|
|
}
|
|
|
|
|
file = fmt.Sprintf("%s.o", name)
|
|
|
|
|
if _, err := os.Stat(file); err == nil {
|
|
|
|
|
return file, true
|
|
|
|
|
}
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// local imports should be canonicalized already.
|
|
|
|
|
// don't want to see "encoding/../encoding/base64"
|
|
|
|
|
// as different from "encoding/base64".
|
|
|
|
|
if q := path.Clean(name); q != name {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("non-canonical import path %q (should be %q)", name, q)
|
2016-03-11 14:28:16 -08:00
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, dir := range idirs {
|
|
|
|
|
file = fmt.Sprintf("%s/%s.a", dir, name)
|
|
|
|
|
if _, err := os.Stat(file); err == nil {
|
|
|
|
|
return file, true
|
|
|
|
|
}
|
|
|
|
|
file = fmt.Sprintf("%s/%s.o", dir, name)
|
|
|
|
|
if _, err := os.Stat(file); err == nil {
|
|
|
|
|
return file, true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-09 08:13:16 -04:00
|
|
|
if obj.GOROOT != "" {
|
2016-03-11 14:28:16 -08:00
|
|
|
suffix := ""
|
|
|
|
|
suffixsep := ""
|
|
|
|
|
if flag_installsuffix != "" {
|
|
|
|
|
suffixsep = "_"
|
|
|
|
|
suffix = flag_installsuffix
|
2016-04-13 18:37:18 -07:00
|
|
|
} else if flag_race {
|
2016-03-11 14:28:16 -08:00
|
|
|
suffixsep = "_"
|
|
|
|
|
suffix = "race"
|
2016-04-13 18:37:18 -07:00
|
|
|
} else if flag_msan {
|
2016-03-11 14:28:16 -08:00
|
|
|
suffixsep = "_"
|
|
|
|
|
suffix = "msan"
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-09 08:13:16 -04:00
|
|
|
file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", obj.GOROOT, obj.GOOS, obj.GOARCH, suffixsep, suffix, name)
|
2016-03-11 14:28:16 -08:00
|
|
|
if _, err := os.Stat(file); err == nil {
|
|
|
|
|
return file, true
|
|
|
|
|
}
|
2016-09-09 08:13:16 -04:00
|
|
|
file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", obj.GOROOT, obj.GOOS, obj.GOARCH, suffixsep, suffix, name)
|
2016-03-11 14:28:16 -08:00
|
|
|
if _, err := os.Stat(file); err == nil {
|
|
|
|
|
return file, true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 16:11:50 -07:00
|
|
|
// loadsys loads the definitions for the low-level runtime functions,
|
2016-03-11 14:28:16 -08:00
|
|
|
// so that the compiler can generate calls to them,
|
2016-10-18 16:11:50 -07:00
|
|
|
// but does not make them visible to user code.
|
2016-03-11 14:28:16 -08:00
|
|
|
func loadsys() {
|
|
|
|
|
block = 1
|
|
|
|
|
|
2017-03-23 17:39:28 -07:00
|
|
|
inimport = true
|
2016-10-18 16:11:50 -07:00
|
|
|
typecheckok = true
|
|
|
|
|
defercheckwidth()
|
|
|
|
|
|
|
|
|
|
typs := runtimeTypes()
|
|
|
|
|
for _, d := range runtimeDecls {
|
2017-03-30 13:19:18 -07:00
|
|
|
sym := Runtimepkg.Lookup(d.name)
|
2016-10-18 16:11:50 -07:00
|
|
|
typ := typs[d.typ]
|
|
|
|
|
switch d.tag {
|
|
|
|
|
case funcTag:
|
2017-03-23 17:39:28 -07:00
|
|
|
importsym(Runtimepkg, sym, ONAME)
|
2016-10-18 16:11:50 -07:00
|
|
|
n := newfuncname(sym)
|
|
|
|
|
n.Type = typ
|
|
|
|
|
declare(n, PFUNC)
|
|
|
|
|
case varTag:
|
2017-03-23 17:39:28 -07:00
|
|
|
importvar(Runtimepkg, sym, typ)
|
2016-10-18 16:11:50 -07:00
|
|
|
default:
|
|
|
|
|
Fatalf("unhandled declaration tag %v", d.tag)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typecheckok = false
|
|
|
|
|
resumecheckwidth()
|
2017-03-23 17:39:28 -07:00
|
|
|
inimport = false
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
func importfile(f *Val) *types.Pkg {
|
2016-03-11 14:28:16 -08:00
|
|
|
path_, ok := f.U.(string)
|
|
|
|
|
if !ok {
|
2017-03-24 11:43:08 -07:00
|
|
|
yyerror("import path must be a string")
|
2017-03-23 17:39:28 -07:00
|
|
|
return nil
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(path_) == 0 {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("import path is empty")
|
2017-03-23 17:39:28 -07:00
|
|
|
return nil
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if isbadimport(path_) {
|
2017-03-23 17:39:28 -07:00
|
|
|
return nil
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The package name main is no longer reserved,
|
|
|
|
|
// but we reserve the import path "main" to identify
|
|
|
|
|
// the main package, just as we reserve the import
|
|
|
|
|
// path "math" to identify the standard math package.
|
|
|
|
|
if path_ == "main" {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("cannot import \"main\"")
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if myimportpath != "" && path_ == myimportpath {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("import %q while compiling that package (import cycle)", path_)
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mapped, ok := importMap[path_]; ok {
|
|
|
|
|
path_ = mapped
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if path_ == "unsafe" {
|
2016-04-13 18:37:18 -07:00
|
|
|
if safemode {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("cannot import package unsafe")
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
imported_unsafe = true
|
2017-03-23 17:39:28 -07:00
|
|
|
return unsafepkg
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if islocalname(path_) {
|
|
|
|
|
if path_[0] == '/' {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("import path cannot be absolute path")
|
2017-03-23 17:39:28 -07:00
|
|
|
return nil
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prefix := Ctxt.Pathname
|
|
|
|
|
if localimport != "" {
|
|
|
|
|
prefix = localimport
|
|
|
|
|
}
|
|
|
|
|
path_ = path.Join(prefix, path_)
|
|
|
|
|
|
|
|
|
|
if isbadimport(path_) {
|
2017-03-23 17:39:28 -07:00
|
|
|
return nil
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file, found := findpkg(path_)
|
|
|
|
|
if !found {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("can't find import: %q", path_)
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 17:39:28 -07:00
|
|
|
importpkg := mkpkg(path_)
|
2016-03-11 14:28:16 -08:00
|
|
|
if importpkg.Imported {
|
2017-03-23 17:39:28 -07:00
|
|
|
return importpkg
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importpkg.Imported = true
|
|
|
|
|
|
|
|
|
|
impf, err := os.Open(file)
|
|
|
|
|
if err != nil {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("can't open import: %q: %v", path_, err)
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
defer impf.Close()
|
|
|
|
|
imp := bufio.NewReader(impf)
|
|
|
|
|
|
2016-12-28 17:58:51 -08:00
|
|
|
const pkgSuffix = ".a"
|
|
|
|
|
if strings.HasSuffix(file, pkgSuffix) {
|
2016-03-11 14:28:16 -08:00
|
|
|
if !skiptopkgdef(imp) {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("import %s: not a package file", file)
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check object header
|
|
|
|
|
p, err := imp.ReadString('\n')
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("reading input: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if len(p) > 0 {
|
|
|
|
|
p = p[:len(p)-1]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if p != "empty archive" {
|
|
|
|
|
if !strings.HasPrefix(p, "go object ") {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("import %s: not a go object file: %s", file, p)
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-09 08:13:16 -04:00
|
|
|
q := fmt.Sprintf("%s %s %s %s", obj.GOOS, obj.GOARCH, obj.Version, obj.Expstring())
|
2016-03-11 14:28:16 -08:00
|
|
|
if p[10:] != q {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q)
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-20 11:19:19 -07:00
|
|
|
// process header lines
|
2016-09-13 15:33:55 -07:00
|
|
|
safe := false
|
2016-05-20 11:19:19 -07:00
|
|
|
for {
|
|
|
|
|
p, err = imp.ReadString('\n')
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("reading input: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if p == "\n" {
|
|
|
|
|
break // header ends with blank line
|
|
|
|
|
}
|
|
|
|
|
if strings.HasPrefix(p, "safe") {
|
2016-09-13 15:33:55 -07:00
|
|
|
safe = true
|
2016-05-20 11:19:19 -07:00
|
|
|
break // ok to ignore rest
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-09-13 15:33:55 -07:00
|
|
|
if safemode && !safe {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("cannot import unsafe package %q", importpkg.Path)
|
2016-09-13 15:33:55 -07:00
|
|
|
}
|
2016-05-20 11:19:19 -07:00
|
|
|
|
2016-12-28 17:58:51 -08:00
|
|
|
// assume files move (get installed) so don't record the full path
|
|
|
|
|
// (e.g., for file "/Users/foo/go/pkg/darwin_amd64/math.a" record "math.a")
|
|
|
|
|
Ctxt.AddImport(file[len(file)-len(path_)-len(pkgSuffix):])
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
// In the importfile, if we find:
|
2016-08-16 12:55:17 -07:00
|
|
|
// $$\n (textual format): not supported anymore
|
|
|
|
|
// $$B\n (binary format) : import directly, then feed the lexer a dummy statement
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
// look for $$
|
|
|
|
|
var c byte
|
|
|
|
|
for {
|
|
|
|
|
c, err = imp.ReadByte()
|
|
|
|
|
if err != nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c == '$' {
|
|
|
|
|
c, err = imp.ReadByte()
|
|
|
|
|
if c == '$' || err != nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get character after $$
|
|
|
|
|
if err == nil {
|
|
|
|
|
c, _ = imp.ReadByte()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch c {
|
|
|
|
|
case '\n':
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("cannot import %s: old export format no longer supported (recompile library)", path_)
|
2017-03-23 17:39:28 -07:00
|
|
|
return nil
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
case 'B':
|
2016-03-18 17:21:32 -07:00
|
|
|
if Debug_export != 0 {
|
|
|
|
|
fmt.Printf("importing %s (%s)\n", path_, file)
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
imp.ReadByte() // skip \n after $$B
|
2017-03-23 17:39:28 -07:00
|
|
|
Import(importpkg, imp)
|
2016-03-11 14:28:16 -08:00
|
|
|
|
|
|
|
|
default:
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("no import in %q", path_)
|
2016-03-11 14:28:16 -08:00
|
|
|
errorexit()
|
|
|
|
|
}
|
2017-03-23 17:39:28 -07:00
|
|
|
|
|
|
|
|
return importpkg
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
2016-12-15 17:17:01 -08:00
|
|
|
func pkgnotused(lineno src.XPos, path string, name string) {
|
2016-03-11 14:28:16 -08:00
|
|
|
// If the package was imported with a name other than the final
|
|
|
|
|
// import path element, show it explicitly in the error message.
|
|
|
|
|
// Note that this handles both renamed imports and imports of
|
|
|
|
|
// packages containing unconventional package declarations.
|
|
|
|
|
// Note that this uses / always, even on Windows, because Go import
|
|
|
|
|
// paths always use forward slashes.
|
|
|
|
|
elem := path
|
|
|
|
|
if i := strings.LastIndex(elem, "/"); i >= 0 {
|
|
|
|
|
elem = elem[i+1:]
|
|
|
|
|
}
|
|
|
|
|
if name == "" || elem == name {
|
|
|
|
|
yyerrorl(lineno, "imported and not used: %q", path)
|
|
|
|
|
} else {
|
|
|
|
|
yyerrorl(lineno, "imported and not used: %q as %s", path, name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func mkpackage(pkgname string) {
|
|
|
|
|
if localpkg.Name == "" {
|
|
|
|
|
if pkgname == "_" {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("invalid package name _")
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
localpkg.Name = pkgname
|
|
|
|
|
} else {
|
|
|
|
|
if pkgname != localpkg.Name {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("package %s; expected %s", pkgname, localpkg.Name)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2017-01-11 15:20:38 -08:00
|
|
|
}
|
|
|
|
|
}
|
2016-03-11 14:28:16 -08:00
|
|
|
|
2017-01-11 15:20:38 -08:00
|
|
|
func clearImports() {
|
|
|
|
|
for _, s := range localpkg.Syms {
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
if asNode(s.Def) == nil {
|
2017-01-11 15:20:38 -08:00
|
|
|
continue
|
|
|
|
|
}
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
if asNode(s.Def).Op == OPACK {
|
2017-01-11 15:20:38 -08:00
|
|
|
// throw away top-level package name leftover
|
|
|
|
|
// from previous file.
|
|
|
|
|
// leave s->block set to cause redeclaration
|
|
|
|
|
// errors if a conflicting top-level name is
|
|
|
|
|
// introduced by a different file.
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
if !asNode(s.Def).Used() && nsyntaxerrors == 0 {
|
|
|
|
|
pkgnotused(asNode(s.Def).Pos, asNode(s.Def).Name.Pkg.Path, s.Name)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2017-01-11 15:20:38 -08:00
|
|
|
s.Def = nil
|
|
|
|
|
continue
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
if IsAlias(s) {
|
2017-01-11 15:20:38 -08:00
|
|
|
// throw away top-level name left over
|
|
|
|
|
// from previous import . "x"
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
if asNode(s.Def).Name != nil && asNode(s.Def).Name.Pack != nil && !asNode(s.Def).Name.Pack.Used() && nsyntaxerrors == 0 {
|
|
|
|
|
pkgnotused(asNode(s.Def).Name.Pack.Pos, asNode(s.Def).Name.Pack.Name.Pkg.Path, "")
|
|
|
|
|
asNode(s.Def).Name.Pack.SetUsed(true)
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
2017-01-11 15:20:38 -08:00
|
|
|
|
|
|
|
|
s.Def = nil
|
|
|
|
|
continue
|
2016-03-11 14:28:16 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
|
|
|
|
|
func IsAlias(sym *types.Sym) bool {
|
|
|
|
|
return sym.Def != nil && asNode(sym.Def).Sym != sym
|
|
|
|
|
}
|