neo-devpack-solidity 0.22.0

Production-focused Solidity-to-NeoVM compilation system
Documentation
#[test]
fn optimize_ir_trims_unreachable_instructions() {
    let module = Module {
        functions: vec![Function {
            name: "foo".to_string(),
            kind: IrFunctionKind::Regular,
            parameters: vec![],
            returns: vec![],
            basic_blocks: vec![BasicBlock {
                instructions: vec![
                    Instruction::Return,
                    Instruction::Drop(ValueType::Boolean),
                    Instruction::ReturnVoid,
                ],
            }],
            local_count: 0,
        }],
        state_variables: vec![],
        events: vec![],
    };

    let optimized = optimize_ir(module, 2);
    let instrs = &optimized.functions[0].basic_blocks[0].instructions;
    assert_eq!(instrs.len(), 1);
    assert!(matches!(instrs[0], Instruction::Return));
}

#[test]
fn optimize_ir_trims_after_unconditional_jump() {
    let module = Module {
        functions: vec![Function {
            name: "bar".to_string(),
            kind: IrFunctionKind::Regular,
            parameters: vec![],
            returns: vec![],
            basic_blocks: vec![BasicBlock {
                instructions: vec![
                    Instruction::Jump { target: 1 },
                    Instruction::Drop(ValueType::Boolean),
                    Instruction::Label(1),
                    Instruction::ReturnVoid,
                ],
            }],
            local_count: 0,
        }],
        state_variables: vec![],
        events: vec![],
    };

    let optimized = optimize_ir(module, 1);
    let instrs = &optimized.functions[0].basic_blocks[0].instructions;
    assert_eq!(instrs.len(), 3);
    assert!(matches!(instrs[0], Instruction::Jump { .. }));
    assert!(matches!(instrs[1], Instruction::Label(_)));
    assert!(matches!(instrs[2], Instruction::ReturnVoid));
}

#[test]
fn optimize_ir_noop_when_disabled() {
    let module = Module {
        functions: vec![Function {
            name: "noop".to_string(),
            kind: IrFunctionKind::Regular,
            parameters: vec![],
            returns: vec![],
            basic_blocks: vec![BasicBlock {
                instructions: vec![Instruction::Return, Instruction::Drop(ValueType::Boolean)],
            }],
            local_count: 0,
        }],
        state_variables: vec![],
        events: vec![],
    };

    let optimized = optimize_ir(module, 0);
    let instrs = &optimized.functions[0].basic_blocks[0].instructions;
    assert_eq!(instrs.len(), 2);
    assert!(matches!(instrs[0], Instruction::Return));
    assert!(matches!(instrs[1], Instruction::Drop(_)));
}

#[test]
fn dedupe_labels_when_optimizer_high() {
    let module = Module {
        functions: vec![Function {
            name: "labels".to_string(),
            kind: IrFunctionKind::Regular,
            parameters: vec![],
            returns: vec![],
            basic_blocks: vec![BasicBlock {
                instructions: vec![
                    Instruction::Label(1),
                    Instruction::Label(2),
                    Instruction::ReturnVoid,
                ],
            }],
            local_count: 0,
        }],
        state_variables: vec![],
        events: vec![],
    };

    let optimized = optimize_ir(module, 3);
    let instrs = &optimized.functions[0].basic_blocks[0].instructions;
    let label_count = instrs
        .iter()
        .filter(|i| matches!(i, Instruction::Label(_)))
        .count();
    assert_eq!(label_count, 1);
}

#[test]
fn deduped_labels_retarget_jumps() {
    let module = Module {
        functions: vec![Function {
            name: "labels".to_string(),
            kind: IrFunctionKind::Regular,
            parameters: vec![],
            returns: vec![],
            basic_blocks: vec![BasicBlock {
                instructions: vec![
                    Instruction::Label(1),
                    Instruction::Label(2),
                    Instruction::Jump { target: 2 },
                    Instruction::ReturnVoid,
                ],
            }],
            local_count: 0,
        }],
        state_variables: vec![],
        events: vec![],
    };

    let optimized = optimize_ir(module, 3);
    let instrs = &optimized.functions[0].basic_blocks[0].instructions;
    assert!(
        matches!(instrs[0], Instruction::Label(1)),
        "first label should be preserved"
    );
    match &instrs[1] {
        Instruction::Jump { target } => {
            assert_eq!(*target, 1, "jump should retarget to canonical label")
        }
        other => panic!("expected jump after label, got {other:?}"),
    }
    let label_count = instrs
        .iter()
        .filter(|i| matches!(i, Instruction::Label(_)))
        .count();
    assert_eq!(label_count, 1);
}

#[test]
fn deduped_labels_retarget_jumps_across_blocks() {
    let module = Module {
        functions: vec![Function {
            name: "labels2".to_string(),
            kind: IrFunctionKind::Regular,
            parameters: vec![],
            returns: vec![],
            basic_blocks: vec![
                BasicBlock {
                    instructions: vec![Instruction::Jump { target: 2 }, Instruction::ReturnVoid],
                },
                BasicBlock {
                    instructions: vec![
                        Instruction::Label(1),
                        Instruction::Label(2),
                        Instruction::ReturnVoid,
                    ],
                },
            ],
            local_count: 0,
        }],
        state_variables: vec![],
        events: vec![],
    };

    let optimized = optimize_ir(module, 3);
    let jump_instrs = &optimized.functions[0].basic_blocks[0].instructions;
    match &jump_instrs[0] {
        Instruction::Jump { target } => assert_eq!(
            *target, 1,
            "jump should retarget to canonical label across blocks"
        ),
        other => panic!("expected jump instruction, got {other:?}"),
    }
    let label_instrs = &optimized.functions[0].basic_blocks[1].instructions;
    assert!(
        matches!(label_instrs[0], Instruction::Label(1)),
        "first label should be retained"
    );
    let label_count = label_instrs
        .iter()
        .filter(|i| matches!(i, Instruction::Label(_)))
        .count();
    assert_eq!(label_count, 1);
}