summaryrefslogtreecommitdiffstats
path: root/src/cmd/compile
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/compare/compare.go7
-rw-r--r--src/cmd/compile/internal/noder/irgen.go26
-rw-r--r--src/cmd/compile/internal/walk/assign.go43
3 files changed, 52 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/compare/compare.go b/src/cmd/compile/internal/compare/compare.go
index e165cd6..cb2f84e 100644
--- a/src/cmd/compile/internal/compare/compare.go
+++ b/src/cmd/compile/internal/compare/compare.go
@@ -148,7 +148,7 @@ func calculateCostForType(t *types.Type) int64 {
return EqStructCost(t)
case types.TSLICE:
// Slices are not comparable.
- base.Fatalf("eqStructFieldCost: unexpected slice type")
+ base.Fatalf("calculateCostForType: unexpected slice type")
case types.TARRAY:
elemCost := calculateCostForType(t.Elem())
cost = t.NumElem() * elemCost
@@ -371,6 +371,11 @@ func eqmem(p, q ir.Node, field int, size int64) ir.Node {
}
func eqmemfunc(size int64, t *types.Type) (fn *ir.Name, needsize bool) {
+ if !base.Ctxt.Arch.CanMergeLoads && t.Alignment() < int64(base.Ctxt.Arch.Alignment) && t.Alignment() < t.Size() {
+ // We can't use larger comparisons if the value might not be aligned
+ // enough for the larger comparison. See issues 46283 and 67160.
+ size = 0
+ }
switch size {
case 1, 2, 4, 8, 16:
buf := fmt.Sprintf("memequal%d", int(size)*8)
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go
index e0b7bb9..145bcc8 100644
--- a/src/cmd/compile/internal/noder/irgen.go
+++ b/src/cmd/compile/internal/noder/irgen.go
@@ -34,7 +34,13 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
posBaseMap := make(map[*syntax.PosBase]*syntax.File)
for i, p := range noders {
files[i] = p.file
- posBaseMap[p.file.Pos().Base()] = p.file
+ // The file.Pos() is the position of the package clause.
+ // If there's a //line directive before that, file.Pos().Base()
+ // refers to that directive, not the file itself.
+ // Make sure to consistently map back to file base, here and
+ // when we look for a file in the conf.Error handler below,
+ // otherwise the file may not be found (was go.dev/issue/67141).
+ posBaseMap[fileBase(p.file.Pos())] = p.file
}
// typechecking
@@ -68,13 +74,12 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
terr := err.(types2.Error)
msg := terr.Msg
if versionErrorRx.MatchString(msg) {
- posBase := terr.Pos.Base()
- for !posBase.IsFileBase() { // line directive base
- posBase = posBase.Pos().Base()
- }
+ posBase := fileBase(terr.Pos)
fileVersion := info.FileVersions[posBase]
file := posBaseMap[posBase]
- if file.GoVersion == fileVersion {
+ if file == nil {
+ // This should never happen, but be careful and don't crash.
+ } else if file.GoVersion == fileVersion {
// If we have a version error caused by //go:build, report it.
msg = fmt.Sprintf("%s (file declares //go:build %s)", msg, fileVersion)
} else {
@@ -149,6 +154,15 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
return pkg, info
}
+// fileBase returns a file's position base given a position in the file.
+func fileBase(pos syntax.Pos) *syntax.PosBase {
+ base := pos.Base()
+ for !base.IsFileBase() { // line directive base
+ base = base.Pos().Base()
+ }
+ return base
+}
+
// A cycleFinder detects anonymous interface cycles (go.dev/issue/56103).
type cycleFinder struct {
cyclic map[*types2.Interface]bool
diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go
index fc3b858..63b6a1d 100644
--- a/src/cmd/compile/internal/walk/assign.go
+++ b/src/cmd/compile/internal/walk/assign.go
@@ -623,21 +623,23 @@ func isAppendOfMake(n ir.Node) bool {
// panicmakeslicelen()
// }
// s := l1
-// n := len(s) + l2
-// // Compare n and s as uint so growslice can panic on overflow of len(s) + l2.
-// // cap is a positive int and n can become negative when len(s) + l2
-// // overflows int. Interpreting n when negative as uint makes it larger
-// // than cap(s). growslice will check the int n arg and panic if n is
-// // negative. This prevents the overflow from being undetected.
-// if uint(n) <= uint(cap(s)) {
-// s = s[:n]
-// } else {
-// s = growslice(T, s.ptr, n, s.cap, l2, T)
+// if l2 != 0 {
+// n := len(s) + l2
+// // Compare n and s as uint so growslice can panic on overflow of len(s) + l2.
+// // cap is a positive int and n can become negative when len(s) + l2
+// // overflows int. Interpreting n when negative as uint makes it larger
+// // than cap(s). growslice will check the int n arg and panic if n is
+// // negative. This prevents the overflow from being undetected.
+// if uint(n) <= uint(cap(s)) {
+// s = s[:n]
+// } else {
+// s = growslice(T, s.ptr, n, s.cap, l2, T)
+// }
+// // clear the new portion of the underlying array.
+// hp := &s[len(s)-l2]
+// hn := l2 * sizeof(T)
+// memclr(hp, hn)
// }
-// // clear the new portion of the underlying array.
-// hp := &s[len(s)-l2]
-// hn := l2 * sizeof(T)
-// memclr(hp, hn)
// }
// s
//
@@ -671,11 +673,18 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
s := typecheck.TempAt(base.Pos, ir.CurFunc, l1.Type())
nodes = append(nodes, ir.NewAssignStmt(base.Pos, s, l1))
+ // if l2 != 0 {
+ // Avoid work if we're not appending anything. But more importantly,
+ // avoid allowing hp to be a past-the-end pointer when clearing. See issue 67255.
+ nifnz := ir.NewIfStmt(base.Pos, ir.NewBinaryExpr(base.Pos, ir.ONE, l2, ir.NewInt(base.Pos, 0)), nil, nil)
+ nifnz.Likely = true
+ nodes = append(nodes, nifnz)
+
elemtype := s.Type().Elem()
// n := s.len + l2
nn := typecheck.TempAt(base.Pos, ir.CurFunc, types.Types[types.TINT])
- nodes = append(nodes, ir.NewAssignStmt(base.Pos, nn, ir.NewBinaryExpr(base.Pos, ir.OADD, ir.NewUnaryExpr(base.Pos, ir.OLEN, s), l2)))
+ nifnz.Body = append(nifnz.Body, ir.NewAssignStmt(base.Pos, nn, ir.NewBinaryExpr(base.Pos, ir.OADD, ir.NewUnaryExpr(base.Pos, ir.OLEN, s), l2)))
// if uint(n) <= uint(s.cap)
nuint := typecheck.Conv(nn, types.Types[types.TUINT])
@@ -697,7 +706,7 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
l2)),
}
- nodes = append(nodes, nif)
+ nifnz.Body = append(nifnz.Body, nif)
// hp := &s[s.len - l2]
// TODO: &s[s.len] - hn?
@@ -723,7 +732,7 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
// if growslice isn't called do we need to do the zeroing ourselves.
nif.Body = append(nif.Body, clr...)
} else {
- nodes = append(nodes, clr...)
+ nifnz.Body = append(nifnz.Body, clr...)
}
typecheck.Stmts(nodes)