diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2004-09-18 18:04:01 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2004-09-18 18:04:01 (GMT) |
commit | 9a4d29bde94d4183ffa1066d4da062e4a2a4e7f2 (patch) | |
tree | f856c641275ae74cdc66a55b773dbdb3864eab63 /generic | |
parent | 1ad855e68849daccd5c7439bc910d5c694af4227 (diff) | |
download | tcl-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.c | 79 |
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: |