]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/gc: update cgo_import_dynamic for AIX
authorClément Chigot <clement.chigot@atos.net>
Fri, 2 Nov 2018 12:14:07 +0000 (13:14 +0100)
committerIan Lance Taylor <iant@golang.org>
Tue, 6 Nov 2018 13:52:48 +0000 (13:52 +0000)
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>
src/cmd/cgo/doc.go
src/cmd/compile/internal/gc/lex.go
src/cmd/compile/internal/gc/lex_test.go

index 157cd94d653abf71214778226ab01ef54e9059ab..08d64130df4368f7031b6689e9661c34ab4034ea 100644 (file)
@@ -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:
index 3b302a5124bd096f1ab43ff9dadf404cb5222fc4..bd68ebffff0a25a7464c71af962463e4ba9c92a8 100644 (file)
@@ -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
index fecf570fa16153f2788cd45dc639a18c7fc61d1e..e05726c9f35fa961c12f99f9297a97f1c0b1c322 100644 (file)
@@ -7,6 +7,7 @@ package gc
 import (
        "cmd/compile/internal/syntax"
        "reflect"
+       "runtime"
        "testing"
 )
 
@@ -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'`}},
@@ -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/`}},
@@ -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
+                       }
                }
+
        }
 }