2009-09-24 12:43:19 -06:00
|
|
|
// Copyright 2009 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.
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2010-07-14 18:17:53 -06:00
|
|
|
"bytes"
|
2010-12-08 11:56:51 -07:00
|
|
|
"debug/elf"
|
|
|
|
"debug/macho"
|
2011-01-20 08:22:20 -07:00
|
|
|
"debug/pe"
|
2009-12-15 16:33:31 -07:00
|
|
|
"fmt"
|
|
|
|
"go/ast"
|
|
|
|
"go/printer"
|
2010-04-09 14:31:05 -06:00
|
|
|
"go/token"
|
2009-12-15 16:33:31 -07:00
|
|
|
"os"
|
|
|
|
"strings"
|
2009-09-24 12:43:19 -06:00
|
|
|
)
|
|
|
|
|
2009-12-17 14:20:56 -07:00
|
|
|
// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
|
2009-09-30 12:51:08 -06:00
|
|
|
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
|
2010-07-14 18:17:53 -06:00
|
|
|
func (p *Package) writeDefs() {
|
2011-03-02 12:22:33 -07:00
|
|
|
fgo2 := creat("_obj/_cgo_gotypes.go")
|
|
|
|
fc := creat("_obj/_cgo_defun.c")
|
|
|
|
fm := creat("_obj/_cgo_main.c")
|
2010-12-17 12:37:11 -07:00
|
|
|
|
2011-03-02 12:22:33 -07:00
|
|
|
fflg := creat("_obj/_cgo_flags")
|
2011-02-01 06:44:18 -07:00
|
|
|
for k, v := range p.CgoFlags {
|
|
|
|
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
|
|
|
|
}
|
|
|
|
fflg.Close()
|
|
|
|
|
2010-12-17 12:37:11 -07:00
|
|
|
// Write C main file for using gcc to resolve imports.
|
|
|
|
fmt.Fprintf(fm, "int main() { return 0; }\n")
|
2011-01-14 11:52:08 -07:00
|
|
|
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
|
|
|
|
fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
|
|
|
|
fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
|
2009-09-30 12:51:08 -06:00
|
|
|
|
|
|
|
// Write second Go output: definitions of _C_xxx.
|
|
|
|
// In a separate file so that the import of "unsafe" does not
|
|
|
|
// pollute the original file.
|
2010-12-13 11:20:04 -07:00
|
|
|
fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
|
2009-12-15 16:33:31 -07:00
|
|
|
fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgo2, "import \"os\"\n\n")
|
2010-12-08 11:56:51 -07:00
|
|
|
fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
|
2009-12-15 16:33:31 -07:00
|
|
|
fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgo2, "func _Cerrno(dst *os.Error, x int) { *dst = os.Errno(x) }\n")
|
2009-09-24 12:43:19 -06:00
|
|
|
|
2010-12-17 10:51:55 -07:00
|
|
|
for name, def := range typedef {
|
2009-12-15 16:33:31 -07:00
|
|
|
fmt.Fprintf(fgo2, "type %s ", name)
|
go/ast: use token.Pos instead of token.Position; adjust all dependent code
Specifically:
* lib/godoc:
- provide file set (FSet) argument to formatters where needed
* src/cmd:
- cgo, ebnflint, godoc, gofmt, goinstall: provide file set (fset) where needed
- godoc: remove local binary search with sort.Search (change by rsc),
extract file set for formatters
* src/pkg:
- exp/eval: remove embedded token.Position fields from nodes and replace
with named token.Pos fields; add corresponding Pos() accessor methods
- go/token: added file.Line(), changed signature of File.Position()
* test/fixedbugs/:
- bug206.go: change test to not rely on token.Pos details
* added various extra comments
* Runs all.bash
* gofmt formats all of src, misc w/o changes
* godoc runs
* performance:
- The new version of godoc consumes about the same space after indexing
has completed, but indexing is half the speed. Significant space savings
are expected from smaller ASTs, but since they are thrown away after a
file has been indexed, this is not visible anymore. The slower indexing
time is due to the much more expensive computation of line information.
However, with the new compressed position information, indexing can be
rewritten and simplified. Furthermore, computing the line info can be
done more efficiently.
New godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
44381 godoc 0.0% 0:38.00 4 19 149 145M 184K 148M 176M
2010/12/03 17:58:35 index updated (39.231s, 18505 unique words, 386387 spots)
2010/12/03 17:58:35 bytes=90858456 footprint=199182584
2010/12/03 17:58:36 bytes=47858568 footprint=167295224
Old godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
23167 godoc 0.0% 0:22.02 4 17 132 129M 184K 132M 173M
2010/12/03 14:51:32 index updated (24.892s, 18765 unique words, 393830 spots)
2010/12/03 14:51:32 bytes=66404528 footprint=163907832
2010/12/03 14:51:32 bytes=46282224 footprint=163907832
The different numbers for unique words/spots stem from the fact the the
two workspaces are not exactly identical. The new godoc maintains a large
file set data structure during indexing which (probably) is the reason
for the larger heap (90858456 vs 66404528) before garbage collection.
R=rsc, r
CC=golang-dev
https://golang.org/cl/3050041
2010-12-06 15:23:18 -07:00
|
|
|
printer.Fprint(fgo2, fset, def)
|
2009-12-15 16:33:31 -07:00
|
|
|
fmt.Fprintf(fgo2, "\n")
|
2009-09-24 12:43:19 -06:00
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
|
2009-09-24 12:43:19 -06:00
|
|
|
|
2010-12-08 11:56:51 -07:00
|
|
|
fmt.Fprintf(fc, cProlog)
|
2009-09-24 12:43:19 -06:00
|
|
|
|
2010-12-08 11:56:51 -07:00
|
|
|
var cVars []string
|
2010-07-14 18:17:53 -06:00
|
|
|
for _, n := range p.Name {
|
|
|
|
if n.Kind != "var" {
|
|
|
|
continue
|
|
|
|
}
|
2010-12-08 11:56:51 -07:00
|
|
|
cVars = append(cVars, n.C)
|
|
|
|
|
2010-12-17 12:37:11 -07:00
|
|
|
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
|
|
|
|
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
|
|
|
|
|
2010-12-08 11:56:51 -07:00
|
|
|
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
|
|
|
|
fmt.Fprintf(fc, "void *·%s = &%s;\n", n.Mangle, n.C)
|
|
|
|
fmt.Fprintf(fc, "\n")
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgo2, "var %s ", n.Mangle)
|
go/ast: use token.Pos instead of token.Position; adjust all dependent code
Specifically:
* lib/godoc:
- provide file set (FSet) argument to formatters where needed
* src/cmd:
- cgo, ebnflint, godoc, gofmt, goinstall: provide file set (fset) where needed
- godoc: remove local binary search with sort.Search (change by rsc),
extract file set for formatters
* src/pkg:
- exp/eval: remove embedded token.Position fields from nodes and replace
with named token.Pos fields; add corresponding Pos() accessor methods
- go/token: added file.Line(), changed signature of File.Position()
* test/fixedbugs/:
- bug206.go: change test to not rely on token.Pos details
* added various extra comments
* Runs all.bash
* gofmt formats all of src, misc w/o changes
* godoc runs
* performance:
- The new version of godoc consumes about the same space after indexing
has completed, but indexing is half the speed. Significant space savings
are expected from smaller ASTs, but since they are thrown away after a
file has been indexed, this is not visible anymore. The slower indexing
time is due to the much more expensive computation of line information.
However, with the new compressed position information, indexing can be
rewritten and simplified. Furthermore, computing the line info can be
done more efficiently.
New godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
44381 godoc 0.0% 0:38.00 4 19 149 145M 184K 148M 176M
2010/12/03 17:58:35 index updated (39.231s, 18505 unique words, 386387 spots)
2010/12/03 17:58:35 bytes=90858456 footprint=199182584
2010/12/03 17:58:36 bytes=47858568 footprint=167295224
Old godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
23167 godoc 0.0% 0:22.02 4 17 132 129M 184K 132M 173M
2010/12/03 14:51:32 index updated (24.892s, 18765 unique words, 393830 spots)
2010/12/03 14:51:32 bytes=66404528 footprint=163907832
2010/12/03 14:51:32 bytes=46282224 footprint=163907832
The different numbers for unique words/spots stem from the fact the the
two workspaces are not exactly identical. The new godoc maintains a large
file set data structure during indexing which (probably) is the reason
for the larger heap (90858456 vs 66404528) before garbage collection.
R=rsc, r
CC=golang-dev
https://golang.org/cl/3050041
2010-12-06 15:23:18 -07:00
|
|
|
printer.Fprint(fgo2, fset, &ast.StarExpr{X: n.Type.Go})
|
2009-12-15 16:33:31 -07:00
|
|
|
fmt.Fprintf(fgo2, "\n")
|
2009-09-24 12:43:19 -06:00
|
|
|
}
|
2009-12-15 16:33:31 -07:00
|
|
|
fmt.Fprintf(fc, "\n")
|
2009-09-24 12:43:19 -06:00
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
for _, n := range p.Name {
|
|
|
|
if n.Const != "" {
|
|
|
|
fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
|
|
|
|
}
|
2009-12-15 22:24:17 -07:00
|
|
|
}
|
|
|
|
fmt.Fprintf(fgo2, "\n")
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
for _, n := range p.Name {
|
|
|
|
if n.FuncType != nil {
|
2011-03-02 12:22:33 -07:00
|
|
|
p.writeDefsFunc(fc, fgo2, n)
|
2009-12-15 16:33:31 -07:00
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
}
|
2009-09-24 12:43:19 -06:00
|
|
|
|
2010-12-17 12:37:11 -07:00
|
|
|
p.writeExports(fgo2, fc, fm)
|
2009-09-24 12:43:19 -06:00
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
fgo2.Close()
|
|
|
|
fc.Close()
|
|
|
|
}
|
|
|
|
|
2010-12-08 11:56:51 -07:00
|
|
|
func dynimport(obj string) (syms, imports []string) {
|
|
|
|
var f interface {
|
|
|
|
ImportedLibraries() ([]string, os.Error)
|
|
|
|
ImportedSymbols() ([]string, os.Error)
|
|
|
|
}
|
|
|
|
var isMacho bool
|
2011-01-20 08:22:20 -07:00
|
|
|
var err1, err2, err3 os.Error
|
2010-12-08 11:56:51 -07:00
|
|
|
if f, err1 = elf.Open(obj); err1 != nil {
|
2011-01-20 08:22:20 -07:00
|
|
|
if f, err2 = pe.Open(obj); err2 != nil {
|
|
|
|
if f, err3 = macho.Open(obj); err3 != nil {
|
|
|
|
fatal("cannot parse %s as ELF (%v) or PE (%v) or Mach-O (%v)", obj, err1, err2, err3)
|
|
|
|
}
|
|
|
|
isMacho = true
|
2010-12-08 11:56:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var err os.Error
|
|
|
|
syms, err = f.ImportedSymbols()
|
|
|
|
if err != nil {
|
|
|
|
fatal("cannot load dynamic symbols: %v", err)
|
|
|
|
}
|
|
|
|
if isMacho {
|
|
|
|
// remove leading _ that OS X insists on
|
|
|
|
for i, s := range syms {
|
|
|
|
if len(s) >= 2 && s[0] == '_' {
|
|
|
|
syms[i] = s[1:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
imports, err = f.ImportedLibraries()
|
|
|
|
if err != nil {
|
|
|
|
fatal("cannot load dynamic imports: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
// Construct a gcc struct matching the 6c argument frame.
|
|
|
|
// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
|
|
|
|
// These assumptions are checked by the gccProlog.
|
|
|
|
// Also assumes that 6c convention is to word-align the
|
|
|
|
// input and output parameters.
|
|
|
|
func (p *Package) structType(n *Name) (string, int64) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
fmt.Fprint(&buf, "struct {\n")
|
|
|
|
off := int64(0)
|
|
|
|
for i, t := range n.FuncType.Params {
|
|
|
|
if off%t.Align != 0 {
|
|
|
|
pad := t.Align - off%t.Align
|
|
|
|
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
|
2009-12-15 16:33:31 -07:00
|
|
|
off += pad
|
2009-09-24 12:43:19 -06:00
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(&buf, "\t\t%s p%d;\n", t.C, i)
|
|
|
|
off += t.Size
|
|
|
|
}
|
|
|
|
if off%p.PtrSize != 0 {
|
|
|
|
pad := p.PtrSize - off%p.PtrSize
|
|
|
|
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
|
|
|
|
off += pad
|
|
|
|
}
|
|
|
|
if t := n.FuncType.Result; t != nil {
|
|
|
|
if off%t.Align != 0 {
|
|
|
|
pad := t.Align - off%t.Align
|
|
|
|
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
|
2009-12-15 16:33:31 -07:00
|
|
|
off += pad
|
2009-09-24 12:43:19 -06:00
|
|
|
}
|
2010-09-07 07:54:20 -06:00
|
|
|
qual := ""
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
if c := t.C.String(); c[len(c)-1] == '*' {
|
2010-09-07 07:54:20 -06:00
|
|
|
qual = "const "
|
|
|
|
}
|
|
|
|
fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
|
2010-07-14 18:17:53 -06:00
|
|
|
off += t.Size
|
|
|
|
}
|
|
|
|
if off%p.PtrSize != 0 {
|
|
|
|
pad := p.PtrSize - off%p.PtrSize
|
|
|
|
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
|
|
|
|
off += pad
|
|
|
|
}
|
|
|
|
if n.AddError {
|
|
|
|
fmt.Fprint(&buf, "\t\tvoid *e[2]; /* os.Error */\n")
|
|
|
|
off += 2 * p.PtrSize
|
|
|
|
}
|
|
|
|
if off == 0 {
|
|
|
|
fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
|
|
|
|
}
|
2011-01-11 08:17:54 -07:00
|
|
|
fmt.Fprintf(&buf, "\t}")
|
2010-07-14 18:17:53 -06:00
|
|
|
return buf.String(), off
|
|
|
|
}
|
|
|
|
|
2011-03-02 12:22:33 -07:00
|
|
|
func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
|
2010-07-14 18:17:53 -06:00
|
|
|
name := n.Go
|
|
|
|
gtype := n.FuncType.Go
|
|
|
|
if n.AddError {
|
|
|
|
// Add "os.Error" to return type list.
|
|
|
|
// Type list is known to be 0 or 1 element - it's a C function.
|
|
|
|
err := &ast.Field{Type: ast.NewIdent("os.Error")}
|
|
|
|
l := gtype.Results.List
|
|
|
|
if len(l) == 0 {
|
|
|
|
l = []*ast.Field{err}
|
|
|
|
} else {
|
|
|
|
l = []*ast.Field{l[0], err}
|
2009-09-24 12:43:19 -06:00
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
t := new(ast.FuncType)
|
|
|
|
*t = *gtype
|
|
|
|
t.Results = &ast.FieldList{List: l}
|
|
|
|
gtype = t
|
2009-12-17 14:20:56 -07:00
|
|
|
}
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
// Go func declaration.
|
|
|
|
d := &ast.FuncDecl{
|
|
|
|
Name: ast.NewIdent(n.Mangle),
|
|
|
|
Type: gtype,
|
|
|
|
}
|
go/ast: use token.Pos instead of token.Position; adjust all dependent code
Specifically:
* lib/godoc:
- provide file set (FSet) argument to formatters where needed
* src/cmd:
- cgo, ebnflint, godoc, gofmt, goinstall: provide file set (fset) where needed
- godoc: remove local binary search with sort.Search (change by rsc),
extract file set for formatters
* src/pkg:
- exp/eval: remove embedded token.Position fields from nodes and replace
with named token.Pos fields; add corresponding Pos() accessor methods
- go/token: added file.Line(), changed signature of File.Position()
* test/fixedbugs/:
- bug206.go: change test to not rely on token.Pos details
* added various extra comments
* Runs all.bash
* gofmt formats all of src, misc w/o changes
* godoc runs
* performance:
- The new version of godoc consumes about the same space after indexing
has completed, but indexing is half the speed. Significant space savings
are expected from smaller ASTs, but since they are thrown away after a
file has been indexed, this is not visible anymore. The slower indexing
time is due to the much more expensive computation of line information.
However, with the new compressed position information, indexing can be
rewritten and simplified. Furthermore, computing the line info can be
done more efficiently.
New godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
44381 godoc 0.0% 0:38.00 4 19 149 145M 184K 148M 176M
2010/12/03 17:58:35 index updated (39.231s, 18505 unique words, 386387 spots)
2010/12/03 17:58:35 bytes=90858456 footprint=199182584
2010/12/03 17:58:36 bytes=47858568 footprint=167295224
Old godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
23167 godoc 0.0% 0:22.02 4 17 132 129M 184K 132M 173M
2010/12/03 14:51:32 index updated (24.892s, 18765 unique words, 393830 spots)
2010/12/03 14:51:32 bytes=66404528 footprint=163907832
2010/12/03 14:51:32 bytes=46282224 footprint=163907832
The different numbers for unique words/spots stem from the fact the the
two workspaces are not exactly identical. The new godoc maintains a large
file set data structure during indexing which (probably) is the reason
for the larger heap (90858456 vs 66404528) before garbage collection.
R=rsc, r
CC=golang-dev
https://golang.org/cl/3050041
2010-12-06 15:23:18 -07:00
|
|
|
printer.Fprint(fgo2, fset, d)
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgo2, "\n")
|
2010-04-09 14:31:05 -06:00
|
|
|
|
2010-08-18 20:29:05 -06:00
|
|
|
if name == "CString" || name == "GoString" || name == "GoStringN" {
|
2010-07-14 18:17:53 -06:00
|
|
|
// The builtins are already defined in the C prolog.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var argSize int64
|
|
|
|
_, argSize = p.structType(n)
|
|
|
|
|
|
|
|
// C wrapper calls into gcc, passing a pointer to the argument frame.
|
2010-12-10 12:32:58 -07:00
|
|
|
fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fc, "\n")
|
|
|
|
fmt.Fprintf(fc, "void\n")
|
2011-03-05 12:24:44 -07:00
|
|
|
if argSize == 0 {
|
|
|
|
argSize++
|
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fc, "·%s(struct{uint8 x[%d];}p)\n", n.Mangle, argSize)
|
|
|
|
fmt.Fprintf(fc, "{\n")
|
2010-12-10 12:32:58 -07:00
|
|
|
fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
|
2010-07-14 18:17:53 -06:00
|
|
|
if n.AddError {
|
|
|
|
// gcc leaves errno in first word of interface at end of p.
|
|
|
|
// check whether it is zero; if so, turn interface into nil.
|
|
|
|
// if not, turn interface into errno.
|
|
|
|
// Go init function initializes ·_Cerrno with an os.Errno
|
|
|
|
// for us to copy.
|
|
|
|
fmt.Fprintln(fc, ` {
|
|
|
|
int32 e;
|
|
|
|
void **v;
|
|
|
|
v = (void**)(&p+1) - 2; /* v = final two void* of p */
|
|
|
|
e = *(int32*)v;
|
|
|
|
v[0] = (void*)0xdeadbeef;
|
|
|
|
v[1] = (void*)0xdeadbeef;
|
|
|
|
if(e == 0) {
|
|
|
|
/* nil interface */
|
|
|
|
v[0] = 0;
|
|
|
|
v[1] = 0;
|
|
|
|
} else {
|
|
|
|
·_Cerrno(v, e); /* fill in v as os.Error for errno e */
|
|
|
|
}
|
|
|
|
}`)
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fc, "}\n")
|
|
|
|
fmt.Fprintf(fc, "\n")
|
2009-12-17 14:20:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// writeOutput creates stubs for a specific source file to be compiled by 6g
|
|
|
|
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
|
2010-07-14 18:17:53 -06:00
|
|
|
func (p *Package) writeOutput(f *File, srcfile string) {
|
2009-12-17 14:20:56 -07:00
|
|
|
base := srcfile
|
|
|
|
if strings.HasSuffix(base, ".go") {
|
|
|
|
base = base[0 : len(base)-3]
|
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
base = strings.Map(slashToUnderscore, base)
|
2011-03-02 12:22:33 -07:00
|
|
|
fgo1 := creat("_obj/" + base + ".cgo1.go")
|
|
|
|
fgcc := creat("_obj/" + base + ".cgo2.c")
|
2009-12-17 14:20:56 -07:00
|
|
|
|
2010-12-08 11:56:51 -07:00
|
|
|
p.GoFiles = append(p.GoFiles, base+".cgo1.go")
|
|
|
|
p.GccFiles = append(p.GccFiles, base+".cgo2.c")
|
|
|
|
|
2009-12-17 14:20:56 -07:00
|
|
|
// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
|
2010-12-13 11:20:04 -07:00
|
|
|
fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
|
2009-12-17 14:20:56 -07:00
|
|
|
fmt.Fprintf(fgo1, "//line %s:1\n", srcfile)
|
go/ast: use token.Pos instead of token.Position; adjust all dependent code
Specifically:
* lib/godoc:
- provide file set (FSet) argument to formatters where needed
* src/cmd:
- cgo, ebnflint, godoc, gofmt, goinstall: provide file set (fset) where needed
- godoc: remove local binary search with sort.Search (change by rsc),
extract file set for formatters
* src/pkg:
- exp/eval: remove embedded token.Position fields from nodes and replace
with named token.Pos fields; add corresponding Pos() accessor methods
- go/token: added file.Line(), changed signature of File.Position()
* test/fixedbugs/:
- bug206.go: change test to not rely on token.Pos details
* added various extra comments
* Runs all.bash
* gofmt formats all of src, misc w/o changes
* godoc runs
* performance:
- The new version of godoc consumes about the same space after indexing
has completed, but indexing is half the speed. Significant space savings
are expected from smaller ASTs, but since they are thrown away after a
file has been indexed, this is not visible anymore. The slower indexing
time is due to the much more expensive computation of line information.
However, with the new compressed position information, indexing can be
rewritten and simplified. Furthermore, computing the line info can be
done more efficiently.
New godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
44381 godoc 0.0% 0:38.00 4 19 149 145M 184K 148M 176M
2010/12/03 17:58:35 index updated (39.231s, 18505 unique words, 386387 spots)
2010/12/03 17:58:35 bytes=90858456 footprint=199182584
2010/12/03 17:58:36 bytes=47858568 footprint=167295224
Old godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
23167 godoc 0.0% 0:22.02 4 17 132 129M 184K 132M 173M
2010/12/03 14:51:32 index updated (24.892s, 18765 unique words, 393830 spots)
2010/12/03 14:51:32 bytes=66404528 footprint=163907832
2010/12/03 14:51:32 bytes=46282224 footprint=163907832
The different numbers for unique words/spots stem from the fact the the
two workspaces are not exactly identical. The new godoc maintains a large
file set data structure during indexing which (probably) is the reason
for the larger heap (90858456 vs 66404528) before garbage collection.
R=rsc, r
CC=golang-dev
https://golang.org/cl/3050041
2010-12-06 15:23:18 -07:00
|
|
|
printer.Fprint(fgo1, fset, f.AST)
|
2009-12-17 14:20:56 -07:00
|
|
|
|
|
|
|
// While we process the vars and funcs, also write 6c and gcc output.
|
|
|
|
// Gcc output starts with the preamble.
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
2009-12-17 14:20:56 -07:00
|
|
|
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
for _, n := range f.Name {
|
|
|
|
if n.FuncType != nil {
|
|
|
|
p.writeOutputFunc(fgcc, n)
|
2009-09-24 12:43:19 -06:00
|
|
|
}
|
|
|
|
}
|
2009-09-30 12:51:08 -06:00
|
|
|
|
2009-12-15 16:33:31 -07:00
|
|
|
fgo1.Close()
|
|
|
|
fgcc.Close()
|
2009-09-24 12:43:19 -06:00
|
|
|
}
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
|
|
|
name := n.Mangle
|
2010-08-18 20:29:05 -06:00
|
|
|
if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cfunc_GoStringN" || p.Written[name] {
|
2010-07-14 18:17:53 -06:00
|
|
|
// The builtins are already defined in the C prolog, and we don't
|
|
|
|
// want to duplicate function definitions we've already done.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.Written[name] = true
|
|
|
|
|
|
|
|
ctype, _ := p.structType(n)
|
|
|
|
|
|
|
|
// Gcc wrapper unpacks the C argument struct
|
|
|
|
// and calls the actual C function.
|
|
|
|
fmt.Fprintf(fgcc, "void\n")
|
2010-12-10 12:32:58 -07:00
|
|
|
fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgcc, "{\n")
|
|
|
|
if n.AddError {
|
|
|
|
fmt.Fprintf(fgcc, "\tint e;\n") // assuming 32 bit (see comment above structType)
|
|
|
|
fmt.Fprintf(fgcc, "\terrno = 0;\n")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgcc, "\t%s *a = v;\n", ctype)
|
|
|
|
fmt.Fprintf(fgcc, "\t")
|
|
|
|
if n.FuncType.Result != nil {
|
|
|
|
fmt.Fprintf(fgcc, "a->r = ")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgcc, "%s(", n.C)
|
|
|
|
for i := range n.FuncType.Params {
|
|
|
|
if i > 0 {
|
|
|
|
fmt.Fprintf(fgcc, ", ")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgcc, "a->p%d", i)
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgcc, ");\n")
|
|
|
|
if n.AddError {
|
|
|
|
fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgcc, "}\n")
|
|
|
|
fmt.Fprintf(fgcc, "\n")
|
|
|
|
}
|
|
|
|
|
2010-04-09 14:31:05 -06:00
|
|
|
// Write out the various stubs we need to support functions exported
|
|
|
|
// from Go so that they are callable from C.
|
2010-12-17 12:37:11 -07:00
|
|
|
func (p *Package) writeExports(fgo2, fc, fm *os.File) {
|
2011-03-02 12:22:33 -07:00
|
|
|
fgcc := creat("_obj/_cgo_export.c")
|
2010-04-09 14:31:05 -06:00
|
|
|
fgcch := creat("_cgo_export.h")
|
|
|
|
|
|
|
|
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
|
|
|
|
fmt.Fprintf(fgcch, "%s\n", gccExportHeaderProlog)
|
|
|
|
|
|
|
|
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
|
|
|
|
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
for _, exp := range p.ExpFunc {
|
2010-04-09 14:31:05 -06:00
|
|
|
fn := exp.Func
|
|
|
|
|
|
|
|
// Construct a gcc struct matching the 6c argument and
|
|
|
|
// result frame.
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype := "struct {\n"
|
2010-04-09 14:31:05 -06:00
|
|
|
off := int64(0)
|
|
|
|
npad := 0
|
|
|
|
if fn.Recv != nil {
|
|
|
|
t := p.cgoType(fn.Recv.List[0].Type)
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
|
2010-04-09 14:31:05 -06:00
|
|
|
off += t.Size
|
|
|
|
}
|
|
|
|
fntype := fn.Type
|
|
|
|
forFieldList(fntype.Params,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
t := p.cgoType(atype)
|
|
|
|
if off%t.Align != 0 {
|
|
|
|
pad := t.Align - off%t.Align
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
2010-04-09 14:31:05 -06:00
|
|
|
off += pad
|
|
|
|
npad++
|
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
|
2010-04-09 14:31:05 -06:00
|
|
|
off += t.Size
|
|
|
|
})
|
|
|
|
if off%p.PtrSize != 0 {
|
|
|
|
pad := p.PtrSize - off%p.PtrSize
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
2010-04-09 14:31:05 -06:00
|
|
|
off += pad
|
|
|
|
npad++
|
|
|
|
}
|
|
|
|
forFieldList(fntype.Results,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
t := p.cgoType(atype)
|
|
|
|
if off%t.Align != 0 {
|
|
|
|
pad := t.Align - off%t.Align
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += fmt.Sprintf("\t\tchar __pad%d[%d]\n", npad, pad)
|
2010-04-09 14:31:05 -06:00
|
|
|
off += pad
|
|
|
|
npad++
|
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
|
2010-04-09 14:31:05 -06:00
|
|
|
off += t.Size
|
|
|
|
})
|
|
|
|
if off%p.PtrSize != 0 {
|
|
|
|
pad := p.PtrSize - off%p.PtrSize
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
2010-04-09 14:31:05 -06:00
|
|
|
off += pad
|
|
|
|
npad++
|
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
if ctype == "struct {\n" {
|
|
|
|
ctype += "\t\tchar unused;\n" // avoid empty struct
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
2010-07-14 18:17:53 -06:00
|
|
|
ctype += "\t}"
|
2010-04-09 14:31:05 -06:00
|
|
|
|
|
|
|
// Get the return type of the wrapper function
|
|
|
|
// compiled by gcc.
|
|
|
|
gccResult := ""
|
|
|
|
if fntype.Results == nil || len(fntype.Results.List) == 0 {
|
|
|
|
gccResult = "void"
|
|
|
|
} else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
|
2010-04-09 14:31:05 -06:00
|
|
|
} else {
|
|
|
|
fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
|
|
|
|
fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
|
|
|
|
forFieldList(fntype.Results,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i)
|
|
|
|
})
|
|
|
|
fmt.Fprintf(fgcch, "};\n")
|
|
|
|
gccResult = "struct " + exp.ExpName + "_return"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build the wrapper function compiled by gcc.
|
|
|
|
s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
|
|
|
|
if fn.Recv != nil {
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
s += p.cgoType(fn.Recv.List[0].Type).C.String()
|
2010-04-09 14:31:05 -06:00
|
|
|
s += " recv"
|
|
|
|
}
|
|
|
|
forFieldList(fntype.Params,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
if i > 0 || fn.Recv != nil {
|
|
|
|
s += ", "
|
|
|
|
}
|
|
|
|
s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
|
|
|
|
})
|
|
|
|
s += ")"
|
|
|
|
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
|
|
|
|
|
2010-12-17 10:51:55 -07:00
|
|
|
fmt.Fprintf(fgcc, "extern _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
|
2010-04-09 14:31:05 -06:00
|
|
|
fmt.Fprintf(fgcc, "\n%s\n", s)
|
|
|
|
fmt.Fprintf(fgcc, "{\n")
|
2010-07-14 18:17:53 -06:00
|
|
|
fmt.Fprintf(fgcc, "\t%s a;\n", ctype)
|
2010-04-09 14:31:05 -06:00
|
|
|
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
|
|
|
|
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
|
|
|
|
}
|
|
|
|
if fn.Recv != nil {
|
|
|
|
fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
|
|
|
|
}
|
|
|
|
forFieldList(fntype.Params,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
|
|
|
|
})
|
2011-03-05 12:24:44 -07:00
|
|
|
fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
|
2010-04-09 14:31:05 -06:00
|
|
|
if gccResult != "void" {
|
|
|
|
if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
|
|
|
|
fmt.Fprintf(fgcc, "\treturn a.r0;\n")
|
|
|
|
} else {
|
|
|
|
forFieldList(fntype.Results,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
|
|
|
|
})
|
|
|
|
fmt.Fprintf(fgcc, "\treturn r;\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgcc, "}\n")
|
|
|
|
|
|
|
|
// Build the wrapper function compiled by 6c/8c
|
2010-08-13 11:42:18 -06:00
|
|
|
goname := exp.Func.Name.Name
|
2010-04-09 14:31:05 -06:00
|
|
|
if fn.Recv != nil {
|
2010-12-17 10:51:55 -07:00
|
|
|
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
|
|
|
fmt.Fprintf(fc, "extern void ·%s();\n", goname)
|
|
|
|
fmt.Fprintf(fc, "\nvoid\n")
|
2010-12-17 10:51:55 -07:00
|
|
|
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
|
2010-04-09 14:31:05 -06:00
|
|
|
fmt.Fprintf(fc, "{\n")
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
|
2010-04-09 14:31:05 -06:00
|
|
|
fmt.Fprintf(fc, "}\n")
|
|
|
|
|
2010-12-17 12:37:11 -07:00
|
|
|
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
|
|
|
|
|
2010-04-09 14:31:05 -06:00
|
|
|
// Calling a function with a receiver from C requires
|
|
|
|
// a Go wrapper function.
|
|
|
|
if fn.Recv != nil {
|
|
|
|
fmt.Fprintf(fgo2, "func %s(recv ", goname)
|
go/ast: use token.Pos instead of token.Position; adjust all dependent code
Specifically:
* lib/godoc:
- provide file set (FSet) argument to formatters where needed
* src/cmd:
- cgo, ebnflint, godoc, gofmt, goinstall: provide file set (fset) where needed
- godoc: remove local binary search with sort.Search (change by rsc),
extract file set for formatters
* src/pkg:
- exp/eval: remove embedded token.Position fields from nodes and replace
with named token.Pos fields; add corresponding Pos() accessor methods
- go/token: added file.Line(), changed signature of File.Position()
* test/fixedbugs/:
- bug206.go: change test to not rely on token.Pos details
* added various extra comments
* Runs all.bash
* gofmt formats all of src, misc w/o changes
* godoc runs
* performance:
- The new version of godoc consumes about the same space after indexing
has completed, but indexing is half the speed. Significant space savings
are expected from smaller ASTs, but since they are thrown away after a
file has been indexed, this is not visible anymore. The slower indexing
time is due to the much more expensive computation of line information.
However, with the new compressed position information, indexing can be
rewritten and simplified. Furthermore, computing the line info can be
done more efficiently.
New godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
44381 godoc 0.0% 0:38.00 4 19 149 145M 184K 148M 176M
2010/12/03 17:58:35 index updated (39.231s, 18505 unique words, 386387 spots)
2010/12/03 17:58:35 bytes=90858456 footprint=199182584
2010/12/03 17:58:36 bytes=47858568 footprint=167295224
Old godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
23167 godoc 0.0% 0:22.02 4 17 132 129M 184K 132M 173M
2010/12/03 14:51:32 index updated (24.892s, 18765 unique words, 393830 spots)
2010/12/03 14:51:32 bytes=66404528 footprint=163907832
2010/12/03 14:51:32 bytes=46282224 footprint=163907832
The different numbers for unique words/spots stem from the fact the the
two workspaces are not exactly identical. The new godoc maintains a large
file set data structure during indexing which (probably) is the reason
for the larger heap (90858456 vs 66404528) before garbage collection.
R=rsc, r
CC=golang-dev
https://golang.org/cl/3050041
2010-12-06 15:23:18 -07:00
|
|
|
printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
|
2010-04-09 14:31:05 -06:00
|
|
|
forFieldList(fntype.Params,
|
|
|
|
func(i int, atype ast.Expr) {
|
2010-11-18 13:34:04 -07:00
|
|
|
fmt.Fprintf(fgo2, ", p%d ", i)
|
go/ast: use token.Pos instead of token.Position; adjust all dependent code
Specifically:
* lib/godoc:
- provide file set (FSet) argument to formatters where needed
* src/cmd:
- cgo, ebnflint, godoc, gofmt, goinstall: provide file set (fset) where needed
- godoc: remove local binary search with sort.Search (change by rsc),
extract file set for formatters
* src/pkg:
- exp/eval: remove embedded token.Position fields from nodes and replace
with named token.Pos fields; add corresponding Pos() accessor methods
- go/token: added file.Line(), changed signature of File.Position()
* test/fixedbugs/:
- bug206.go: change test to not rely on token.Pos details
* added various extra comments
* Runs all.bash
* gofmt formats all of src, misc w/o changes
* godoc runs
* performance:
- The new version of godoc consumes about the same space after indexing
has completed, but indexing is half the speed. Significant space savings
are expected from smaller ASTs, but since they are thrown away after a
file has been indexed, this is not visible anymore. The slower indexing
time is due to the much more expensive computation of line information.
However, with the new compressed position information, indexing can be
rewritten and simplified. Furthermore, computing the line info can be
done more efficiently.
New godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
44381 godoc 0.0% 0:38.00 4 19 149 145M 184K 148M 176M
2010/12/03 17:58:35 index updated (39.231s, 18505 unique words, 386387 spots)
2010/12/03 17:58:35 bytes=90858456 footprint=199182584
2010/12/03 17:58:36 bytes=47858568 footprint=167295224
Old godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
23167 godoc 0.0% 0:22.02 4 17 132 129M 184K 132M 173M
2010/12/03 14:51:32 index updated (24.892s, 18765 unique words, 393830 spots)
2010/12/03 14:51:32 bytes=66404528 footprint=163907832
2010/12/03 14:51:32 bytes=46282224 footprint=163907832
The different numbers for unique words/spots stem from the fact the the
two workspaces are not exactly identical. The new godoc maintains a large
file set data structure during indexing which (probably) is the reason
for the larger heap (90858456 vs 66404528) before garbage collection.
R=rsc, r
CC=golang-dev
https://golang.org/cl/3050041
2010-12-06 15:23:18 -07:00
|
|
|
printer.Fprint(fgo2, fset, atype)
|
2010-04-09 14:31:05 -06:00
|
|
|
})
|
|
|
|
fmt.Fprintf(fgo2, ")")
|
|
|
|
if gccResult != "void" {
|
|
|
|
fmt.Fprint(fgo2, " (")
|
|
|
|
forFieldList(fntype.Results,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
if i > 0 {
|
|
|
|
fmt.Fprint(fgo2, ", ")
|
|
|
|
}
|
go/ast: use token.Pos instead of token.Position; adjust all dependent code
Specifically:
* lib/godoc:
- provide file set (FSet) argument to formatters where needed
* src/cmd:
- cgo, ebnflint, godoc, gofmt, goinstall: provide file set (fset) where needed
- godoc: remove local binary search with sort.Search (change by rsc),
extract file set for formatters
* src/pkg:
- exp/eval: remove embedded token.Position fields from nodes and replace
with named token.Pos fields; add corresponding Pos() accessor methods
- go/token: added file.Line(), changed signature of File.Position()
* test/fixedbugs/:
- bug206.go: change test to not rely on token.Pos details
* added various extra comments
* Runs all.bash
* gofmt formats all of src, misc w/o changes
* godoc runs
* performance:
- The new version of godoc consumes about the same space after indexing
has completed, but indexing is half the speed. Significant space savings
are expected from smaller ASTs, but since they are thrown away after a
file has been indexed, this is not visible anymore. The slower indexing
time is due to the much more expensive computation of line information.
However, with the new compressed position information, indexing can be
rewritten and simplified. Furthermore, computing the line info can be
done more efficiently.
New godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
44381 godoc 0.0% 0:38.00 4 19 149 145M 184K 148M 176M
2010/12/03 17:58:35 index updated (39.231s, 18505 unique words, 386387 spots)
2010/12/03 17:58:35 bytes=90858456 footprint=199182584
2010/12/03 17:58:36 bytes=47858568 footprint=167295224
Old godoc, immediately after indexing completed (best of three runs):
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
23167 godoc 0.0% 0:22.02 4 17 132 129M 184K 132M 173M
2010/12/03 14:51:32 index updated (24.892s, 18765 unique words, 393830 spots)
2010/12/03 14:51:32 bytes=66404528 footprint=163907832
2010/12/03 14:51:32 bytes=46282224 footprint=163907832
The different numbers for unique words/spots stem from the fact the the
two workspaces are not exactly identical. The new godoc maintains a large
file set data structure during indexing which (probably) is the reason
for the larger heap (90858456 vs 66404528) before garbage collection.
R=rsc, r
CC=golang-dev
https://golang.org/cl/3050041
2010-12-06 15:23:18 -07:00
|
|
|
printer.Fprint(fgo2, fset, atype)
|
2010-04-09 14:31:05 -06:00
|
|
|
})
|
|
|
|
fmt.Fprint(fgo2, ")")
|
|
|
|
}
|
|
|
|
fmt.Fprint(fgo2, " {\n")
|
|
|
|
fmt.Fprint(fgo2, "\t")
|
|
|
|
if gccResult != "void" {
|
|
|
|
fmt.Fprint(fgo2, "return ")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name)
|
|
|
|
forFieldList(fntype.Params,
|
|
|
|
func(i int, atype ast.Expr) {
|
|
|
|
if i > 0 {
|
|
|
|
fmt.Fprint(fgo2, ", ")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(fgo2, "p%d", i)
|
|
|
|
})
|
|
|
|
fmt.Fprint(fgo2, ")\n")
|
|
|
|
fmt.Fprint(fgo2, "}\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call a function for each entry in an ast.FieldList, passing the
|
|
|
|
// index into the list and the type.
|
|
|
|
func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
|
|
|
|
if fl == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
i := 0
|
|
|
|
for _, r := range fl.List {
|
|
|
|
if r.Names == nil {
|
|
|
|
fn(i, r.Type)
|
|
|
|
i++
|
|
|
|
} else {
|
|
|
|
for _ = range r.Names {
|
|
|
|
fn(i, r.Type)
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
func c(repr string, args ...interface{}) *TypeRepr {
|
|
|
|
return &TypeRepr{repr, args}
|
|
|
|
}
|
|
|
|
|
2010-04-09 14:31:05 -06:00
|
|
|
// Map predeclared Go types to Type.
|
|
|
|
var goTypes = map[string]*Type{
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
"int": &Type{Size: 4, Align: 4, C: c("int")},
|
|
|
|
"uint": &Type{Size: 4, Align: 4, C: c("uint")},
|
|
|
|
"int8": &Type{Size: 1, Align: 1, C: c("schar")},
|
|
|
|
"uint8": &Type{Size: 1, Align: 1, C: c("uchar")},
|
|
|
|
"int16": &Type{Size: 2, Align: 2, C: c("short")},
|
|
|
|
"uint16": &Type{Size: 2, Align: 2, C: c("ushort")},
|
|
|
|
"int32": &Type{Size: 4, Align: 4, C: c("int")},
|
|
|
|
"uint32": &Type{Size: 4, Align: 4, C: c("uint")},
|
|
|
|
"int64": &Type{Size: 8, Align: 8, C: c("int64")},
|
|
|
|
"uint64": &Type{Size: 8, Align: 8, C: c("uint64")},
|
|
|
|
"float": &Type{Size: 4, Align: 4, C: c("float")},
|
|
|
|
"float32": &Type{Size: 4, Align: 4, C: c("float")},
|
|
|
|
"float64": &Type{Size: 8, Align: 8, C: c("double")},
|
|
|
|
"complex": &Type{Size: 8, Align: 8, C: c("__complex float")},
|
|
|
|
"complex64": &Type{Size: 8, Align: 8, C: c("__complex float")},
|
|
|
|
"complex128": &Type{Size: 16, Align: 16, C: c("__complex double")},
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Map an ast type to a Type.
|
2010-07-14 18:17:53 -06:00
|
|
|
func (p *Package) cgoType(e ast.Expr) *Type {
|
2010-04-09 14:31:05 -06:00
|
|
|
switch t := e.(type) {
|
|
|
|
case *ast.StarExpr:
|
|
|
|
x := p.cgoType(t.X)
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
|
2010-04-09 14:31:05 -06:00
|
|
|
case *ast.ArrayType:
|
|
|
|
if t.Len == nil {
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize + 8, Align: p.PtrSize, C: c("GoSlice")}
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
|
|
|
case *ast.StructType:
|
|
|
|
// TODO
|
|
|
|
case *ast.FuncType:
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
|
2010-04-09 14:31:05 -06:00
|
|
|
case *ast.InterfaceType:
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: 3 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
|
2010-04-09 14:31:05 -06:00
|
|
|
case *ast.MapType:
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
|
2010-04-09 14:31:05 -06:00
|
|
|
case *ast.ChanType:
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
|
2010-04-09 14:31:05 -06:00
|
|
|
case *ast.Ident:
|
|
|
|
// Look up the type in the top level declarations.
|
|
|
|
// TODO: Handle types defined within a function.
|
2010-07-14 18:17:53 -06:00
|
|
|
for _, d := range p.Decl {
|
2010-04-09 14:31:05 -06:00
|
|
|
gd, ok := d.(*ast.GenDecl)
|
|
|
|
if !ok || gd.Tok != token.TYPE {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, spec := range gd.Specs {
|
|
|
|
ts, ok := spec.(*ast.TypeSpec)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
2010-08-13 11:42:18 -06:00
|
|
|
if ts.Name.Name == t.Name {
|
2010-04-09 14:31:05 -06:00
|
|
|
return p.cgoType(ts.Type)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-12-17 10:51:55 -07:00
|
|
|
for name, def := range typedef {
|
2010-08-13 11:42:18 -06:00
|
|
|
if name == t.Name {
|
2010-04-09 14:31:05 -06:00
|
|
|
return p.cgoType(def)
|
|
|
|
}
|
|
|
|
}
|
2010-08-13 11:42:18 -06:00
|
|
|
if t.Name == "uintptr" {
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")}
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
2010-08-13 11:42:18 -06:00
|
|
|
if t.Name == "string" {
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")}
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
2010-08-13 11:42:18 -06:00
|
|
|
if r, ok := goTypes[t.Name]; ok {
|
2010-04-09 14:31:05 -06:00
|
|
|
if r.Align > p.PtrSize {
|
|
|
|
r.Align = p.PtrSize
|
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
2011-01-11 09:12:06 -07:00
|
|
|
case *ast.SelectorExpr:
|
|
|
|
id, ok := t.X.(*ast.Ident)
|
|
|
|
if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
|
2011-01-11 09:12:06 -07:00
|
|
|
}
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
2010-12-13 11:20:04 -07:00
|
|
|
error(e.Pos(), "unrecognized Go type %T", e)
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 16:05:57 -07:00
|
|
|
return &Type{Size: 4, Align: 4, C: c("int")}
|
2010-04-09 14:31:05 -06:00
|
|
|
}
|
|
|
|
|
2009-09-24 12:43:19 -06:00
|
|
|
const gccProlog = `
|
|
|
|
// Usual nonsense: if x and y are not equal, the type will be invalid
|
|
|
|
// (have a negative array count) and an inscrutable error will come
|
|
|
|
// out of the compiler and hopefully mention "name".
|
|
|
|
#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
|
|
|
|
|
|
|
|
// Check at compile time that the sizes we use match our expectations.
|
|
|
|
#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)
|
|
|
|
|
|
|
|
__cgo_size_assert(char, 1)
|
|
|
|
__cgo_size_assert(short, 2)
|
|
|
|
__cgo_size_assert(int, 4)
|
|
|
|
typedef long long __cgo_long_long;
|
|
|
|
__cgo_size_assert(__cgo_long_long, 8)
|
|
|
|
__cgo_size_assert(float, 4)
|
|
|
|
__cgo_size_assert(double, 8)
|
2010-07-14 18:17:53 -06:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
2009-09-24 12:43:19 -06:00
|
|
|
`
|
|
|
|
|
|
|
|
const builtinProlog = `
|
|
|
|
typedef struct { char *p; int n; } _GoString_;
|
|
|
|
_GoString_ GoString(char *p);
|
2010-08-18 20:29:05 -06:00
|
|
|
_GoString_ GoStringN(char *p, int l);
|
2009-09-24 12:43:19 -06:00
|
|
|
char *CString(_GoString_);
|
|
|
|
`
|
|
|
|
|
|
|
|
const cProlog = `
|
|
|
|
#include "runtime.h"
|
|
|
|
#include "cgocall.h"
|
|
|
|
|
2010-07-14 18:17:53 -06:00
|
|
|
void ·_Cerrno(void*, int32);
|
|
|
|
|
2009-09-24 12:43:19 -06:00
|
|
|
void
|
2010-07-14 18:17:53 -06:00
|
|
|
·_Cfunc_GoString(int8 *p, String s)
|
2009-09-24 12:43:19 -06:00
|
|
|
{
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
s = runtime·gostring((byte*)p);
|
2009-09-24 12:43:19 -06:00
|
|
|
FLUSH(&s);
|
|
|
|
}
|
|
|
|
|
2010-08-18 20:29:05 -06:00
|
|
|
void
|
|
|
|
·_Cfunc_GoStringN(int8 *p, int32 l, String s)
|
|
|
|
{
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
s = runtime·gostringn((byte*)p, l);
|
2010-08-18 20:29:05 -06:00
|
|
|
FLUSH(&s);
|
|
|
|
}
|
|
|
|
|
2009-09-24 12:43:19 -06:00
|
|
|
void
|
2010-07-14 18:17:53 -06:00
|
|
|
·_Cfunc_CString(String s, int8 *p)
|
2009-09-24 12:43:19 -06:00
|
|
|
{
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
p = runtime·cmalloc(s.len+1);
|
|
|
|
runtime·mcpy((byte*)p, s.str, s.len);
|
2009-09-24 12:43:19 -06:00
|
|
|
p[s.len] = 0;
|
|
|
|
FLUSH(&p);
|
|
|
|
}
|
|
|
|
`
|
2010-04-09 14:31:05 -06:00
|
|
|
|
|
|
|
const gccExportHeaderProlog = `
|
|
|
|
typedef unsigned int uint;
|
|
|
|
typedef signed char schar;
|
|
|
|
typedef unsigned char uchar;
|
|
|
|
typedef unsigned short ushort;
|
|
|
|
typedef long long int64;
|
|
|
|
typedef unsigned long long uint64;
|
2010-09-08 17:24:53 -06:00
|
|
|
typedef __SIZE_TYPE__ uintptr;
|
2010-04-09 14:31:05 -06:00
|
|
|
|
|
|
|
typedef struct { char *p; int n; } GoString;
|
|
|
|
typedef void *GoMap;
|
|
|
|
typedef void *GoChan;
|
|
|
|
typedef struct { void *t; void *v; } GoInterface;
|
|
|
|
`
|