From 3a4e156ae1789970d37e8e53b053c2e0c8ab2465 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9my=20Oudompheng?= Date: Fri, 5 Oct 2012 23:30:49 +0200 Subject: [PATCH] cmd/5g: fix out of registers in nested calls, add compiler torture test. R=golang-dev, dave, daniel.morsing, rsc CC=golang-dev, remy https://golang.org/cl/6586072 --- src/cmd/5g/cgen.c | 24 +++++-- test/torture.go | 171 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 test/torture.go diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 79efab4947..eaa813fcf7 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -16,7 +16,7 @@ cgen(Node *n, Node *res) { Node *nl, *nr, *r; Node n1, n2, n3, f0, f1; - int a, w; + int a, w, rg; Prog *p1, *p2, *p3; Addr addr; @@ -406,7 +406,22 @@ cgen(Node *n, Node *res) break; case OCALLMETH: - cgen_callmeth(n, 0); + case OCALLFUNC: + // Release res so that it is available for cgen_call. + // Pick it up again after the call. + rg = -1; + if(n->ullman >= UINF) { + if(res->op == OREGISTER || res->op == OINDREG) { + rg = res->val.u.reg; + reg[rg]--; + } + } + if(n->op == OCALLMETH) + cgen_callmeth(n, 0); + else + cgen_call(n, 0); + if(rg >= 0) + reg[rg]++; cgen_callret(n, res); break; @@ -415,11 +430,6 @@ cgen(Node *n, Node *res) cgen_callret(n, res); break; - case OCALLFUNC: - cgen_call(n, 0); - cgen_callret(n, res); - break; - case OMOD: case ODIV: a = optoas(n->op, nl->type); diff --git a/test/torture.go b/test/torture.go new file mode 100644 index 0000000000..fdc5ddae0f --- /dev/null +++ b/test/torture.go @@ -0,0 +1,171 @@ +// compile + +// Copyright 2012 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. + +// Various tests for expressions with high complexity. + +package main + +// Concatenate 16 4-bit integers into a 64-bit number. +func concat(s *[16]byte) uint64 { + r := (((((((((((((((uint64(s[0])<<4| + uint64(s[1]))<<4| + uint64(s[2]))<<4| + uint64(s[3]))<<4| + uint64(s[4]))<<4| + uint64(s[5]))<<4| + uint64(s[6]))<<4| + uint64(s[7]))<<4| + uint64(s[8]))<<4| + uint64(s[9]))<<4| + uint64(s[10]))<<4| + uint64(s[11]))<<4| + uint64(s[12]))<<4| + uint64(s[13]))<<4| + uint64(s[14]))<<4 | + uint64(s[15])) + return r +} + +// Compute the determinant of a 4x4-matrix by the sum +// over all index permutations. +func determinant(m [4][4]float64) float64 { + return m[0][0]*m[1][1]*m[2][2]*m[3][3] - + m[0][0]*m[1][1]*m[2][3]*m[3][2] - + m[0][0]*m[1][2]*m[2][1]*m[3][3] + + m[0][0]*m[1][2]*m[2][3]*m[3][1] + + m[0][0]*m[1][3]*m[2][1]*m[3][2] - + m[0][0]*m[1][3]*m[2][2]*m[3][1] - + m[0][1]*m[1][0]*m[2][2]*m[3][3] + + m[0][1]*m[1][0]*m[2][3]*m[3][2] + + m[0][1]*m[1][2]*m[2][0]*m[3][3] - + m[0][1]*m[1][2]*m[2][3]*m[3][0] - + m[0][1]*m[1][3]*m[2][0]*m[3][2] + + m[0][1]*m[1][3]*m[2][2]*m[3][0] + + m[0][2]*m[1][0]*m[2][1]*m[3][3] - + m[0][2]*m[1][0]*m[2][3]*m[3][1] - + m[0][2]*m[1][1]*m[2][0]*m[3][3] + + m[0][2]*m[1][1]*m[2][3]*m[3][0] + + m[0][2]*m[1][3]*m[2][0]*m[3][1] - + m[0][2]*m[1][3]*m[2][1]*m[3][0] - + m[0][3]*m[1][0]*m[2][1]*m[3][2] + + m[0][3]*m[1][0]*m[2][2]*m[3][1] + + m[0][3]*m[1][1]*m[2][0]*m[3][2] - + m[0][3]*m[1][1]*m[2][2]*m[3][0] - + m[0][3]*m[1][2]*m[2][0]*m[3][1] + + m[0][3]*m[1][2]*m[2][1]*m[3][0] +} + +// A right-leaning tree of byte multiplications. +func righttree(a, b, c, d uint8) uint8 { + return a * (b * (c * (d * + (a * (b * (c * (d * + (a * (b * (c * (d * + (a * (b * (c * (d * + (a * (b * (c * (d * + a * (b * (c * d))))))))))))))))))))) + +} + +// A left-leaning tree of byte multiplications. +func lefttree(a, b, c, d uint8) uint8 { + return ((((((((((((((((((a * b) * c) * d * + a) * b) * c) * d * + a) * b) * c) * d * + a) * b) * c) * d * + a) * b) * c) * d * + a) * b) * c) * d) +} + +type T struct { + Next I +} + +type I interface{} + +// A chains of type assertions. +func ChainT(t *T) *T { + return t. + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T). + Next.(*T) +} + +type U struct { + Children []J +} + +func (u *U) Child(n int) J { return u.Children[n] } + +type J interface { + Child(n int) J +} + +func ChainUAssert(u *U) *U { + return u.Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U). + Child(0).(*U) +} + +func ChainUNoAssert(u *U) *U { + return u.Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0). + Child(0).(*U) +} -- 2.48.1