From 76e1f260cdceb3866ed6b7b4b8d893c5d570a060 Mon Sep 17 00:00:00 2001 From: David Pichardie Date: Tue, 29 Oct 2024 09:57:49 -0700 Subject: [PATCH] [inferpython][end of 3.10 upgrade] adding ROT_N opcode Summary: this is also a good excuse to factor a bit other opcodes Reviewed By: skcho Differential Revision: D65051170 Privacy Context Container: L1208441 fbshipit-source-id: bf7d9085e66f0225accf437041eab57f010e2da1 --- infer/src/python/PyIR.ml | 39 +++++++++------- infer/src/python/unit/PyIRTestMatch.ml | 65 +++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/infer/src/python/PyIR.ml b/infer/src/python/PyIR.ml index 1c2a34d8cc..b33ff8e313 100644 --- a/infer/src/python/PyIR.ml +++ b/infer/src/python/PyIR.ml @@ -1038,6 +1038,20 @@ module State = struct (exps, st) + let rot_n st n = + let {loc; stack} = st in + if n <= 0 then L.die InternalError "rot_n need a positive argument" + else if List.length stack < n then + let msg = F.asprintf "rot_n with n = %d is impossible" n in + Error (L.InternalError, loc, Error.EmptyStack msg) + else + let top_n, rest = List.split_n stack n in + let top = List.hd_exn top_n in + let top_1_n = List.tl_exn top_n in + let stack = top_1_n @ [top] @ rest in + Ok {st with stack} + + (* TODO: use the [exn_handlers] info to mark statement that can possibly raise * something *) let push_stmt ({stmts; loc} as st) stmt = {st with stmts= (loc, stmt) :: stmts} @@ -1899,28 +1913,16 @@ let parse_bytecode st ({FFI.Code.co_consts; co_names; co_varnames} as code) | "POP_BLOCK" -> Ok (st, None) | "ROT_TWO" -> - let* tos0, st = State.pop st in - let* tos1, st = State.pop st in - let st = State.push_symbol st tos0 in - let st = State.push_symbol st tos1 in + let* st = State.rot_n st 2 in Ok (st, None) | "ROT_THREE" -> - let* tos0, st = State.pop st in - let* tos1, st = State.pop st in - let* tos2, st = State.pop st in - let st = State.push_symbol st tos0 in - let st = State.push_symbol st tos2 in - let st = State.push_symbol st tos1 in + let* st = State.rot_n st 3 in Ok (st, None) | "ROT_FOUR" -> - let* tos0, st = State.pop st in - let* tos1, st = State.pop st in - let* tos2, st = State.pop st in - let* tos3, st = State.pop st in - let st = State.push_symbol st tos0 in - let st = State.push_symbol st tos3 in - let st = State.push_symbol st tos2 in - let st = State.push_symbol st tos1 in + let* st = State.rot_n st 4 in + Ok (st, None) + | "ROT_N" -> + let* st = State.rot_n st arg in Ok (st, None) | "SETUP_WITH" -> let* context_manager, st = State.pop_and_cast st in @@ -2236,6 +2238,7 @@ let get_successors_offset {FFI.Instruction.opname; arg} = | "ROT_TWO" | "ROT_THREE" | "ROT_FOUR" + | "ROT_N" | "SETUP_WITH" | "SETUP_FINALLY" | "POP_FINALLY" diff --git a/infer/src/python/unit/PyIRTestMatch.ml b/infer/src/python/unit/PyIRTestMatch.ml index 43ce2fb0a4..1181cacd61 100644 --- a/infer/src/python/unit/PyIRTestMatch.ml +++ b/infer/src/python/unit/PyIRTestMatch.ml @@ -721,5 +721,66 @@ def main(): |} in PyIR.test source ; - [%expect {| - IR error: Unsupported opcode: ROT_N |}] + [%expect + {| + module dummy: + + function toplevel(): + b0: + n0 <- $MakeFunction["main", "dummy.main", None, None, None, None] + TOPLEVEL[main] <- n0 + return None + + + function dummy.main(a, b, c): + b0: + n0 <- GLOBAL[o] + if $MatchSequence(n0) then jmp b1 else jmp b9(n0) + + b1: + n1 <- $Compare.eq($GetLen(n0), 1, None) + if n1 then jmp b2 else jmp b9(n0) + + b2: + n2 <- GLOBAL[ast] + n3 <- n2.Cons1 + n4 <- $MatchClass(n0[0], n3, 2, $BuildTuple()) + if $BoolOfMatchClass(n4) then jmp b3 else jmp b9($AttributesOfMatchClass(n4)) + + b3: + n5 <- $AttributesOfMatchClass(n4)[1] + n6 <- GLOBAL[ast] + n7 <- n6.Const2 + n8 <- $MatchClass(n5, n7, 1, $BuildTuple()) + if $BoolOfMatchClass(n8) then jmp b4 else jmp b8 + + b4: + n9 <- $AttributesOfMatchClass(n8)[0] + if $MatchSequence(n9) then jmp b5 else jmp b7 + + b5: + n10 <- $Compare.eq($GetLen(n9), 3, None) + if n10 then jmp b6 else jmp b7 + + b6: + n13 <- $AttributesOfMatchClass(n8) + n14 <- $AttributesOfMatchClass(n4) + LOCAL[a] <- n9[0] + LOCAL[b] <- n9[1] + LOCAL[c] <- n9[2] + n15 <- GLOBAL[action] + n16 <- LOCAL[a] + n17 <- LOCAL[b] + n18 <- LOCAL[c] + n19 <- $Call(n15, n16, n17, n18, None) + return None + + b7: + jmp b8 + + b8: + n11 <- $AttributesOfMatchClass(n8) + jmp b9($AttributesOfMatchClass(n4)) + + b9(n12): + return None |}]