@@ -392,6 +392,11 @@ pub enum Insn {
392392 Defined { op_type : usize , obj : VALUE , pushval : VALUE , v : InsnId } ,
393393 GetConstantPath { ic : * const iseq_inline_constant_cache } ,
394394
395+ /// Get a global variable named `id`
396+ GetGlobal { id : ID , state : InsnId } ,
397+ /// Set a global variable named `id` to `val`
398+ SetGlobal { id : ID , val : InsnId , state : InsnId } ,
399+
395400 //NewObject?
396401 /// Get an instance variable `id` from `self_val`
397402 GetIvar { self_val : InsnId , id : ID , state : InsnId } ,
@@ -459,7 +464,7 @@ impl Insn {
459464 Insn :: ArraySet { .. } | Insn :: Snapshot { .. } | Insn :: Jump ( _)
460465 | Insn :: IfTrue { .. } | Insn :: IfFalse { .. } | Insn :: Return { .. }
461466 | Insn :: PatchPoint { .. } | Insn :: SetIvar { .. } | Insn :: ArrayExtend { .. }
462- | Insn :: ArrayPush { .. } | Insn :: SideExit { .. } => false ,
467+ | Insn :: ArrayPush { .. } | Insn :: SideExit { .. } | Insn :: SetGlobal { .. } => false ,
463468 _ => true ,
464469 }
465470 }
@@ -625,6 +630,8 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
625630 Insn :: DefinedIvar { self_val, id, .. } => write ! ( f, "DefinedIvar {self_val}, :{}" , id. contents_lossy( ) . into_owned( ) ) ,
626631 Insn :: GetIvar { self_val, id, .. } => write ! ( f, "GetIvar {self_val}, :{}" , id. contents_lossy( ) . into_owned( ) ) ,
627632 Insn :: SetIvar { self_val, id, val, .. } => write ! ( f, "SetIvar {self_val}, :{}, {val}" , id. contents_lossy( ) . into_owned( ) ) ,
633+ Insn :: GetGlobal { id, .. } => write ! ( f, "GetGlobal :{}" , id. contents_lossy( ) . into_owned( ) ) ,
634+ Insn :: SetGlobal { id, val, .. } => write ! ( f, "SetGlobal :{}, {val}" , id. contents_lossy( ) . into_owned( ) ) ,
628635 Insn :: ToArray { val, .. } => write ! ( f, "ToArray {val}" ) ,
629636 Insn :: ToNewArray { val, .. } => write ! ( f, "ToNewArray {val}" ) ,
630637 Insn :: ArrayExtend { left, right, .. } => write ! ( f, "ArrayExtend {left}, {right}" ) ,
@@ -982,6 +989,8 @@ impl Function {
982989 }
983990 & NewRange { low, high, flag, state } => NewRange { low : find ! ( low) , high : find ! ( high) , flag, state : find ! ( state) } ,
984991 ArrayMax { elements, state } => ArrayMax { elements : find_vec ! ( * elements) , state : find ! ( * state) } ,
992+ & GetGlobal { id, state } => GetGlobal { id, state } ,
993+ & SetGlobal { id, val, state } => SetGlobal { id, val : find ! ( val) , state } ,
985994 & GetIvar { self_val, id, state } => GetIvar { self_val : find ! ( self_val) , id, state } ,
986995 & SetIvar { self_val, id, val, state } => SetIvar { self_val : find ! ( self_val) , id, val, state } ,
987996 & ToArray { val, state } => ToArray { val : find ! ( val) , state } ,
@@ -1012,7 +1021,7 @@ impl Function {
10121021 assert ! ( self . insns[ insn. 0 ] . has_output( ) ) ;
10131022 match & self . insns [ insn. 0 ] {
10141023 Insn :: Param { .. } => unimplemented ! ( "params should not be present in block.insns" ) ,
1015- Insn :: ArraySet { .. } | Insn :: Snapshot { .. } | Insn :: Jump ( _)
1024+ Insn :: SetGlobal { .. } | Insn :: ArraySet { .. } | Insn :: Snapshot { .. } | Insn :: Jump ( _)
10161025 | Insn :: IfTrue { .. } | Insn :: IfFalse { .. } | Insn :: Return { .. }
10171026 | Insn :: PatchPoint { .. } | Insn :: SetIvar { .. } | Insn :: ArrayExtend { .. }
10181027 | Insn :: ArrayPush { .. } | Insn :: SideExit { .. } =>
@@ -1063,6 +1072,7 @@ impl Function {
10631072 Insn :: DefinedIvar { .. } => types:: BasicObject ,
10641073 Insn :: GetConstantPath { .. } => types:: BasicObject ,
10651074 Insn :: ArrayMax { .. } => types:: BasicObject ,
1075+ Insn :: GetGlobal { .. } => types:: BasicObject ,
10661076 Insn :: GetIvar { .. } => types:: BasicObject ,
10671077 Insn :: ToNewArray { .. } => types:: ArrayExact ,
10681078 Insn :: ToArray { .. } => types:: ArrayExact ,
@@ -1568,7 +1578,8 @@ impl Function {
15681578 | Insn :: Test { val }
15691579 | Insn :: IsNil { val } =>
15701580 worklist. push_back ( val) ,
1571- Insn :: GuardType { val, state, .. }
1581+ Insn :: SetGlobal { val, state, .. }
1582+ | Insn :: GuardType { val, state, .. }
15721583 | Insn :: GuardBitEquals { val, state, .. }
15731584 | Insn :: ToArray { val, state }
15741585 | Insn :: ToNewArray { val, state } => {
@@ -1635,6 +1646,7 @@ impl Function {
16351646 worklist. push_back ( val) ;
16361647 worklist. push_back ( state) ;
16371648 }
1649+ Insn :: GetGlobal { state, .. } |
16381650 Insn :: SideExit { state } => worklist. push_back ( state) ,
16391651 }
16401652 }
@@ -2435,6 +2447,18 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
24352447 let send = fun. push_insn ( block, Insn :: Send { self_val : recv, call_info : CallInfo { method_name } , cd, blockiseq, args, state : exit_id } ) ;
24362448 state. stack_push ( send) ;
24372449 }
2450+ YARVINSN_getglobal => {
2451+ let id = ID ( get_arg ( pc, 0 ) . as_u64 ( ) ) ;
2452+ let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
2453+ let result = fun. push_insn ( block, Insn :: GetGlobal { id, state : exit_id } ) ;
2454+ state. stack_push ( result) ;
2455+ }
2456+ YARVINSN_setglobal => {
2457+ let id = ID ( get_arg ( pc, 0 ) . as_u64 ( ) ) ;
2458+ let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
2459+ let val = state. stack_pop ( ) ?;
2460+ fun. push_insn ( block, Insn :: SetGlobal { id, val, state : exit_id } ) ;
2461+ }
24382462 YARVINSN_getinstancevariable => {
24392463 let id = ID ( get_arg ( pc, 0 ) . as_u64 ( ) ) ;
24402464 // ic is in arg 1
@@ -3711,6 +3735,35 @@ mod tests {
37113735 "# ] ] ) ;
37123736 }
37133737
3738+ #[ test]
3739+ fn test_setglobal ( ) {
3740+ eval ( "
3741+ def test = $foo = 1
3742+ test
3743+ " ) ;
3744+ assert_method_hir_with_opcode ( "test" , YARVINSN_setglobal , expect ! [ [ r#"
3745+ fn test:
3746+ bb0(v0:BasicObject):
3747+ v2:Fixnum[1] = Const Value(1)
3748+ SetGlobal :$foo, v2
3749+ Return v2
3750+ "# ] ] ) ;
3751+ }
3752+
3753+ #[ test]
3754+ fn test_getglobal ( ) {
3755+ eval ( "
3756+ def test = $foo
3757+ test
3758+ " ) ;
3759+ assert_method_hir_with_opcode ( "test" , YARVINSN_getglobal , expect ! [ [ r#"
3760+ fn test:
3761+ bb0(v0:BasicObject):
3762+ v3:BasicObject = GetGlobal :$foo
3763+ Return v3
3764+ "# ] ] ) ;
3765+ }
3766+
37143767 #[ test]
37153768 fn test_splatarray_mut ( ) {
37163769 eval ( "
0 commit comments