@@ -18,7 +18,7 @@ pub enum CmpOperator {
1818}
1919
2020impl CmpOperator {
21- pub fn from_bytecode ( n : u32 ) -> Self {
21+ pub fn from_bytecode ( n : usize ) -> Self {
2222 match n {
2323 0 => CmpOperator :: Lt ,
2424 1 => CmpOperator :: Leq ,
@@ -69,9 +69,10 @@ pub enum Instruction {
6969 LoadFast ( usize ) ,
7070 StoreFast ( usize ) ,
7171 LoadGlobal ( usize ) ,
72- CallFunction ( usize , usize ) , // nb_args, nb_kwargs
73- RaiseVarargs ( u16 ) ,
74- MakeFunction ( usize , usize , usize ) , // nb_default_args, nb_default_kwargs, nb_annot
72+ CallFunction ( usize , bool ) , // nb_args + nb_kwargs, has_kwargs
73+ RaiseVarargs ( usize ) ,
74+ MakeFunction { has_defaults : bool , has_kwdefaults : bool , has_annotations : bool , has_closure : bool } ,
75+ BuildConstKeyMap ( usize ) ,
7576}
7677
7778#[ derive( Debug ) ]
@@ -123,55 +124,65 @@ impl<'a, I> Iterator for InstructionDecoder<I> where I: Iterator<Item=&'a u8> {
123124 self . pending_nops -= 1 ;
124125 return Some ( Instruction :: Nop )
125126 } ;
126- self . bytestream . next ( ) . map ( |opcode| {
127- match * opcode {
128- 1 => Instruction :: PopTop ,
129- 4 => Instruction :: DupTop ,
130- 25 => Instruction :: BinarySubscr ,
131- 68 => Instruction :: GetIter ,
132- 71 => Instruction :: LoadBuildClass ,
133- 83 => Instruction :: ReturnValue ,
134- 87 => Instruction :: PopBlock ,
135- 88 => Instruction :: EndFinally ,
136- 89 => Instruction :: PopExcept ,
137- 90 => Instruction :: StoreName ( self . read_argument ( ) as usize ) ,
138- 93 => Instruction :: ForIter ( self . read_argument ( ) as usize ) ,
139- 95 => Instruction :: StoreAttr ( self . read_argument ( ) as usize ) ,
140- 97 => Instruction :: StoreGlobal ( self . read_argument ( ) as usize ) ,
141- 100 => Instruction :: LoadConst ( self . read_argument ( ) as usize ) ,
142- 101 => Instruction :: LoadName ( self . read_argument ( ) as usize ) ,
143- 102 => Instruction :: BuildTuple ( self . read_argument ( ) as usize ) ,
144- 106 => Instruction :: LoadAttr ( self . read_argument ( ) as usize ) ,
145- 107 => Instruction :: CompareOp ( CmpOperator :: from_bytecode ( self . read_argument ( ) ) ) ,
146- 110 => Instruction :: JumpForward ( self . read_argument ( ) as usize + 2 ) , // +2, because JumpForward takes 3 bytes, and the relative address is computed from the next instruction.
147- 113 => Instruction :: JumpAbsolute ( self . read_argument ( ) as usize ) ,
148- 114 => Instruction :: PopJumpIfFalse ( self . read_argument ( ) as usize ) ,
149- 116 => Instruction :: LoadGlobal ( self . read_argument ( ) as usize ) ,
150- 120 => Instruction :: SetupLoop ( self . read_argument ( ) as usize + 2 ) ,
151- 121 => Instruction :: SetupExcept ( self . read_argument ( ) as usize + 2 ) ,
152- 124 => Instruction :: LoadFast ( self . read_argument ( ) as usize ) ,
153- 125 => Instruction :: StoreFast ( self . read_argument ( ) as usize ) ,
154- 130 => Instruction :: RaiseVarargs ( self . read_argument ( ) as u16 ) ,
155- 131 => Instruction :: CallFunction ( self . read_byte ( ) as usize , self . read_byte ( ) as usize ) ,
156- 132 => {
157- let arg = self . read_argument ( ) ;
158- let nb_pos = arg & 0xFF ;
159- let nb_kw = ( arg >> 8 ) & 0xFF ;
160- //let nb_annot = (arg >> 16) & 0x7FF; // TODO
161- let nb_annot = 0 ;
162- Instruction :: MakeFunction ( nb_pos as usize , nb_kw as usize , nb_annot as usize )
163- } ,
164- 144 => { self . arg_prefix = Some ( self . read_argument ( ) ) ; Instruction :: Nop } ,
165- _ => panic ! ( format!( "Opcode not supported: {}" , opcode) ) ,
127+ let mut opcode = 144 ;
128+ let mut oparg: usize = 0 ;
129+ while opcode == 144 {
130+ match self . bytestream . next ( ) {
131+ Some ( op) => { opcode = * op } ,
132+ None => return None ,
166133 }
167- } )
134+ oparg = ( oparg << 8 ) | ( * self . bytestream . next ( ) . unwrap ( ) as usize ) ;
135+ self . pending_nops += 1 ;
136+ }
137+ self . pending_nops -= 1 ;
138+ let inst = match opcode {
139+ 1 => Instruction :: PopTop ,
140+ 4 => Instruction :: DupTop ,
141+ 25 => Instruction :: BinarySubscr ,
142+ 68 => Instruction :: GetIter ,
143+ 71 => Instruction :: LoadBuildClass ,
144+ 83 => Instruction :: ReturnValue ,
145+ 87 => Instruction :: PopBlock ,
146+ 88 => Instruction :: EndFinally ,
147+ 89 => Instruction :: PopExcept ,
148+ 90 => Instruction :: StoreName ( oparg) ,
149+ 93 => Instruction :: ForIter ( oparg) ,
150+ 95 => Instruction :: StoreAttr ( oparg) ,
151+ 97 => Instruction :: StoreGlobal ( oparg) ,
152+ 100 => Instruction :: LoadConst ( oparg) ,
153+ 101 => Instruction :: LoadName ( oparg) ,
154+ 102 => Instruction :: BuildTuple ( oparg) ,
155+ 106 => Instruction :: LoadAttr ( oparg) ,
156+ 107 => Instruction :: CompareOp ( CmpOperator :: from_bytecode ( oparg) ) ,
157+ 110 => Instruction :: JumpForward ( oparg) ,
158+ 113 => Instruction :: JumpAbsolute ( oparg) ,
159+ 114 => Instruction :: PopJumpIfFalse ( oparg) ,
160+ 116 => Instruction :: LoadGlobal ( oparg) ,
161+ 120 => Instruction :: SetupLoop ( oparg + 1 ) ,
162+ 121 => Instruction :: SetupExcept ( oparg + 1 ) ,
163+ 124 => Instruction :: LoadFast ( oparg) ,
164+ 125 => Instruction :: StoreFast ( oparg) ,
165+ 130 => Instruction :: RaiseVarargs ( oparg) ,
166+ 131 => Instruction :: CallFunction ( oparg, false ) ,
167+ 132 => Instruction :: MakeFunction {
168+ has_defaults : oparg & 0x01 != 0 ,
169+ has_kwdefaults : oparg & 0x02 != 0 ,
170+ has_annotations : oparg & 0x04 != 0 ,
171+ has_closure : oparg & 0x08 != 0 ,
172+ } ,
173+ 141 => Instruction :: CallFunction ( oparg, true ) ,
174+ 156 => Instruction :: BuildConstKeyMap ( oparg) ,
175+ 144 => panic ! ( "The impossible happened." ) ,
176+ _ => panic ! ( format!( "Opcode not supported: {:?}" , ( opcode, oparg) ) ) ,
177+ } ;
178+ Some ( inst)
168179 }
169180}
170181
171182#[ test]
172183fn test_load_read ( ) {
173- let bytes: Vec < u8 > = vec ! [ 124 , 1 , 0 , 83 ] ;
184+ let bytes: Vec < u8 > = vec ! [ 124 , 1 , 83 , 0 ] ;
174185 let reader = InstructionDecoder :: new ( bytes. iter ( ) ) ;
175186 let instructions: Vec < Instruction > = reader. collect ( ) ;
176- assert_eq ! ( vec![ Instruction :: LoadFast ( 1 ) , Instruction :: Nop , Instruction :: Nop , Instruction :: ReturnValue ] , instructions) ;
187+ assert_eq ! ( vec![ Instruction :: LoadFast ( 1 ) , Instruction :: ReturnValue ] , instructions) ;
177188}
0 commit comments