Skip to content

Commit

Permalink
cmd/compile/internal/gc: update cgo_import_dynamic for AIX
Browse files Browse the repository at this point in the history
On AIX, cmd/link needs two information in order to generate a dynamic
import, the library and its object needed. Currently, cmd/link isn't
able to retrieve this object only with the name of the library.
Therefore, the library pattern in cgo_import_dynamic must be
"lib.a/obj.o".

Change-Id: Ib8b8aaa9807c9fa6af46ece4e312d58073ed6ec1
Reviewed-on: https://go-review.googlesource.com/c/146957
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
Clément Chigot authored and ianlancetaylor committed Nov 6, 2018
1 parent 0e4a0b9 commit e1978a2
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 11 deletions.
4 changes: 4 additions & 0 deletions src/cmd/cgo/doc.go
Expand Up @@ -827,6 +827,10 @@ The directives are:
possibly version in the dynamic library, and the optional "<library>"
names the specific library where the symbol should be found.
On AIX, the library pattern is slightly different. It must be
"lib.a/obj.o" with obj.o the member of this library exporting
this symbol.
In the <remote>, # or @ can be used to introduce a symbol version.
Examples:
Expand Down
8 changes: 8 additions & 0 deletions src/cmd/compile/internal/gc/lex.go
Expand Up @@ -114,6 +114,14 @@ func (p *noder) pragcgo(pos syntax.Pos, text string) {
case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]):
case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]):
f[3] = strings.Trim(f[3], `"`)
if objabi.GOOS == "aix" && f[3] != "" {
// On Aix, library pattern must be "lib.a/object.o"
n := strings.Split(f[3], "/")
if len(n) != 2 || !strings.HasSuffix(n[0], ".a") || !strings.HasSuffix(n[1], ".o") {
p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["lib.a/object.o"]]`})
return
}
}
default:
p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`})
return
Expand Down
56 changes: 45 additions & 11 deletions src/cmd/compile/internal/gc/lex_test.go
Expand Up @@ -7,6 +7,7 @@ package gc
import (
"cmd/compile/internal/syntax"
"reflect"
"runtime"
"testing"
)

Expand Down Expand Up @@ -49,10 +50,12 @@ func TestPragmaFields(t *testing.T) {
}

func TestPragcgo(t *testing.T) {
var tests = []struct {
type testStruct struct {
in string
want []string
}{
}

var tests = []testStruct{
{`go:cgo_export_dynamic local`, []string{`cgo_export_dynamic`, `local`}},
{`go:cgo_export_dynamic local remote`, []string{`cgo_export_dynamic`, `local`, `remote`}},
{`go:cgo_export_dynamic local' remote'`, []string{`cgo_export_dynamic`, `local'`, `remote'`}},
Expand All @@ -61,8 +64,6 @@ func TestPragcgo(t *testing.T) {
{`go:cgo_export_static local' remote'`, []string{`cgo_export_static`, `local'`, `remote'`}},
{`go:cgo_import_dynamic local`, []string{`cgo_import_dynamic`, `local`}},
{`go:cgo_import_dynamic local remote`, []string{`cgo_import_dynamic`, `local`, `remote`}},
{`go:cgo_import_dynamic local remote "library"`, []string{`cgo_import_dynamic`, `local`, `remote`, `library`}},
{`go:cgo_import_dynamic local' remote' "lib rary"`, []string{`cgo_import_dynamic`, `local'`, `remote'`, `lib rary`}},
{`go:cgo_import_static local`, []string{`cgo_import_static`, `local`}},
{`go:cgo_import_static local'`, []string{`cgo_import_static`, `local'`}},
{`go:cgo_dynamic_linker "/path/"`, []string{`cgo_dynamic_linker`, `/path/`}},
Expand All @@ -71,17 +72,50 @@ func TestPragcgo(t *testing.T) {
{`go:cgo_ldflag "a rg"`, []string{`cgo_ldflag`, `a rg`}},
}

if runtime.GOOS != "aix" {
tests = append(tests, []testStruct{
{`go:cgo_import_dynamic local remote "library"`, []string{`cgo_import_dynamic`, `local`, `remote`, `library`}},
{`go:cgo_import_dynamic local' remote' "lib rary"`, []string{`cgo_import_dynamic`, `local'`, `remote'`, `lib rary`}},
}...)
} else {
// cgo_import_dynamic with a library is slightly different on AIX
// as the library field must follow the pattern [libc.a/object.o].
tests = append(tests, []testStruct{
{`go:cgo_import_dynamic local remote "lib.a/obj.o"`, []string{`cgo_import_dynamic`, `local`, `remote`, `lib.a/obj.o`}},
// This test must fail.
{`go:cgo_import_dynamic local' remote' "library"`, []string{`<unknown position>: usage: //go:cgo_import_dynamic local [remote ["lib.a/object.o"]]`}},
}...)

}

var p noder
var nopos syntax.Pos
for _, tt := range tests {
p.pragcgobuf = nil
p.pragcgo(nopos, tt.in)

got := p.pragcgobuf
want := [][]string{tt.want}
if !reflect.DeepEqual(got, want) {
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, got, want)
continue
p.err = make(chan syntax.Error)
gotch := make(chan [][]string)
go func() {
p.pragcgobuf = nil
p.pragcgo(nopos, tt.in)
if p.pragcgobuf != nil {
gotch <- p.pragcgobuf
}
}()

select {
case e := <-p.err:
want := tt.want[0]
if e.Error() != want {
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, e, want)
continue
}
case got := <-gotch:
want := [][]string{tt.want}
if !reflect.DeepEqual(got, want) {
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, got, want)
continue
}
}

}
}

0 comments on commit e1978a2

Please sign in to comment.