@@ -138,6 +138,40 @@ impl Invariant {
138138 }
139139}
140140
141+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
142+ pub enum SpecialObjectType {
143+ VMCore = 1 ,
144+ CBase = 2 ,
145+ ConstBase = 3 ,
146+ }
147+
148+ impl From < u32 > for SpecialObjectType {
149+ fn from ( value : u32 ) -> Self {
150+ match value {
151+ 1 => SpecialObjectType :: VMCore ,
152+ 2 => SpecialObjectType :: CBase ,
153+ 3 => SpecialObjectType :: ConstBase ,
154+ _ => panic ! ( "Invalid special object type: {}" , value) ,
155+ }
156+ }
157+ }
158+
159+ impl From < SpecialObjectType > for u32 {
160+ fn from ( special_type : SpecialObjectType ) -> Self {
161+ special_type as u32
162+ }
163+ }
164+
165+ impl std:: fmt:: Display for SpecialObjectType {
166+ fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
167+ match self {
168+ SpecialObjectType :: VMCore => write ! ( f, "VMCore" ) ,
169+ SpecialObjectType :: CBase => write ! ( f, "CBase" ) ,
170+ SpecialObjectType :: ConstBase => write ! ( f, "ConstBase" ) ,
171+ }
172+ }
173+ }
174+
141175/// Print adaptor for [`Invariant`]. See [`PtrPrintMap`].
142176pub struct InvariantPrinter < ' a > {
143177 inner : Invariant ,
@@ -365,6 +399,9 @@ pub enum Insn {
365399 StringCopy { val : InsnId } ,
366400 StringIntern { val : InsnId } ,
367401
402+ /// Put special object (VMCORE, CBASE, etc.) based on value_type
403+ PutSpecialObject { value_type : SpecialObjectType } ,
404+
368405 /// Call `to_a` on `val` if the method is defined, or make a new array `[val]` otherwise.
369406 ToArray { val : InsnId , state : InsnId } ,
370407 /// Call `to_a` on `val` if the method is defined, or make a new array `[val]` otherwise. If we
@@ -482,6 +519,7 @@ impl Insn {
482519 match self {
483520 Insn :: Const { .. } => false ,
484521 Insn :: Param { .. } => false ,
522+ Insn :: PutSpecialObject { .. } => false ,
485523 Insn :: StringCopy { .. } => false ,
486524 Insn :: NewArray { .. } => false ,
487525 Insn :: NewHash { .. } => false ,
@@ -630,6 +668,9 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
630668 Insn :: ArrayExtend { left, right, .. } => write ! ( f, "ArrayExtend {left}, {right}" ) ,
631669 Insn :: ArrayPush { array, val, .. } => write ! ( f, "ArrayPush {array}, {val}" ) ,
632670 Insn :: SideExit { .. } => write ! ( f, "SideExit" ) ,
671+ Insn :: PutSpecialObject { value_type } => {
672+ write ! ( f, "PutSpecialObject {}" , value_type)
673+ }
633674 insn => { write ! ( f, "{insn:?}" ) }
634675 }
635676 }
@@ -943,6 +984,7 @@ impl Function {
943984 FixnumGe { left, right } => FixnumGe { left : find ! ( * left) , right : find ! ( * right) } ,
944985 FixnumLt { left, right } => FixnumLt { left : find ! ( * left) , right : find ! ( * right) } ,
945986 FixnumLe { left, right } => FixnumLe { left : find ! ( * left) , right : find ! ( * right) } ,
987+ PutSpecialObject { value_type } => PutSpecialObject { value_type : * value_type } ,
946988 SendWithoutBlock { self_val, call_info, cd, args, state } => SendWithoutBlock {
947989 self_val : find ! ( * self_val) ,
948990 call_info : call_info. clone ( ) ,
@@ -1056,6 +1098,7 @@ impl Function {
10561098 Insn :: FixnumLe { .. } => types:: BoolExact ,
10571099 Insn :: FixnumGt { .. } => types:: BoolExact ,
10581100 Insn :: FixnumGe { .. } => types:: BoolExact ,
1101+ Insn :: PutSpecialObject { .. } => types:: BasicObject ,
10591102 Insn :: SendWithoutBlock { .. } => types:: BasicObject ,
10601103 Insn :: SendWithoutBlockDirect { .. } => types:: BasicObject ,
10611104 Insn :: Send { .. } => types:: BasicObject ,
@@ -1542,7 +1585,8 @@ impl Function {
15421585 necessary[ insn_id. 0 ] = true ;
15431586 match self . find ( insn_id) {
15441587 Insn :: Const { .. } | Insn :: Param { .. }
1545- | Insn :: PatchPoint ( ..) | Insn :: GetConstantPath { .. } =>
1588+ | Insn :: PatchPoint ( ..) | Insn :: GetConstantPath { .. }
1589+ | Insn :: PutSpecialObject { .. } =>
15461590 { }
15471591 Insn :: ArrayMax { elements, state }
15481592 | Insn :: NewArray { elements, state } => {
@@ -2074,6 +2118,10 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
20742118 YARVINSN_nop => { } ,
20752119 YARVINSN_putnil => { state. stack_push ( fun. push_insn ( block, Insn :: Const { val : Const :: Value ( Qnil ) } ) ) ; } ,
20762120 YARVINSN_putobject => { state. stack_push ( fun. push_insn ( block, Insn :: Const { val : Const :: Value ( get_arg ( pc, 0 ) ) } ) ) ; } ,
2121+ YARVINSN_putspecialobject => {
2122+ let value_type = SpecialObjectType :: from ( get_arg ( pc, 0 ) . as_u32 ( ) ) ;
2123+ state. stack_push ( fun. push_insn ( block, Insn :: PutSpecialObject { value_type } ) ) ;
2124+ }
20772125 YARVINSN_putstring | YARVINSN_putchilledstring => {
20782126 // TODO(max): Do something different for chilled string
20792127 let val = fun. push_insn ( block, Insn :: Const { val : Const :: Value ( get_arg ( pc, 0 ) ) } ) ;
@@ -3806,6 +3854,25 @@ mod tests {
38063854 "# ] ] ) ;
38073855 }
38083856
3857+ #[ test]
3858+ fn test_putspecialobject_callee ( ) {
3859+ eval ( "
3860+ def test
3861+ alias aliased __callee__
3862+ end
3863+ " ) ;
3864+ assert_method_hir_with_opcode ( "test" , YARVINSN_putspecialobject , expect ! [ [ r#"
3865+ fn test:
3866+ bb0(v0:BasicObject):
3867+ v2:BasicObject = PutSpecialObject VMCore
3868+ v3:BasicObject = PutSpecialObject CBase
3869+ v4:StaticSymbol[VALUE(0x1000)] = Const Value(VALUE(0x1000))
3870+ v5:StaticSymbol[VALUE(0x1008)] = Const Value(VALUE(0x1008))
3871+ v7:BasicObject = SendWithoutBlock v2, :core#set_method_alias, v3, v4, v5
3872+ Return v7
3873+ "# ] ] ) ;
3874+ }
3875+
38093876 #[ test]
38103877 fn test_branchnil ( ) {
38113878 eval ( "
0 commit comments