| // Copyright 2015 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. |
| |
| // This file implements support functionality for iimport.go. |
| |
| package importer |
| |
| import ( |
| "cmd/compile/internal/base" |
| "cmd/compile/internal/types2" |
| "fmt" |
| "go/token" |
| "internal/pkgbits" |
| "sync" |
| ) |
| |
| func assert(p bool) { |
| base.Assert(p) |
| } |
| |
| func errorf(format string, args ...interface{}) { |
| panic(fmt.Sprintf(format, args...)) |
| } |
| |
| const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go |
| |
| // Synthesize a token.Pos |
| type fakeFileSet struct { |
| fset *token.FileSet |
| files map[string]*token.File |
| } |
| |
| func (s *fakeFileSet) pos(file string, line, column int) token.Pos { |
| // TODO(mdempsky): Make use of column. |
| |
| // Since we don't know the set of needed file positions, we |
| // reserve maxlines positions per file. |
| const maxlines = 64 * 1024 |
| f := s.files[file] |
| if f == nil { |
| f = s.fset.AddFile(file, -1, maxlines) |
| s.files[file] = f |
| // Allocate the fake linebreak indices on first use. |
| // TODO(adonovan): opt: save ~512KB using a more complex scheme? |
| fakeLinesOnce.Do(func() { |
| fakeLines = make([]int, maxlines) |
| for i := range fakeLines { |
| fakeLines[i] = i |
| } |
| }) |
| f.SetLines(fakeLines) |
| } |
| |
| if line > maxlines { |
| line = 1 |
| } |
| |
| // Treat the file as if it contained only newlines |
| // and column=1: use the line number as the offset. |
| return f.Pos(line - 1) |
| } |
| |
| var ( |
| fakeLines []int |
| fakeLinesOnce sync.Once |
| ) |
| |
| func chanDir(d int) types2.ChanDir { |
| // tag values must match the constants in cmd/compile/internal/gc/go.go |
| switch d { |
| case 1 /* Crecv */ : |
| return types2.RecvOnly |
| case 2 /* Csend */ : |
| return types2.SendOnly |
| case 3 /* Cboth */ : |
| return types2.SendRecv |
| default: |
| errorf("unexpected channel dir %d", d) |
| return 0 |
| } |
| } |
| |
| var predeclared = []types2.Type{ |
| // basic types |
| types2.Typ[types2.Bool], |
| types2.Typ[types2.Int], |
| types2.Typ[types2.Int8], |
| types2.Typ[types2.Int16], |
| types2.Typ[types2.Int32], |
| types2.Typ[types2.Int64], |
| types2.Typ[types2.Uint], |
| types2.Typ[types2.Uint8], |
| types2.Typ[types2.Uint16], |
| types2.Typ[types2.Uint32], |
| types2.Typ[types2.Uint64], |
| types2.Typ[types2.Uintptr], |
| types2.Typ[types2.Float32], |
| types2.Typ[types2.Float64], |
| types2.Typ[types2.Complex64], |
| types2.Typ[types2.Complex128], |
| types2.Typ[types2.String], |
| |
| // basic type aliases |
| types2.Universe.Lookup("byte").Type(), |
| types2.Universe.Lookup("rune").Type(), |
| |
| // error |
| types2.Universe.Lookup("error").Type(), |
| |
| // untyped types |
| types2.Typ[types2.UntypedBool], |
| types2.Typ[types2.UntypedInt], |
| types2.Typ[types2.UntypedRune], |
| types2.Typ[types2.UntypedFloat], |
| types2.Typ[types2.UntypedComplex], |
| types2.Typ[types2.UntypedString], |
| types2.Typ[types2.UntypedNil], |
| |
| // package unsafe |
| types2.Typ[types2.UnsafePointer], |
| |
| // invalid type |
| types2.Typ[types2.Invalid], // only appears in packages with errors |
| |
| // used internally by gc; never used by this package or in .a files |
| // not to be confused with the universe any |
| anyType{}, |
| |
| // comparable |
| types2.Universe.Lookup("comparable").Type(), |
| |
| // any |
| types2.Universe.Lookup("any").Type(), |
| } |
| |
| type anyType struct{} |
| |
| func (t anyType) Underlying() types2.Type { return t } |
| func (t anyType) String() string { return "any" } |
| |
| // See cmd/compile/internal/noder.derivedInfo. |
| type derivedInfo struct { |
| idx pkgbits.Index |
| needed bool |
| } |
| |
| // See cmd/compile/internal/noder.typeInfo. |
| type typeInfo struct { |
| idx pkgbits.Index |
| derived bool |
| } |