Source file src/go/internal/gcimporter/support.go

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file implements support functionality for iimport.go.
     6  
     7  package gcimporter
     8  
     9  import (
    10  	"fmt"
    11  	"go/token"
    12  	"go/types"
    13  	"internal/pkgbits"
    14  	"sync"
    15  )
    16  
    17  func assert(b bool) {
    18  	if !b {
    19  		panic("assertion failed")
    20  	}
    21  }
    22  
    23  func errorf(format string, args ...any) {
    24  	panic(fmt.Sprintf(format, args...))
    25  }
    26  
    27  // deltaNewFile is a magic line delta offset indicating a new file.
    28  // We use -64 because it is rare; see issue 20080 and CL 41619.
    29  // -64 is the smallest int that fits in a single byte as a varint.
    30  const deltaNewFile = -64
    31  
    32  // Synthesize a token.Pos
    33  type fakeFileSet struct {
    34  	fset  *token.FileSet
    35  	files map[string]*fileInfo
    36  }
    37  
    38  type fileInfo struct {
    39  	file     *token.File
    40  	lastline int
    41  }
    42  
    43  const maxlines = 64 * 1024
    44  
    45  func (s *fakeFileSet) pos(file string, line, column int) token.Pos {
    46  	// TODO(mdempsky): Make use of column.
    47  
    48  	// Since we don't know the set of needed file positions, we reserve
    49  	// maxlines positions per file. We delay calling token.File.SetLines until
    50  	// all positions have been calculated (by way of fakeFileSet.setLines), so
    51  	// that we can avoid setting unnecessary lines. See also golang/go#46586.
    52  	f := s.files[file]
    53  	if f == nil {
    54  		f = &fileInfo{file: s.fset.AddFile(file, -1, maxlines)}
    55  		s.files[file] = f
    56  	}
    57  
    58  	if line > maxlines {
    59  		line = 1
    60  	}
    61  	if line > f.lastline {
    62  		f.lastline = line
    63  	}
    64  
    65  	// Return a fake position assuming that f.file consists only of newlines.
    66  	return token.Pos(f.file.Base() + line - 1)
    67  }
    68  
    69  func (s *fakeFileSet) setLines() {
    70  	fakeLinesOnce.Do(func() {
    71  		fakeLines = make([]int, maxlines)
    72  		for i := range fakeLines {
    73  			fakeLines[i] = i
    74  		}
    75  	})
    76  	for _, f := range s.files {
    77  		f.file.SetLines(fakeLines[:f.lastline])
    78  	}
    79  }
    80  
    81  var (
    82  	fakeLines     []int
    83  	fakeLinesOnce sync.Once
    84  )
    85  
    86  func chanDir(d int) types.ChanDir {
    87  	// tag values must match the constants in cmd/compile/internal/gc/go.go
    88  	switch d {
    89  	case 1 /* Crecv */ :
    90  		return types.RecvOnly
    91  	case 2 /* Csend */ :
    92  		return types.SendOnly
    93  	case 3 /* Cboth */ :
    94  		return types.SendRecv
    95  	default:
    96  		errorf("unexpected channel dir %d", d)
    97  		return 0
    98  	}
    99  }
   100  
   101  var predeclared = []types.Type{
   102  	// basic types
   103  	types.Typ[types.Bool],
   104  	types.Typ[types.Int],
   105  	types.Typ[types.Int8],
   106  	types.Typ[types.Int16],
   107  	types.Typ[types.Int32],
   108  	types.Typ[types.Int64],
   109  	types.Typ[types.Uint],
   110  	types.Typ[types.Uint8],
   111  	types.Typ[types.Uint16],
   112  	types.Typ[types.Uint32],
   113  	types.Typ[types.Uint64],
   114  	types.Typ[types.Uintptr],
   115  	types.Typ[types.Float32],
   116  	types.Typ[types.Float64],
   117  	types.Typ[types.Complex64],
   118  	types.Typ[types.Complex128],
   119  	types.Typ[types.String],
   120  
   121  	// basic type aliases
   122  	types.Universe.Lookup("byte").Type(),
   123  	types.Universe.Lookup("rune").Type(),
   124  
   125  	// error
   126  	types.Universe.Lookup("error").Type(),
   127  
   128  	// untyped types
   129  	types.Typ[types.UntypedBool],
   130  	types.Typ[types.UntypedInt],
   131  	types.Typ[types.UntypedRune],
   132  	types.Typ[types.UntypedFloat],
   133  	types.Typ[types.UntypedComplex],
   134  	types.Typ[types.UntypedString],
   135  	types.Typ[types.UntypedNil],
   136  
   137  	// package unsafe
   138  	types.Typ[types.UnsafePointer],
   139  
   140  	// invalid type
   141  	types.Typ[types.Invalid], // only appears in packages with errors
   142  
   143  	// used internally by gc; never used by this package or in .a files
   144  	// not to be confused with the universe any
   145  	anyType{},
   146  
   147  	// comparable
   148  	types.Universe.Lookup("comparable").Type(),
   149  
   150  	// any
   151  	types.Universe.Lookup("any").Type(),
   152  }
   153  
   154  type anyType struct{}
   155  
   156  func (t anyType) Underlying() types.Type { return t }
   157  func (t anyType) String() string         { return "any" }
   158  
   159  // See cmd/compile/internal/noder.derivedInfo.
   160  type derivedInfo struct {
   161  	idx    pkgbits.Index
   162  	needed bool
   163  }
   164  
   165  // See cmd/compile/internal/noder.typeInfo.
   166  type typeInfo struct {
   167  	idx     pkgbits.Index
   168  	derived bool
   169  }
   170  
   171  // See cmd/compile/internal/types.SplitVargenSuffix.
   172  func splitVargenSuffix(name string) (base, suffix string) {
   173  	i := len(name)
   174  	for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
   175  		i--
   176  	}
   177  	const dot = "ยท"
   178  	if i >= len(dot) && name[i-len(dot):i] == dot {
   179  		i -= len(dot)
   180  		return name[:i], name[i:]
   181  	}
   182  	return name, ""
   183  }
   184  

View as plain text