@@ -275,167 +275,6 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
275275 arg : OpArg ,
276276 ) -> Result < ( ) , JitCompileError > {
277277 match instruction {
278- Instruction :: ExtendedArg => Ok ( ( ) ) ,
279- Instruction :: PopJumpIfFalse ( target) => {
280- let cond = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
281- let val = self . boolean_val ( cond) ?;
282- let then_block = self . get_or_create_block ( target. get ( arg) ) ;
283- let else_block = self . builder . create_block ( ) ;
284-
285- self . builder
286- . ins ( )
287- . brif ( val, else_block, & [ ] , then_block, & [ ] ) ;
288- self . builder . switch_to_block ( else_block) ;
289-
290- Ok ( ( ) )
291- }
292- Instruction :: PopJumpIfTrue ( target) => {
293- let cond = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
294- let val = self . boolean_val ( cond) ?;
295- let then_block = self . get_or_create_block ( target. get ( arg) ) ;
296- let else_block = self . builder . create_block ( ) ;
297-
298- self . builder
299- . ins ( )
300- . brif ( val, then_block, & [ ] , else_block, & [ ] ) ;
301- self . builder . switch_to_block ( else_block) ;
302-
303- Ok ( ( ) )
304- }
305-
306- Instruction :: Jump ( target) => {
307- let target_block = self . get_or_create_block ( target. get ( arg) ) ;
308- self . builder . ins ( ) . jump ( target_block, & [ ] ) ;
309- Ok ( ( ) )
310- }
311- Instruction :: LoadFast ( idx) => {
312- let local = self . variables [ idx. get ( arg) as usize ]
313- . as_ref ( )
314- . ok_or ( JitCompileError :: BadBytecode ) ?;
315- self . stack . push ( JitValue :: from_type_and_value (
316- local. ty . clone ( ) ,
317- self . builder . use_var ( local. var ) ,
318- ) ) ;
319- Ok ( ( ) )
320- }
321- Instruction :: StoreFast ( idx) => {
322- let val = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
323- self . store_variable ( idx. get ( arg) , val)
324- }
325- Instruction :: LoadConst { idx } => {
326- let val = self
327- . prepare_const ( bytecode. constants [ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
328- self . stack . push ( val) ;
329- Ok ( ( ) )
330- }
331- Instruction :: BuildTuple ( size) => {
332- let elements = self . pop_multiple ( size. get ( arg) as usize ) ;
333- self . stack . push ( JitValue :: Tuple ( elements) ) ;
334- Ok ( ( ) )
335- }
336- Instruction :: UnpackSequence ( size) => {
337- let val = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
338-
339- let elements = match val {
340- JitValue :: Tuple ( elements) => elements,
341- _ => return Err ( JitCompileError :: NotSupported ) ,
342- } ;
343-
344- if elements. len ( ) != size. get ( arg) as usize {
345- return Err ( JitCompileError :: NotSupported ) ;
346- }
347-
348- self . stack . extend ( elements. into_iter ( ) . rev ( ) ) ;
349- Ok ( ( ) )
350- }
351- Instruction :: ReturnValue => {
352- let val = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
353- self . return_value ( val)
354- }
355- Instruction :: ReturnConst ( idx) => {
356- let val = self
357- . prepare_const ( bytecode. constants [ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
358- self . return_value ( val)
359- }
360- Instruction :: CompareOperation ( op) => {
361- let op = op. get ( arg) ;
362- // the rhs is popped off first
363- let b = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
364- let a = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
365-
366- let a_type: Option < JitType > = a. to_jit_type ( ) ;
367- let b_type: Option < JitType > = b. to_jit_type ( ) ;
368-
369- match ( a, b) {
370- ( JitValue :: Int ( a) , JitValue :: Int ( b) )
371- | ( JitValue :: Bool ( a) , JitValue :: Bool ( b) )
372- | ( JitValue :: Bool ( a) , JitValue :: Int ( b) )
373- | ( JitValue :: Int ( a) , JitValue :: Bool ( b) ) => {
374- let operand_one = match a_type. unwrap ( ) {
375- JitType :: Bool => self . builder . ins ( ) . uextend ( types:: I64 , a) ,
376- _ => a,
377- } ;
378-
379- let operand_two = match b_type. unwrap ( ) {
380- JitType :: Bool => self . builder . ins ( ) . uextend ( types:: I64 , b) ,
381- _ => b,
382- } ;
383-
384- let cond = match op {
385- ComparisonOperator :: Equal => IntCC :: Equal ,
386- ComparisonOperator :: NotEqual => IntCC :: NotEqual ,
387- ComparisonOperator :: Less => IntCC :: SignedLessThan ,
388- ComparisonOperator :: LessOrEqual => IntCC :: SignedLessThanOrEqual ,
389- ComparisonOperator :: Greater => IntCC :: SignedGreaterThan ,
390- ComparisonOperator :: GreaterOrEqual => IntCC :: SignedGreaterThanOrEqual ,
391- } ;
392-
393- let val = self . builder . ins ( ) . icmp ( cond, operand_one, operand_two) ;
394- self . stack . push ( JitValue :: Bool ( val) ) ;
395- Ok ( ( ) )
396- }
397- ( JitValue :: Float ( a) , JitValue :: Float ( b) ) => {
398- let cond = match op {
399- ComparisonOperator :: Equal => FloatCC :: Equal ,
400- ComparisonOperator :: NotEqual => FloatCC :: NotEqual ,
401- ComparisonOperator :: Less => FloatCC :: LessThan ,
402- ComparisonOperator :: LessOrEqual => FloatCC :: LessThanOrEqual ,
403- ComparisonOperator :: Greater => FloatCC :: GreaterThan ,
404- ComparisonOperator :: GreaterOrEqual => FloatCC :: GreaterThanOrEqual ,
405- } ;
406-
407- let val = self . builder . ins ( ) . fcmp ( cond, a, b) ;
408- self . stack . push ( JitValue :: Bool ( val) ) ;
409- Ok ( ( ) )
410- }
411- _ => Err ( JitCompileError :: NotSupported ) ,
412- }
413- }
414- Instruction :: UnaryOperation ( op) => {
415- let op = op. get ( arg) ;
416- let a = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
417- match ( op, a) {
418- ( UnaryOperator :: Minus , JitValue :: Int ( val) ) => {
419- // Compile minus as 0 - a.
420- let zero = self . builder . ins ( ) . iconst ( types:: I64 , 0 ) ;
421- let out = self . compile_sub ( zero, val) ;
422- self . stack . push ( JitValue :: Int ( out) ) ;
423- Ok ( ( ) )
424- }
425- ( UnaryOperator :: Plus , JitValue :: Int ( val) ) => {
426- // Nothing to do
427- self . stack . push ( JitValue :: Int ( val) ) ;
428- Ok ( ( ) )
429- }
430- ( UnaryOperator :: Not , a) => {
431- let boolean = self . boolean_val ( a) ?;
432- let not_boolean = self . builder . ins ( ) . bxor_imm ( boolean, 1 ) ;
433- self . stack . push ( JitValue :: Bool ( not_boolean) ) ;
434- Ok ( ( ) )
435- }
436- _ => Err ( JitCompileError :: NotSupported ) ,
437- }
438- }
439278 Instruction :: BinaryOperation ( op) | Instruction :: BinaryOperationInplace ( op) => {
440279 let op = op. get ( arg) ;
441280 // the rhs is popped off first
@@ -561,26 +400,11 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
561400
562401 Ok ( ( ) )
563402 }
564- Instruction :: SetupLoop => {
565- let loop_head = self . builder . create_block ( ) ;
566- self . builder . ins ( ) . jump ( loop_head, & [ ] ) ;
567- self . builder . switch_to_block ( loop_head) ;
568- Ok ( ( ) )
569- }
570- Instruction :: PopBlock => {
571- // TODO: block support
403+ Instruction :: BuildTuple ( size) => {
404+ let elements = self . pop_multiple ( size. get ( arg) as usize ) ;
405+ self . stack . push ( JitValue :: Tuple ( elements) ) ;
572406 Ok ( ( ) )
573407 }
574- Instruction :: LoadGlobal ( idx) => {
575- let name = & bytecode. names [ idx. get ( arg) as usize ] ;
576-
577- if name. as_ref ( ) != bytecode. obj_name . as_ref ( ) {
578- Err ( JitCompileError :: NotSupported )
579- } else {
580- self . stack . push ( JitValue :: FuncRef ( func_ref) ) ;
581- Ok ( ( ) )
582- }
583- }
584408 Instruction :: CallFunctionPositional ( nargs) => {
585409 let nargs = nargs. get ( arg) ;
586410
@@ -601,20 +425,195 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
601425 _ => Err ( JitCompileError :: BadBytecode ) ,
602426 }
603427 }
428+ Instruction :: CompareOperation ( op) => {
429+ let op = op. get ( arg) ;
430+ // the rhs is popped off first
431+ let b = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
432+ let a = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
433+
434+ let a_type: Option < JitType > = a. to_jit_type ( ) ;
435+ let b_type: Option < JitType > = b. to_jit_type ( ) ;
436+
437+ match ( a, b) {
438+ ( JitValue :: Int ( a) , JitValue :: Int ( b) )
439+ | ( JitValue :: Bool ( a) , JitValue :: Bool ( b) )
440+ | ( JitValue :: Bool ( a) , JitValue :: Int ( b) )
441+ | ( JitValue :: Int ( a) , JitValue :: Bool ( b) ) => {
442+ let operand_one = match a_type. unwrap ( ) {
443+ JitType :: Bool => self . builder . ins ( ) . uextend ( types:: I64 , a) ,
444+ _ => a,
445+ } ;
446+
447+ let operand_two = match b_type. unwrap ( ) {
448+ JitType :: Bool => self . builder . ins ( ) . uextend ( types:: I64 , b) ,
449+ _ => b,
450+ } ;
451+
452+ let cond = match op {
453+ ComparisonOperator :: Equal => IntCC :: Equal ,
454+ ComparisonOperator :: NotEqual => IntCC :: NotEqual ,
455+ ComparisonOperator :: Less => IntCC :: SignedLessThan ,
456+ ComparisonOperator :: LessOrEqual => IntCC :: SignedLessThanOrEqual ,
457+ ComparisonOperator :: Greater => IntCC :: SignedGreaterThan ,
458+ ComparisonOperator :: GreaterOrEqual => IntCC :: SignedGreaterThanOrEqual ,
459+ } ;
460+
461+ let val = self . builder . ins ( ) . icmp ( cond, operand_one, operand_two) ;
462+ self . stack . push ( JitValue :: Bool ( val) ) ;
463+ Ok ( ( ) )
464+ }
465+ ( JitValue :: Float ( a) , JitValue :: Float ( b) ) => {
466+ let cond = match op {
467+ ComparisonOperator :: Equal => FloatCC :: Equal ,
468+ ComparisonOperator :: NotEqual => FloatCC :: NotEqual ,
469+ ComparisonOperator :: Less => FloatCC :: LessThan ,
470+ ComparisonOperator :: LessOrEqual => FloatCC :: LessThanOrEqual ,
471+ ComparisonOperator :: Greater => FloatCC :: GreaterThan ,
472+ ComparisonOperator :: GreaterOrEqual => FloatCC :: GreaterThanOrEqual ,
473+ } ;
474+
475+ let val = self . builder . ins ( ) . fcmp ( cond, a, b) ;
476+ self . stack . push ( JitValue :: Bool ( val) ) ;
477+ Ok ( ( ) )
478+ }
479+ _ => Err ( JitCompileError :: NotSupported ) ,
480+ }
481+ }
482+ Instruction :: ExtendedArg => Ok ( ( ) ) ,
483+ Instruction :: Jump ( target) => {
484+ let target_block = self . get_or_create_block ( target. get ( arg) ) ;
485+ self . builder . ins ( ) . jump ( target_block, & [ ] ) ;
486+ Ok ( ( ) )
487+ }
488+ Instruction :: LoadConst { idx } => {
489+ let val = self
490+ . prepare_const ( bytecode. constants [ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
491+ self . stack . push ( val) ;
492+ Ok ( ( ) )
493+ }
494+ Instruction :: LoadFast ( idx) => {
495+ let local = self . variables [ idx. get ( arg) as usize ]
496+ . as_ref ( )
497+ . ok_or ( JitCompileError :: BadBytecode ) ?;
498+ self . stack . push ( JitValue :: from_type_and_value (
499+ local. ty . clone ( ) ,
500+ self . builder . use_var ( local. var ) ,
501+ ) ) ;
502+ Ok ( ( ) )
503+ }
504+ Instruction :: LoadGlobal ( idx) => {
505+ let name = & bytecode. names [ idx. get ( arg) as usize ] ;
506+
507+ if name. as_ref ( ) != bytecode. obj_name . as_ref ( ) {
508+ Err ( JitCompileError :: NotSupported )
509+ } else {
510+ self . stack . push ( JitValue :: FuncRef ( func_ref) ) ;
511+ Ok ( ( ) )
512+ }
513+ }
604514 Instruction :: Nop => Ok ( ( ) ) ,
515+ Instruction :: Pop => {
516+ self . stack . pop ( ) ;
517+ Ok ( ( ) )
518+ }
519+ Instruction :: PopBlock => {
520+ // TODO: block support
521+ Ok ( ( ) )
522+ }
523+ Instruction :: PopJumpIfFalse ( target) => {
524+ let cond = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
525+ let val = self . boolean_val ( cond) ?;
526+ let then_block = self . get_or_create_block ( target. get ( arg) ) ;
527+ let else_block = self . builder . create_block ( ) ;
528+
529+ self . builder
530+ . ins ( )
531+ . brif ( val, else_block, & [ ] , then_block, & [ ] ) ;
532+ self . builder . switch_to_block ( else_block) ;
533+
534+ Ok ( ( ) )
535+ }
536+ Instruction :: PopJumpIfTrue ( target) => {
537+ let cond = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
538+ let val = self . boolean_val ( cond) ?;
539+ let then_block = self . get_or_create_block ( target. get ( arg) ) ;
540+ let else_block = self . builder . create_block ( ) ;
541+
542+ self . builder
543+ . ins ( )
544+ . brif ( val, then_block, & [ ] , else_block, & [ ] ) ;
545+ self . builder . switch_to_block ( else_block) ;
546+
547+ Ok ( ( ) )
548+ }
549+ Instruction :: Resume ( _resume_arg) => {
550+ // TODO: Implement the resume instruction
551+ Ok ( ( ) )
552+ }
553+ Instruction :: ReturnConst ( idx) => {
554+ let val = self
555+ . prepare_const ( bytecode. constants [ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
556+ self . return_value ( val)
557+ }
558+ Instruction :: ReturnValue => {
559+ let val = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
560+ self . return_value ( val)
561+ }
562+ Instruction :: SetupLoop => {
563+ let loop_head = self . builder . create_block ( ) ;
564+ self . builder . ins ( ) . jump ( loop_head, & [ ] ) ;
565+ self . builder . switch_to_block ( loop_head) ;
566+ Ok ( ( ) )
567+ }
568+ Instruction :: StoreFast ( idx) => {
569+ let val = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
570+ self . store_variable ( idx. get ( arg) , val)
571+ }
605572 Instruction :: Swap ( index) => {
606573 let len = self . stack . len ( ) ;
607574 let i = len - 1 ;
608575 let j = len - 1 - index. get ( arg) as usize ;
609576 self . stack . swap ( i, j) ;
610577 Ok ( ( ) )
611578 }
612- Instruction :: Pop => {
613- self . stack . pop ( ) ;
614- Ok ( ( ) )
579+ Instruction :: UnaryOperation ( op) => {
580+ let op = op. get ( arg) ;
581+ let a = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
582+ match ( op, a) {
583+ ( UnaryOperator :: Minus , JitValue :: Int ( val) ) => {
584+ // Compile minus as 0 - a.
585+ let zero = self . builder . ins ( ) . iconst ( types:: I64 , 0 ) ;
586+ let out = self . compile_sub ( zero, val) ;
587+ self . stack . push ( JitValue :: Int ( out) ) ;
588+ Ok ( ( ) )
589+ }
590+ ( UnaryOperator :: Plus , JitValue :: Int ( val) ) => {
591+ // Nothing to do
592+ self . stack . push ( JitValue :: Int ( val) ) ;
593+ Ok ( ( ) )
594+ }
595+ ( UnaryOperator :: Not , a) => {
596+ let boolean = self . boolean_val ( a) ?;
597+ let not_boolean = self . builder . ins ( ) . bxor_imm ( boolean, 1 ) ;
598+ self . stack . push ( JitValue :: Bool ( not_boolean) ) ;
599+ Ok ( ( ) )
600+ }
601+ _ => Err ( JitCompileError :: NotSupported ) ,
602+ }
615603 }
616- Instruction :: Resume ( _resume_arg) => {
617- // TODO: Implement the resume instruction
604+ Instruction :: UnpackSequence ( size) => {
605+ let val = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
606+
607+ let elements = match val {
608+ JitValue :: Tuple ( elements) => elements,
609+ _ => return Err ( JitCompileError :: NotSupported ) ,
610+ } ;
611+
612+ if elements. len ( ) != size. get ( arg) as usize {
613+ return Err ( JitCompileError :: NotSupported ) ;
614+ }
615+
616+ self . stack . extend ( elements. into_iter ( ) . rev ( ) ) ;
618617 Ok ( ( ) )
619618 }
620619 _ => Err ( JitCompileError :: NotSupported ) ,
0 commit comments