Commit e1978a2d authored by Clément Chigot's avatar Clément Chigot Committed by Ian Lance Taylor

cmd/compile/internal/gc: update cgo_import_dynamic for AIX

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: 's avatarIan Lance Taylor <iant@golang.org>
parent 0e4a0b93
...@@ -827,6 +827,10 @@ The directives are: ...@@ -827,6 +827,10 @@ The directives are:
possibly version in the dynamic library, and the optional "<library>" possibly version in the dynamic library, and the optional "<library>"
names the specific library where the symbol should be found. 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. In the <remote>, # or @ can be used to introduce a symbol version.
Examples: Examples:
......
...@@ -114,6 +114,14 @@ func (p *noder) pragcgo(pos syntax.Pos, text string) { ...@@ -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) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]):
case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]): case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]):
f[3] = strings.Trim(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: default:
p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`}) p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`})
return return
......
...@@ -7,6 +7,7 @@ package gc ...@@ -7,6 +7,7 @@ package gc
import ( import (
"cmd/compile/internal/syntax" "cmd/compile/internal/syntax"
"reflect" "reflect"
"runtime"
"testing" "testing"
) )
...@@ -49,10 +50,12 @@ func TestPragmaFields(t *testing.T) { ...@@ -49,10 +50,12 @@ func TestPragmaFields(t *testing.T) {
} }
func TestPragcgo(t *testing.T) { func TestPragcgo(t *testing.T) {
var tests = []struct { type testStruct struct {
in string in string
want []string want []string
}{ }
var tests = []testStruct{
{`go:cgo_export_dynamic local`, []string{`cgo_export_dynamic`, `local`}}, {`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`}},
{`go:cgo_export_dynamic local' remote'`, []string{`cgo_export_dynamic`, `local'`, `remote'`}}, {`go:cgo_export_dynamic local' remote'`, []string{`cgo_export_dynamic`, `local'`, `remote'`}},
...@@ -61,8 +64,6 @@ func TestPragcgo(t *testing.T) { ...@@ -61,8 +64,6 @@ func TestPragcgo(t *testing.T) {
{`go:cgo_export_static local' remote'`, []string{`cgo_export_static`, `local'`, `remote'`}}, {`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`, []string{`cgo_import_dynamic`, `local`}},
{`go:cgo_import_dynamic local remote`, []string{`cgo_import_dynamic`, `local`, `remote`}}, {`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_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/`}}, {`go:cgo_dynamic_linker "/path/"`, []string{`cgo_dynamic_linker`, `/path/`}},
...@@ -71,17 +72,50 @@ func TestPragcgo(t *testing.T) { ...@@ -71,17 +72,50 @@ func TestPragcgo(t *testing.T) {
{`go:cgo_ldflag "a rg"`, []string{`cgo_ldflag`, `a rg`}}, {`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 p noder
var nopos syntax.Pos var nopos syntax.Pos
for _, tt := range tests { for _, tt := range tests {
p.pragcgobuf = nil
p.pragcgo(nopos, tt.in)
got := p.pragcgobuf p.err = make(chan syntax.Error)
want := [][]string{tt.want} gotch := make(chan [][]string)
if !reflect.DeepEqual(got, want) { go func() {
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, got, want) p.pragcgobuf = nil
continue 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
}
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment