From 4dec8ef35a0071064b3fd68203ae5ce66c6f9b6b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 4 Aug 2009 19:16:57 -0700 Subject: [PATCH] get function calls out of the way before allocating registers in shift and div. fix behavior when res == a reserved register. R=ken OCL=32765 CL=32767 --- src/cmd/6g/ggen.c | 58 +++++++++++++++++++++++++++++++-------- src/pkg/time/time_test.go | 8 +++--- test/fixedbugs/bug180.go | 17 ++++++++++++ 3 files changed, 68 insertions(+), 15 deletions(-) create mode 100644 test/fixedbugs/bug180.go diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index f51839f49b2..63dbd68354b 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -534,28 +534,37 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx) void cgen_div(int op, Node *nl, Node *nr, Node *res) { - Node ax, dx, oldax, olddx; + Node ax, dx, oldax, olddx, n1, n2; int rax, rdx; - if(nl->ullman >= UINF || nr->ullman >= UINF) - fatal("cgen_div UINF"); + if(nl->ullman >= UINF) { + tempname(&n1, nl->type); + cgen(nl, &n1); + nl = &n1; + } + if(nr->ullman >= UINF) { + tempname(&n2, nr->type); + cgen(nr, &n2); + nr = &n2; + } rax = reg[D_AX]; rdx = reg[D_DX]; - + nodreg(&ax, types[TINT64], D_AX); nodreg(&dx, types[TINT64], D_DX); regalloc(&ax, nl->type, &ax); regalloc(&dx, nl->type, &dx); // save current ax and dx if they are live + // and not the destination memset(&oldax, 0, sizeof oldax); memset(&olddx, 0, sizeof olddx); - if(rax > 0) { + if(rax > 0 && !samereg(&ax, res)) { regalloc(&oldax, nl->type, N); gmove(&ax, &oldax); } - if(rdx > 0) { + if(rdx > 0 && !samereg(&dx, res)) { regalloc(&olddx, nl->type, N); gmove(&dx, &olddx); } @@ -565,11 +574,11 @@ cgen_div(int op, Node *nl, Node *nr, Node *res) regfree(&ax); regfree(&dx); - if(rax > 0) { + if(oldax.op != 0) { gmove(&oldax, &ax); regfree(&oldax); } - if(rdx > 0) { + if(olddx.op != 0) { gmove(&olddx, &dx); regfree(&olddx); } @@ -584,8 +593,8 @@ cgen_div(int op, Node *nl, Node *nr, Node *res) void cgen_shift(int op, Node *nl, Node *nr, Node *res) { - Node n1, n2, n3; - int a; + Node n1, n2, n3, n4, n5, cx, oldcx; + int a, rcx; Prog *p1; uvlong sc; @@ -607,11 +616,33 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) goto ret; } + if(nl->ullman >= UINF) { + tempname(&n4, nl->type); + cgen(nl, &n4); + nl = &n4; + } + if(nr->ullman >= UINF) { + tempname(&n5, nr->type); + cgen(nr, &n5); + nr = &n5; + } + + rcx = reg[D_CX]; nodreg(&n1, types[TUINT32], D_CX); regalloc(&n1, nr->type, &n1); // to hold the shift type in CX regalloc(&n3, types[TUINT64], &n1); // to clear high bits of CX - regalloc(&n2, nl->type, res); + nodreg(&cx, types[TUINT64], D_CX); + memset(&oldcx, 0, sizeof oldcx); + if(rcx > 0 && !samereg(&cx, res)) { + regalloc(&oldcx, types[TUINT64], N); + gmove(&cx, &oldcx); + } + + if(samereg(&cx, res)) + regalloc(&n2, nl->type, N); + else + regalloc(&n2, nl->type, res); if(nl->ullman >= nr->ullman) { cgen(nl, &n2); cgen(nr, &n1); @@ -637,6 +668,11 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) patch(p1, pc); gins(a, &n1, &n2); + if(oldcx.op != 0) { + gmove(&oldcx, &cx); + regfree(&oldcx); + } + gmove(&n2, res); regfree(&n1); diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go index 41e6736e836..2457d8561ad 100644 --- a/src/pkg/time/time_test.go +++ b/src/pkg/time/time_test.go @@ -60,8 +60,8 @@ func TestSecondsToUTC(t *testing.T) { } if !same(tm, golden) { t.Errorf("SecondsToUTC(%d):", sec); - t.Errorf(" want=%v", *golden); - t.Errorf(" have=%v", *tm); + t.Errorf(" want=%+v", *golden); + t.Errorf(" have=%+v", *tm); } } } @@ -77,8 +77,8 @@ func TestSecondsToLocalTime(t *testing.T) { } if !same(tm, golden) { t.Errorf("SecondsToLocalTime(%d):", sec); - t.Errorf(" want=%v", *golden); - t.Errorf(" have=%v", *tm); + t.Errorf(" want=%+v", *golden); + t.Errorf(" have=%+v", *tm); } } } diff --git a/test/fixedbugs/bug180.go b/test/fixedbugs/bug180.go new file mode 100644 index 00000000000..e2934486058 --- /dev/null +++ b/test/fixedbugs/bug180.go @@ -0,0 +1,17 @@ +// $G $D/$F.go && $L $F.$A && ./$A.out + +// Copyright 2009 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. + +package main + +func shift(x int) int { + return 1<<(1<<(1<<(uint(x)))); +} + +func main() { + if n := shift(2); n != 1<<(1<<(1<<2)) { + panicln("bad shift", n); + } +}