def test_branch_conditional_direct(resources, tmpdir):
    test_file = os.path.join(resources, 'branch_conditional_direct.pbtxt')
    cfg = user_callgraph.Callgraph.from_proto(test_file)
    source_gen = source_generator.SourceGenerator(tmpdir, cfg)
    source_gen.write_files()
    output = compile_and_check_function_for_asm(
        tmpdir, 'function_2',
        switch_processor(X86_CONDITIONAL_DIRECT, ARM_CONDITIONAL_DIRECT))
    assert output, 'Missing indirect branch'
def test_branch_implicit_fallthrough(resources, tmpdir):
    test_file = os.path.join(resources, 'branch_implicit_fallthrough.pbtxt')
    cfg = user_callgraph.Callgraph.from_proto(test_file)
    source_gen = source_generator.SourceGenerator(tmpdir, cfg)
    source_gen.write_files()
    output = compile_and_check_function_for_asm(
        tmpdir, 'function_2',
        switch_processor(X86_CONDITIONAL_DIRECT, ARM_CONDITIONAL_DIRECT))
    assert output, 'Implicit fallthrough branch error'
def test_branch_direct_call(resources, tmpdir):
    test_file = os.path.join(resources, 'branch_direct_call.pbtxt')
    cfg = user_callgraph.Callgraph.from_proto(test_file)
    source_gen = source_generator.SourceGenerator(tmpdir, cfg)
    source_gen.write_files()
    output = compile_and_check_function_for_asm(
        tmpdir, 'function_2', switch_processor(X86_DIRECT_CALL,
                                               ARM_DIRECT_CALL))
    assert output, 'Missing direct function call'
def test_prefetch_off(resources, tmpdir):
    test_file = os.path.join(resources, 'prefetch_cb.pbtxt')
    cfg = user_callgraph.Callgraph.from_proto(test_file)
    source_gen = source_generator.SourceGenerator(tmpdir, cfg)
    source_gen.write_files()
    # Prefetch does not exist on x86, but we still want to ensure code compiles
    result = compile_and_check_function_for_asm(tmpdir, 'function_0', 'prfm')
    if platform.machine() == 'aarch64':
        assert not result
def test_write_onecallchain(resources, tmpdir):
    test_file = os.path.join(resources, 'onecallchain.pbtxt')
    expected_dir = os.path.join(resources, 'write_onecallchain')
    cfg = user_callgraph.Callgraph.from_proto(test_file)
    source_gen = source_generator.SourceGenerator(tmpdir, cfg)
    source_gen.write_files(num_files=1)
    output = dircmp(tmpdir, expected_dir)
    diff_files = set(output.same_files) ^ set(output.left_list)
    assert diff_files == set(), f'Different files: {diff_files}'
def test_dfs(resources, tmpdir, num_files):
    depth = 10
    test_file = os.path.join(resources, 'dfs', f'dfs_depth{depth}_cfg.pb')
    cfg = user_callgraph.Callgraph.from_proto(test_file)
    source_gen = source_generator.SourceGenerator(tmpdir, cfg)
    source_gen.write_files(num_files)
    misc_c_files = ['main.c']
    c_files = glob.glob(f'{tmpdir}/*.c')
    assert len(c_files) == pytest.approx(num_files + len(misc_c_files), 1)
    for c_file in c_files:
        with open(c_file, 'r') as f:
            matches = re.findall(source_gen.get_header_import_string(),
                                 f.read())
            assert len(matches) == 1
Example #7
0
#!/usr/bin/python3
"""Generate source files from provided callgraph."""

import argparse
from frontend.code_generator import source_generator
from frontend.code_generator import user_callgraph

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('callgraph', type=str, help='path to cfg protobuf')
    parser.add_argument('output_dir',
                        type=str,
                        help='directory to output c/source files to')
    parser.add_argument('--num-files',
                        default=None,
                        type=int,
                        help='number of c files to write to')
    args = parser.parse_args()
    callgraph = user_callgraph.Callgraph.from_proto(args.callgraph)
    sg = source_generator.SourceGenerator(args.output_dir, callgraph)
    sg.write_files(args.num_files)