pub fn generate_modifier_dispatch(
    contract_no: usize,
    func: &Function,
    modifier: &Function,
    cfg_no: usize,
    args: &[Expression],
    ns: &Namespace,
) -> ControlFlowGraph {
    let name = format!(
        "sol::modifier::{}::{}::{}",
        &ns.contracts[contract_no].name,
        func.llvm_symbol(ns),
        modifier.llvm_symbol(ns)
    );
    let mut cfg = ControlFlowGraph::new(name, None);

    cfg.params = func.params.clone();
    cfg.returns = func.returns.clone();

    let mut vartab = Vartable::new_with_syms(&func.symtable, ns.next_id);

    vartab.add_symbol_table(&modifier.symtable);
    let mut loops = LoopScopes::new();

    // a modifier takes the same arguments as the function it is applied to. This way we can pass
    // the arguments to the function
    for (i, arg) in func.symtable.arguments.iter().enumerate() {
        if let Some(pos) = arg {
            let var = &func.symtable.vars[pos];
            cfg.add(
                &mut vartab,
                Instr::Set {
                    loc: pt::Loc(0, 0, 0),
                    res: *pos,
                    expr: Expression::FunctionArg(var.id.loc, var.ty.clone(), i),
                },
            );
        }
    }

    // now set the modifier args
    for (i, arg) in modifier.symtable.arguments.iter().enumerate() {
        if let Some(pos) = arg {
            let expr = expression(&args[i], &mut cfg, contract_no, ns, &mut vartab);
            cfg.add(
                &mut vartab,
                Instr::Set {
                    loc: pt::Loc(0, 0, 0),
                    res: *pos,
                    expr,
                },
            );
        }
    }

    // modifiers do not have return values in their syntax, but the return values from the function
    // need to be passed on. So, we need to create some var
    let mut value = Vec::new();
    for (i, arg) in func.returns.iter().enumerate() {
        value.push(Expression::Variable(
            arg.loc,
            arg.ty.clone(),
            func.symtable.returns[i],
        ));
    }

    let return_instr = Instr::Return { value };

    // create the instruction for the place holder
    let placeholder = Instr::Call {
        res: func.symtable.returns.clone(),
        call: InternalCallTy::Static(cfg_no),
        args: func
            .params
            .iter()
            .enumerate()
            .map(|(i, p)| Expression::FunctionArg(p.loc, p.ty.clone(), i))
            .collect(),
    };

    for stmt in &modifier.body {
        statement(
            stmt,
            func,
            &mut cfg,
            contract_no,
            ns,
            &mut vartab,
            &mut loops,
            Some(&placeholder),
            Some(&return_instr),
        );
    }

    cfg.vars = vartab.drain();

    cfg
}
/// Generate the CFG for a modifier on a function
Generate the CFG for a modifier on a function
Generate the CFG for a modifier on a function
pub fn generate_modifier_dispatch(
    contract_no: usize,
    func: &Function,
    modifier: &Function,
    cfg_no: usize,
    args: &[Expression],
    ns: &Namespace,
) -> ControlFlowGraph {
    let name = format!(
        "sol::modifier::{}::{}::{}",
        &ns.contracts[contract_no].name,
        func.llvm_symbol(ns),
        modifier.llvm_symbol(ns)
    );
    let mut cfg = ControlFlowGraph::new(name, None);
    cfg.params = func.params.clone();
    cfg.returns = func.returns.clone();
    let mut vartab = Vartable::new_with_syms(&func.symtable, ns.next_id);
    vartab.add_symbol_table(&modifier.symtable);
    let mut loops = LoopScopes::new();
    // a modifier takes the same arguments as the function it is applied to. This way we can pass
    // the arguments to the function
    for (i, arg) in func.symtable.arguments.iter().enumerate() {
        if let Some(pos) = arg {
            let var = &func.symtable.vars[pos];
            cfg.add(
                &mut vartab,
                Instr::Set {
                    loc: pt::Loc(0, 0, 0),
                    res: *pos,
                    expr: Expression::FunctionArg(var.id.loc, var.ty.clone(), i),
                },
            );
        }
    }
    // now set the modifier args
    for (i, arg) in modifier.symtable.arguments.iter().enumerate() {
        if let Some(pos) = arg {
            let expr = expression(&args[i], &mut cfg, contract_no, ns, &mut vartab);
            cfg.add(
                &mut vartab,
                Instr::Set {
                    loc: pt::Loc(0, 0, 0),
                    res: *pos,
                    expr,
                },
            );
        }
    }
    // modifiers do not have return values in their syntax, but the return values from the function
    // need to be passed on. So, we need to create some var
    let mut value = Vec::new();
    for (i, arg) in func.returns.iter().enumerate() {
        value.push(Expression::Variable(
            arg.loc,
            arg.ty.clone(),
            func.symtable.returns[i],
        ));
    }
    let return_instr = Instr::Return { value };
    // create the instruction for the place holder
    let placeholder = Instr::Call {
        res: func.symtable.returns.clone(),
        call: InternalCallTy::Static(cfg_no),
        args: func
            .params
            .iter()
            .enumerate()
            .map(|(i, p)| Expression::FunctionArg(p.loc, p.ty.clone(), i))
            .collect(),
    };
    for stmt in &modifier.body {
        statement(
            stmt,
            func,
            &mut cfg,
            contract_no,
            ns,
            &mut vartab,
            &mut loops,
            Some(&placeholder),
            Some(&return_instr),
        );
    }
    cfg.vars = vartab.drain();
    cfg
}
pub fn generate_modifier_dispatch ( contract_no : usize , func : & Function , modifier : & Function , cfg_no : usize , args : & [ Expression ] , ns : & Namespace , ) -> ControlFlowGraph { let name = format ! ( " " ns contracts [ contract_no ] name func llvm_symbol ( ns ) modifier llvm_symbol ( ns ) ) ; let mut cfg = ControlFlowGraph :: new ( name , None ) ; cfg . params = func . params . clone ( ) ; cfg . returns = func . returns . clone ( ) ; let mut vartab = Vartable :: new_with_syms ( & func . symtable , ns . next_id ) ; vartab . add_symbol_table ( & modifier . symtable ) ; let mut loops = LoopScopes :: new ( ) ; // a modifier takes the same arguments as the function it is applied to. This way we can pass // the arguments to the function for ( i , arg ) in func . symtable . arguments . iter ( ) . enumerate ( ) { if let Some ( pos ) = arg { let var = & func . symtable . vars [ pos ] ; cfg . add ( & mut vartab , Instr :: Set { loc : pt :: Loc ( 0 , 0 , 0 ) , res : * pos , expr : Expression :: FunctionArg ( var . id . loc , var . ty . clone ( ) , i ) , } , ) ; } } // now set the modifier args for ( i , arg ) in modifier . symtable . arguments . iter ( ) . enumerate ( ) { if let Some ( pos ) = arg { let expr = expression ( & args [ i ] , & mut cfg , contract_no , ns , & mut vartab ) ; cfg . add ( & mut vartab , Instr :: Set { loc : pt :: Loc ( 0 , 0 , 0 ) , res : * pos , expr , } , ) ; } } // modifiers do not have return values in their syntax, but the return values from the function // need to be passed on. So, we need to create some var let mut value = Vec :: new ( ) ; for ( i , arg ) in func . returns . iter ( ) . enumerate ( ) { value . push ( Expression :: Variable ( arg . loc , arg . ty . clone ( ) , func . symtable . returns [ i ] , ) ) ; } let return_instr = Instr :: Return { value } ; // create the instruction for the place holder let placeholder = Instr :: Call { res : func . symtable . returns . clone ( ) , call : InternalCallTy :: Static ( cfg_no ) , args : func . params . iter ( ) . enumerate ( ) . map ( | ( i , p ) | Expression :: FunctionArg ( p . loc , p . ty . clone ( ) , i ) ) . collect ( ) , } ; for stmt in & modifier . body { statement ( stmt , func , & mut cfg , contract_no , ns , & mut vartab , & mut loops , Some ( & placeholder ) , Some ( & return_instr ) , ) ; } cfg . vars = vartab . drain ( ) ; cfg }
Generate the CFG for a modifier on a function
Generate the CFG for a modifier on a function
contract_no
usize
func
&Function
modifier
&Function
cfg_no
usize
args
&[Expression]
ns
&Namespace
contract_no
usize
func
&Function
modifier
&Function
cfg_no
usize
args
&[Expression]
ns
&Namespace