Quellcode durchsuchen

[eval] deal with bit shifts > 31

closes #10752
Simon Krajewski vor 3 Jahren
Ursprung
Commit
45db4d93b5

+ 3 - 1
src/core/globals.ml

@@ -155,4 +155,6 @@ module MessageKind = struct
 		| DKMissingFields -> 7
 end
 
-type compiler_message = string * pos * MessageKind.t * MessageSeverity.t
+type compiler_message = string * pos * MessageKind.t * MessageSeverity.t
+
+let i32_31 = Int32.of_int 31

+ 12 - 3
src/macro/eval/evalMisc.ml

@@ -248,15 +248,24 @@ let op_xor p v1 v2 = match v1,v2 with
 	| _ -> invalid_binop OpXor v1 v2 p
 
 let op_shl p v1 v2 = match v1,v2 with
-	| VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_left i1 (Int32.to_int i2))
+	| VInt32 i1,VInt32 i2 ->
+		let i2 = Int32.logand i2 i32_31 in
+		let i2 = Int32.to_int i2 in
+		vint32 (Int32.shift_left i1 i2)
 	| _ -> invalid_binop OpShl v1 v2 p
 
 let op_shr p v1 v2 = match v1,v2 with
-	| VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_right i1 (Int32.to_int i2))
+	| VInt32 i1,VInt32 i2 ->
+		let i2 = Int32.logand i2 i32_31 in
+		let i2 = Int32.to_int i2 in
+		vint32 (Int32.shift_right i1 i2)
 	| _ -> invalid_binop OpShr v1 v2 p
 
 let op_ushr p v1 v2 = match v1,v2 with
-	| VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_right_logical i1 (Int32.to_int i2))
+	| VInt32 i1,VInt32 i2 ->
+		let i2 = Int32.logand i2 i32_31 in
+		let i2 = Int32.to_int i2 in
+		vint32 (Int32.shift_right_logical i1 i2)
 	| _ -> invalid_binop OpUShr v1 v2 p
 
 let op_mod p v1 v2 = match v1,v2 with

+ 3 - 3
src/optimization/optimizerTexpr.ml

@@ -136,9 +136,9 @@ let optimize_binop e op e1 e2 =
 		| OpAnd -> opt Int32.logand
 		| OpOr -> opt Int32.logor
 		| OpXor -> opt Int32.logxor
-		| OpShl -> opt (fun a b -> Int32.shift_left a (Int32.to_int b))
-		| OpShr -> opt (fun a b -> Int32.shift_right a (Int32.to_int b))
-		| OpUShr -> opt (fun a b -> Int32.shift_right_logical a (Int32.to_int b))
+		| OpShl -> opt (fun a b -> Int32.shift_left a (Int32.to_int (Int32.logand b i32_31)))
+		| OpShr -> opt (fun a b -> Int32.shift_right a (Int32.to_int (Int32.logand b i32_31)))
+		| OpUShr -> opt (fun a b -> Int32.shift_right_logical a (Int32.to_int (Int32.logand b i32_31)))
 		| OpEq -> ebool (=)
 		| OpNotEq -> ebool (<>)
 		| OpGt -> ebool (>)

+ 14 - 0
tests/unit/src/unit/issues/Issue10752.hx

@@ -0,0 +1,14 @@
+package unit.issues;
+
+class Issue10752 extends Test {
+	function shl(x, y)
+		return x << y;
+
+	function test() {
+		eq(2, shl(1, 33));
+		eq(2, 1 << 33);
+
+		eq(1 >> 1, 1 >> 33);
+		eq(1 >>> 1, 1 >>> 33);
+	}
+}