mirror of
https://github.com/golang/go
synced 2024-11-25 04:57:56 -07:00
misc/cgo/life: fix, add to build
#pragma dynexport is no longer needed for this use of cgo, since the gcc and gc code are now linked together into the same binary. It may still be necessary later. On the Mac, you cannot use the GOT to resolve symbols that exist in the current binary, so 6l and 8l translate the GOT-loading mov instructions into lea instructions. On ELF systems, we could use the GOT for those symbols, but for consistency 6l and 8l apply the same translation. The translation is sketchy in the extreme (depending on the relocation being in a mov instruction) but it verifies that the instruction is a mov before rewriting it to lea. Also makes typedefs global across files. Fixes #1335. Fixes #1345. R=iant, r CC=golang-dev https://golang.org/cl/3650042
This commit is contained in:
parent
a890d70cc1
commit
0cd3475386
@ -7,25 +7,15 @@ include ../../../src/Make.inc
|
|||||||
TARG=life
|
TARG=life
|
||||||
|
|
||||||
CGOFILES=\
|
CGOFILES=\
|
||||||
life.go
|
life.go\
|
||||||
|
|
||||||
LDPATH_freebsd=-Wl,-R,`pwd`
|
CGO_OFILES=\
|
||||||
LDPATH_linux=-Wl,-R,`pwd`
|
c-life.o\
|
||||||
LDPATH_darwin=
|
|
||||||
|
|
||||||
CGO_LDFLAGS=_cgo_export.o c-life.so $(LDPATH_$(GOOS))
|
CLEANFILES+=life
|
||||||
CGO_DEPS=_cgo_export.o c-life.so
|
|
||||||
|
|
||||||
CLEANFILES += life
|
|
||||||
|
|
||||||
include ../../../src/Make.pkg
|
include ../../../src/Make.pkg
|
||||||
|
|
||||||
c-life.o: c-life.c _cgo_export.h
|
|
||||||
gcc $(_CGO_CFLAGS_$(GOARCH)) -g -c -fPIC $(CFLAGS) c-life.c
|
|
||||||
|
|
||||||
c-life.so: c-life.o
|
|
||||||
gcc $(_CGO_CFLAGS_$(GOARCH)) -o $@ c-life.o $(_CGO_LDFLAGS_$(GOOS))
|
|
||||||
|
|
||||||
life: install main.go
|
life: install main.go
|
||||||
$(GC) main.go
|
$(GC) main.go
|
||||||
$(LD) -o $@ main.$O
|
$(LD) -o $@ main.$O
|
||||||
|
17
misc/cgo/life/golden.out
Normal file
17
misc/cgo/life/golden.out
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
* life
|
||||||
|
|
||||||
|
|
||||||
|
XXX XXX
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
XXX XXX
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
11
misc/cgo/life/test.bash
Executable file
11
misc/cgo/life/test.bash
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2010 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.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
gomake life
|
||||||
|
echo '*' life >run.out
|
||||||
|
./life >>run.out
|
||||||
|
diff run.out golden.out
|
||||||
|
gomake clean
|
21
src/Make.pkg
21
src/Make.pkg
@ -37,8 +37,8 @@ INSTALLFILES+=$(pkgdir)/$(TARG).a
|
|||||||
# must be done here so they apply to the main rules.
|
# must be done here so they apply to the main rules.
|
||||||
ifdef CGOFILES
|
ifdef CGOFILES
|
||||||
GOFILES+=$(patsubst %.go,%.cgo1.go,$(CGOFILES)) _cgo_gotypes.go
|
GOFILES+=$(patsubst %.go,%.cgo1.go,$(CGOFILES)) _cgo_gotypes.go
|
||||||
GCC_OFILES=$(patsubst %.go,%.cgo2.o,$(CGOFILES))
|
CGO_OFILES+=$(patsubst %.go,%.cgo2.o,$(CGOFILES)) _cgo_export.o
|
||||||
OFILES+=_cgo_defun.$O _cgo_import.$O $(GCC_OFILES)
|
OFILES+=_cgo_defun.$O _cgo_import.$O $(CGO_OFILES)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PREREQ+=$(patsubst %,%.make,$(DEPS))
|
PREREQ+=$(patsubst %,%.make,$(DEPS))
|
||||||
@ -111,8 +111,10 @@ dir:
|
|||||||
# x.cgo2.c - C implementations compiled with gcc to create a dynamic library
|
# x.cgo2.c - C implementations compiled with gcc to create a dynamic library
|
||||||
#
|
#
|
||||||
|
|
||||||
|
ifdef CGOFILES
|
||||||
_cgo_defun.c: $(CGOFILES)
|
_cgo_defun.c: $(CGOFILES)
|
||||||
CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES)
|
CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES)
|
||||||
|
endif
|
||||||
|
|
||||||
# Ugly but necessary
|
# Ugly but necessary
|
||||||
_cgo_gotypes.go _cgo_export.c _cgo_export.h: _cgo_defun.c
|
_cgo_gotypes.go _cgo_export.c _cgo_export.h: _cgo_defun.c
|
||||||
@ -122,24 +124,25 @@ _cgo_gotypes.go _cgo_export.c _cgo_export.h: _cgo_defun.c
|
|||||||
@true
|
@true
|
||||||
|
|
||||||
# Compile rules for gcc source files.
|
# Compile rules for gcc source files.
|
||||||
%.cgo2.o: %.cgo2.c
|
%.o: %.c
|
||||||
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.cgo2.c
|
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.c
|
||||||
|
|
||||||
_cgo_export.o: _cgo_export.c _cgo_export.h
|
|
||||||
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) _cgo_export.c
|
|
||||||
|
|
||||||
# To find out which symbols are needed from external libraries
|
# To find out which symbols are needed from external libraries
|
||||||
# and which libraries are needed, we build a simple a.out that
|
# and which libraries are needed, we build a simple a.out that
|
||||||
# links all the objects we just created and then use cgo -dynimport
|
# links all the objects we just created and then use cgo -dynimport
|
||||||
# to inspect it. That is, we make gcc tell us which dynamic symbols
|
# to inspect it. That is, we make gcc tell us which dynamic symbols
|
||||||
# and libraries are involved, instead of duplicating gcc's logic ourselves.
|
# and libraries are involved, instead of duplicating gcc's logic ourselves.
|
||||||
_cgo_main.c:
|
# After main we have to define all the symbols that will be provided
|
||||||
|
# by Go code. That's crosscall2 and any exported symbols.
|
||||||
|
_cgo_main.c: _cgo_defun.c
|
||||||
echo 'int main() { return 0; }' >$@
|
echo 'int main() { return 0; }' >$@
|
||||||
|
echo 'int crosscall2;' >>$@
|
||||||
|
awk -F'(' '/^_cgoexp_/ {print "int " $$1 ";"}' _cgo_defun.c >>$@
|
||||||
|
|
||||||
_cgo_main.o: _cgo_main.c
|
_cgo_main.o: _cgo_main.c
|
||||||
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) _cgo_main.c
|
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) _cgo_main.c
|
||||||
|
|
||||||
_cgo1_.o: _cgo_main.o $(GCC_OFILES)
|
_cgo1_.o: _cgo_main.o $(CGO_OFILES)
|
||||||
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ $^ $(CGO_LDFLAGS)
|
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ $^ $(CGO_LDFLAGS)
|
||||||
|
|
||||||
_cgo_import.c: _cgo1_.o
|
_cgo_import.c: _cgo1_.o
|
||||||
|
@ -193,14 +193,28 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_X86_64_PLT32:
|
case 256 + R_X86_64_PLT32:
|
||||||
addpltsym(targ);
|
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
r->sym = lookup(".plt", 0);
|
|
||||||
r->add += 4;
|
r->add += 4;
|
||||||
r->add += targ->plt;
|
if(targ->dynimpname != nil) {
|
||||||
|
addpltsym(targ);
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add += targ->plt;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_X86_64_GOTPCREL:
|
case 256 + R_X86_64_GOTPCREL:
|
||||||
|
if(targ->dynimpname == nil) {
|
||||||
|
// have symbol
|
||||||
|
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
||||||
|
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
||||||
|
diag("unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->p[r->off-2] = 0x8d;
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->add += 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
addgotsym(targ);
|
addgotsym(targ);
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
r->sym = lookup(".got", 0);
|
r->sym = lookup(".got", 0);
|
||||||
@ -244,8 +258,21 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
|
case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
|
||||||
|
if(targ->dynimpname == nil) {
|
||||||
|
// have symbol
|
||||||
|
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
||||||
|
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
||||||
|
diag("unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->p[r->off-2] = 0x8d;
|
||||||
|
r->type = D_PCREL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
|
case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
|
||||||
// TODO: What is the difference between these two?
|
if(targ->dynimpname == nil)
|
||||||
|
diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
|
||||||
addgotsym(targ);
|
addgotsym(targ);
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
r->sym = lookup(".got", 0);
|
r->sym = lookup(".got", 0);
|
||||||
@ -446,9 +473,12 @@ adddynsym(Sym *s)
|
|||||||
if(s->dynid >= 0)
|
if(s->dynid >= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(s->dynimpname == nil)
|
||||||
|
diag("adddynsym: no dynamic name for %s", s->name);
|
||||||
|
|
||||||
if(iself) {
|
if(iself) {
|
||||||
s->dynid = nelfsym++;
|
s->dynid = nelfsym++;
|
||||||
|
|
||||||
d = lookup(".dynsym", 0);
|
d = lookup(".dynsym", 0);
|
||||||
name = s->dynimpname;
|
name = s->dynimpname;
|
||||||
if(name == nil)
|
if(name == nil)
|
||||||
@ -512,10 +542,29 @@ adddynsym(Sym *s)
|
|||||||
adduint32(d, str->size);
|
adduint32(d, str->size);
|
||||||
adduint8(str, '_');
|
adduint8(str, '_');
|
||||||
addstring(str, name);
|
addstring(str, name);
|
||||||
adduint8(d, 0x01); // type - N_EXT - external symbol
|
if(s->type == SDYNIMPORT) {
|
||||||
adduint8(d, 0); // section
|
adduint8(d, 0x01); // type - N_EXT - external symbol
|
||||||
|
adduint8(d, 0); // section
|
||||||
|
} else {
|
||||||
|
adduint8(d, 0x0f);
|
||||||
|
switch(s->type) {
|
||||||
|
default:
|
||||||
|
case STEXT:
|
||||||
|
adduint8(d, 1);
|
||||||
|
break;
|
||||||
|
case SDATA:
|
||||||
|
adduint8(d, 2);
|
||||||
|
break;
|
||||||
|
case SBSS:
|
||||||
|
adduint8(d, 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
adduint16(d, 0); // desc
|
adduint16(d, 0); // desc
|
||||||
adduint64(d, 0); // value
|
if(s->type == SDYNIMPORT)
|
||||||
|
adduint64(d, 0); // value
|
||||||
|
else
|
||||||
|
addaddr(d, s);
|
||||||
} else {
|
} else {
|
||||||
diag("adddynsym: unsupported binary format");
|
diag("adddynsym: unsupported binary format");
|
||||||
}
|
}
|
||||||
|
@ -501,7 +501,7 @@ enum
|
|||||||
D_SIZE, /* 8l internal */
|
D_SIZE, /* 8l internal */
|
||||||
D_PCREL,
|
D_PCREL,
|
||||||
D_GOTOFF,
|
D_GOTOFF,
|
||||||
D_GOTPCREL,
|
D_GOTREL,
|
||||||
|
|
||||||
T_TYPE = 1<<0,
|
T_TYPE = 1<<0,
|
||||||
T_INDEX = 1<<1,
|
T_INDEX = 1<<1,
|
||||||
|
@ -183,14 +183,27 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_386_PLT32:
|
case 256 + R_386_PLT32:
|
||||||
addpltsym(targ);
|
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
r->sym = lookup(".plt", 0);
|
|
||||||
r->add += 4;
|
r->add += 4;
|
||||||
r->add += targ->plt;
|
if(targ->dynimpname != nil) {
|
||||||
|
addpltsym(targ);
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add += targ->plt;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_386_GOT32:
|
case 256 + R_386_GOT32:
|
||||||
|
if(targ->dynimpname == nil) {
|
||||||
|
// have symbol
|
||||||
|
// turn MOVL of GOT entry into LEAL of symbol itself
|
||||||
|
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
||||||
|
diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->p[r->off-2] = 0x8d;
|
||||||
|
r->type = D_GOTOFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
addgotsym(targ);
|
addgotsym(targ);
|
||||||
r->type = D_CONST; // write r->add during relocsym
|
r->type = D_CONST; // write r->add during relocsym
|
||||||
r->sym = S;
|
r->sym = S;
|
||||||
@ -233,6 +246,17 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 512 + MACHO_FAKE_GOTPCREL:
|
case 512 + MACHO_FAKE_GOTPCREL:
|
||||||
|
if(targ->dynimpname == nil) {
|
||||||
|
// have symbol
|
||||||
|
// turn MOVL of GOT entry into LEAL of symbol itself
|
||||||
|
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
||||||
|
diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->p[r->off-2] = 0x8d;
|
||||||
|
r->type = D_PCREL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
addgotsym(targ);
|
addgotsym(targ);
|
||||||
r->sym = lookup(".got", 0);
|
r->sym = lookup(".got", 0);
|
||||||
r->add += targ->got;
|
r->add += targ->got;
|
||||||
@ -429,6 +453,9 @@ adddynsym(Sym *s)
|
|||||||
if(s->dynid >= 0)
|
if(s->dynid >= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(s->dynimpname == nil)
|
||||||
|
diag("adddynsym: no dynamic name for %s", s->name, *(int32*)0);
|
||||||
|
|
||||||
if(iself) {
|
if(iself) {
|
||||||
s->dynid = nelfsym++;
|
s->dynid = nelfsym++;
|
||||||
|
|
||||||
|
@ -377,7 +377,6 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.Typedef = conv.typedef
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
|
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
|
||||||
@ -596,11 +595,11 @@ type typeConv struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var tagGen int
|
var tagGen int
|
||||||
|
var typedef = make(map[string]ast.Expr)
|
||||||
|
|
||||||
func (c *typeConv) Init(ptrSize int64) {
|
func (c *typeConv) Init(ptrSize int64) {
|
||||||
c.ptrSize = ptrSize
|
c.ptrSize = ptrSize
|
||||||
c.m = make(map[dwarf.Type]*Type)
|
c.m = make(map[dwarf.Type]*Type)
|
||||||
c.typedef = make(map[string]ast.Expr)
|
|
||||||
c.bool = c.Ident("bool")
|
c.bool = c.Ident("bool")
|
||||||
c.byte = c.Ident("byte")
|
c.byte = c.Ident("byte")
|
||||||
c.int8 = c.Ident("int8")
|
c.int8 = c.Ident("int8")
|
||||||
@ -808,7 +807,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
|||||||
t.Go = name // publish before recursive calls
|
t.Go = name // publish before recursive calls
|
||||||
switch dt.Kind {
|
switch dt.Kind {
|
||||||
case "union", "class":
|
case "union", "class":
|
||||||
c.typedef[name.Name] = c.Opaque(t.Size)
|
typedef[name.Name] = c.Opaque(t.Size)
|
||||||
if t.C == "" {
|
if t.C == "" {
|
||||||
t.C = fmt.Sprintf("typeof(unsigned char[%d])", t.Size)
|
t.C = fmt.Sprintf("typeof(unsigned char[%d])", t.Size)
|
||||||
}
|
}
|
||||||
@ -818,7 +817,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
|||||||
t.C = csyntax
|
t.C = csyntax
|
||||||
}
|
}
|
||||||
t.Align = align
|
t.Align = align
|
||||||
c.typedef[name.Name] = g
|
typedef[name.Name] = g
|
||||||
}
|
}
|
||||||
|
|
||||||
case *dwarf.TypedefType:
|
case *dwarf.TypedefType:
|
||||||
@ -837,8 +836,8 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
|||||||
sub := c.Type(dt.Type)
|
sub := c.Type(dt.Type)
|
||||||
t.Size = sub.Size
|
t.Size = sub.Size
|
||||||
t.Align = sub.Align
|
t.Align = sub.Align
|
||||||
if _, ok := c.typedef[name.Name]; !ok {
|
if _, ok := typedef[name.Name]; !ok {
|
||||||
c.typedef[name.Name] = sub.Go
|
typedef[name.Name] = sub.Go
|
||||||
}
|
}
|
||||||
|
|
||||||
case *dwarf.UcharType:
|
case *dwarf.UcharType:
|
||||||
@ -882,7 +881,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
|||||||
}
|
}
|
||||||
s = strings.Join(strings.Split(s, " ", -1), "") // strip spaces
|
s = strings.Join(strings.Split(s, " ", -1), "") // strip spaces
|
||||||
name := c.Ident("_Ctype_" + s)
|
name := c.Ident("_Ctype_" + s)
|
||||||
c.typedef[name.Name] = t.Go
|
typedef[name.Name] = t.Go
|
||||||
t.Go = name
|
t.Go = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,18 +232,6 @@ func (p *Package) Record(f *File) {
|
|||||||
error(token.NoPos, "inconsistent package names: %s, %s", p.PackageName, f.Package)
|
error(token.NoPos, "inconsistent package names: %s, %s", p.PackageName, f.Package)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Typedef == nil {
|
|
||||||
p.Typedef = f.Typedef
|
|
||||||
} else {
|
|
||||||
for k, v := range f.Typedef {
|
|
||||||
if p.Typedef[k] == nil {
|
|
||||||
p.Typedef[k] = v
|
|
||||||
} else if !reflect.DeepEqual(p.Typedef[k], v) {
|
|
||||||
error(token.NoPos, "inconsistent definitions for C type %s", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Name == nil {
|
if p.Name == nil {
|
||||||
p.Name = f.Name
|
p.Name = f.Name
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,7 +42,7 @@ func (p *Package) writeDefs() {
|
|||||||
fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
|
fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
|
||||||
fmt.Fprintf(fgo2, "func _Cerrno(dst *os.Error, x int) { *dst = os.Errno(x) }\n")
|
fmt.Fprintf(fgo2, "func _Cerrno(dst *os.Error, x int) { *dst = os.Errno(x) }\n")
|
||||||
|
|
||||||
for name, def := range p.Typedef {
|
for name, def := range typedef {
|
||||||
fmt.Fprintf(fgo2, "type %s ", name)
|
fmt.Fprintf(fgo2, "type %s ", name)
|
||||||
printer.Fprint(fgo2, fset, def)
|
printer.Fprint(fgo2, fset, def)
|
||||||
fmt.Fprintf(fgo2, "\n")
|
fmt.Fprintf(fgo2, "\n")
|
||||||
@ -321,10 +321,6 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
|||||||
// Write out the various stubs we need to support functions exported
|
// Write out the various stubs we need to support functions exported
|
||||||
// from Go so that they are callable from C.
|
// from Go so that they are callable from C.
|
||||||
func (p *Package) writeExports(fgo2, fc *os.File) {
|
func (p *Package) writeExports(fgo2, fc *os.File) {
|
||||||
if len(p.ExpFunc) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fgcc := creat("_cgo_export.c")
|
fgcc := creat("_cgo_export.c")
|
||||||
fgcch := creat("_cgo_export.h")
|
fgcch := creat("_cgo_export.h")
|
||||||
|
|
||||||
@ -424,7 +420,7 @@ func (p *Package) writeExports(fgo2, fc *os.File) {
|
|||||||
s += ")"
|
s += ")"
|
||||||
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
|
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
|
||||||
|
|
||||||
fmt.Fprintf(fgcc, "extern _cgoexp_%s(void *, int);\n", exp.ExpName)
|
fmt.Fprintf(fgcc, "extern _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
|
||||||
fmt.Fprintf(fgcc, "\n%s\n", s)
|
fmt.Fprintf(fgcc, "\n%s\n", s)
|
||||||
fmt.Fprintf(fgcc, "{\n")
|
fmt.Fprintf(fgcc, "{\n")
|
||||||
fmt.Fprintf(fgcc, "\t%s a;\n", ctype)
|
fmt.Fprintf(fgcc, "\t%s a;\n", ctype)
|
||||||
@ -438,7 +434,7 @@ func (p *Package) writeExports(fgo2, fc *os.File) {
|
|||||||
func(i int, atype ast.Expr) {
|
func(i int, atype ast.Expr) {
|
||||||
fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
|
fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
|
||||||
})
|
})
|
||||||
fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp_%s, &a, (int) sizeof a);\n", exp.ExpName)
|
fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, (int) sizeof a);\n", cPrefix, exp.ExpName)
|
||||||
if gccResult != "void" {
|
if gccResult != "void" {
|
||||||
if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
|
if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
|
||||||
fmt.Fprintf(fgcc, "\treturn a.r0;\n")
|
fmt.Fprintf(fgcc, "\treturn a.r0;\n")
|
||||||
@ -455,12 +451,11 @@ func (p *Package) writeExports(fgo2, fc *os.File) {
|
|||||||
// Build the wrapper function compiled by 6c/8c
|
// Build the wrapper function compiled by 6c/8c
|
||||||
goname := exp.Func.Name.Name
|
goname := exp.Func.Name.Name
|
||||||
if fn.Recv != nil {
|
if fn.Recv != nil {
|
||||||
goname = "_cgoexpwrap_" + fn.Recv.List[0].Names[0].Name + "_" + goname
|
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fc, "#pragma dynexport _cgoexp_%s _cgoexp_%s\n", exp.ExpName, exp.ExpName)
|
|
||||||
fmt.Fprintf(fc, "extern void ·%s();\n", goname)
|
fmt.Fprintf(fc, "extern void ·%s();\n", goname)
|
||||||
fmt.Fprintf(fc, "\nvoid\n")
|
fmt.Fprintf(fc, "\nvoid\n")
|
||||||
fmt.Fprintf(fc, "_cgoexp_%s(void *a, int32 n)\n", exp.ExpName)
|
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
|
||||||
fmt.Fprintf(fc, "{\n")
|
fmt.Fprintf(fc, "{\n")
|
||||||
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
|
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
|
||||||
fmt.Fprintf(fc, "}\n")
|
fmt.Fprintf(fc, "}\n")
|
||||||
@ -584,7 +579,7 @@ func (p *Package) cgoType(e ast.Expr) *Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for name, def := range p.Typedef {
|
for name, def := range typedef {
|
||||||
if name == t.Name {
|
if name == t.Name {
|
||||||
return p.cgoType(def)
|
return p.cgoType(def)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ ifeq ($(ENABLED),1)
|
|||||||
|
|
||||||
# Unwarranted chumminess with Make.pkg's cgo rules.
|
# Unwarranted chumminess with Make.pkg's cgo rules.
|
||||||
# Do not try this at home.
|
# Do not try this at home.
|
||||||
GCC_OFILES=\
|
CGO_OFILES=\
|
||||||
$(GOARCH).o\
|
$(GOARCH).o\
|
||||||
$(GOOS)_$(GOARCH).o\
|
$(GOOS)_$(GOARCH).o\
|
||||||
util.o\
|
util.o\
|
||||||
@ -27,7 +27,7 @@ GCC_OFILES=\
|
|||||||
OFILES=\
|
OFILES=\
|
||||||
iscgo.$O\
|
iscgo.$O\
|
||||||
_cgo_import.$O\
|
_cgo_import.$O\
|
||||||
$(GCC_OFILES)\
|
$(CGO_OFILES)\
|
||||||
|
|
||||||
CGO_LDFLAGS=-lpthread
|
CGO_LDFLAGS=-lpthread
|
||||||
|
|
||||||
@ -41,6 +41,11 @@ endif
|
|||||||
|
|
||||||
include ../../../Make.pkg
|
include ../../../Make.pkg
|
||||||
|
|
||||||
|
ifeq ($(ENABLED),1)
|
||||||
|
_cgo_defun.c:
|
||||||
|
echo >$@
|
||||||
|
endif
|
||||||
|
|
||||||
$(GOARCH).o: $(GOARCH).S
|
$(GOARCH).o: $(GOARCH).S
|
||||||
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -O2 -fPIC -o $@ -c $^
|
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -O2 -fPIC -o $@ -c $^
|
||||||
|
|
||||||
|
@ -84,6 +84,14 @@ if [[ $(uname | tr A-Z a-z | sed 's/mingw/windows/') != *windows* ]]; then
|
|||||||
fi
|
fi
|
||||||
) || exit $?
|
) || exit $?
|
||||||
|
|
||||||
|
[ "$GOARCH" == arm ] ||
|
||||||
|
(xcd ../misc/cgo/life
|
||||||
|
if [[ $(uname | tr A-Z a-z | sed 's/mingw/windows/') != *windows* ]]; then
|
||||||
|
gomake clean
|
||||||
|
./test.bash
|
||||||
|
fi
|
||||||
|
) || exit $?
|
||||||
|
|
||||||
(xcd pkg/exp/ogle
|
(xcd pkg/exp/ogle
|
||||||
gomake clean
|
gomake clean
|
||||||
time gomake ogle
|
time gomake ogle
|
||||||
|
Loading…
Reference in New Issue
Block a user