TARG=life
CGOFILES=\
- life.go
+ life.go\
-LDPATH_freebsd=-Wl,-R,`pwd`
-LDPATH_linux=-Wl,-R,`pwd`
-LDPATH_darwin=
+CGO_OFILES=\
+ c-life.o\
-CGO_LDFLAGS=_cgo_export.o c-life.so $(LDPATH_$(GOOS))
-CGO_DEPS=_cgo_export.o c-life.so
-
-CLEANFILES += life
+CLEANFILES+=life
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
$(GC) main.go
$(LD) -o $@ main.$O
--- /dev/null
+* life
+
+
+ XXX XXX
+
+
+
+
+
+
+
+ XXX XXX
+
+
+
+
+
--- /dev/null
+#!/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
# must be done here so they apply to the main rules.
ifdef CGOFILES
GOFILES+=$(patsubst %.go,%.cgo1.go,$(CGOFILES)) _cgo_gotypes.go
-GCC_OFILES=$(patsubst %.go,%.cgo2.o,$(CGOFILES))
-OFILES+=_cgo_defun.$O _cgo_import.$O $(GCC_OFILES)
+CGO_OFILES+=$(patsubst %.go,%.cgo2.o,$(CGOFILES)) _cgo_export.o
+OFILES+=_cgo_defun.$O _cgo_import.$O $(CGO_OFILES)
endif
PREREQ+=$(patsubst %,%.make,$(DEPS))
# x.cgo2.c - C implementations compiled with gcc to create a dynamic library
#
+ifdef CGOFILES
_cgo_defun.c: $(CGOFILES)
CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES)
+endif
# Ugly but necessary
_cgo_gotypes.go _cgo_export.c _cgo_export.h: _cgo_defun.c
@true
# Compile rules for gcc source files.
-%.cgo2.o: %.cgo2.c
- $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.cgo2.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
+%.o: %.c
+ $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.c
# To find out which symbols are needed from external libraries
# and which libraries are needed, we build a simple a.out that
# 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
# 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 crosscall2;' >>$@
+ awk -F'(' '/^_cgoexp_/ {print "int " $$1 ";"}' _cgo_defun.c >>$@
_cgo_main.o: _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)
_cgo_import.c: _cgo1_.o
return;
case 256 + R_X86_64_PLT32:
- addpltsym(targ);
r->type = D_PCREL;
- r->sym = lookup(".plt", 0);
r->add += 4;
- r->add += targ->plt;
+ if(targ->dynimpname != nil) {
+ addpltsym(targ);
+ r->sym = lookup(".plt", 0);
+ r->add += targ->plt;
+ }
return;
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);
r->type = D_PCREL;
r->sym = lookup(".got", 0);
return;
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:
- // 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);
r->type = D_PCREL;
r->sym = lookup(".got", 0);
if(s->dynid >= 0)
return;
+ if(s->dynimpname == nil)
+ diag("adddynsym: no dynamic name for %s", s->name);
+
if(iself) {
s->dynid = nelfsym++;
-
+
d = lookup(".dynsym", 0);
name = s->dynimpname;
if(name == nil)
adduint32(d, str->size);
adduint8(str, '_');
addstring(str, name);
- adduint8(d, 0x01); // type - N_EXT - external symbol
- adduint8(d, 0); // section
+ if(s->type == SDYNIMPORT) {
+ 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
- adduint64(d, 0); // value
+ if(s->type == SDYNIMPORT)
+ adduint64(d, 0); // value
+ else
+ addaddr(d, s);
} else {
diag("adddynsym: unsupported binary format");
}
D_SIZE, /* 8l internal */
D_PCREL,
D_GOTOFF,
- D_GOTPCREL,
+ D_GOTREL,
T_TYPE = 1<<0,
T_INDEX = 1<<1,
return;
case 256 + R_386_PLT32:
- addpltsym(targ);
r->type = D_PCREL;
- r->sym = lookup(".plt", 0);
r->add += 4;
- r->add += targ->plt;
+ if(targ->dynimpname != nil) {
+ addpltsym(targ);
+ r->sym = lookup(".plt", 0);
+ r->add += targ->plt;
+ }
return;
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);
r->type = D_CONST; // write r->add during relocsym
r->sym = S;
return;
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);
r->sym = lookup(".got", 0);
r->add += targ->got;
if(s->dynid >= 0)
return;
+ if(s->dynimpname == nil)
+ diag("adddynsym: no dynamic name for %s", s->name, *(int32*)0);
+
if(iself) {
s->dynid = nelfsym++;
}
}
}
- f.Typedef = conv.typedef
}
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
}
var tagGen int
+var typedef = make(map[string]ast.Expr)
func (c *typeConv) Init(ptrSize int64) {
c.ptrSize = ptrSize
c.m = make(map[dwarf.Type]*Type)
- c.typedef = make(map[string]ast.Expr)
c.bool = c.Ident("bool")
c.byte = c.Ident("byte")
c.int8 = c.Ident("int8")
t.Go = name // publish before recursive calls
switch dt.Kind {
case "union", "class":
- c.typedef[name.Name] = c.Opaque(t.Size)
+ typedef[name.Name] = c.Opaque(t.Size)
if t.C == "" {
t.C = fmt.Sprintf("typeof(unsigned char[%d])", t.Size)
}
t.C = csyntax
}
t.Align = align
- c.typedef[name.Name] = g
+ typedef[name.Name] = g
}
case *dwarf.TypedefType:
sub := c.Type(dt.Type)
t.Size = sub.Size
t.Align = sub.Align
- if _, ok := c.typedef[name.Name]; !ok {
- c.typedef[name.Name] = sub.Go
+ if _, ok := typedef[name.Name]; !ok {
+ typedef[name.Name] = sub.Go
}
case *dwarf.UcharType:
}
s = strings.Join(strings.Split(s, " ", -1), "") // strip spaces
name := c.Ident("_Ctype_" + s)
- c.typedef[name.Name] = t.Go
+ typedef[name.Name] = t.Go
t.Go = name
}
}
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 {
p.Name = f.Name
} else {
fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\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)
printer.Fprint(fgo2, fset, def)
fmt.Fprintf(fgo2, "\n")
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fc *os.File) {
- if len(p.ExpFunc) == 0 {
- return
- }
-
fgcc := creat("_cgo_export.c")
fgcch := creat("_cgo_export.h")
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")
fmt.Fprintf(fgcc, "\t%s a;\n", ctype)
func(i int, atype ast.Expr) {
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 len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
fmt.Fprintf(fgcc, "\treturn a.r0;\n")
// Build the wrapper function compiled by 6c/8c
goname := exp.Func.Name.Name
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, "\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, "\truntime·cgocallback(·%s, a, n);\n", goname)
fmt.Fprintf(fc, "}\n")
}
}
}
- for name, def := range p.Typedef {
+ for name, def := range typedef {
if name == t.Name {
return p.cgoType(def)
}
# Unwarranted chumminess with Make.pkg's cgo rules.
# Do not try this at home.
-GCC_OFILES=\
+CGO_OFILES=\
$(GOARCH).o\
$(GOOS)_$(GOARCH).o\
util.o\
OFILES=\
iscgo.$O\
_cgo_import.$O\
- $(GCC_OFILES)\
+ $(CGO_OFILES)\
CGO_LDFLAGS=-lpthread
include ../../../Make.pkg
+ifeq ($(ENABLED),1)
+_cgo_defun.c:
+ echo >$@
+endif
+
$(GOARCH).o: $(GOARCH).S
$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -O2 -fPIC -o $@ -c $^
fi
) || 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
gomake clean
time gomake ogle