summaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/gc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/gc')
-rw-r--r--src/cmd/compile/internal/gc/asm_test.go14
-rw-r--r--src/cmd/compile/internal/gc/noder.go28
-rw-r--r--src/cmd/compile/internal/gc/walk.go14
3 files changed, 54 insertions, 2 deletions
diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go
index 08ec638f44..95c354380e 100644
--- a/src/cmd/compile/internal/gc/asm_test.go
+++ b/src/cmd/compile/internal/gc/asm_test.go
@@ -909,6 +909,20 @@ var linuxAMD64Tests = []*asmTest{
`,
[]string{"b\\+40\\(SP\\)"},
},
+ {
+ `
+ func f73(a,b [3]int16) bool {
+ return a == b
+ }`,
+ []string{"\tCMPL\t[A-Z]"},
+ },
+ {
+ `
+ func f74(a,b [12]int8) bool {
+ return a == b
+ }`,
+ []string{"\tCMPQ\t[A-Z]", "\tCMPL\t[A-Z]"},
+ },
}
var linux386Tests = []*asmTest{
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 7cd941206b..37fad2d714 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -1190,8 +1190,22 @@ func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
}
p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
+ case strings.HasPrefix(text, "go:cgo_import_dynamic "):
+ // This is permitted for general use because Solaris
+ // code relies on it in golang.org/x/sys/unix and others.
+ fields := pragmaFields(text)
+ if len(fields) >= 4 {
+ lib := strings.Trim(fields[3], `"`)
+ if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
+ p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
+ }
+ p.pragcgobuf += p.pragcgo(pos, text)
+ return pragmaValue("go:cgo_import_dynamic")
+ }
+ fallthrough
case strings.HasPrefix(text, "go:cgo_"):
- // For security, we disallow //go:cgo_* directives outside cgo-generated files.
+ // For security, we disallow //go:cgo_* directives other
+ // than cgo_import_dynamic outside cgo-generated files.
// Exception: they are allowed in the standard library, for runtime and syscall.
if !isCgoGeneratedFile(pos) && !compiling_std {
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
@@ -1227,6 +1241,18 @@ func isCgoGeneratedFile(pos src.Pos) bool {
return strings.HasPrefix(filepath.Base(filepath.Clean(pos.AbsFilename())), "_cgo_")
}
+// safeArg reports whether arg is a "safe" command-line argument,
+// meaning that when it appears in a command-line, it probably
+// doesn't have some special meaning other than its own name.
+// This is copied from SafeArg in cmd/go/internal/load/pkg.go.
+func safeArg(name string) bool {
+ if name == "" {
+ return false
+ }
+ c := name[0]
+ return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
+}
+
func mkname(sym *types.Sym) *Node {
n := oldname(sym)
if n.Name != nil && n.Name.Pack != nil {
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index ab2e38208d..7909072340 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1272,6 +1272,13 @@ opswitch:
}
if cs != nil {
cmp := Op(n.Etype)
+ // Our comparison below assumes that the non-constant string
+ // is on the left hand side, so rewrite "" cmp x to x cmp "".
+ // See issue 24817.
+ if Isconst(n.Left, CTSTR) {
+ cmp = brrev(cmp)
+ }
+
// maxRewriteLen was chosen empirically.
// It is the value that minimizes cmd/go file size
// across most architectures.
@@ -3390,18 +3397,23 @@ func walkcompare(n *Node, init *Nodes) *Node {
i++
remains -= t.Elem().Width
} else {
+ elemType := t.Elem().ToUnsigned()
cmplw := nod(OINDEX, cmpl, nodintconst(int64(i)))
- cmplw = conv(cmplw, convType)
+ cmplw = conv(cmplw, elemType) // convert to unsigned
+ cmplw = conv(cmplw, convType) // widen
cmprw := nod(OINDEX, cmpr, nodintconst(int64(i)))
+ cmprw = conv(cmprw, elemType)
cmprw = conv(cmprw, convType)
// For code like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ...
// ssa will generate a single large load.
for offset := int64(1); offset < step; offset++ {
lb := nod(OINDEX, cmpl, nodintconst(int64(i+offset)))
+ lb = conv(lb, elemType)
lb = conv(lb, convType)
lb = nod(OLSH, lb, nodintconst(int64(8*t.Elem().Width*offset)))
cmplw = nod(OOR, cmplw, lb)
rb := nod(OINDEX, cmpr, nodintconst(int64(i+offset)))
+ rb = conv(rb, elemType)
rb = conv(rb, convType)
rb = nod(OLSH, rb, nodintconst(int64(8*t.Elem().Width*offset)))
cmprw = nod(OOR, cmprw, rb)