summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-random
diff options
context:
space:
mode:
authorRory OConnell <[email protected]>2020-06-29 14:25:59 -0700
committerRory OConnell <[email protected]>2020-06-29 14:25:59 -0700
commit3cf48713a2d39e624e9b755bfcfae6fb51a861c9 (patch)
tree6c767dd06de89ca06f6690b0bd2d1200e5b9d004 /mrbgems/mruby-random
parent6d5652114e2105b1e9d81b353b3c9335ca3b4dd5 (diff)
downloadmruby-3cf48713a2d39e624e9b755bfcfae6fb51a861c9.tar.gz
mruby-3cf48713a2d39e624e9b755bfcfae6fb51a861c9.zip
Work around more MSC optimzer bugs
Diffstat (limited to 'mrbgems/mruby-random')
-rw-r--r--mrbgems/mruby-random/src/random.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c
index 55bea5713..10c81b946 100644
--- a/mrbgems/mruby-random/src/random.c
+++ b/mrbgems/mruby-random/src/random.c
@@ -220,12 +220,30 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary)
/*
* MSC compiler bug generating invalid instructions with optimization
- * enabled
+ * enabled. MSC errantly uses a hardcoded value with optimizations on
+ * when using a fixed value from a union.
+ * Creating a temp volatile variable and reassigning back to the original
+ * value tricks the compiler to not perform this optimization;
*/
#if defined _MSC_VER && _MSC_VER >= 1923
- volatile mrb_value rr;
- rr = r;
- r = rr;
+ /* C++ will not cast away volatile easily, so we cannot do something like
+ * volatile mrb_value rr = r; r = (mrb_value)rr; with C++.
+ * That cast does work with C.
+ * We also have to trick the compiler to not optimize away the const_cast entirely
+ * by creating and manipulating an intermediate volatile pointer.
+ */
+ volatile mrb_value *v_r;
+ volatile mrb_int ii;
+ mrb_value *p_r;
+ v_r = &r;
+ ii = 2;
+ v_r = v_r + 2;
+#if defined __cplusplus
+ p_r = const_cast<mrb_value*>(v_r - ii);
+#else
+ p_r = (mrb_value*)v_r - ii;
+#endif
+ r = *p_r;
#endif
if (RARRAY_LEN(ary) > 1) {