Commit b4e9f704 authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: remove support for textual export format

Fixes #15323.

Change-Id: I50e996e6fde6b24327cb45dd84da31deef4dcc56
Reviewed-on: https://go-review.googlesource.com/27171
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent e492d9f0
...@@ -174,8 +174,8 @@ const exportInlined = true // default: true ...@@ -174,8 +174,8 @@ const exportInlined = true // default: true
// errors. // errors.
// If disabled, only named types are tracked, possibly leading to slightly // If disabled, only named types are tracked, possibly leading to slightly
// less efficient encoding in rare cases. It also prevents the export of // less efficient encoding in rare cases. It also prevents the export of
// some corner-case type declarations (but those are not handled correctly // some corner-case type declarations (but those were not handled correctly
// with with the textual export format either). // with the former textual export format either).
// TODO(gri) enable and remove once issues caused by it are fixed // TODO(gri) enable and remove once issues caused by it are fixed
const trackAllTypes = false const trackAllTypes = false
......
...@@ -80,7 +80,6 @@ func Import(in *bufio.Reader) { ...@@ -80,7 +80,6 @@ func Import(in *bufio.Reader) {
p.pkg() p.pkg()
// defer some type-checking until all types are read in completely // defer some type-checking until all types are read in completely
// (parser.go:import_package)
tcok := typecheckok tcok := typecheckok
typecheckok = true typecheckok = true
defercheckwidth() defercheckwidth()
......
...@@ -9,14 +9,12 @@ import ( ...@@ -9,14 +9,12 @@ import (
"bytes" "bytes"
"cmd/internal/bio" "cmd/internal/bio"
"fmt" "fmt"
"sort"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
) )
var ( var (
newexport bool // if set, use new export format Debug_export int // if set, print debugging information about export data
Debug_export int // if set, print debugging information about export data
exportsize int exportsize int
) )
...@@ -94,18 +92,6 @@ func autoexport(n *Node, ctxt Class) { ...@@ -94,18 +92,6 @@ func autoexport(n *Node, ctxt Class) {
} }
} }
func dumppkg(p *Pkg) {
if p == nil || p == localpkg || p.Exported || p == builtinpkg {
return
}
p.Exported = true
suffix := ""
if !p.Direct {
suffix = " // indirect"
}
exportf("\timport %s %q%s\n", p.Name, p.Path, suffix)
}
// Look for anything we need for the inline body // Look for anything we need for the inline body
func reexportdeplist(ll Nodes) { func reexportdeplist(ll Nodes) {
for _, n := range ll.Slice() { for _, n := range ll.Slice() {
...@@ -224,53 +210,6 @@ func reexportdep(n *Node) { ...@@ -224,53 +210,6 @@ func reexportdep(n *Node) {
reexportdeplist(n.Nbody) reexportdeplist(n.Nbody)
} }
func dumpexportconst(s *Sym) {
n := typecheck(s.Def, Erv)
if n == nil || n.Op != OLITERAL {
Fatalf("dumpexportconst: oconst nil: %v", s)
}
t := n.Type // may or may not be specified
dumpexporttype(t)
if t != nil && !t.IsUntyped() {
exportf("\tconst %v %v = %v\n", sconv(s, FmtSharp), Tconv(t, FmtSharp), vconv(n.Val(), FmtSharp))
} else {
exportf("\tconst %v = %v\n", sconv(s, FmtSharp), vconv(n.Val(), FmtSharp))
}
}
func dumpexportvar(s *Sym) {
n := s.Def
n = typecheck(n, Erv|Ecall)
if n == nil || n.Type == nil {
Yyerror("variable exported but not defined: %v", s)
return
}
t := n.Type
dumpexporttype(t)
if t.Etype == TFUNC && n.Class == PFUNC {
if n.Func != nil && n.Func.Inl.Len() != 0 {
// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
if Debug['l'] < 2 {
typecheckinl(n)
}
// NOTE: The space after %#S here is necessary for ld's export data parser.
exportf("\tfunc %v %v { %v }\n", sconv(s, FmtSharp), Tconv(t, FmtShort|FmtSharp), hconv(n.Func.Inl, FmtSharp|FmtBody))
reexportdeplist(n.Func.Inl)
} else {
exportf("\tfunc %v %v\n", sconv(s, FmtSharp), Tconv(t, FmtShort|FmtSharp))
}
} else {
exportf("\tvar %v %v\n", sconv(s, FmtSharp), Tconv(t, FmtSharp))
}
}
// methodbyname sorts types by symbol name. // methodbyname sorts types by symbol name.
type methodbyname []*Field type methodbyname []*Field
...@@ -278,167 +217,44 @@ func (x methodbyname) Len() int { return len(x) } ...@@ -278,167 +217,44 @@ func (x methodbyname) Len() int { return len(x) }
func (x methodbyname) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x methodbyname) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x methodbyname) Less(i, j int) bool { return x[i].Sym.Name < x[j].Sym.Name } func (x methodbyname) Less(i, j int) bool { return x[i].Sym.Name < x[j].Sym.Name }
func dumpexporttype(t *Type) {
if t == nil {
return
}
if t.Printed || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
return
}
t.Printed = true
if t.Sym != nil {
dumppkg(t.Sym.Pkg)
}
switch t.Etype {
case TSTRUCT, TINTER:
for _, f := range t.Fields().Slice() {
dumpexporttype(f.Type)
}
case TFUNC:
dumpexporttype(t.Recvs())
dumpexporttype(t.Results())
dumpexporttype(t.Params())
case TMAP:
dumpexporttype(t.Val())
dumpexporttype(t.Key())
case TARRAY, TCHAN, TPTR32, TPTR64, TSLICE:
dumpexporttype(t.Elem())
}
if t.Sym == nil {
return
}
var m []*Field
for _, f := range t.Methods().Slice() {
dumpexporttype(f.Type)
m = append(m, f)
}
sort.Sort(methodbyname(m))
exportf("\ttype %v %v\n", sconv(t.Sym, FmtSharp), Tconv(t, FmtSharp|FmtLong))
for _, f := range m {
if f.Nointerface {
exportf("\t//go:nointerface\n")
}
if f.Type.Nname() != nil && f.Type.Nname().Func.Inl.Len() != 0 { // nname was set by caninl
// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
if Debug['l'] < 2 {
typecheckinl(f.Type.Nname())
}
exportf("\tfunc %v %v %v { %v }\n", Tconv(f.Type.Recvs(), FmtSharp), sconv(f.Sym, FmtShort|FmtByte|FmtSharp), Tconv(f.Type, FmtShort|FmtSharp), hconv(f.Type.Nname().Func.Inl, FmtSharp|FmtBody))
reexportdeplist(f.Type.Nname().Func.Inl)
} else {
exportf("\tfunc %v %v %v\n", Tconv(f.Type.Recvs(), FmtSharp), sconv(f.Sym, FmtShort|FmtByte|FmtSharp), Tconv(f.Type, FmtShort|FmtSharp))
}
}
}
func dumpsym(s *Sym) {
if s.Flags&SymExported != 0 {
return
}
s.Flags |= SymExported
if s.Def == nil {
Yyerror("unknown export symbol: %v", s)
return
}
// print("dumpsym %O %+S\n", s->def->op, s);
dumppkg(s.Pkg)
switch s.Def.Op {
default:
Yyerror("unexpected export symbol: %v %v", s.Def.Op, s)
case OLITERAL:
dumpexportconst(s)
case OTYPE:
if s.Def.Type.Etype == TFORW {
Yyerror("export of incomplete type %v", s)
} else {
dumpexporttype(s.Def.Type)
}
case ONAME:
dumpexportvar(s)
}
}
func dumpexport() { func dumpexport() {
if buildid != "" { if buildid != "" {
exportf("build id %q\n", buildid) exportf("build id %q\n", buildid)
} }
size := 0 // size of export section without enclosing markers size := 0 // size of export section without enclosing markers
if newexport { // The linker also looks for the $$ marker - use char after $$ to distinguish format.
// binary export exportf("\n$$B\n") // indicate binary export format
// The linker also looks for the $$ marker - use char after $$ to distinguish format. if debugFormat {
exportf("\n$$B\n") // indicate binary format // save a copy of the export data
if debugFormat { var copy bytes.Buffer
// save a copy of the export data bcopy := bufio.NewWriter(&copy)
var copy bytes.Buffer size = export(bcopy, Debug_export != 0)
bcopy := bufio.NewWriter(&copy) bcopy.Flush() // flushing to bytes.Buffer cannot fail
size = export(bcopy, Debug_export != 0) if n, err := bout.Write(copy.Bytes()); n != size || err != nil {
bcopy.Flush() // flushing to bytes.Buffer cannot fail Fatalf("error writing export data: got %d bytes, want %d bytes, err = %v", n, size, err)
if n, err := bout.Write(copy.Bytes()); n != size || err != nil {
Fatalf("error writing export data: got %d bytes, want %d bytes, err = %v", n, size, err)
}
// export data must contain no '$' so that we can find the end by searching for "$$"
if bytes.IndexByte(copy.Bytes(), '$') >= 0 {
Fatalf("export data contains $")
}
// verify that we can read the copied export data back in
// (use empty package map to avoid collisions)
savedPkgMap := pkgMap
savedPkgs := pkgs
pkgMap = make(map[string]*Pkg)
pkgs = nil
importpkg = mkpkg("")
Import(bufio.NewReader(&copy)) // must not die
importpkg = nil
pkgs = savedPkgs
pkgMap = savedPkgMap
} else {
size = export(bout.Writer, Debug_export != 0)
} }
exportf("\n$$\n") // export data must contain no '$' so that we can find the end by searching for "$$"
} else { // TODO(gri) is this still needed?
// textual export if bytes.IndexByte(copy.Bytes(), '$') >= 0 {
lno := lineno Fatalf("export data contains $")
exportf("\n$$\n") // indicate textual format
exportsize = 0
exportf("package %s", localpkg.Name)
if safemode {
exportf(" safe")
} }
exportf("\n")
for _, p := range pkgs { // verify that we can read the copied export data back in
if p.Direct { // (use empty package map to avoid collisions)
dumppkg(p) savedPkgMap := pkgMap
} savedPkgs := pkgs
} pkgMap = make(map[string]*Pkg)
pkgs = nil
// exportlist grows during iteration - cannot use range importpkg = mkpkg("")
for i := 0; i < len(exportlist); i++ { Import(bufio.NewReader(&copy)) // must not die
n := exportlist[i] importpkg = nil
lineno = n.Lineno pkgs = savedPkgs
dumpsym(n.Sym) pkgMap = savedPkgMap
} } else {
size = export(bout.Writer, Debug_export != 0)
size = exportsize
exportf("\n$$\n")
lineno = lno
} }
exportf("\n$$\n")
if Debug_export != 0 { if Debug_export != 0 {
fmt.Printf("export data size = %d bytes\n", size) fmt.Printf("export data size = %d bytes\n", size)
......
...@@ -73,7 +73,7 @@ const ( ...@@ -73,7 +73,7 @@ const (
const ( const (
FErr = iota FErr = iota
FDbg FDbg
FExp _ // formerly FExp - leave gap for now just in case there's some hard-wired dependency on the const value
FTypeId FTypeId
) )
...@@ -113,7 +113,8 @@ func setfmode(flags *FmtFlag) (fm int, fb bool) { ...@@ -113,7 +113,8 @@ func setfmode(flags *FmtFlag) (fm int, fb bool) {
if *flags&FmtSign != 0 { if *flags&FmtSign != 0 {
fmtmode = FDbg fmtmode = FDbg
} else if *flags&FmtSharp != 0 { } else if *flags&FmtSharp != 0 {
fmtmode = FExp // for textual export format - no longer supported
Fatalf("textual export format request")
} else if *flags&FmtLeft != 0 { } else if *flags&FmtLeft != 0 {
fmtmode = FTypeId fmtmode = FTypeId
} }
...@@ -340,7 +341,7 @@ func vconv(v Val, flag FmtFlag) string { ...@@ -340,7 +341,7 @@ func vconv(v Val, flag FmtFlag) string {
switch u := v.U.(type) { switch u := v.U.(type) {
case *Mpint: case *Mpint:
if !u.Rune { if !u.Rune {
if (flag&FmtSharp != 0) || fmtmode == FExp { if flag&FmtSharp != 0 {
return bconv(u, FmtSharp) return bconv(u, FmtSharp)
} }
return bconv(u, 0) return bconv(u, 0)
...@@ -359,13 +360,13 @@ func vconv(v Val, flag FmtFlag) string { ...@@ -359,13 +360,13 @@ func vconv(v Val, flag FmtFlag) string {
return fmt.Sprintf("('\\x00' + %v)", u) return fmt.Sprintf("('\\x00' + %v)", u)
case *Mpflt: case *Mpflt:
if (flag&FmtSharp != 0) || fmtmode == FExp { if flag&FmtSharp != 0 {
return fconv(u, 0) return fconv(u, 0)
} }
return fconv(u, FmtSharp) return fconv(u, FmtSharp)
case *Mpcplx: case *Mpcplx:
if (flag&FmtSharp != 0) || fmtmode == FExp { if flag&FmtSharp != 0 {
return fmt.Sprintf("(%v+%vi)", &u.Real, &u.Imag) return fmt.Sprintf("(%v+%vi)", &u.Real, &u.Imag)
} }
if v.U.(*Mpcplx).Real.CmpFloat64(0) == 0 { if v.U.(*Mpcplx).Real.CmpFloat64(0) == 0 {
...@@ -474,14 +475,6 @@ func symfmt(s *Sym, flag FmtFlag) string { ...@@ -474,14 +475,6 @@ func symfmt(s *Sym, flag FmtFlag) string {
return s.Pkg.Name + "." + s.Name // dcommontype, typehash return s.Pkg.Name + "." + s.Name // dcommontype, typehash
} }
return s.Pkg.Prefix + "." + s.Name // (methodsym), typesym, weaksym return s.Pkg.Prefix + "." + s.Name // (methodsym), typesym, weaksym
case FExp:
if s.Name != "" && s.Name[0] == '.' {
Fatalf("exporting synthetic symbol %s", s.Name)
}
if s.Pkg != builtinpkg {
return fmt.Sprintf("@%q.%s", s.Pkg.Path, s.Name)
}
} }
} }
...@@ -493,8 +486,7 @@ func symfmt(s *Sym, flag FmtFlag) string { ...@@ -493,8 +486,7 @@ func symfmt(s *Sym, flag FmtFlag) string {
p = s.Name[i+1:] p = s.Name[i+1:]
} }
// exportname needs to see the name without the prefix too. if fmtmode == FDbg {
if (fmtmode == FExp && !exportname(p)) || fmtmode == FDbg {
return fmt.Sprintf("@%q.%s", s.Pkg.Path, p) return fmt.Sprintf("@%q.%s", s.Pkg.Path, p)
} }
...@@ -559,9 +551,7 @@ func typefmt(t *Type, flag FmtFlag) string { ...@@ -559,9 +551,7 @@ func typefmt(t *Type, flag FmtFlag) string {
if flag&FmtUnsigned != 0 { if flag&FmtUnsigned != 0 {
return sconv(t.Sym, FmtUnsigned) return sconv(t.Sym, FmtUnsigned)
} }
fallthrough
case FExp:
if t.Sym.Pkg == localpkg && t.Vargen != 0 { if t.Sym.Pkg == localpkg && t.Vargen != 0 {
return fmt.Sprintf("%v·%d", t.Sym, t.Vargen) return fmt.Sprintf("%v·%d", t.Sym, t.Vargen)
} }
...@@ -660,15 +650,11 @@ func typefmt(t *Type, flag FmtFlag) string { ...@@ -660,15 +650,11 @@ func typefmt(t *Type, flag FmtFlag) string {
switch t.Results().NumFields() { switch t.Results().NumFields() {
case 0: case 0:
break // nothing to do
case 1: case 1:
if fmtmode != FExp { buf.WriteString(" ")
buf.WriteString(" ") buf.WriteString(Tconv(t.Results().Field(0).Type, 0)) // struct->field->field's type
buf.WriteString(Tconv(t.Results().Field(0).Type, 0)) // struct->field->field's type
break
}
fallthrough
default: default:
buf.WriteString(" ") buf.WriteString(" ")
...@@ -733,25 +719,15 @@ func typefmt(t *Type, flag FmtFlag) string { ...@@ -733,25 +719,15 @@ func typefmt(t *Type, flag FmtFlag) string {
return "undefined" return "undefined"
case TUNSAFEPTR: case TUNSAFEPTR:
if fmtmode == FExp {
return "@\"unsafe\".Pointer"
}
return "unsafe.Pointer" return "unsafe.Pointer"
case TDDDFIELD: case TDDDFIELD:
if fmtmode == FExp {
Fatalf("cannot use TDDDFIELD with old exporter")
}
return fmt.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.DDDField()) return fmt.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.DDDField())
case Txxx: case Txxx:
return "Txxx" return "Txxx"
} }
if fmtmode == FExp {
Fatalf("missing %v case during export", t.Etype)
}
// Don't know how to handle - fall back to detailed prints. // Don't know how to handle - fall back to detailed prints.
return fmt.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.Elem()) return fmt.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.Elem())
} }
...@@ -793,14 +769,6 @@ func stmtfmt(n *Node) string { ...@@ -793,14 +769,6 @@ func stmtfmt(n *Node) string {
switch n.Op { switch n.Op {
case ODCL: case ODCL:
if fmtmode == FExp {
switch n.Left.Class {
case PPARAM, PPARAMOUT, PAUTO, PAUTOHEAP:
f += fmt.Sprintf("var %v %v", n.Left, n.Left.Type)
goto ret
}
}
f += fmt.Sprintf("var %v %v", n.Left.Sym, n.Left.Type) f += fmt.Sprintf("var %v %v", n.Left.Sym, n.Left.Type)
case ODCLFIELD: case ODCLFIELD:
...@@ -814,10 +782,6 @@ func stmtfmt(n *Node) string { ...@@ -814,10 +782,6 @@ func stmtfmt(n *Node) string {
// preceded by the DCL which will be re-parsed and typechecked to reproduce // preceded by the DCL which will be re-parsed and typechecked to reproduce
// the "v = <N>" again. // the "v = <N>" again.
case OAS, OASWB: case OAS, OASWB:
if fmtmode == FExp && n.Right == nil {
break
}
if n.Colas && !complexinit { if n.Colas && !complexinit {
f += fmt.Sprintf("%v := %v", n.Left, n.Right) f += fmt.Sprintf("%v := %v", n.Left, n.Right)
} else { } else {
...@@ -947,7 +911,6 @@ func stmtfmt(n *Node) string { ...@@ -947,7 +911,6 @@ func stmtfmt(n *Node) string {
f += fmt.Sprintf("%v: ", n.Left) f += fmt.Sprintf("%v: ", n.Left)
} }
ret:
if extrablock { if extrablock {
f += "}" f += "}"
} }
...@@ -1124,23 +1087,9 @@ func exprfmt(n *Node, prec int) string { ...@@ -1124,23 +1087,9 @@ func exprfmt(n *Node, prec int) string {
// Special case: name used as local variable in export. // Special case: name used as local variable in export.
// _ becomes ~b%d internally; print as _ for export // _ becomes ~b%d internally; print as _ for export
case ONAME: case ONAME:
if (fmtmode == FExp || fmtmode == FErr) && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' { if fmtmode == FErr && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
return "_" return "_"
} }
if fmtmode == FExp && n.Sym != nil && !isblank(n) && n.Name.Vargen > 0 {
return fmt.Sprintf("%v·%d", n.Sym, n.Name.Vargen)
}
// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
// but for export, this should be rendered as (*pkg.T).meth.
// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
if fmtmode == FExp && n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
if n.Left.Type.IsPtr() {
return fmt.Sprintf("(%v).%v", n.Left.Type, sconv(n.Right.Sym, FmtShort|FmtByte))
} else {
return fmt.Sprintf("%v.%v", n.Left.Type, sconv(n.Right.Sym, FmtShort|FmtByte))
}
}
fallthrough fallthrough
case OPACK, ONONAME: case OPACK, ONONAME:
...@@ -1209,63 +1158,20 @@ func exprfmt(n *Node, prec int) string { ...@@ -1209,63 +1158,20 @@ func exprfmt(n *Node, prec int) string {
return "composite literal" return "composite literal"
} }
if fmtmode == FExp && ptrlit {
// typecheck has overwritten OIND by OTYPE with pointer type.
return fmt.Sprintf("(&%v{ %v })", n.Right.Type.Elem(), hconv(n.List, FmtComma))
}
return fmt.Sprintf("(%v{ %v })", n.Right, hconv(n.List, FmtComma)) return fmt.Sprintf("(%v{ %v })", n.Right, hconv(n.List, FmtComma))
case OPTRLIT: case OPTRLIT:
if fmtmode == FExp && n.Left.Implicit {
return Nconv(n.Left, 0)
}
return fmt.Sprintf("&%v", n.Left) return fmt.Sprintf("&%v", n.Left)
case OSTRUCTLIT: case OSTRUCTLIT, OARRAYLIT, OMAPLIT:
if fmtmode == FExp { // requires special handling of field names
var f string
if n.Implicit {
f += "{"
} else {
f += fmt.Sprintf("(%v{", n.Type)
}
for i1, n1 := range n.List.Slice() {
f += fmt.Sprintf(" %v:%v", sconv(n1.Left.Sym, FmtShort|FmtByte), n1.Right)
if i1+1 < n.List.Len() {
f += ","
} else {
f += " "
}
}
if !n.Implicit {
f += "})"
return f
}
f += "}"
return f
}
fallthrough
case OARRAYLIT, OMAPLIT:
if fmtmode == FErr { if fmtmode == FErr {
return fmt.Sprintf("%v literal", n.Type) return fmt.Sprintf("%v literal", n.Type)
} }
if fmtmode == FExp && n.Implicit {
return fmt.Sprintf("{ %v }", hconv(n.List, FmtComma))
}
return fmt.Sprintf("(%v{ %v })", n.Type, hconv(n.List, FmtComma)) return fmt.Sprintf("(%v{ %v })", n.Type, hconv(n.List, FmtComma))
case OKEY: case OKEY:
if n.Left != nil && n.Right != nil { if n.Left != nil && n.Right != nil {
if fmtmode == FExp && n.Left.Type == structkey { return fmt.Sprintf("%v:%v", n.Left, n.Right)
// requires special handling of field names
return fmt.Sprintf("%v:%v", sconv(n.Left.Sym, FmtShort|FmtByte), n.Right)
} else {
return fmt.Sprintf("%v:%v", n.Left, n.Right)
}
} }
if n.Left == nil && n.Right != nil { if n.Left == nil && n.Right != nil {
...@@ -1473,7 +1379,7 @@ func nodefmt(n *Node, flag FmtFlag) string { ...@@ -1473,7 +1379,7 @@ func nodefmt(n *Node, flag FmtFlag) string {
// we almost always want the original, except in export mode for literals // we almost always want the original, except in export mode for literals
// this saves the importer some work, and avoids us having to redo some // this saves the importer some work, and avoids us having to redo some
// special casing for package unsafe // special casing for package unsafe
if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil { if n.Op != OLITERAL && n.Orig != nil {
n = n.Orig n = n.Orig
} }
...@@ -1643,7 +1549,7 @@ func Fldconv(f *Field, flag FmtFlag) string { ...@@ -1643,7 +1549,7 @@ func Fldconv(f *Field, flag FmtFlag) string {
// Take the name from the original, lest we substituted it with ~r%d or ~b%d. // Take the name from the original, lest we substituted it with ~r%d or ~b%d.
// ~r%d is a (formerly) unnamed result. // ~r%d is a (formerly) unnamed result.
if (fmtmode == FErr || fmtmode == FExp) && f.Nname != nil { if fmtmode == FErr && f.Nname != nil {
if f.Nname.Orig != nil { if f.Nname.Orig != nil {
s = f.Nname.Orig.Sym s = f.Nname.Orig.Sym
if s != nil && s.Name[0] == '~' { if s != nil && s.Name[0] == '~' {
...@@ -1666,12 +1572,6 @@ func Fldconv(f *Field, flag FmtFlag) string { ...@@ -1666,12 +1572,6 @@ func Fldconv(f *Field, flag FmtFlag) string {
} else { } else {
name = sconv(s, 0) name = sconv(s, 0)
} }
} else if fmtmode == FExp {
if f.Embedded != 0 && s.Pkg != nil && len(s.Pkg.Path) > 0 {
name = fmt.Sprintf("@%q.?", s.Pkg.Path)
} else {
name = "?"
}
} }
} }
...@@ -1759,7 +1659,7 @@ func Nconv(n *Node, flag FmtFlag) string { ...@@ -1759,7 +1659,7 @@ func Nconv(n *Node, flag FmtFlag) string {
var str string var str string
switch fmtmode { switch fmtmode {
case FErr, FExp: case FErr:
str = nodefmt(n, flag) str = nodefmt(n, flag)
case FDbg: case FDbg:
......
...@@ -469,12 +469,6 @@ l0: ...@@ -469,12 +469,6 @@ l0:
l.nlsemi = true l.nlsemi = true
goto lx goto lx
case '#', '$', '?', '@', '\\':
if importpkg != nil {
goto lx
}
fallthrough
default: default:
// anything else is illegal // anything else is illegal
Yyerror("syntax error: illegal character %#U", c) Yyerror("syntax error: illegal character %#U", c)
...@@ -536,7 +530,7 @@ func (l *lexer) ident(c rune) { ...@@ -536,7 +530,7 @@ func (l *lexer) ident(c rune) {
// general case // general case
for { for {
if c >= utf8.RuneSelf { if c >= utf8.RuneSelf {
if unicode.IsLetter(c) || c == '_' || unicode.IsDigit(c) || importpkg != nil && c == 0xb7 { if unicode.IsLetter(c) || c == '_' || unicode.IsDigit(c) {
if cp.Len() == 0 && unicode.IsDigit(c) { if cp.Len() == 0 && unicode.IsDigit(c) {
Yyerror("identifier cannot begin with digit %#U", c) Yyerror("identifier cannot begin with digit %#U", c)
} }
...@@ -672,18 +666,10 @@ func (l *lexer) number(c rune) { ...@@ -672,18 +666,10 @@ func (l *lexer) number(c rune) {
cp.WriteByte(byte(c)) cp.WriteByte(byte(c))
c = l.getr() c = l.getr()
} }
// Falling through to exponent parsing here permits invalid
// floating-point numbers with fractional mantissa and base-2
// (p or P) exponent. We don't care because base-2 exponents
// can only show up in machine-generated textual export data
// which will use correct formatting.
} }
// exponent // exponent
// base-2 exponent (p or P) is only allowed in export data (see #9036) if c == 'e' || c == 'E' {
// TODO(gri) Once we switch to binary import data, importpkg will
// always be nil in this function. Simplify the code accordingly.
if c == 'e' || c == 'E' || importpkg != nil && (c == 'p' || c == 'P') {
isInt = false isInt = false
cp.WriteByte(byte(c)) cp.WriteByte(byte(c))
c = l.getr() c = l.getr()
...@@ -1124,9 +1110,7 @@ redo: ...@@ -1124,9 +1110,7 @@ redo:
case 0: case 0:
yyerrorl(lexlineno, "illegal NUL byte") yyerrorl(lexlineno, "illegal NUL byte")
case '\n': case '\n':
if importpkg == nil { lexlineno++
lexlineno++
}
case utf8.RuneError: case utf8.RuneError:
if w == 1 { if w == 1 {
yyerrorl(lexlineno, "illegal UTF-8 sequence") yyerrorl(lexlineno, "illegal UTF-8 sequence")
......
...@@ -182,7 +182,6 @@ func Main() { ...@@ -182,7 +182,6 @@ func Main() {
obj.Flagcount("live", "debug liveness analysis", &debuglive) obj.Flagcount("live", "debug liveness analysis", &debuglive)
obj.Flagcount("m", "print optimization decisions", &Debug['m']) obj.Flagcount("m", "print optimization decisions", &Debug['m'])
flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer") flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
flag.BoolVar(&newexport, "newexport", true, "use new export format") // TODO(gri) remove eventually (issue 15323)
flag.BoolVar(&nolocalimports, "nolocalimports", false, "reject local (relative) imports") flag.BoolVar(&nolocalimports, "nolocalimports", false, "reject local (relative) imports")
flag.StringVar(&outfile, "o", "", "write output to `file`") flag.StringVar(&outfile, "o", "", "write output to `file`")
flag.StringVar(&myimportpath, "p", "", "set expected package import `path`") flag.StringVar(&myimportpath, "p", "", "set expected package import `path`")
...@@ -644,24 +643,10 @@ func loadsys() { ...@@ -644,24 +643,10 @@ func loadsys() {
iota_ = -1000000 iota_ = -1000000
incannedimport = 1 incannedimport = 1
// The first byte in the binary export format is a 'c' or 'd' importpkg = Runtimepkg
// specifying the encoding format. We could just check that Import(bufio.NewReader(strings.NewReader(runtimeimport)))
// byte, but this is a perhaps more robust. Also, it is not importpkg = unsafepkg
// speed-critical. Import(bufio.NewReader(strings.NewReader(unsafeimport)))
// TODO(gri) simplify once textual export format has gone
if strings.HasPrefix(runtimeimport, "package") {
// textual export format
importpkg = Runtimepkg
parse_import(bufio.NewReader(strings.NewReader(runtimeimport)), nil)
importpkg = unsafepkg
parse_import(bufio.NewReader(strings.NewReader(unsafeimport)), nil)
} else {
// binary export format
importpkg = Runtimepkg
Import(bufio.NewReader(strings.NewReader(runtimeimport)))
importpkg = unsafepkg
Import(bufio.NewReader(strings.NewReader(unsafeimport)))
}
importpkg = nil importpkg = nil
incannedimport = 0 incannedimport = 0
...@@ -804,8 +789,8 @@ func importfile(f *Val, indent []byte) { ...@@ -804,8 +789,8 @@ func importfile(f *Val, indent []byte) {
linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib
// In the importfile, if we find: // In the importfile, if we find:
// $$\n (old format): position the input right after $$\n and return // $$\n (textual format): not supported anymore
// $$B\n (new format): import directly, then feed the lexer a dummy statement // $$B\n (binary format) : import directly, then feed the lexer a dummy statement
// look for $$ // look for $$
var c byte var c byte
...@@ -829,11 +814,9 @@ func importfile(f *Val, indent []byte) { ...@@ -829,11 +814,9 @@ func importfile(f *Val, indent []byte) {
switch c { switch c {
case '\n': case '\n':
// old export format Yyerror("cannot import %s: old export format no longer supported (recompile library)", path_)
parse_import(imp, indent)
case 'B': case 'B':
// new export format
if Debug_export != 0 { if Debug_export != 0 {
fmt.Printf("importing %s (%s)\n", path_, file) fmt.Printf("importing %s (%s)\n", path_, file)
} }
......
...@@ -66,16 +66,9 @@ func mkbuiltin(w io.Writer, name string) { ...@@ -66,16 +66,9 @@ func mkbuiltin(w io.Writer, name string) {
} }
// Look for $$B that introduces binary export data. // Look for $$B that introduces binary export data.
textual := false // TODO(gri) remove once we switched to binary export format
i := bytes.Index(b, []byte("\n$$B\n")) i := bytes.Index(b, []byte("\n$$B\n"))
if i < 0 { if i < 0 {
// Look for $$ that introduces textual export data. log.Fatal("did not find beginning of export data")
i = bytes.Index(b, []byte("\n$$\n"))
if i < 0 {
log.Fatal("did not find beginning of export data")
}
textual = true
i-- // textual data doesn't have B
} }
b = b[i+5:] b = b[i+5:]
...@@ -87,27 +80,15 @@ func mkbuiltin(w io.Writer, name string) { ...@@ -87,27 +80,15 @@ func mkbuiltin(w io.Writer, name string) {
b = b[:i+4] b = b[:i+4]
// Process and reformat export data. // Process and reformat export data.
const n = 40 // number of bytes per line
fmt.Fprintf(w, "\nconst %simport = \"\"", name) fmt.Fprintf(w, "\nconst %simport = \"\"", name)
if textual { for len(b) > 0 {
for _, p := range bytes.SplitAfter(b, []byte("\n")) { i := len(b)
// Chop leading white space. if i > n {
p = bytes.TrimLeft(p, " \t") i = n
if len(p) == 0 {
continue
}
fmt.Fprintf(w, " +\n\t%q", p)
}
} else {
const n = 40 // number of bytes per line
for len(b) > 0 {
i := len(b)
if i > n {
i = n
}
fmt.Fprintf(w, " +\n\t%q", b[:i])
b = b[i:]
} }
fmt.Fprintf(w, " +\n\t%q", b[:i])
b = b[i:]
} }
fmt.Fprintf(w, "\n") fmt.Fprintf(w, "\n")
} }
This diff is collapsed.
This diff is collapsed.
...@@ -46,20 +46,6 @@ func compile(t *testing.T, dirname, filename string) string { ...@@ -46,20 +46,6 @@ func compile(t *testing.T, dirname, filename string) string {
return filepath.Join(dirname, filename[:len(filename)-2]+"o") return filepath.Join(dirname, filename[:len(filename)-2]+"o")
} }
// TODO(gri) Remove this function once we switched to new export format by default.
func compileNewExport(t *testing.T, dirname, filename string) string {
testenv.MustHaveGoBuild(t)
cmd := exec.Command("go", "tool", "compile", "-newexport", filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
t.Logf("%s", out)
t.Fatalf("go tool compile %s failed: %s", filename, err)
}
// filename should end with ".go"
return filepath.Join(dirname, filename[:len(filename)-2]+"o")
}
func testPath(t *testing.T, path, srcDir string) *types.Package { func testPath(t *testing.T, path, srcDir string) *types.Package {
t0 := time.Now() t0 := time.Now()
pkg, err := Import(make(map[string]*types.Package), path, srcDir) pkg, err := Import(make(map[string]*types.Package), path, srcDir)
...@@ -121,6 +107,8 @@ func TestImportTestdata(t *testing.T) { ...@@ -121,6 +107,8 @@ func TestImportTestdata(t *testing.T) {
// additional packages that are not strictly required for // additional packages that are not strictly required for
// import processing alone (they are exported to err "on // import processing alone (they are exported to err "on
// the safe side"). // the safe side").
// TODO(gri) update the want list to be precise, now that
// the textual export data is gone.
got := fmt.Sprint(pkg.Imports()) got := fmt.Sprint(pkg.Imports())
for _, want := range []string{"go/ast", "go/token"} { for _, want := range []string{"go/ast", "go/token"} {
if !strings.Contains(got, want) { if !strings.Contains(got, want) {
...@@ -130,31 +118,6 @@ func TestImportTestdata(t *testing.T) { ...@@ -130,31 +118,6 @@ func TestImportTestdata(t *testing.T) {
} }
} }
// TODO(gri) Remove this function once we switched to new export format by default
// (and update the comment and want list in TestImportTestdata).
func TestImportTestdataNewExport(t *testing.T) {
// This package only handles gc export data.
if runtime.Compiler != "gc" {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
return
}
if outFn := compileNewExport(t, "testdata", "exports.go"); outFn != "" {
defer os.Remove(outFn)
}
if pkg := testPath(t, "./testdata/exports", "."); pkg != nil {
// The package's Imports list must include all packages
// explicitly imported by exports.go, plus all packages
// referenced indirectly via exported objects in exports.go.
want := `[package ast ("go/ast") package token ("go/token")]`
got := fmt.Sprint(pkg.Imports())
if got != want {
t.Errorf(`Package("exports").Imports() = %s, want %s`, got, want)
}
}
}
func TestImportStdLib(t *testing.T) { func TestImportStdLib(t *testing.T) {
skipSpecialPlatforms(t) skipSpecialPlatforms(t)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment