def insert_ref_count_opcodes(ir: FuncIR) -> None: """Insert reference count inc/dec opcodes to a function. This is the entry point to this module. """ cfg = get_cfg(ir.blocks) borrowed = set(reg for reg in ir.env.regs() if reg.is_borrowed) args = set(reg for reg in ir.env.regs() if ir.env.indexes[reg] < len(ir.args)) regs = [reg for reg in ir.env.regs() if isinstance(reg, Register)] live = analyze_live_regs(ir.blocks, cfg) borrow = analyze_borrowed_arguments(ir.blocks, cfg, borrowed) defined = analyze_must_defined_regs(ir.blocks, cfg, args, regs) cache = {} # type: BlockCache for block in ir.blocks[:]: if isinstance(block.ops[-1], (Branch, Goto)): insert_branch_inc_and_decrefs(block, cache, ir.blocks, live.before, borrow.before, borrow.after, defined.after, ir.env) transform_block(block, live.before, live.after, borrow.before, defined.after, ir.env) # Find all the xdecs we inserted and note the registers down as # needing to be initialized. for block in ir.blocks: for op in block.ops: if isinstance(op, DecRef) and op.is_xdec: ir.env.vars_needing_init.add(op.src) cleanup_cfg(ir.blocks)
def run_case(self, testcase: DataDrivenTestCase) -> None: """Perform a data-flow analysis test case.""" with use_custom_builtins( os.path.join(self.data_prefix, ICODE_GEN_BUILTINS), testcase): # replace native_int with platform specific ints int_format_str = 'int32' if IS_32_BIT_PLATFORM else 'int64' testcase.output = [ s.replace('native_int', int_format_str) for s in testcase.output ] try: ir = build_ir_for_single_file(testcase.input) except CompileError as e: actual = e.messages else: actual = [] for fn in ir: if (fn.name == TOP_LEVEL_NAME and not testcase.name.endswith('_toplevel')): continue exceptions.insert_exception_handling(fn) actual.extend(format_func(fn)) cfg = analysis.get_cfg(fn.blocks) args = set(reg for reg, i in fn.env.indexes.items() if i < len(fn.args)) name = testcase.name if name.endswith('_MaybeDefined'): # Forward, maybe analysis_result = analysis.analyze_maybe_defined_regs( fn.blocks, cfg, args) elif name.endswith('_Liveness'): # Backward, maybe analysis_result = analysis.analyze_live_regs( fn.blocks, cfg) elif name.endswith('_MustDefined'): # Forward, must analysis_result = analysis.analyze_must_defined_regs( fn.blocks, cfg, args, regs=fn.env.regs()) elif name.endswith('_BorrowedArgument'): # Forward, must analysis_result = analysis.analyze_borrowed_arguments( fn.blocks, cfg, args) else: assert False, 'No recognized _AnalysisName suffix in test case' for key in sorted(analysis_result.before.keys(), key=lambda x: (x[0].label, x[1])): pre = ', '.join( sorted(reg.name for reg in analysis_result.before[key])) post = ', '.join( sorted(reg.name for reg in analysis_result.after[key])) actual.append('%-8s %-23s %s' % ((key[0].label, key[1]), '{%s}' % pre, '{%s}' % post)) assert_test_output(testcase, actual, 'Invalid source code output')
def insert_ref_count_opcodes(ir: FuncIR) -> None: """Insert reference count inc/dec opcodes to a function. This is the entry point to this module. """ cfg = get_cfg(ir.blocks) args = set([Register(i) for i in range(len(ir.args))]) live = analyze_live_regs(ir.blocks, cfg) borrow = analyze_borrowed_arguments(ir.blocks, cfg, args) for block in ir.blocks[:]: if isinstance(block.ops[-1], (Branch, Goto)): insert_branch_inc_and_decrefs(block, ir.blocks, live.before, borrow.before, borrow.after, ir.env) transform_block(block, live.before, live.after, borrow.before, ir.env)
def insert_ref_count_opcodes(ir: FuncIR) -> None: """Insert reference count inc/dec opcodes to a function. This is the entry point to this module. """ cfg = get_cfg(ir.blocks) borrowed = set(reg for reg in ir.env.regs() if reg.is_borrowed) live = analyze_live_regs(ir.blocks, cfg) borrow = analyze_borrowed_arguments(ir.blocks, cfg, borrowed) cache = {} # type: BlockCache for block in ir.blocks[:]: if isinstance(block.ops[-1], (Branch, Goto)): insert_branch_inc_and_decrefs(block, cache, ir.blocks, live.before, borrow.before, borrow.after, ir.env) transform_block(block, live.before, live.after, borrow.before, ir.env)
def run_case(self, testcase: DataDrivenTestCase) -> None: """Perform a data-flow analysis test case.""" with use_custom_builtins(os.path.join(self.data_prefix, ICODE_GEN_BUILTINS), testcase): program_text = '\n'.join(testcase.input) options = Options() options.use_builtins_fixtures = True options.show_traceback = True options.python_version = (3, 6) options.export_types = True source = build.BuildSource('main', '__main__', program_text) try: # Construct input as a single single. # Parse and type check the input program. result = build.build(sources=[source], options=options, alt_lib_path=test_temp_dir) except CompileError as e: actual = e.messages else: if result.errors: actual = result.errors else: modules = genops.build_ir([result.files['__main__']], result.types) module = modules[0][1] assert len(module.functions) == 2, ( "Only 1 function definition expected per test case") fn = module.functions[0] actual = format_func(fn) actual = actual[actual.index('L0:'):] cfg = analysis.get_cfg(fn.blocks) args = set(reg for reg, i in fn.env.indexes.items() if i < len(fn.args)) name = testcase.name if name.endswith('_MaybeDefined'): # Forward, maybe analysis_result = analysis.analyze_maybe_defined_regs(fn.blocks, cfg, args) elif name.endswith('_Liveness'): # Backward, maybe analysis_result = analysis.analyze_live_regs(fn.blocks, cfg) elif name.endswith('_MustDefined'): # Forward, must analysis_result = analysis.analyze_must_defined_regs( fn.blocks, cfg, args, regs=fn.env.regs()) elif name.endswith('_BorrowedArgument'): # Forward, must analysis_result = analysis.analyze_borrowed_arguments(fn.blocks, cfg, args) else: assert False, 'No recognized _AnalysisName suffix in test case' actual.append('') for key in sorted(analysis_result.before.keys(), key=lambda x: (x[0].label, x[1])): pre = ', '.join(sorted(reg.name for reg in analysis_result.before[key])) post = ', '.join(sorted(reg.name for reg in analysis_result.after[key])) actual.append('%-8s %-23s %s' % ((key[0].label, key[1]), '{%s}' % pre, '{%s}' % post)) assert_test_output(testcase, actual, 'Invalid source code output')
def run_case(self, testcase: DataDrivenTestCase) -> None: """Perform a data-flow analysis test case.""" with use_custom_builtins( os.path.join(test_data_prefix, ICODE_GEN_BUILTINS), testcase): expected_output = testcase.output program_text = '\n'.join(testcase.input) options = Options() options.use_builtins_fixtures = True options.show_traceback = True source = build.BuildSource('main', '__main__', program_text) try: # Construct input as a single single. # Parse and type check the input program. result = build.build(sources=[source], options=options, alt_lib_path=test_temp_dir) except CompileError as e: actual = e.messages else: if result.errors: actual = result.errors else: module = genops.build_ir(result.files['__main__'], result.types) assert len( module.functions ) == 1, "Only 1 function definition expected per test case" fn = module.functions[0] actual = format_func(fn) actual = actual[actual.index('L0:'):] cfg = analysis.get_cfg(fn.blocks) args = set([Register(i) for i in range(len(fn.args))]) name = testcase.name if name.endswith('_MaybeDefined'): # Forward, maybe analysis_result = analysis.analyze_maybe_defined_regs( fn.blocks, cfg, args) elif name.endswith('_Liveness'): # Backward, maybe analysis_result = analysis.analyze_live_regs( fn.blocks, cfg) elif name.endswith('_MustDefined'): # Forward, must analysis_result = analysis.analyze_must_defined_regs( fn.blocks, cfg, args, num_regs=fn.env.num_regs()) elif name.endswith('_BorrowedArgument'): # Forward, must analysis_result = analysis.analyze_borrowed_arguments( fn.blocks, cfg, args) else: assert False, 'No recognized _AnalysisName suffix in test case' actual.append('') for key in sorted(analysis_result.before.keys()): pre = ', '.join(fn.env.names[reg] for reg in analysis_result.before[key]) post = ', '.join(fn.env.names[reg] for reg in analysis_result.after[key]) actual.append('%-8s %-23s %s' % (key, '{%s}' % pre, '{%s}' % post)) assert_string_arrays_equal_wildcards( expected_output, actual, 'Invalid source code output ({}, line {})'.format( testcase.file, testcase.line))