base.DebugSSA = ssa.PhaseOption
base.ParseFlags()
- types.LocalPkg = types.NewPkg("", "")
- types.LocalPkg.Prefix = "\"\""
+ types.LocalPkg = types.NewPkg(base.Ctxt.Pkgpath, "")
// We won't know localpkg's height until after import
// processing. In the mean time, set to MaxPkgHeight to ensure
types.ParseLangFlag()
- symABIs := ssagen.NewSymABIs(base.Ctxt.Pkgpath)
+ symABIs := ssagen.NewSymABIs()
if base.Flag.SymABIs != "" {
symABIs.ReadSymABIs(base.Flag.SymABIs)
}
// Parse and typecheck input.
noder.LoadPackage(flag.Args())
+
+ // As a convenience to users (toolchain maintainers, in particular),
+ // when compiling a package named "main", we default the package
+ // path to "main" if the -p flag was not specified.
if base.Ctxt.Pkgpath == obj.UnlinkablePkg && types.LocalPkg.Name == "main" {
base.Ctxt.Pkgpath = "main"
+ types.LocalPkg.Path = "main"
+ types.LocalPkg.Prefix = "main"
}
dwarfgen.RecordPackageName()
"cmd/internal/objabi"
"encoding/json"
"fmt"
+ "strings"
)
// These modes say which kind of object file to generate.
func ggloblnod(nam *ir.Name) {
s := nam.Linksym()
+
+ // main_inittask and runtime_inittask in package runtime (and in
+ // test/initempty.go) aren't real variable declarations, but
+ // linknamed variables pointing to the compiler's generated
+ // .inittask symbol. The real symbol was already written out in
+ // pkginit.Task, so we need to avoid writing them out a second time
+ // here, otherwise base.Ctxt.Globl will fail.
+ if strings.HasSuffix(s.Name, "..inittask") && s.OnList() {
+ return
+ }
+
s.Gotype = reflectdata.TypeLinksym(nam.Type())
flags := 0
if nam.Readonly() {
}
basename := filepath.Base(filename)
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-o", outname, filename)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p", strings.TrimSuffix(outname, ".o"), "-o", outname, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
base.Flag.Lang = fmt.Sprintf("go1.%d", goversion.Version)
types.ParseLangFlag()
- assert(types.LocalPkg.Path == "")
types.LocalPkg.Height = 0 // reset so pkgReader.pkgIdx doesn't complain
target := typecheck.Target
case types2.Unsafe:
w.String("unsafe")
default:
+ // TODO(mdempsky): Write out pkg.Path() for curpkg too.
var path string
if pkg != w.p.curpkg {
path = pkg.Path()
return
}
- str := p.Path
- if p == types.LocalPkg {
- // Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
- str = base.Ctxt.Pkgpath
- }
-
s := base.Ctxt.Lookup("type..importpath." + p.Prefix + ".")
- ot := dnameData(s, 0, str, "", nil, false)
+ ot := dnameData(s, 0, p.Path, "", nil, false)
objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
s.Set(obj.AttrContentAddressable, true)
p.Pathsym = s
for _, b := range f.Blocks {
for _, v := range b.Values {
if mem, ok := IsNewObject(v); ok {
+ // While compiling package runtime itself, we might see user
+ // calls to newobject, which will have result type
+ // unsafe.Pointer instead. We can't easily infer how large the
+ // allocated memory is, so just skip it.
+ if types.LocalPkg.Path == "runtime" && v.Type.IsUnsafePtr() {
+ continue
+ }
+
nptr := v.Type.Elem().Size() / ptrSize
if nptr > 64 {
nptr = 64
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/obj"
- "cmd/internal/objabi"
)
// SymABIs records information provided by the assembler about symbol
type SymABIs struct {
defs map[string]obj.ABI
refs map[string]obj.ABISet
-
- localPrefix string
}
-func NewSymABIs(myimportpath string) *SymABIs {
- var localPrefix string
- if myimportpath != "" {
- localPrefix = objabi.PathToPrefix(myimportpath) + "."
- }
-
+func NewSymABIs() *SymABIs {
return &SymABIs{
- defs: make(map[string]obj.ABI),
- refs: make(map[string]obj.ABISet),
- localPrefix: localPrefix,
+ defs: make(map[string]obj.ABI),
+ refs: make(map[string]obj.ABISet),
}
}
// canonicalize returns the canonical name used for a linker symbol in
// s's maps. Symbols in this package may be written either as "".X or
// with the package's import path already in the symbol. This rewrites
-// both to `"".`, which matches compiler-generated linker symbol names.
+// both to use the full path, which matches compiler-generated linker
+// symbol names.
func (s *SymABIs) canonicalize(linksym string) string {
- // If the symbol is already prefixed with localPrefix,
- // rewrite it to start with "" so it matches the
- // compiler's internal symbol names.
- if s.localPrefix != "" && strings.HasPrefix(linksym, s.localPrefix) {
- return `"".` + linksym[len(s.localPrefix):]
+ // If the symbol is already prefixed with "", rewrite it to start
+ // with LocalPkg.Prefix.
+ //
+ // TODO(mdempsky): Have cmd/asm stop writing out symbols like this.
+ if strings.HasPrefix(linksym, `"".`) {
+ return types.LocalPkg.Prefix + linksym[2:]
}
return linksym
}
continue
}
sym := nam.Sym()
- var symName string
- if sym.Linkname != "" {
- symName = s.canonicalize(sym.Linkname)
- } else {
- // These names will already be canonical.
+
+ symName := sym.Linkname
+ if symName == "" {
symName = sym.Pkg.Prefix + "." + sym.Name
}
+ symName = s.canonicalize(symName)
// Apply definitions.
defABI, hasDefABI := s.defs[symName]
for _, nam := range funcsyms {
s := nam.Sym()
sf := s.Pkg.Lookup(ir.FuncSymName(s)).Linksym()
+
+ // While compiling package runtime, we might try to create
+ // funcsyms for functions from both types.LocalPkg and
+ // ir.Pkgs.Runtime.
+ if base.Flag.CompilingRuntime && sf.OnList() {
+ continue
+ }
+
// Function values must always reference ABIInternal
// entry points.
target := s.Linksym()
statuniqgen++
typecheck.Declare(n, ir.PEXTERN)
n.SetType(t)
+ n.Linksym().Set(obj.AttrStatic, true)
return n
}
b.WriteString(q)
b.WriteByte('.')
switch mode {
- case fmtTypeIDName:
- // If name is a generic instantiation, it might have local package placeholders
- // in it. Replace those placeholders with the package name. See issue 49547.
- name = strings.Replace(name, LocalPkg.Prefix, q, -1)
case fmtTypeIDHash:
// If name is a generic instantiation, don't hash the instantiating types.
// This isn't great, but it is safe. If we hash the instantiating types, then
return tconv(t, 0, fmtGo)
}
-// LinkString returns an unexpanded string description of t, suitable
-// for use in link symbols. "Unexpanded" here means that the
-// description uses `"".` to qualify identifiers from the current
-// package, and "expansion" refers to the renaming step performed by
-// the linker to replace these qualifiers with proper `path/to/pkg.`
-// qualifiers.
+// LinkString returns a string description of t, suitable for use in
+// link symbols.
//
-// After expansion, the description corresponds to type identity. That
-// is, for any pair of types t1 and t2, Identical(t1, t2) and
-// expand(t1.LinkString()) == expand(t2.LinkString()) report the same
-// value.
-//
-// Within a single compilation unit, LinkString always returns the
-// same unexpanded description for identical types. Thus it's safe to
-// use as a map key to implement a type-identity-keyed map. However,
-// make sure all LinkString calls used for this purpose happen within
-// the same compile process; the string keys are not stable across
-// multiple processes.
+// The description corresponds to type identity. That is, for any pair
+// of types t1 and t2, Identical(t1, t2) == (t1.LinkString() ==
+// t2.LinkString()) is true. Thus it's safe to use as a map key to
+// implement a type-identity-keyed map.
func (t *Type) LinkString() string {
return tconv(t, 0, fmtTypeID)
}
if myimportpath == "" || varSym.Local() {
return
}
- var varname string
- if varSym.Pkg == "_" {
- // The frontend uses package "_" to mark symbols that should not
- // be referenced by index, e.g. linkname'd symbols.
- varname = varSym.Name
- } else {
- // Convert "".<name> into a fully qualified package.sym name.
- varname = objabi.PathToPrefix(myimportpath) + varSym.Name[len(`""`):]
- }
+ varname := varSym.Name
dieSymName := dwarf.InfoPrefix + varname
dieSym := ctxt.LookupInit(dieSymName, func(s *LSym) {
s.Type = objabi.SDWARFVAR
Flag_maymorestack string // If not "", call this function before stack checks
Bso *bufio.Writer
Pathname string
- Pkgpath string // the current package's import path, "" if unknown
+ Pkgpath string // the current package's import path
hashmu sync.Mutex // protects hash, funchash
hash map[string]*LSym // name -> sym mapping
funchash map[string]*LSym // name -> sym mapping for ABIInternal syms
if s.OnList() {
ctxt.Diag("symbol %s listed multiple times", s.Name)
}
+ // TODO(mdempsky): Remove once cmd/asm stops writing "" symbols.
name := strings.Replace(s.Name, "\"\"", ctxt.Pkgpath, -1)
s.Func().FuncID = objabi.GetFuncID(name, flag&WRAPPER != 0 || flag&ABIWRAPPER != 0)
s.Func().FuncFlag = ctxt.toFuncFlag(flag)
} else if flag&TLSBSS != 0 {
s.Type = objabi.STLSBSS
}
- if strings.HasPrefix(s.Name, "\"\"."+StaticNamePref) {
- s.Set(AttrStatic, true)
- }
}
// EmitEntryLiveness generates PCDATA Progs after p to switch to the
"bytes"
"cmd/internal/sys"
"debug/macho"
+ "internal/buildcfg"
"internal/testenv"
"io/ioutil"
"os"
testenv.MustHaveGoBuild(t)
t.Parallel()
+ if buildcfg.Experiment.Unified {
+ t.Skip("TODO(mdempsky): Fix ICE when importing unlinkable objects for GOEXPERIMENT=unified")
+ }
+
tmpdir := t.TempDir()
xSrc := filepath.Join(tmpdir, "x.go")
}
basename := filepath.Base(filename)
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-o", outname, filename)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p", strings.TrimSuffix(outname, ".o"), "-o", outname, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
F()
})(nil), ""},
{(*TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678)(nil), "TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678"},
- {(*B[A])(nil), "B[reflectlite_test.A]"},
- {(*B[B[A]])(nil), "B[reflectlite_test.B[reflectlite_test.A]]"},
+ {(*B[A])(nil), "B[internal/reflectlite_test.A]"},
+ {(*B[B[A]])(nil), "B[internal/reflectlite_test.B[internal/reflectlite_test.A]]"},
}
func TestNames(t *testing.T) {
func F() {
// 3735936685 is 0xdeaddead. On ARM64 R27 is REGTMP.
// clobber x, y at entry. not clobber z (stack object).
- // amd64:`MOVL\t\$3735936685, ""\.x`, `MOVL\t\$3735936685, ""\.y`, -`MOVL\t\$3735936685, ""\.z`
- // arm64:`MOVW\tR27, ""\.x`, `MOVW\tR27, ""\.y`, -`MOVW\tR27, ""\.z`
+ // amd64:`MOVL\t\$3735936685, command-line-arguments\.x`, `MOVL\t\$3735936685, command-line-arguments\.y`, -`MOVL\t\$3735936685, command-line-arguments\.z`
+ // arm64:`MOVW\tR27, command-line-arguments\.x`, `MOVW\tR27, command-line-arguments\.y`, -`MOVW\tR27, command-line-arguments\.z`
x, y, z := p1, p2, p3
addrTaken(&z)
// x is dead at the call (the value of x is loaded before the CALL), y is not
- // amd64:`MOVL\t\$3735936685, ""\.x`, -`MOVL\t\$3735936685, ""\.y`
- // arm64:`MOVW\tR27, ""\.x`, -`MOVW\tR27, ""\.y`
+ // amd64:`MOVL\t\$3735936685, command-line-arguments\.x`, -`MOVL\t\$3735936685, command-line-arguments\.y`
+ // arm64:`MOVW\tR27, command-line-arguments\.x`, -`MOVW\tR27, command-line-arguments\.y`
use(x)
- // amd64:`MOVL\t\$3735936685, ""\.x`, `MOVL\t\$3735936685, ""\.y`
- // arm64:`MOVW\tR27, ""\.x`, `MOVW\tR27, ""\.y`
+ // amd64:`MOVL\t\$3735936685, command-line-arguments\.x`, `MOVL\t\$3735936685, command-line-arguments\.y`
+ // arm64:`MOVW\tR27, command-line-arguments\.x`, `MOVW\tR27, command-line-arguments\.y`
use(y)
}
// Check that arrays compare use 2/4/8 byte compares
func CompareArray1(a, b [2]byte) bool {
- // amd64:`CMPW\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPW\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
// arm64:-`MOVBU\t`
// ppc64le:-`MOVBZ\t`
// s390x:-`MOVBZ\t`
}
func CompareArray2(a, b [3]uint16) bool {
- // amd64:`CMPL\t""[.+_a-z0-9]+\(SP\), [A-Z]`
- // amd64:`CMPW\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPL\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPW\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
return a == b
}
func CompareArray3(a, b [3]int16) bool {
- // amd64:`CMPL\t""[.+_a-z0-9]+\(SP\), [A-Z]`
- // amd64:`CMPW\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPL\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPW\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
return a == b
}
func CompareArray4(a, b [12]int8) bool {
- // amd64:`CMPQ\t""[.+_a-z0-9]+\(SP\), [A-Z]`
- // amd64:`CMPL\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPL\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
return a == b
}
func CompareArray5(a, b [15]byte) bool {
- // amd64:`CMPQ\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
return a == b
}
// Make sure offsets are folded into loads and stores.
func offsets_fold(_, a [20]byte) (b [20]byte) {
- // arm64:`MOVD\t""\.a\+[0-9]+\(FP\), R[0-9]+`,`MOVD\tR[0-9]+, ""\.b\+[0-9]+\(FP\)`
+ // arm64:`MOVD\tcommand-line-arguments\.a\+[0-9]+\(FP\), R[0-9]+`,`MOVD\tR[0-9]+, command-line-arguments\.b\+[0-9]+\(FP\)`
b = a
return
}
var x64 [2]uint64
func compMem1() int {
- // amd64:`CMPB\t"".x\+1\(SB\), [$]0`
+ // amd64:`CMPB\tcommand-line-arguments.x\+1\(SB\), [$]0`
if x[1] {
return 1
}
- // amd64:`CMPB\t"".x8\+1\(SB\), [$]7`
+ // amd64:`CMPB\tcommand-line-arguments.x8\+1\(SB\), [$]7`
if x8[1] == 7 {
return 1
}
- // amd64:`CMPW\t"".x16\+2\(SB\), [$]7`
+ // amd64:`CMPW\tcommand-line-arguments.x16\+2\(SB\), [$]7`
if x16[1] == 7 {
return 1
}
- // amd64:`CMPL\t"".x32\+4\(SB\), [$]7`
+ // amd64:`CMPL\tcommand-line-arguments.x32\+4\(SB\), [$]7`
if x32[1] == 7 {
return 1
}
- // amd64:`CMPQ\t"".x64\+8\(SB\), [$]7`
+ // amd64:`CMPQ\tcommand-line-arguments.x64\+8\(SB\), [$]7`
if x64[1] == 7 {
return 1
}
ch1 := make(chan int)
ch2 := make(chan int)
for {
- // amd64:-`MOVQ\t[$]0, ""..autotmp_3`
+ // amd64:-`MOVQ\t[$]0, command-line-arguments..autotmp_3`
select {
case <-ch1:
case <-ch2:
func zeroSize() {
c := make(chan struct{})
- // amd64:`MOVQ\t\$0, ""\.s\+56\(SP\)`
+ // amd64:`MOVQ\t\$0, command-line-arguments\.s\+56\(SP\)`
var s *int
// force s to be a stack object, also use some (fixed) stack space
g(&s, 1, 2, 3, 4, 5)
- // amd64:`LEAQ\t""\..*\+55\(SP\)`
+ // amd64:`LEAQ\tcommand-line-arguments\..*\+55\(SP\)`
c <- struct{}{}
}
0
0
0
-main.T.X
issue20014.dir/a.T.X
+main.T.X
// 6g/8g print the offset as dec, but 5g/9g print the offset as hex.
patterns := []string{
- `rel 0\+\d t=1 \"\"\.x\+8\r?\n`, // y = &x.b
- `rel 0\+\d t=1 \"\"\.x\+(28|1c)\r?\n`, // z = &x.d.q
- `rel 0\+\d t=1 \"\"\.b\+5\r?\n`, // c = &b[5]
- `rel 0\+\d t=1 \"\"\.x\+(88|58)\r?\n`, // w = &x.f[3].r
+ `rel 0\+\d t=1 p\.x\+8\r?\n`, // y = &x.b
+ `rel 0\+\d t=1 p\.x\+(28|1c)\r?\n`, // z = &x.d.q
+ `rel 0\+\d t=1 p\.b\+5\r?\n`, // c = &b[5]
+ `rel 0\+\d t=1 p\.x\+(88|58)\r?\n`, // w = &x.f[3].r
}
for _, p := range patterns {
if ok, err := regexp.Match(p, out); !ok || err != nil {