summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2004-09-18 18:04:01 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2004-09-18 18:04:01 (GMT)
commit9a4d29bde94d4183ffa1066d4da062e4a2a4e7f2 (patch)
treef856c641275ae74cdc66a55b773dbdb3864eab63 /generic
parent1ad855e68849daccd5c7439bc910d5c694af4227 (diff)
downloadtcl-9a4d29bde94d4183ffa1066d4da062e4a2a4e7f2.zip
tcl-9a4d29bde94d4183ffa1066d4da062e4a2a4e7f2.tar.gz
tcl-9a4d29bde94d4183ffa1066d4da062e4a2a4e7f2.tar.bz2
Make sure large shifts shift for real. [Bug 868467]
Diffstat (limited to 'generic')
-rw-r--r--generic/tclExecute.c79
1 files changed, 72 insertions, 7 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index b965944..a5dd499 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclExecute.c,v 1.147 2004/09/11 13:45:15 msofer Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.148 2004/09/18 18:04:04 dkf Exp $
*/
#ifdef STDC_HEADERS
@@ -3600,11 +3600,42 @@ TclExecuteByteCode(interp, codePtr)
#ifdef TCL_COMPILE_DEBUG
w2 = Tcl_LongAsWide(i2);
#endif /* TCL_COMPILE_DEBUG */
- wResult = w << i2;
+ wResult = w;
+ /*
+ * Shift in steps when the shift gets large to prevent
+ * annoying compiler/processor bugs. [Bug 868467]
+ */
+ if (i2 >= 64) {
+ wResult = Tcl_LongAsWide(0);
+ } else if (i2 > 60) {
+ wResult = w << 30;
+ wResult <<= 30;
+ wResult <<= i2-60;
+ } else if (i2 > 30) {
+ wResult = w << 30;
+ wResult <<= i2-30;
+ } else {
+ wResult = w << i2;
+ }
doWide = 1;
break;
}
- iResult = i << i2;
+ /*
+ * Shift in steps when the shift gets large to prevent
+ * annoying compiler/processor bugs. [Bug 868467]
+ */
+ if (i2 >= 64) {
+ iResult = 0;
+ } else if (i2 > 60) {
+ iResult = i << 30;
+ iResult <<= 30;
+ iResult <<= i2-60;
+ } else if (i2 > 30) {
+ iResult = i << 30;
+ iResult <<= i2-30;
+ } else {
+ iResult = i << i2;
+ }
break;
case INST_RSHIFT:
/*
@@ -3621,17 +3652,51 @@ TclExecuteByteCode(interp, codePtr)
w2 = Tcl_LongAsWide(i2);
#endif /* TCL_COMPILE_DEBUG */
if (w < 0) {
- wResult = ~((~w) >> i2);
+ wResult = ~w;
+ }
+ /*
+ * Shift in steps when the shift gets large to prevent
+ * annoying compiler/processor bugs. [Bug 868467]
+ */
+ if (i2 >= 64) {
+ wResult = Tcl_LongAsWide(0);
+ } else if (i2 > 60) {
+ wResult <<= 30;
+ wResult <<= 30;
+ wResult <<= i2-60;
+ } else if (i2 > 30) {
+ wResult <<= 30;
+ wResult <<= i2-30;
} else {
- wResult = w >> i2;
+ wResult <<= i2;
+ }
+ if (w < 0) {
+ wResult = ~wResult;
}
doWide = 1;
break;
}
if (i < 0) {
- iResult = ~((~i) >> i2);
+ iResult = ~i;
+ }
+ /*
+ * Shift in steps when the shift gets large to prevent
+ * annoying compiler/processor bugs. [Bug 868467]
+ */
+ if (i2 >= 64) {
+ iResult = 0;
+ } else if (i2 > 60) {
+ iResult <<= 30;
+ iResult <<= 30;
+ iResult <<= i2-60;
+ } else if (i2 > 30) {
+ iResult <<= 30;
+ iResult <<= i2-30;
} else {
- iResult = i >> i2;
+ iResult <<= i2;
+ }
+ if (i < 0) {
+ iResult = ~iResult;
}
break;
case INST_BITOR: