return args, err
}
-// Translate rewrites f.AST, the original Go input, to remove
-// references to the imported package C, replacing them with
-// references to the equivalent Go types, functions, and variables.
-func (p *Package) Translate(f *File) {
+// loadDebug runs gcc to load debug information for the File. The debug
+// information will be saved to the debugs field of the file, and be
+// processed when Translate is called on the file later.
+// loadDebug is called concurrently with different files.
+func (f *File) loadDebug(p *Package) {
for _, cref := range f.Ref {
// Convert C.ulong to C.unsigned long, etc.
cref.Name.C = cname(cref.Name.Go)
}
- var debugs []*debug // debug data from iterations of gccDebug
ft := fileTypedefs{typedefs: make(map[string]bool)}
numTypedefs := -1
for len(ft.typedefs) > numTypedefs {
}
needType := p.guessKinds(f)
if len(needType) > 0 {
- debugs = append(debugs, p.loadDWARF(f, &ft, needType))
+ f.debugs = append(f.debugs, p.loadDWARF(f, &ft, needType))
}
// In godefs mode we're OK with the typedefs, which
break
}
}
+}
+// Translate rewrites f.AST, the original Go input, to remove
+// references to the imported package C, replacing them with
+// references to the equivalent Go types, functions, and variables.
+// Preconditions: File.loadDebug must be called prior to translate.
+func (p *Package) Translate(f *File) {
var conv typeConv
conv.Init(p.PtrSize, p.IntSize)
- for _, d := range debugs {
+ for _, d := range f.debugs {
p.recordTypes(f, d, &conv)
}
p.prepareNames(f)
// guessKinds tricks gcc into revealing the kind of each
// name xxx for the references C.xxx in the Go input.
// The kind is either a constant, type, or variable.
+// guessKinds is called concurrently with different files.
func (p *Package) guessKinds(f *File) []*Name {
// Determine kinds for names we already know about,
// like #defines or 'struct foo', before bothering with gcc.
// loadDWARF parses the DWARF debug information generated
// by gcc to learn the details of the constants, variables, and types
// being referred to as C.xxx.
+// loadDwarf is called concurrently with different files.
func (p *Package) loadDWARF(f *File, ft *fileTypedefs, names []*Name) *debug {
// Extract the types from the DWARF section of an object
// from a well-formed C program. Gcc only generates DWARF info
// gccCmd returns the gcc command line to use for compiling
// the input.
+// gccCommand is called concurrently for different files.
func (p *Package) gccCmd(ofile string) []string {
c := append(gccBaseCmd,
"-w", // no warnings
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
// returns the corresponding DWARF data and, if present, debug data block.
+// gccDebug is called concurrently with different C programs.
func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) {
ofile := gccTmp()
runGcc(stdin, p.gccCmd(ofile))
// gccErrors runs gcc over the C program stdin and returns
// the errors that gcc prints. That is, this function expects
// gcc to fail.
+// gccErrors is called concurrently with different C programs.
func (p *Package) gccErrors(stdin []byte, extraArgs ...string) string {
// TODO(rsc): require failure
args := p.gccCmd(gccTmp())
"cmd/internal/edit"
"cmd/internal/hash"
"cmd/internal/objabi"
+ "cmd/internal/par"
"cmd/internal/telemetry/counter"
)
NoCallbacks map[string]bool // C function names that with #cgo nocallback directive
NoEscapes map[string]bool // C function names that with #cgo noescape directive
Edit *edit.Buffer
+
+ debugs []*debug // debug data from iterations of gccDebug. Initialized by File.loadDebug.
}
func (f *File) offset(p token.Pos) int {
h := hash.New32()
io.WriteString(h, *importPath)
var once sync.Once
- var wg sync.WaitGroup
+ q := par.NewQueue(runtime.GOMAXPROCS(0))
fs := make([]*File, len(goFiles))
for i, input := range goFiles {
if *srcDir != "" {
fatalf("%s", err)
}
- wg.Add(1)
- go func() {
- defer wg.Done()
+ q.Add(func() {
// Apply trimpath to the file path. The path won't be read from after this point.
input, _ = objabi.ApplyRewrites(input, *trimpath)
if strings.ContainsAny(input, "\r\n") {
})
fs[i] = f
- }()
+
+ f.loadDebug(p)
+ })
}
- wg.Wait()
+ <-q.Idle()
cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6])