From 9c21ce54dd3625aac3b948b509a9562b684434bc Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9my=20Oudompheng?= Date: Mon, 9 Sep 2013 20:36:19 +0200 Subject: [PATCH] cmd/6g: handle very wide offsets. Fixes #6036. R=golang-dev, bradfitz, rsc CC=golang-dev https://golang.org/cl/12992043 --- src/cmd/6g/cgen.c | 3 +++ src/cmd/6g/gg.h | 1 + src/cmd/6g/gsubr.c | 27 +++++++++++++++++++++++ test/fixedbugs/issue6036.go | 44 +++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 test/fixedbugs/issue6036.go diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index d08caf6c25..fd79c099b1 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -937,6 +937,7 @@ igen(Node *n, Node *a, Node *res) igen(n->left, a, res); a->xoffset += n->xoffset; a->type = n->type; + fixlargeoffset(a); return; case ODOTPTR: @@ -945,6 +946,7 @@ igen(Node *n, Node *a, Node *res) a->op = OINDREG; a->xoffset += n->xoffset; a->type = n->type; + fixlargeoffset(a); return; case OCALLFUNC: @@ -993,6 +995,7 @@ igen(Node *n, Node *a, Node *res) // Compute &a[i] as &a + i*width. a->type = n->type; a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width; + fixlargeoffset(a); return; } } diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index f2f3ac1c16..3ef59c788e 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -132,6 +132,7 @@ void afunclit(Addr*, Node*); void nodfconst(Node*, Type*, Mpflt*); void gtrack(Sym*); void gargsize(vlong); +void fixlargeoffset(Node *n); /* * cplx.c diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index 9e8a2b229a..0e45cc0ebe 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -1067,6 +1067,29 @@ gins(int as, Node *f, Node *t) return p; } +void +fixlargeoffset(Node *n) +{ + Node a; + + if(n == N) + return; + if(n->op != OINDREG) + return; + if(n->val.u.reg == D_SP) // stack offset cannot be large + return; + if(n->xoffset != (int32)n->xoffset) { + // offset too large, add to register instead. + a = *n; + a.op = OREGISTER; + a.type = types[tptr]; + a.xoffset = 0; + cgen_checknil(&a); + ginscon(optoas(OADD, types[tptr]), n->xoffset, &a); + n->xoffset = 0; + } +} + /* * generate code to compute n; * make a refer to result. @@ -2015,6 +2038,7 @@ odot: a->type = D_NONE; a->index = D_NONE; + fixlargeoffset(&n1); naddr(&n1, a, 1); goto yes; @@ -2176,6 +2200,7 @@ oindex_const: n2 = *reg; n2.op = OINDREG; n2.xoffset = v*w; + fixlargeoffset(&n2); a->type = D_NONE; a->index = D_NONE; naddr(&n2, a, 1); @@ -2188,6 +2213,7 @@ oindex_const: reg->op = OREGISTER; } n1.xoffset += v*w; + fixlargeoffset(&n1); a->type = D_NONE; a->index= D_NONE; naddr(&n1, a, 1); @@ -2223,6 +2249,7 @@ oindex_const_sudo: n2 = *reg; n2.op = OINDREG; n2.xoffset = v*w; + fixlargeoffset(&n2); a->type = D_NONE; a->index = D_NONE; naddr(&n2, a, 1); diff --git a/test/fixedbugs/issue6036.go b/test/fixedbugs/issue6036.go new file mode 100644 index 0000000000..5f787c5690 --- /dev/null +++ b/test/fixedbugs/issue6036.go @@ -0,0 +1,44 @@ +// +build amd64 +// compile + +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 6036: 6g's backend generates OINDREG with +// offsets larger than 32-bit. + +package main + +type T struct { + Large [1 << 31]byte + A int + B int +} + +func F(t *T) { + t.B = t.A +} + +type T2 [1<<31 + 2]byte + +func F2(t *T2) { + t[1<<31+1] = 42 +} + +type T3 [1<<15 + 1][1<<15 + 1]int + +func F3(t *T3) { + t[1<<15][1<<15] = 42 +} + +type S struct { + A int32 + B int32 +} + +type T4 [1<<29 + 1]S + +func F4(t *T4) { + t[1<<29].B = 42 +} -- 2.50.0