Skip to content

Commit 6795687

Browse files
committed
cmd/cgo: use __gcc_struct__ for go exported functions
Fixes #6833 R=minux.ma, iant CC=golang-dev https://golang.org/cl/35790045
1 parent 52ee63f commit 6795687

File tree

4 files changed

+54
-10
lines changed

4 files changed

+54
-10
lines changed

misc/cgo/test/cgo_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func TestCflags(t *testing.T) { testCflags(t) }
4343
func Test5337(t *testing.T) { test5337(t) }
4444
func Test5548(t *testing.T) { test5548(t) }
4545
func Test5603(t *testing.T) { test5603(t) }
46+
func Test6833(t *testing.T) { test6833(t) }
4647
func Test3250(t *testing.T) { test3250(t) }
4748
func TestCallbackStack(t *testing.T) { testCallbackStack(t) }
4849
func TestFpVar(t *testing.T) { testFpVar(t) }

misc/cgo/test/issue6833.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2013 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package cgotest
6+
7+
/*
8+
extern unsigned long long issue6833Func(unsigned int, unsigned long long);
9+
*/
10+
import "C"
11+
12+
import "testing"
13+
14+
//export GoIssue6833Func
15+
func GoIssue6833Func(aui uint, aui64 uint64) uint64 {
16+
return aui64 + uint64(aui)
17+
}
18+
19+
func test6833(t *testing.T) {
20+
ui := 7
21+
ull := uint64(0x4000300020001000)
22+
v := uint64(C.issue6833Func(C.uint(ui), C.ulonglong(ull)))
23+
exp := uint64(ui) + ull
24+
if v != exp {
25+
t.Errorf("issue6833Func() returns %x, expected %x", v, exp)
26+
}
27+
}

misc/cgo/test/issue6833_c.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2013 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
#include "_cgo_export.h"
6+
7+
unsigned long long
8+
issue6833Func(unsigned int aui, unsigned long long aull) {
9+
return GoIssue6833Func(aui, aull);
10+
}

src/cmd/cgo/out.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -529,15 +529,8 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
529529
}
530530
// We're trying to write a gcc struct that matches 6c/8c/5c's layout.
531531
// Use packed attribute to force no padding in this struct in case
532-
// gcc has different packing requirements. For example,
533-
// on 386 Windows, gcc wants to 8-align int64s, but 8c does not.
534-
// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
535-
// and http://golang.org/issue/5603.
536-
extraAttr := ""
537-
if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
538-
extraAttr = ", __gcc_struct__"
539-
}
540-
fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__%v)) *a = v;\n", ctype, extraAttr)
532+
// gcc has different packing requirements.
533+
fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
541534
fmt.Fprintf(fgcc, "\t")
542535
if t := n.FuncType.Result; t != nil {
543536
fmt.Fprintf(fgcc, "a->r = ")
@@ -618,6 +611,19 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
618611
fmt.Fprintf(fgcc, "\n")
619612
}
620613

614+
// packedAttribute returns host compiler struct attribute that will be
615+
// used to match 6c/8c/5c's struct layout. For example, on 386 Windows,
616+
// gcc wants to 8-align int64s, but 8c does not.
617+
// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
618+
// and http://golang.org/issue/5603.
619+
func (p *Package) packedAttribute() string {
620+
s := "__attribute__((__packed__"
621+
if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
622+
s += ", __gcc_struct__"
623+
}
624+
return s + "))"
625+
}
626+
621627
// Write out the various stubs we need to support functions exported
622628
// from Go so that they are callable from C.
623629
func (p *Package) writeExports(fgo2, fc, fm *os.File) {
@@ -727,7 +733,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
727733
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
728734
fmt.Fprintf(fgcc, "\n%s\n", s)
729735
fmt.Fprintf(fgcc, "{\n")
730-
fmt.Fprintf(fgcc, "\t%s __attribute__((packed)) a;\n", ctype)
736+
fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
731737
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
732738
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
733739
}

0 commit comments

Comments
 (0)