pub fn br_table<I>(
        &mut self,
        targets: I,
        default: Option<BrTarget<Label>>,
        pass_args: impl FnOnce(&mut Self),
    ) where
        I: IntoIterator<Item = Option<BrTarget<Label>>>,
        I::IntoIter: ExactSizeIterator,
    {
        let mut targets = targets.into_iter();
        let count = targets.len();

        let mut selector = self.pop();

        pass_args(self);

        if let Some(imm) = selector.imm_i32() {
            if let Some(target) = targets.nth(imm as _).or(Some(default)).and_then(|a| a) {
                match target {
                    BrTarget::Label(label) => self.br(label),
                    BrTarget::Return => {
                        dynasm!(self.asm
                            ; ret
                        );
                    }
                }
            }
        } else {
            let end_label = self.create_label();

            if count > 0 {
                let (selector_reg, pop_selector) = self
                    .into_temp_reg(GPRType::Rq, &mut selector)
                    .map(|r| (r, false))
                    .unwrap_or_else(|| {
                        self.push_physical(ValueLocation::Reg(RAX));
                        self.block_state.regs.mark_used(RAX);
                        (RAX, true)
                    });

                let (tmp, pop_tmp) = if let Some(reg) = self.take_reg(I64) {
                    (reg, false)
                } else {
                    let out_reg = if selector_reg == RAX { RCX } else { RAX };

                    self.push_physical(ValueLocation::Reg(out_reg));
                    self.block_state.regs.mark_used(out_reg);

                    (out_reg, true)
                };

                self.immediate_to_reg(tmp, (count as u32).into());
                dynasm!(self.asm
                    ; cmp Rq(selector_reg.rq().unwrap()), Rq(tmp.rq().unwrap())
                    ; cmova Rq(selector_reg.rq().unwrap()), Rq(tmp.rq().unwrap())
                    ; lea Rq(tmp.rq().unwrap()), [>start_label]
                    ; lea Rq(selector_reg.rq().unwrap()), [
                        Rq(selector_reg.rq().unwrap()) * 5
                    ]
                    ; add Rq(selector_reg.rq().unwrap()), Rq(tmp.rq().unwrap())
                );

                if pop_tmp {
                    dynasm!(self.asm
                        ; pop Rq(tmp.rq().unwrap())
                    );
                } else {
                    self.block_state.regs.release(tmp);
                }

                if pop_selector {
                    dynasm!(self.asm
                        ; pop Rq(selector_reg.rq().unwrap())
                    );
                }

                dynasm!(self.asm
                    ; jmp Rq(selector_reg.rq().unwrap())
                ; start_label:
                );

                for target in targets {
                    let label = target
                        .map(|target| self.target_to_label(target))
                        .unwrap_or(end_label);
                    dynasm!(self.asm
                        ; jmp =>label.0
                    );
                }
            }

            if let Some(def) = default {
                match def {
                    BrTarget::Label(label) => dynasm!(self.asm
                        ; jmp =>label.0
                    ),
                    BrTarget::Return => dynasm!(self.asm
                        ; ret
                    ),
                }
            }

            self.define_label(end_label);
        }

        self.free_value(selector);
    }
/// If `default` is `None` then the default is just continuing execution
If `default` is `None` then the default is just continuing execution
If ` default ` is ` None ` then the default is just continuing execution
pub fn br_table<I>(
        &mut self,
        targets: I,
        default: Option<BrTarget<Label>>,
        pass_args: impl FnOnce(&mut Self),
    ) where
        I: IntoIterator<Item = Option<BrTarget<Label>>>,
        I::IntoIter: ExactSizeIterator,
    {
        let mut targets = targets.into_iter();
        let count = targets.len();
        let mut selector = self.pop();
        pass_args(self);
        if let Some(imm) = selector.imm_i32() {
            if let Some(target) = targets.nth(imm as _).or(Some(default)).and_then(|a| a) {
                match target {
                    BrTarget::Label(label) => self.br(label),
                    BrTarget::Return => {
                        dynasm!(self.asm
                            ; ret
                        );
                    }
                }
            }
        } else {
            let end_label = self.create_label();
            if count > 0 {
                let (selector_reg, pop_selector) = self
                    .into_temp_reg(GPRType::Rq, &mut selector)
                    .map(|r| (r, false))
                    .unwrap_or_else(|| {
                        self.push_physical(ValueLocation::Reg(RAX));
                        self.block_state.regs.mark_used(RAX);
                        (RAX, true)
                    });
                let (tmp, pop_tmp) = if let Some(reg) = self.take_reg(I64) {
                    (reg, false)
                } else {
                    let out_reg = if selector_reg == RAX { RCX } else { RAX };
                    self.push_physical(ValueLocation::Reg(out_reg));
                    self.block_state.regs.mark_used(out_reg);
                    (out_reg, true)
                };
                self.immediate_to_reg(tmp, (count as u32).into());
                dynasm!(self.asm
                    ; cmp Rq(selector_reg.rq().unwrap()), Rq(tmp.rq().unwrap())
                    ; cmova Rq(selector_reg.rq().unwrap()), Rq(tmp.rq().unwrap())
                    ; lea Rq(tmp.rq().unwrap()), [>start_label]
                    ; lea Rq(selector_reg.rq().unwrap()), [
                        Rq(selector_reg.rq().unwrap()) * 5
                    ]
                    ; add Rq(selector_reg.rq().unwrap()), Rq(tmp.rq().unwrap())
                );
                if pop_tmp {
                    dynasm!(self.asm
                        ; pop Rq(tmp.rq().unwrap())
                    );
                } else {
                    self.block_state.regs.release(tmp);
                }
                if pop_selector {
                    dynasm!(self.asm
                        ; pop Rq(selector_reg.rq().unwrap())
                    );
                }
                dynasm!(self.asm
                    ; jmp Rq(selector_reg.rq().unwrap())
                ; start_label:
                );
                for target in targets {
                    let label = target
                        .map(|target| self.target_to_label(target))
                        .unwrap_or(end_label);
                    dynasm!(self.asm
                        ; jmp =>label.0
                    );
                }
            }
            if let Some(def) = default {
                match def {
                    BrTarget::Label(label) => dynasm!(self.asm
                        ; jmp =>label.0
                    ),
                    BrTarget::Return => dynasm!(self.asm
                        ; ret
                    ),
                }
            }
            self.define_label(end_label);
        }
        self.free_value(selector);
    }
pub fn br_table < I > ( & mut self , targets : I , default : Option < BrTarget < Label > > , pass_args : impl FnOnce ( & mut Self ) , ) where I : IntoIterator < Item = Option < BrTarget < Label > > > , I :: IntoIter : ExactSizeIterator , { let mut targets = targets . into_iter ( ) ; let count = targets . len ( ) ; let mut selector = self . pop ( ) ; pass_args ( self ) ; if let Some ( imm ) = selector . imm_i32 ( ) { if let Some ( target ) = targets . nth ( imm as _ ) . or ( Some ( default ) ) . and_then ( | a | a ) { match target { BrTarget :: Label ( label ) => self . br ( label ) , BrTarget :: Return => { dynasm ! ( self asm ret ) ; } } } } else { let end_label = self . create_label ( ) ; if count > 0 { let ( selector_reg , pop_selector ) = self . into_temp_reg ( GPRType :: Rq , & mut selector ) . map ( | r | ( r , false ) ) . unwrap_or_else ( | | { self . push_physical ( ValueLocation :: Reg ( RAX ) ) ; self . block_state . regs . mark_used ( RAX ) ; ( RAX , true ) } ) ; let ( tmp , pop_tmp ) = if let Some ( reg ) = self . take_reg ( I64 ) { ( reg , false ) } else { let out_reg = if selector_reg == RAX { RCX } else { RAX } ; self . push_physical ( ValueLocation :: Reg ( out_reg ) ) ; self . block_state . regs . mark_used ( out_reg ) ; ( out_reg , true ) } ; self . immediate_to_reg ( tmp , ( count as u32 ) . into ( ) ) ; dynasm ! ( self asm cmp Rq ( selector_reg rq ( ) unwrap ( ) ) Rq ( tmp rq ( ) unwrap ( ) ) cmova Rq ( selector_reg rq ( ) unwrap ( ) ) Rq ( tmp rq ( ) unwrap ( ) ) lea Rq ( tmp rq ( ) unwrap ( ) ) [ start_label ] lea Rq ( selector_reg rq ( ) unwrap ( ) ) [ Rq ( selector_reg rq ( ) unwrap ( ) ) 5 ] add Rq ( selector_reg rq ( ) unwrap ( ) ) Rq ( tmp rq ( ) unwrap ( ) ) ) ; if pop_tmp { dynasm ! ( self asm pop Rq ( tmp rq ( ) unwrap ( ) ) ) ; } else { self . block_state . regs . release ( tmp ) ; } if pop_selector { dynasm ! ( self asm pop Rq ( selector_reg rq ( ) unwrap ( ) ) ) ; } dynasm ! ( self asm jmp Rq ( selector_reg rq ( ) unwrap ( ) ) start_label ) ; for target in targets { let label = target . map ( | target | self . target_to_label ( target ) ) . unwrap_or ( end_label ) ; dynasm ! ( self asm jmp label 0 ) ; } } if let Some ( def ) = default { match def { BrTarget :: Label ( label ) => dynasm ! ( self asm jmp label 0 ) , BrTarget :: Return => dynasm ! ( self asm ret ) , } } self . define_label ( end_label ) ; } self . free_value ( selector ) ; }
If `default` is `None` then the default is just continuing execution
If ` default ` is ` None ` then the default is just continuing execution
&mut self
targets
I
default
Option<BrTarget<Label>>
pass_args
impl FnOnce(&mut Self)