diff --git a/expected_results.json b/expected_results.json index 07bcd11c..1c57377f 100644 --- a/expected_results.json +++ b/expected_results.json @@ -1 +1 @@ -{"chapter_6/valid/rh_assignment.c": {"return_code": 1}, "chapter_6/valid/if_nested_2.c": {"return_code": 2}, "chapter_6/valid/if_nested_3.c": {"return_code": 3}, "chapter_6/valid/nested_ternary.c": {"return_code": 7}, "chapter_6/valid/binary_false_condition.c": {"return_code": 0}, "chapter_6/valid/else.c": {"return_code": 2}, "chapter_6/valid/nested_ternary_2.c": {"return_code": 15}, "chapter_6/valid/ternary_short_circuit.c": {"return_code": 1}, "chapter_6/valid/multiple_if.c": {"return_code": 8}, "chapter_6/valid/if_null_body.c": {"return_code": 1}, "chapter_6/valid/ternary_rh_binop.c": {"return_code": 1}, "chapter_6/valid/ternary_middle_assignment.c": {"return_code": 2}, "chapter_6/valid/if_nested_4.c": {"return_code": 4}, "chapter_6/valid/ternary_middle_binop.c": {"return_code": 1}, "chapter_6/valid/if_taken.c": {"return_code": 1}, "chapter_6/valid/if_not_taken.c": {"return_code": 0}, "chapter_6/valid/if_nested_5.c": {"return_code": 1}, "chapter_6/valid/assign_ternary.c": {"return_code": 2}, "chapter_6/valid/ternary.c": {"return_code": 4}, "chapter_6/valid/if_nested.c": {"return_code": 1}, "chapter_6/valid/ternary_short_circuit_2.c": {"return_code": 2}, "chapter_6/valid/binary_condition.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label_and_var.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label_main_2.c": {"return_code": 0}, "chapter_6/valid/extra_credit/bitwise_ternary.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label_main.c": {"return_code": 0}, "chapter_6/valid/extra_credit/goto_nested_label.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_backwards.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label.c": {"return_code": 1}, "chapter_6/valid/extra_credit/compound_if_expression.c": {"return_code": 1}, "chapter_6/valid/extra_credit/goto_after_declaration.c": {"return_code": 1}, "chapter_8/valid/for.c": {"return_code": 16}, "chapter_8/valid/continue.c": {"return_code": 1}, "chapter_8/valid/multi_continue_same_loop.c": {"return_code": 1}, "chapter_8/valid/for_absent_post.c": {"return_code": 0}, "chapter_8/valid/null_for_header.c": {"return_code": 4}, "chapter_8/valid/nested_loop.c": {"return_code": 1}, "chapter_8/valid/nested_break.c": {"return_code": 250}, "chapter_8/valid/do_while.c": {"return_code": 16}, "chapter_8/valid/for_absent_condition.c": {"return_code": 0}, "chapter_8/valid/do_while_break_immediate.c": {"return_code": 10}, "chapter_8/valid/continue_empty_post.c": {"return_code": 30}, "chapter_8/valid/nested_continue.c": {"return_code": 24}, "chapter_8/valid/break.c": {"return_code": 1}, "chapter_8/valid/for_nested_shadow.c": {"return_code": 1}, "chapter_8/valid/empty_expression.c": {"return_code": 0}, "chapter_8/valid/multi_break.c": {"return_code": 1}, "chapter_8/valid/for_decl.c": {"return_code": 101}, "chapter_8/valid/for_shadow.c": {"return_code": 1}, "chapter_8/valid/break_immediate.c": {"return_code": 1}, "chapter_8/valid/while.c": {"return_code": 6}, "chapter_8/valid/empty_loop_body.c": {"return_code": 252}, "chapter_8/valid/extra_credit/switch_fallthrough.c": {"return_code": 4}, "chapter_8/valid/extra_credit/compound_assignment_for_loop.c": {"return_code": 10}, "chapter_8/valid/extra_credit/switch_break.c": {"return_code": 5}, "chapter_8/valid/extra_credit/switch_default.c": {"return_code": 22}, "chapter_8/valid/extra_credit/switch_default_fallthrough.c": {"return_code": 0}, "chapter_8/valid/extra_credit/switch_with_loop.c": {"return_code": 123}, "chapter_8/valid/extra_credit/switch_assign_in_body.c": {"return_code": 3}, "chapter_8/valid/extra_credit/switch_in_loop.c": {"return_code": 1}, "chapter_8/valid/extra_credit/switch_no_case.c": {"return_code": 4}, "chapter_8/valid/extra_credit/switch_nested_case.c": {"return_code": 3}, "chapter_8/valid/extra_credit/switch_nested_not_taken.c": {"return_code": 2}, "chapter_8/valid/extra_credit/switch_decl.c": {"return_code": 7}, "chapter_8/valid/extra_credit/switch_with_continue.c": {"return_code": 5}, "chapter_8/valid/extra_credit/switch_empty.c": {"return_code": 10}, "chapter_8/valid/extra_credit/goto_loop_body.c": {"return_code": 1}, "chapter_8/valid/extra_credit/goto_bypass_condition.c": {"return_code": 10}, "chapter_8/valid/extra_credit/switch_nested_switch.c": {"return_code": 1}, "chapter_8/valid/extra_credit/switch_block.c": {"return_code": 1}, "chapter_8/valid/extra_credit/switch_default_not_last.c": {"return_code": 0}, "chapter_8/valid/extra_credit/switch_assign_in_condition.c": {"return_code": 2}, "chapter_8/valid/extra_credit/switch.c": {"return_code": 3}, "chapter_8/valid/extra_credit/switch_goto_mid_case.c": {"return_code": 1}, "chapter_14/valid/libraries/static_pointer.c": {"return_code": 0}, "chapter_14/valid/libraries/global_pointer.c": {"return_code": 1}, "chapter_14/valid/function_calls/address_of_argument.c": {"return_code": 0}, "chapter_14/valid/function_calls/update_value_through_pointer_parameter.c": {"return_code": 0}, "chapter_14/valid/function_calls/return_pointer.c": {"return_code": 0}, "chapter_14/valid/extra_credit/incr_through_pointer.c": {"return_code": 11}, "chapter_14/valid/extra_credit/compound_assign_through_pointer.c": {"return_code": 1}, "chapter_14/valid/declarators/declare_pointer_in_for_loop.c": {"return_code": 5}, "chapter_14/valid/declarators/abstract_declarators.c": {"return_code": 0}, "chapter_14/valid/declarators/declarators.c": {"return_code": 0}, "chapter_14/valid/dereference/static_var_indirection.c": {"return_code": 0}, "chapter_14/valid/dereference/multilevel_indirection.c": {"return_code": 0}, "chapter_14/valid/dereference/read_through_pointers.c": {"return_code": 0}, "chapter_14/valid/dereference/update_through_pointers.c": {"return_code": 0}, "chapter_14/valid/dereference/address_of_dereference.c": {"return_code": 0}, "chapter_14/valid/dereference/simple.c": {"return_code": 3}, "chapter_14/valid/dereference/dereference_expression_result.c": {"return_code": 0}, "chapter_14/valid/casts/cast_between_pointer_types.c": {"return_code": 0}, "chapter_14/valid/casts/pointer_int_casts.c": {"return_code": 0}, "chapter_14/valid/casts/null_pointer_conversion.c": {"return_code": 0}, "chapter_14/valid/comparisons/compare_pointers.c": {"return_code": 0}, "chapter_14/valid/comparisons/pointers_as_conditions.c": {"return_code": 0}, "chapter_14/valid/comparisons/compare_to_null.c": {"return_code": 0}, "chapter_10/valid/static_then_extern.c": {"return_code": 3}, "chapter_10/valid/push_arg_on_page_boundary.c": {"return_code": 1}, "chapter_10/valid/static_local_multiple_scopes.c": {"return_code": 0, "stdout": "Aa\nBb\nCc\nDd\nEe\nFf\nGg\nHh\nIi\nJj\nKk\nLl\nMm\nNn\nOo\nPp\nQq\nRr\nSs\nTt\nUu\nVv\nWw\nXx\nYy\nZz\n"}, "chapter_10/valid/tentative_definition.c": {"return_code": 5}, "chapter_10/valid/static_variables_in_expressions.c": {"return_code": 0}, "chapter_10/valid/static_recursive_call.c": {"return_code": 0, "stdout": "ABCDEFGHIJKLMNOPQRSTUVWXYZ"}, "chapter_10/valid/shadow_static_local_var.c": {"return_code": 0}, "chapter_10/valid/multiple_static_local.c": {"return_code": 29}, "chapter_10/valid/multiple_static_file_scope_vars.c": {"return_code": 4}, "chapter_10/valid/static_local_uninitialized.c": {"return_code": 4}, "chapter_10/valid/type_before_storage_class.c": {"return_code": 7}, "chapter_10/valid/extern_block_scope_variable.c": {"return_code": 3}, "chapter_10/valid/distinct_local_and_extern.c": {"return_code": 7}, "chapter_10/valid/libraries/internal_hides_external_linkage.c": {"return_code": 0}, "chapter_10/valid/libraries/external_tentative_var.c": {"return_code": 0}, "chapter_10/valid/libraries/external_linkage_function.c": {"return_code": 0}, "chapter_10/valid/libraries/external_variable.c": {"return_code": 0}, "chapter_10/valid/libraries/internal_linkage_var.c": {"return_code": 0}, "chapter_10/valid/libraries/external_var_scoping.c": {"return_code": 0}, "chapter_10/valid/libraries/internal_linkage_function.c": {"return_code": 0}, "chapter_10/valid/extra_credit/goto_skip_static_initializer.c": {"return_code": 10}, "chapter_2/valid/neg.c": {"return_code": 251}, "chapter_2/valid/negate_int_max.c": {"return_code": 1}, "chapter_2/valid/redundant_parens.c": {"return_code": 246}, "chapter_2/valid/neg_zero.c": {"return_code": 0}, "chapter_2/valid/bitwise_int_min.c": {"return_code": 254}, "chapter_2/valid/bitwise_zero.c": {"return_code": 255}, "chapter_2/valid/parens_3.c": {"return_code": 4}, "chapter_2/valid/parens_2.c": {"return_code": 253}, "chapter_2/valid/bitwise.c": {"return_code": 243}, "chapter_2/valid/nested_ops_2.c": {"return_code": 1}, "chapter_2/valid/nested_ops.c": {"return_code": 2}, "chapter_2/valid/parens.c": {"return_code": 254}, "chapter_1/valid/return_0.c": {"return_code": 0}, "chapter_1/valid/newlines.c": {"return_code": 0}, "chapter_1/valid/return_2.c": {"return_code": 2}, "chapter_1/valid/multi_digit.c": {"return_code": 100}, "chapter_1/valid/tabs.c": {"return_code": 0}, "chapter_1/valid/spaces.c": {"return_code": 0}, "chapter_1/valid/no_newlines.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/logical.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/arithmetic_ops.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/static_initialized_double.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/comparisons.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/simple.c": {"return_code": 1}, "chapter_13/valid/floating_expressions/loop_controlling_expression.c": {"return_code": 100}, "chapter_13/valid/libraries/double_parameters.c": {"return_code": 0}, "chapter_13/valid/libraries/use_arg_after_fun_call.c": {"return_code": 4}, "chapter_13/valid/libraries/double_and_int_params_recursive.c": {"return_code": 0}, "chapter_13/valid/libraries/extern_double.c": {"return_code": 1}, "chapter_13/valid/libraries/double_params_and_result.c": {"return_code": 1}, "chapter_13/valid/explicit_casts/cvttsd2i_rewrite.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/double_to_signed.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/unsigned_to_double.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/signed_to_double.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/double_to_unsigned.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/convert_for_assignment.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/common_type.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/static_initializers.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/complex_arithmetic_common_type.c": {"return_code": 1}, "chapter_13/valid/constants/round_constants.c": {"return_code": 0}, "chapter_13/valid/constants/constant_doubles.c": {"return_code": 0}, "chapter_13/valid/special_values/subnormal_not_zero.c": {"return_code": 0}, "chapter_13/valid/special_values/negative_zero.c": {"return_code": 0}, "chapter_13/valid/special_values/infinity.c": {"return_code": 0}, "chapter_13/valid/function_calls/double_parameters.c": {"return_code": 0}, "chapter_13/valid/function_calls/double_and_int_parameters.c": {"return_code": 0}, "chapter_13/valid/function_calls/standard_library_call.c": {"return_code": 0}, "chapter_13/valid/function_calls/use_arg_after_fun_call.c": {"return_code": 4}, "chapter_13/valid/function_calls/return_double.c": {"return_code": 1}, "chapter_13/valid/function_calls/double_and_int_params_recursive.c": {"return_code": 0}, "chapter_13/valid/extra_credit/compound_assign.c": {"return_code": 1}, "chapter_13/valid/extra_credit/nan.c": {"return_code": 0}, "chapter_13/valid/extra_credit/compound_assign_implicit_cast.c": {"return_code": 1}, "chapter_18/valid/params_and_returns/temporary_lifetime.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/ignore_retval.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_space_overlap.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_big_struct_on_page_boundary.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/simple.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_struct_on_page_boundary.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_incomplete_type.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/stack_clobber.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/libraries/return_calling_conventions.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/libraries/missing_retval.c": {"return_code": 1}, "chapter_18/valid/params_and_returns/libraries/access_retval_members.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/libraries/retval_struct_sizes.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/semantic_analysis/resolve_tags.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/semantic_analysis/namespaces.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/semantic_analysis/incomplete_structs.c": {"return_code": 0, "stdout": "I'm a struct!\n"}, "chapter_18/valid/no_structure_parameters/semantic_analysis/cast_struct_to_void.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/global_struct.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/param_struct_pointer.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/return_struct_pointer.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/opaque_struct.c": {"return_code": 0, "stdout": "new struct\nstatic struct\nglobal struct\n"}, "chapter_18/valid/no_structure_parameters/libraries/array_of_structs.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/auto_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/static_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/nested_static_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/nested_auto_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/smoke_tests/static_vs_auto.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/smoke_tests/simple.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/size_and_offset_calculations/member_offsets.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/size_and_offset_calculations/sizeof_exps.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/size_and_offset_calculations/sizeof_type.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/arrow.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/linked_list.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/static_structs.c": {"return_code": 0, "stdout": "zero\nmn\nop\nwx\nyz\nBCD\nCDE\nDEF\nEFG\nbcd\ncde\n"}, "chapter_18/valid/no_structure_parameters/scalar_member_access/nested_struct.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/dot.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/parse_and_lex/postfix_precedence.c": {"return_code": 1}, "chapter_18/valid/no_structure_parameters/parse_and_lex/trailing_comma.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/parse_and_lex/space_around_struct_member.c": {"return_code": 1}, "chapter_18/valid/no_structure_parameters/parse_and_lex/struct_member_looks_like_const.c": {"return_code": 3}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct_through_pointer.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct_with_arrow_operator.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/stack_clobber.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct_with_dot_operator.c": {"return_code": 0}, "chapter_18/valid/parameters/pass_args_on_page_boundary.c": {"return_code": 0}, "chapter_18/valid/parameters/incomplete_param_type.c": {"return_code": 3}, "chapter_18/valid/parameters/simple.c": {"return_code": 0}, "chapter_18/valid/parameters/stack_clobber.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/param_calling_conventions.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/struct_sizes.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/pass_struct.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/modify_param.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/classify_params.c": {"return_code": 0}, "chapter_15/valid/initialization/automatic.c": {"return_code": 0}, "chapter_15/valid/initialization/static.c": {"return_code": 0}, "chapter_15/valid/initialization/trailing_comma_initializer.c": {"return_code": 3}, "chapter_15/valid/initialization/automatic_nested.c": {"return_code": 0}, "chapter_15/valid/initialization/static_nested.c": {"return_code": 0}, "chapter_15/valid/libraries/set_array_val.c": {"return_code": 0}, "chapter_15/valid/libraries/return_pointer_to_array.c": {"return_code": 0}, "chapter_15/valid/libraries/global_array.c": {"return_code": 0}, "chapter_15/valid/subscripting/subscript_nested.c": {"return_code": 0}, "chapter_15/valid/subscripting/subscript_pointer.c": {"return_code": 0}, "chapter_15/valid/subscripting/array_of_pointers_to_arrays.c": {"return_code": 0}, "chapter_15/valid/subscripting/simple_subscripts.c": {"return_code": 0}, "chapter_15/valid/subscripting/simple.c": {"return_code": 3}, "chapter_15/valid/subscripting/complex_operands.c": {"return_code": 0}, "chapter_15/valid/subscripting/addition_subscript_equivalence.c": {"return_code": 0}, "chapter_15/valid/subscripting/subscript_precedence.c": {"return_code": 1}, "chapter_15/valid/allocation/test_alignment.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/pointer_add.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/add_dereference_and_assign.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/pointer_diff.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/compare.c": {"return_code": 0}, "chapter_15/valid/extra_credit/incr_ptr.c": {"return_code": 1}, "chapter_15/valid/declarators/big_array.c": {"return_code": 0}, "chapter_15/valid/declarators/equivalent_declarators.c": {"return_code": 0}, "chapter_15/valid/declarators/return_nested_array.c": {"return_code": 0}, "chapter_15/valid/declarators/array_as_argument.c": {"return_code": 0}, "chapter_15/valid/declarators/for_loop_array.c": {"return_code": 0}, "chapter_15/valid/casts/multi_dim_casts.c": {"return_code": 0}, "chapter_15/valid/casts/implicit_and_explicit_conversions.c": {"return_code": 0}, "chapter_15/valid/casts/cast_array_of_pointers.c": {"return_code": 1}, "chapter_17/valid/void/cast_to_void.c": {"return_code": 12}, "chapter_17/valid/void/void_function.c": {"return_code": 0}, "chapter_17/valid/void/void_for_loop.c": {"return_code": 0, "stdout": "ZYXWVUTSRQPONMLKJIHGFEDCBAABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUTSRQPONMLKJIHGFEDCBA"}, "chapter_17/valid/void/ternary.c": {"return_code": 0}, "chapter_17/valid/libraries/pass_alloced_memory.c": {"return_code": 0}, "chapter_17/valid/libraries/test_for_memory_leaks.c": {"return_code": 0}, "chapter_17/valid/libraries/sizeof_extern.c": {"return_code": 1}, "chapter_17/valid/sizeof/sizeof_basic_types.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_consts.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_expressions.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_array.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_derived_types.c": {"return_code": 0}, "chapter_17/valid/sizeof/simple.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_result_is_ulong.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_not_evaluated.c": {"return_code": 4}, "chapter_17/valid/void_pointer/array_of_pointers_to_void.c": {"return_code": 0}, "chapter_17/valid/void_pointer/conversion_by_assignment.c": {"return_code": 0}, "chapter_17/valid/void_pointer/explicit_cast.c": {"return_code": 0}, "chapter_17/valid/void_pointer/simple.c": {"return_code": 100}, "chapter_17/valid/void_pointer/memory_management_functions.c": {"return_code": 0}, "chapter_17/valid/void_pointer/common_pointer_type.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/addr_of_string.c": {"return_code": 0, "stdout": "Sample\tstring!\n\n"}, "chapter_16/valid/strings_as_lvalues/standard_library_calls.c": {"return_code": 0, "stdout": "Hello, World!\n"}, "chapter_16/valid/strings_as_lvalues/array_of_strings.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/cast_string_pointer.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/empty_string.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/pointer_operations.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/simple.c": {"return_code": 108}, "chapter_16/valid/strings_as_lvalues/adjacent_strings.c": {"return_code": 0, "stdout": "Hello, World\n"}, "chapter_16/valid/strings_as_lvalues/string_special_characters.c": {"return_code": 0, "stdout": "Hello\"world\nHello\\World\nLine\nbreak!\nTesting, 123.\n^@1 _\\]\n"}, "chapter_16/valid/strings_as_lvalues/strings_in_function_calls.c": {"return_code": 0}, "chapter_16/valid/libraries/return_char.c": {"return_code": 0}, "chapter_16/valid/libraries/char_arguments.c": {"return_code": 0}, "chapter_16/valid/libraries/global_char.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/array_init_special_chars.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/terminating_null_bytes.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/simple.c": {"return_code": 99}, "chapter_16/valid/strings_as_initializers/partial_initialize_via_string.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/adjacent_strings_in_initializer.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/transfer_by_eightbyte.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/literals_and_compound_initializers.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/write_to_array.c": {"return_code": 0, "stdout": "abc\nabx\nHello\nWorld\nJello\n"}, "chapter_16/valid/strings_as_initializers/test_alignment.c": {"return_code": 0}, "chapter_16/valid/char_constants/return_char_constant.c": {"return_code": 99}, "chapter_16/valid/char_constants/escape_sequences.c": {"return_code": 0}, "chapter_16/valid/char_constants/control_characters.c": {"return_code": 0}, "chapter_16/valid/char_constants/char_constant_operations.c": {"return_code": 0}, "chapter_16/valid/chars/partial_initialization.c": {"return_code": 0}, "chapter_16/valid/chars/convert_by_assignment.c": {"return_code": 0}, "chapter_16/valid/chars/type_specifiers.c": {"return_code": 0}, "chapter_16/valid/chars/push_arg_on_page_boundary.c": {"return_code": 1}, "chapter_16/valid/chars/integer_promotion.c": {"return_code": 0}, "chapter_16/valid/chars/chained_casts.c": {"return_code": 0}, "chapter_16/valid/chars/return_char.c": {"return_code": 0}, "chapter_16/valid/chars/char_arguments.c": {"return_code": 0}, "chapter_16/valid/chars/char_expressions.c": {"return_code": 0}, "chapter_16/valid/chars/access_through_char_pointer.c": {"return_code": 0}, "chapter_16/valid/chars/common_type.c": {"return_code": 0}, "chapter_16/valid/chars/static_initializers.c": {"return_code": 0}, "chapter_16/valid/chars/explicit_casts.c": {"return_code": 0}, "chapter_9/valid/arguments_in_registers/parameter_shadows_own_function.c": {"return_code": 2}, "chapter_9/valid/arguments_in_registers/expression_args.c": {"return_code": 2}, "chapter_9/valid/arguments_in_registers/single_arg.c": {"return_code": 6}, "chapter_9/valid/arguments_in_registers/hello_world.c": {"return_code": 0, "stdout": "Hello, World!\n"}, "chapter_9/valid/arguments_in_registers/parameter_shadows_function.c": {"return_code": 3}, "chapter_9/valid/arguments_in_registers/parameters_are_preserved.c": {"return_code": 1}, "chapter_9/valid/arguments_in_registers/forward_decl_multi_arg.c": {"return_code": 1}, "chapter_9/valid/arguments_in_registers/fibonacci.c": {"return_code": 8}, "chapter_9/valid/arguments_in_registers/param_shadows_local_var.c": {"return_code": 20}, "chapter_9/valid/no_arguments/function_shadows_variable.c": {"return_code": 11}, "chapter_9/valid/no_arguments/use_function_in_expression.c": {"return_code": 21}, "chapter_9/valid/no_arguments/no_return_value.c": {"return_code": 3}, "chapter_9/valid/no_arguments/multiple_declarations.c": {"return_code": 3}, "chapter_9/valid/no_arguments/precedence.c": {"return_code": 0}, "chapter_9/valid/no_arguments/forward_decl.c": {"return_code": 3}, "chapter_9/valid/no_arguments/variable_shadows_function.c": {"return_code": 7}, "chapter_9/valid/libraries/system_call.c": {"return_code": 0, "stdout": "H"}, "chapter_9/valid/libraries/many_args.c": {"return_code": 115}, "chapter_9/valid/libraries/addition.c": {"return_code": 3}, "chapter_9/valid/libraries/no_function_calls/division.c": {"return_code": 1}, "chapter_9/valid/libraries/no_function_calls/local_stack_variables.c": {"return_code": 100}, "chapter_9/valid/extra_credit/compound_assign_function_result.c": {"return_code": 1}, "chapter_9/valid/extra_credit/goto_label_multiple_functions.c": {"return_code": 5}, "chapter_9/valid/extra_credit/goto_shared_name.c": {"return_code": 1}, "chapter_9/valid/stack_arguments/call_putchar.c": {"return_code": 8, "stdout": "A"}, "chapter_9/valid/stack_arguments/lots_of_arguments.c": {"return_code": 1}, "chapter_9/valid/stack_arguments/stack_alignment.c": {"return_code": 1}, "chapter_9/valid/stack_arguments/test_for_memory_leaks.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/logical.c": {"return_code": 0}, "chapter_12/valid/unsigned_expressions/arithmetic_wraparound.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/arithmetic_ops.c": {"return_code": 0}, "chapter_12/valid/unsigned_expressions/comparisons.c": {"return_code": 0}, "chapter_12/valid/unsigned_expressions/simple.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/static_variables.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/locals.c": {"return_code": 0}, "chapter_12/valid/libraries/unsigned_args.c": {"return_code": 0}, "chapter_12/valid/libraries/unsigned_global_var.c": {"return_code": 1}, "chapter_12/valid/explicit_casts/same_size_conversion.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/extension.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/round_trip_casts.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/chained_casts.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/truncate.c": {"return_code": 0}, "chapter_12/valid/type_specifiers/signed_type_specifiers.c": {"return_code": 0}, "chapter_12/valid/type_specifiers/unsigned_type_specifiers.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/convert_by_assignment.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/promote_constants.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/common_type.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/static_initializers.c": {"return_code": 0}, "chapter_12/valid/extra_credit/switch_uint.c": {"return_code": 0}, "chapter_12/valid/extra_credit/compound_assign_uint.c": {"return_code": 1}, "chapter_12/valid/extra_credit/bitwise_unsigned_shift.c": {"return_code": 1}, "chapter_12/valid/extra_credit/bitwise_unsigned_ops.c": {"return_code": 1}, "chapter_5/valid/null_then_return.c": {"return_code": 0}, "chapter_5/valid/empty_function_body.c": {"return_code": 0}, "chapter_5/valid/short_circuit_or.c": {"return_code": 0}, "chapter_5/valid/assignment_in_initializer.c": {"return_code": 0}, "chapter_5/valid/non_short_circuit_or.c": {"return_code": 1}, "chapter_5/valid/null_statement.c": {"return_code": 0}, "chapter_5/valid/short_circuit_and_fail.c": {"return_code": 0}, "chapter_5/valid/local_var_missing_return.c": {"return_code": 0}, "chapter_5/valid/exp_then_declaration.c": {"return_code": 1}, "chapter_5/valid/add_variables.c": {"return_code": 3}, "chapter_5/valid/assign_val_in_initializer.c": {"return_code": 5}, "chapter_5/valid/assignment_lowest_precedence.c": {"return_code": 1}, "chapter_5/valid/allocate_temps_and_vars.c": {"return_code": 1}, "chapter_5/valid/use_assignment_result.c": {"return_code": 4}, "chapter_5/valid/use_val_in_own_initializer.c": {"return_code": 0}, "chapter_5/valid/unused_exp.c": {"return_code": 0}, "chapter_5/valid/return_var.c": {"return_code": 2}, "chapter_5/valid/mixed_precedence_assignment.c": {"return_code": 4}, "chapter_5/valid/assign.c": {"return_code": 2}, "chapter_5/valid/extra_credit/bitwise_shiftr_assign.c": {"return_code": 77}, "chapter_5/valid/extra_credit/bitwise_shiftl_variable.c": {"return_code": 24}, "chapter_5/valid/extra_credit/compound_bitwise_and.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_minus.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_multiply.c": {"return_code": 12}, "chapter_5/valid/extra_credit/compound_bitwise_xor.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_bitwise_or.c": {"return_code": 31}, "chapter_5/valid/extra_credit/compound_assignment_chained.c": {"return_code": 4}, "chapter_5/valid/extra_credit/compound_divide.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_bitwise_shiftr.c": {"return_code": 102}, "chapter_5/valid/extra_credit/compound_assignment_use_result.c": {"return_code": 8}, "chapter_5/valid/extra_credit/compound_bitwise_shiftl.c": {"return_code": 48}, "chapter_5/valid/extra_credit/compound_plus.c": {"return_code": 4}, "chapter_5/valid/extra_credit/compound_mod.c": {"return_code": 2}, "chapter_5/valid/extra_credit/bitwise_and_vars.c": {"return_code": 1}, "chapter_7/valid/declaration_only.c": {"return_code": 1}, "chapter_7/valid/assign_to_self_2.c": {"return_code": 3}, "chapter_7/valid/hidden_then_visible.c": {"return_code": 1}, "chapter_7/valid/hidden_variable.c": {"return_code": 1}, "chapter_7/valid/assign_to_self.c": {"return_code": 4}, "chapter_7/valid/inner_uninitialized.c": {"return_code": 4}, "chapter_7/valid/multiple_vars_same_name.c": {"return_code": 2}, "chapter_7/valid/use_in_inner_scope.c": {"return_code": 3}, "chapter_7/valid/empty_blocks.c": {"return_code": 30}, "chapter_7/valid/nested_if.c": {"return_code": 1}, "chapter_7/valid/similar_var_names.c": {"return_code": 28}, "chapter_7/valid/extra_credit/goto_before_declaration.c": {"return_code": 0}, "chapter_7/valid/extra_credit/compound_subtract_in_block.c": {"return_code": 1}, "chapter_7/valid/extra_credit/goto_inner_scope.c": {"return_code": 1}, "chapter_4/valid/le_true.c": {"return_code": 2}, "chapter_4/valid/ne_true.c": {"return_code": 1}, "chapter_4/valid/ge_false.c": {"return_code": 0}, "chapter_4/valid/not_zero.c": {"return_code": 1}, "chapter_4/valid/precedence_2.c": {"return_code": 0}, "chapter_4/valid/ge_true.c": {"return_code": 2}, "chapter_4/valid/eq_precedence.c": {"return_code": 1}, "chapter_4/valid/eq_false.c": {"return_code": 0}, "chapter_4/valid/or_short_circuit.c": {"return_code": 1}, "chapter_4/valid/not_sum.c": {"return_code": 1}, "chapter_4/valid/precedence_4.c": {"return_code": 1}, "chapter_4/valid/and_short_circuit.c": {"return_code": 0}, "chapter_4/valid/precedence_3.c": {"return_code": 0}, "chapter_4/valid/compare_arithmetic_results.c": {"return_code": 1}, "chapter_4/valid/and_false.c": {"return_code": 0}, "chapter_4/valid/precedence_5.c": {"return_code": 1}, "chapter_4/valid/associativity.c": {"return_code": 1}, "chapter_4/valid/gt_true.c": {"return_code": 1}, "chapter_4/valid/lt_false.c": {"return_code": 0}, "chapter_4/valid/or_true.c": {"return_code": 3}, "chapter_4/valid/or_false.c": {"return_code": 0}, "chapter_4/valid/eq_true.c": {"return_code": 1}, "chapter_4/valid/ne_false.c": {"return_code": 0}, "chapter_4/valid/multi_short_circuit.c": {"return_code": 0}, "chapter_4/valid/gt_false.c": {"return_code": 0}, "chapter_4/valid/operate_on_booleans.c": {"return_code": 0}, "chapter_4/valid/not.c": {"return_code": 0}, "chapter_4/valid/le_false.c": {"return_code": 0}, "chapter_4/valid/nested_ops.c": {"return_code": 0}, "chapter_4/valid/precedence.c": {"return_code": 1}, "chapter_4/valid/not_sum_2.c": {"return_code": 0}, "chapter_4/valid/and_true.c": {"return_code": 1}, "chapter_4/valid/lt_true.c": {"return_code": 1}, "chapter_4/valid/extra_credit/bitwise_precedence.c": {"return_code": 1}, "chapter_3/valid/mod.c": {"return_code": 0}, "chapter_3/valid/unop_add.c": {"return_code": 0}, "chapter_3/valid/associativity_3.c": {"return_code": 8}, "chapter_3/valid/mult.c": {"return_code": 6}, "chapter_3/valid/sub.c": {"return_code": 255}, "chapter_3/valid/div_neg.c": {"return_code": 254}, "chapter_3/valid/unop_parens.c": {"return_code": 253}, "chapter_3/valid/add.c": {"return_code": 3}, "chapter_3/valid/associativity.c": {"return_code": 252}, "chapter_3/valid/associativity_2.c": {"return_code": 1}, "chapter_3/valid/div.c": {"return_code": 2}, "chapter_3/valid/sub_neg.c": {"return_code": 3}, "chapter_3/valid/associativity_and_precedence.c": {"return_code": 10}, "chapter_3/valid/parens.c": {"return_code": 14}, "chapter_3/valid/precedence.c": {"return_code": 14}, "chapter_3/valid/extra_credit/bitwise_shiftr.c": {"return_code": 62}, "chapter_3/valid/extra_credit/bitwise_and.c": {"return_code": 1}, "chapter_3/valid/extra_credit/bitwise_shiftl.c": {"return_code": 140}, "chapter_3/valid/extra_credit/bitwise_or.c": {"return_code": 3}, "chapter_3/valid/extra_credit/bitwise_shift_precedence.c": {"return_code": 0}, "chapter_3/valid/extra_credit/bitwise_xor.c": {"return_code": 6}, "chapter_3/valid/extra_credit/bitwise_shift_associativity_2.c": {"return_code": 16}, "chapter_3/valid/extra_credit/bitwise_shift_associativity.c": {"return_code": 66}, "chapter_3/valid/extra_credit/bitwise_precedence.c": {"return_code": 21}, "chapter_11/valid/long_expressions/long_args.c": {"return_code": 0}, "chapter_11/valid/long_expressions/logical.c": {"return_code": 0}, "chapter_11/valid/long_expressions/type_specifiers.c": {"return_code": 0}, "chapter_11/valid/long_expressions/multi_op.c": {"return_code": 1}, "chapter_11/valid/long_expressions/large_constants.c": {"return_code": 0}, "chapter_11/valid/long_expressions/arithmetic_ops.c": {"return_code": 0}, "chapter_11/valid/long_expressions/return_long.c": {"return_code": 1}, "chapter_11/valid/long_expressions/comparisons.c": {"return_code": 0}, "chapter_11/valid/long_expressions/simple.c": {"return_code": 1}, "chapter_11/valid/long_expressions/static_long.c": {"return_code": 1}, "chapter_11/valid/long_expressions/long_and_int_locals.c": {"return_code": 0}, "chapter_11/valid/long_expressions/assign.c": {"return_code": 1}, "chapter_11/valid/libraries/long_args.c": {"return_code": 0}, "chapter_11/valid/libraries/maintain_stack_alignment.c": {"return_code": 12}, "chapter_11/valid/libraries/return_long.c": {"return_code": 1}, "chapter_11/valid/libraries/long_global_var.c": {"return_code": 0}, "chapter_11/valid/explicit_casts/truncate.c": {"return_code": 0}, "chapter_11/valid/explicit_casts/sign_extend.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/convert_by_assignment.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/common_type.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/long_constants.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/convert_function_arguments.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/convert_static_initializer.c": {"return_code": 0}, "chapter_11/valid/extra_credit/bitwise_long_op.c": {"return_code": 1}, "chapter_11/valid/extra_credit/compound_assign_to_int.c": {"return_code": 1}, "chapter_11/valid/extra_credit/compound_assign_to_long.c": {"return_code": 1}, "chapter_11/valid/extra_credit/switch_int.c": {"return_code": 1}, "chapter_11/valid/extra_credit/switch_long.c": {"return_code": 1}, "chapter_19/constant_folding/all_types/fold_truncate.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_cast_to_double.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_ulong.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_double.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_extensions_and_copies.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_long.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_uint.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_cast_from_double.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_unary.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_conditional_jump.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_binary.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_control_flow.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_exception.c": {"return_code": 0}, "chapter_19/unreachable_code_elimination/remove_useless_starting_label.c": {"return_code": 99}, "chapter_19/unreachable_code_elimination/dead_for_loop.c": {"return_code": 10}, "chapter_19/unreachable_code_elimination/keep_final_jump.c": {"return_code": 17}, "chapter_19/unreachable_code_elimination/remove_jump_keep_label.c": {"return_code": 10}, "chapter_19/unreachable_code_elimination/dead_branch_inside_loop.c": {"return_code": 19}, "chapter_19/unreachable_code_elimination/empty.c": {"return_code": 0}, "chapter_19/unreachable_code_elimination/infinite_loop.c": {"return_code": 11}, "chapter_19/unreachable_code_elimination/constant_if_else.c": {"return_code": 45}, "chapter_19/unreachable_code_elimination/dead_blocks_with_predecessors.c": {"return_code": 5}, "chapter_19/unreachable_code_elimination/remove_conditional_jumps.c": {"return_code": 1}, "chapter_19/unreachable_code_elimination/dead_after_return.c": {"return_code": 2}, "chapter_19/unreachable_code_elimination/empty_block.c": {"return_code": 1}, "chapter_19/unreachable_code_elimination/dead_after_if_else.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/pointer_arithmetic.c": {"return_code": 2}, "chapter_19/copy_propagation/all_types/store_doesnt_kill.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/unsigned_wraparound.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/propagate_doubles.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/unsigned_compare.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/signed_unsigned_conversion.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/char_type_conversion.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/not_char.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/char_round_trip_2.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/alias_analysis.c": {"return_code": 24}, "chapter_19/copy_propagation/all_types/const_fold_sign_extend.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/copy_struct.c": {"return_code": 6}, "chapter_19/copy_propagation/all_types/propagate_null_pointer.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/char_round_trip.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/const_fold_type_conversions.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/const_fold_sign_extend_2.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/dont_propagate/static_are_aliased.c": {"return_code": 8}, "chapter_19/copy_propagation/all_types/dont_propagate/store_kills_aliased.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/dont_propagate/copy_to_offset.c": {"return_code": 3}, "chapter_19/copy_propagation/all_types/dont_propagate/dont_propagate_addr_of.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/dont_propagate/type_conversion.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/dont_propagate/zero_neg_zero_different.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/dont_propagate/funcall_kills_aliased.c": {"return_code": 2}, "chapter_19/copy_propagation/int_only/propagate_fun_args.c": {"return_code": 220}, "chapter_19/copy_propagation/int_only/killed_then_redefined.c": {"return_code": 2}, "chapter_19/copy_propagation/int_only/redundant_copies_2.c": {"return_code": 10}, "chapter_19/copy_propagation/int_only/multi_path_no_kill.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/redundant_copies.c": {"return_code": 10}, "chapter_19/copy_propagation/int_only/fig_19_8.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/kill_and_add_copies.c": {"return_code": 14}, "chapter_19/copy_propagation/int_only/multi_instance_same_copy.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/init_all_copies.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/complex_const_fold.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/copy_prop_const_fold.c": {"return_code": 6}, "chapter_19/copy_propagation/int_only/prop_static_var.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/propagate_var.c": {"return_code": 6}, "chapter_19/copy_propagation/int_only/multi_path.c": {"return_code": 6}, "chapter_19/copy_propagation/int_only/loop.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/dont_propagate/source_killed_on_one_path.c": {"return_code": 8}, "chapter_19/copy_propagation/int_only/dont_propagate/one_reaching_copy.c": {"return_code": 3}, "chapter_19/copy_propagation/int_only/dont_propagate/listing_20_15.c": {"return_code": 101}, "chapter_19/copy_propagation/int_only/dont_propagate/dest_killed.c": {"return_code": 4}, "chapter_19/copy_propagation/int_only/dont_propagate/no_copies_reach_entry.c": {"return_code": 4}, "chapter_19/copy_propagation/int_only/dont_propagate/add_all_blocks_to_worklist.c": {"return_code": 4}, "chapter_19/copy_propagation/int_only/dont_propagate/multi_values.c": {"return_code": 7}, "chapter_19/copy_propagation/int_only/dont_propagate/static_dst_killed.c": {"return_code": 4}, "chapter_19/copy_propagation/int_only/dont_propagate/static_src_killed.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/dont_propagate/source_killed.c": {"return_code": 10}, "chapter_19/dead_store_elimination/all_types/aliased_dead_at_exit.c": {"return_code": 1}, "chapter_19/dead_store_elimination/all_types/getaddr_doesnt_gen.c": {"return_code": 0}, "chapter_19/dead_store_elimination/all_types/copy_to_dead_struct.c": {"return_code": 4}, "chapter_19/dead_store_elimination/all_types/dont_elim/copytooffset_doesnt_kill.c": {"return_code": 101}, "chapter_19/dead_store_elimination/all_types/dont_elim/store_generates_dst.c": {"return_code": 4}, "chapter_19/dead_store_elimination/all_types/dont_elim/load_generates_pointer.c": {"return_code": 10}, "chapter_19/dead_store_elimination/all_types/dont_elim/load_through_pointer.c": {"return_code": 10}, "chapter_19/dead_store_elimination/all_types/dont_elim/pass_pointer_to_fun.c": {"return_code": 5}, "chapter_19/dead_store_elimination/all_types/dont_elim/never_kill_store.c": {"return_code": 4}, "chapter_19/dead_store_elimination/all_types/dont_elim/copyfromoffset_gen.c": {"return_code": 3}, "chapter_19/dead_store_elimination/int_only/fig_19_12.c": {"return_code": 9}, "chapter_19/dead_store_elimination/int_only/use_and_kill.c": {"return_code": 5}, "chapter_19/dead_store_elimination/int_only/dead_store_static_var.c": {"return_code": 1}, "chapter_19/dead_store_elimination/int_only/loop_dead_store.c": {"return_code": 51}, "chapter_19/dead_store_elimination/int_only/simple.c": {"return_code": 3}, "chapter_19/dead_store_elimination/int_only/elim_second_copy.c": {"return_code": 10}, "chapter_19/dead_store_elimination/int_only/dont_elim/static_vars_at_exit.c": {"return_code": 1}, "chapter_19/dead_store_elimination/int_only/dont_elim/used_one_path.c": {"return_code": 40}, "chapter_19/dead_store_elimination/int_only/dont_elim/dont_remove_funcall.c": {"return_code": 0, "stdout": "C"}, "chapter_19/dead_store_elimination/int_only/dont_elim/add_all_to_worklist.c": {"return_code": 0, "stdout": "L"}, "chapter_19/dead_store_elimination/int_only/dont_elim/loop.c": {"return_code": 54}, "chapter_19/dead_store_elimination/int_only/dont_elim/static_vars_fun.c": {"return_code": 5}, "chapter_19/whole_pipeline/all_types/alias_analysis_change.c": {"return_code": 0}, "chapter_19/whole_pipeline/int_only/dead_condition.c": {"return_code": 10}, "chapter_19/whole_pipeline/int_only/elim_and_copy_prop.c": {"return_code": 10}, "chapter_19/whole_pipeline/int_only/remainder_test.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/mixed_ints.c": {"return_code": 9}, "chapter_20/all_types/no_coalescing/dbl_trivially_colorable.c": {"return_code": 3}, "chapter_20/all_types/no_coalescing/spill_movz_dst.c": {"return_code": 29}, "chapter_20/all_types/no_coalescing/push_xmm.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/dbl_fun_call.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/stack_alignment.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/track_dbl_arg_registers.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/fourteen_pseudos_interfere.c": {"return_code": 0}, "chapter_20/all_types/no_coalescing/div_interference.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/test_spilling_dbls.c": {"return_code": 3}, "chapter_20/all_types/no_coalescing/store_pointer_in_register.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/same_instr_interference.c": {"return_code": 6}, "chapter_20/int_only/no_coalescing/spills_rewrites_compare.c": {"return_code": 3}, "chapter_20/int_only/no_coalescing/copy_and_separate_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/spills_and_rewrites.c": {"return_code": 23}, "chapter_20/int_only/no_coalescing/cmp_liveness.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/rewrite_large_multiply.c": {"return_code": 58}, "chapter_20/int_only/no_coalescing/spill_callee_saved.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/test_spill_metric.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/unary_interference.c": {"return_code": 10}, "chapter_20/int_only/no_coalescing/optimistic_coloring.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/track_arg_registers.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/many_pseudos_fewer_conflicts.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/same_instr_no_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/copy_no_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/force_spill.c": {"return_code": 9}, "chapter_20/int_only/no_coalescing/callee_saved_stack_alignment.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/idiv_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/preserve_across_fun_call.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/use_all_hardregs.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/test_spill_metric_2.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/loop.c": {"return_code": 6}, "chapter_20/int_only/no_coalescing/trivially_colorable.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/cdq_interference.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/cdq_generates_ax.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/callee_saved_live_at_exit.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/coalesce_prevents_spill.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/george_coalesce.c": {"return_code": 1}, "chapter_20/int_only/with_coalescing/unary_generates_dst.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/briggs_coalesce.c": {"return_code": 2}, "chapter_20/int_only/with_coalescing/bin_generates_dst.c": {"return_code": 187}, "chapter_20/int_only/with_coalescing/briggs_coalesce_tmps.c": {"return_code": 1}, "chapter_20/int_only/with_coalescing/cmp_generates_operands.c": {"return_code": 1}, "chapter_20/int_only/with_coalescing/funcall_generates_args.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/eax_live_at_exit.c": {"return_code": 1}} \ No newline at end of file +{"chapter_6/valid/rh_assignment.c": {"return_code": 1}, "chapter_6/valid/if_nested_2.c": {"return_code": 2}, "chapter_6/valid/if_nested_3.c": {"return_code": 3}, "chapter_6/valid/nested_ternary.c": {"return_code": 7}, "chapter_6/valid/binary_false_condition.c": {"return_code": 0}, "chapter_6/valid/else.c": {"return_code": 2}, "chapter_6/valid/nested_ternary_2.c": {"return_code": 15}, "chapter_6/valid/ternary_short_circuit.c": {"return_code": 1}, "chapter_6/valid/multiple_if.c": {"return_code": 8}, "chapter_6/valid/if_null_body.c": {"return_code": 1}, "chapter_6/valid/ternary_rh_binop.c": {"return_code": 1}, "chapter_6/valid/ternary_middle_assignment.c": {"return_code": 2}, "chapter_6/valid/if_nested_4.c": {"return_code": 4}, "chapter_6/valid/ternary_middle_binop.c": {"return_code": 1}, "chapter_6/valid/if_taken.c": {"return_code": 1}, "chapter_6/valid/if_not_taken.c": {"return_code": 0}, "chapter_6/valid/if_nested_5.c": {"return_code": 1}, "chapter_6/valid/assign_ternary.c": {"return_code": 2}, "chapter_6/valid/ternary.c": {"return_code": 4}, "chapter_6/valid/if_nested.c": {"return_code": 1}, "chapter_6/valid/ternary_short_circuit_2.c": {"return_code": 2}, "chapter_6/valid/binary_condition.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label_and_var.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label_main_2.c": {"return_code": 0}, "chapter_6/valid/extra_credit/bitwise_ternary.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label_main.c": {"return_code": 0}, "chapter_6/valid/extra_credit/goto_nested_label.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_backwards.c": {"return_code": 5}, "chapter_6/valid/extra_credit/goto_label.c": {"return_code": 1}, "chapter_6/valid/extra_credit/compound_if_expression.c": {"return_code": 1}, "chapter_6/valid/extra_credit/goto_after_declaration.c": {"return_code": 1}, "chapter_8/valid/for.c": {"return_code": 16}, "chapter_8/valid/continue.c": {"return_code": 1}, "chapter_8/valid/multi_continue_same_loop.c": {"return_code": 1}, "chapter_8/valid/for_absent_post.c": {"return_code": 0}, "chapter_8/valid/null_for_header.c": {"return_code": 4}, "chapter_8/valid/nested_loop.c": {"return_code": 1}, "chapter_8/valid/nested_break.c": {"return_code": 250}, "chapter_8/valid/do_while.c": {"return_code": 16}, "chapter_8/valid/for_absent_condition.c": {"return_code": 0}, "chapter_8/valid/do_while_break_immediate.c": {"return_code": 10}, "chapter_8/valid/continue_empty_post.c": {"return_code": 30}, "chapter_8/valid/nested_continue.c": {"return_code": 24}, "chapter_8/valid/break.c": {"return_code": 1}, "chapter_8/valid/for_nested_shadow.c": {"return_code": 1}, "chapter_8/valid/empty_expression.c": {"return_code": 0}, "chapter_8/valid/multi_break.c": {"return_code": 1}, "chapter_8/valid/for_decl.c": {"return_code": 101}, "chapter_8/valid/for_shadow.c": {"return_code": 1}, "chapter_8/valid/break_immediate.c": {"return_code": 1}, "chapter_8/valid/while.c": {"return_code": 6}, "chapter_8/valid/empty_loop_body.c": {"return_code": 252}, "chapter_8/valid/extra_credit/switch_fallthrough.c": {"return_code": 4}, "chapter_8/valid/extra_credit/compound_assignment_for_loop.c": {"return_code": 10}, "chapter_8/valid/extra_credit/switch_break.c": {"return_code": 5}, "chapter_8/valid/extra_credit/switch_default.c": {"return_code": 22}, "chapter_8/valid/extra_credit/switch_default_fallthrough.c": {"return_code": 0}, "chapter_8/valid/extra_credit/switch_with_loop.c": {"return_code": 123}, "chapter_8/valid/extra_credit/switch_assign_in_body.c": {"return_code": 3}, "chapter_8/valid/extra_credit/switch_in_loop.c": {"return_code": 1}, "chapter_8/valid/extra_credit/switch_no_case.c": {"return_code": 4}, "chapter_8/valid/extra_credit/switch_nested_case.c": {"return_code": 3}, "chapter_8/valid/extra_credit/switch_nested_not_taken.c": {"return_code": 2}, "chapter_8/valid/extra_credit/switch_decl.c": {"return_code": 7}, "chapter_8/valid/extra_credit/switch_with_continue.c": {"return_code": 5}, "chapter_8/valid/extra_credit/switch_empty.c": {"return_code": 10}, "chapter_8/valid/extra_credit/goto_loop_body.c": {"return_code": 1}, "chapter_8/valid/extra_credit/goto_bypass_condition.c": {"return_code": 10}, "chapter_8/valid/extra_credit/switch_nested_switch.c": {"return_code": 1}, "chapter_8/valid/extra_credit/switch_block.c": {"return_code": 1}, "chapter_8/valid/extra_credit/switch_default_not_last.c": {"return_code": 0}, "chapter_8/valid/extra_credit/switch_assign_in_condition.c": {"return_code": 2}, "chapter_8/valid/extra_credit/switch.c": {"return_code": 3}, "chapter_8/valid/extra_credit/switch_goto_mid_case.c": {"return_code": 1}, "chapter_14/valid/libraries/static_pointer.c": {"return_code": 0}, "chapter_14/valid/libraries/global_pointer.c": {"return_code": 1}, "chapter_14/valid/function_calls/address_of_argument.c": {"return_code": 0}, "chapter_14/valid/function_calls/update_value_through_pointer_parameter.c": {"return_code": 0}, "chapter_14/valid/function_calls/return_pointer.c": {"return_code": 0}, "chapter_14/valid/extra_credit/incr_through_pointer.c": {"return_code": 11}, "chapter_14/valid/extra_credit/compound_assign_through_pointer.c": {"return_code": 1}, "chapter_14/valid/declarators/declare_pointer_in_for_loop.c": {"return_code": 5}, "chapter_14/valid/declarators/abstract_declarators.c": {"return_code": 0}, "chapter_14/valid/declarators/declarators.c": {"return_code": 0}, "chapter_14/valid/dereference/static_var_indirection.c": {"return_code": 0}, "chapter_14/valid/dereference/multilevel_indirection.c": {"return_code": 0}, "chapter_14/valid/dereference/read_through_pointers.c": {"return_code": 0}, "chapter_14/valid/dereference/update_through_pointers.c": {"return_code": 0}, "chapter_14/valid/dereference/address_of_dereference.c": {"return_code": 0}, "chapter_14/valid/dereference/simple.c": {"return_code": 3}, "chapter_14/valid/dereference/dereference_expression_result.c": {"return_code": 0}, "chapter_14/valid/casts/cast_between_pointer_types.c": {"return_code": 0}, "chapter_14/valid/casts/pointer_int_casts.c": {"return_code": 0}, "chapter_14/valid/casts/null_pointer_conversion.c": {"return_code": 0}, "chapter_14/valid/comparisons/compare_pointers.c": {"return_code": 0}, "chapter_14/valid/comparisons/pointers_as_conditions.c": {"return_code": 0}, "chapter_14/valid/comparisons/compare_to_null.c": {"return_code": 0}, "chapter_10/valid/static_then_extern.c": {"return_code": 3}, "chapter_10/valid/push_arg_on_page_boundary.c": {"return_code": 1}, "chapter_10/valid/static_local_multiple_scopes.c": {"return_code": 0, "stdout": "Aa\nBb\nCc\nDd\nEe\nFf\nGg\nHh\nIi\nJj\nKk\nLl\nMm\nNn\nOo\nPp\nQq\nRr\nSs\nTt\nUu\nVv\nWw\nXx\nYy\nZz\n"}, "chapter_10/valid/tentative_definition.c": {"return_code": 5}, "chapter_10/valid/static_variables_in_expressions.c": {"return_code": 0}, "chapter_10/valid/static_recursive_call.c": {"return_code": 0, "stdout": "ABCDEFGHIJKLMNOPQRSTUVWXYZ"}, "chapter_10/valid/shadow_static_local_var.c": {"return_code": 0}, "chapter_10/valid/multiple_static_local.c": {"return_code": 29}, "chapter_10/valid/multiple_static_file_scope_vars.c": {"return_code": 4}, "chapter_10/valid/static_local_uninitialized.c": {"return_code": 4}, "chapter_10/valid/type_before_storage_class.c": {"return_code": 7}, "chapter_10/valid/extern_block_scope_variable.c": {"return_code": 3}, "chapter_10/valid/distinct_local_and_extern.c": {"return_code": 7}, "chapter_10/valid/libraries/internal_hides_external_linkage.c": {"return_code": 0}, "chapter_10/valid/libraries/external_tentative_var.c": {"return_code": 0}, "chapter_10/valid/libraries/external_linkage_function.c": {"return_code": 0}, "chapter_10/valid/libraries/external_variable.c": {"return_code": 0}, "chapter_10/valid/libraries/internal_linkage_var.c": {"return_code": 0}, "chapter_10/valid/libraries/external_var_scoping.c": {"return_code": 0}, "chapter_10/valid/libraries/internal_linkage_function.c": {"return_code": 0}, "chapter_10/valid/extra_credit/goto_skip_static_initializer.c": {"return_code": 10}, "chapter_2/valid/neg.c": {"return_code": 251}, "chapter_2/valid/negate_int_max.c": {"return_code": 1}, "chapter_2/valid/redundant_parens.c": {"return_code": 246}, "chapter_2/valid/neg_zero.c": {"return_code": 0}, "chapter_2/valid/bitwise_int_min.c": {"return_code": 254}, "chapter_2/valid/bitwise_zero.c": {"return_code": 255}, "chapter_2/valid/parens_3.c": {"return_code": 4}, "chapter_2/valid/parens_2.c": {"return_code": 253}, "chapter_2/valid/bitwise.c": {"return_code": 243}, "chapter_2/valid/nested_ops_2.c": {"return_code": 1}, "chapter_2/valid/nested_ops.c": {"return_code": 2}, "chapter_2/valid/parens.c": {"return_code": 254}, "chapter_1/valid/return_0.c": {"return_code": 0}, "chapter_1/valid/newlines.c": {"return_code": 0}, "chapter_1/valid/return_2.c": {"return_code": 2}, "chapter_1/valid/multi_digit.c": {"return_code": 100}, "chapter_1/valid/tabs.c": {"return_code": 0}, "chapter_1/valid/spaces.c": {"return_code": 0}, "chapter_1/valid/no_newlines.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/logical.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/arithmetic_ops.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/static_initialized_double.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/comparisons.c": {"return_code": 0}, "chapter_13/valid/floating_expressions/simple.c": {"return_code": 1}, "chapter_13/valid/floating_expressions/loop_controlling_expression.c": {"return_code": 100}, "chapter_13/valid/libraries/double_parameters.c": {"return_code": 0}, "chapter_13/valid/libraries/use_arg_after_fun_call.c": {"return_code": 4}, "chapter_13/valid/libraries/double_and_int_params_recursive.c": {"return_code": 0}, "chapter_13/valid/libraries/extern_double.c": {"return_code": 1}, "chapter_13/valid/libraries/double_params_and_result.c": {"return_code": 1}, "chapter_13/valid/explicit_casts/cvttsd2i_rewrite.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/double_to_signed.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/unsigned_to_double.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/signed_to_double.c": {"return_code": 0}, "chapter_13/valid/explicit_casts/double_to_unsigned.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/convert_for_assignment.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/common_type.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/static_initializers.c": {"return_code": 0}, "chapter_13/valid/implicit_casts/complex_arithmetic_common_type.c": {"return_code": 1}, "chapter_13/valid/constants/round_constants.c": {"return_code": 0}, "chapter_13/valid/constants/constant_doubles.c": {"return_code": 0}, "chapter_13/valid/special_values/subnormal_not_zero.c": {"return_code": 0}, "chapter_13/valid/special_values/negative_zero.c": {"return_code": 0}, "chapter_13/valid/special_values/infinity.c": {"return_code": 0}, "chapter_13/valid/function_calls/double_parameters.c": {"return_code": 0}, "chapter_13/valid/function_calls/double_and_int_parameters.c": {"return_code": 0}, "chapter_13/valid/function_calls/standard_library_call.c": {"return_code": 0}, "chapter_13/valid/function_calls/use_arg_after_fun_call.c": {"return_code": 4}, "chapter_13/valid/function_calls/return_double.c": {"return_code": 1}, "chapter_13/valid/function_calls/double_and_int_params_recursive.c": {"return_code": 0}, "chapter_13/valid/extra_credit/compound_assign.c": {"return_code": 1}, "chapter_13/valid/extra_credit/nan.c": {"return_code": 0}, "chapter_13/valid/extra_credit/compound_assign_implicit_cast.c": {"return_code": 1}, "chapter_18/valid/params_and_returns/temporary_lifetime.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/ignore_retval.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_space_overlap.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_big_struct_on_page_boundary.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/simple.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_struct_on_page_boundary.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/return_incomplete_type.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/stack_clobber.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/libraries/return_calling_conventions.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/libraries/missing_retval.c": {"return_code": 1}, "chapter_18/valid/params_and_returns/libraries/access_retval_members.c": {"return_code": 0}, "chapter_18/valid/params_and_returns/libraries/retval_struct_sizes.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/semantic_analysis/resolve_tags.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/semantic_analysis/namespaces.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/semantic_analysis/incomplete_structs.c": {"return_code": 0, "stdout": "I'm a struct!\n"}, "chapter_18/valid/no_structure_parameters/semantic_analysis/cast_struct_to_void.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/global_struct.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/param_struct_pointer.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/return_struct_pointer.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/opaque_struct.c": {"return_code": 0, "stdout": "new struct\nstatic struct\nglobal struct\n"}, "chapter_18/valid/no_structure_parameters/libraries/array_of_structs.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/auto_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/static_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/nested_static_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/libraries/initializers/nested_auto_struct_initializers.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/smoke_tests/static_vs_auto.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/smoke_tests/simple.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/size_and_offset_calculations/member_offsets.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/size_and_offset_calculations/sizeof_exps.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/size_and_offset_calculations/sizeof_type.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/arrow.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/linked_list.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/static_structs.c": {"return_code": 0, "stdout": "zero\nmn\nop\nwx\nyz\nBCD\nCDE\nDEF\nEFG\nbcd\ncde\n"}, "chapter_18/valid/no_structure_parameters/scalar_member_access/nested_struct.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/scalar_member_access/dot.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/parse_and_lex/postfix_precedence.c": {"return_code": 1}, "chapter_18/valid/no_structure_parameters/parse_and_lex/trailing_comma.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/parse_and_lex/space_around_struct_member.c": {"return_code": 1}, "chapter_18/valid/no_structure_parameters/parse_and_lex/struct_member_looks_like_const.c": {"return_code": 3}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct_through_pointer.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct_with_arrow_operator.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/stack_clobber.c": {"return_code": 0}, "chapter_18/valid/no_structure_parameters/struct_copy/copy_struct_with_dot_operator.c": {"return_code": 0}, "chapter_18/valid/parameters/pass_args_on_page_boundary.c": {"return_code": 0}, "chapter_18/valid/parameters/incomplete_param_type.c": {"return_code": 3}, "chapter_18/valid/parameters/simple.c": {"return_code": 0}, "chapter_18/valid/parameters/stack_clobber.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/param_calling_conventions.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/struct_sizes.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/pass_struct.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/modify_param.c": {"return_code": 0}, "chapter_18/valid/parameters/libraries/classify_params.c": {"return_code": 0}, "chapter_15/valid/initialization/automatic.c": {"return_code": 0}, "chapter_15/valid/initialization/static.c": {"return_code": 0}, "chapter_15/valid/initialization/trailing_comma_initializer.c": {"return_code": 3}, "chapter_15/valid/initialization/automatic_nested.c": {"return_code": 0}, "chapter_15/valid/initialization/static_nested.c": {"return_code": 0}, "chapter_15/valid/libraries/set_array_val.c": {"return_code": 0}, "chapter_15/valid/libraries/return_pointer_to_array.c": {"return_code": 0}, "chapter_15/valid/libraries/global_array.c": {"return_code": 0}, "chapter_15/valid/subscripting/subscript_nested.c": {"return_code": 0}, "chapter_15/valid/subscripting/subscript_pointer.c": {"return_code": 0}, "chapter_15/valid/subscripting/array_of_pointers_to_arrays.c": {"return_code": 0}, "chapter_15/valid/subscripting/simple_subscripts.c": {"return_code": 0}, "chapter_15/valid/subscripting/simple.c": {"return_code": 3}, "chapter_15/valid/subscripting/complex_operands.c": {"return_code": 0}, "chapter_15/valid/subscripting/addition_subscript_equivalence.c": {"return_code": 0}, "chapter_15/valid/subscripting/subscript_precedence.c": {"return_code": 1}, "chapter_15/valid/allocation/test_alignment.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/pointer_add.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/add_dereference_and_assign.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/pointer_diff.c": {"return_code": 0}, "chapter_15/valid/pointer_arithmetic/compare.c": {"return_code": 0}, "chapter_15/valid/extra_credit/incr_ptr.c": {"return_code": 1}, "chapter_15/valid/declarators/big_array.c": {"return_code": 0}, "chapter_15/valid/declarators/equivalent_declarators.c": {"return_code": 0}, "chapter_15/valid/declarators/return_nested_array.c": {"return_code": 0}, "chapter_15/valid/declarators/array_as_argument.c": {"return_code": 0}, "chapter_15/valid/declarators/for_loop_array.c": {"return_code": 0}, "chapter_15/valid/casts/multi_dim_casts.c": {"return_code": 0}, "chapter_15/valid/casts/implicit_and_explicit_conversions.c": {"return_code": 0}, "chapter_15/valid/casts/cast_array_of_pointers.c": {"return_code": 1}, "chapter_17/valid/void/cast_to_void.c": {"return_code": 12}, "chapter_17/valid/void/void_function.c": {"return_code": 0}, "chapter_17/valid/void/void_for_loop.c": {"return_code": 0, "stdout": "ZYXWVUTSRQPONMLKJIHGFEDCBAABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUTSRQPONMLKJIHGFEDCBA"}, "chapter_17/valid/void/ternary.c": {"return_code": 0}, "chapter_17/valid/libraries/pass_alloced_memory.c": {"return_code": 0}, "chapter_17/valid/libraries/test_for_memory_leaks.c": {"return_code": 0}, "chapter_17/valid/libraries/sizeof_extern.c": {"return_code": 1}, "chapter_17/valid/sizeof/sizeof_basic_types.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_consts.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_expressions.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_array.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_derived_types.c": {"return_code": 0}, "chapter_17/valid/sizeof/simple.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_result_is_ulong.c": {"return_code": 0}, "chapter_17/valid/sizeof/sizeof_not_evaluated.c": {"return_code": 4}, "chapter_17/valid/void_pointer/array_of_pointers_to_void.c": {"return_code": 0}, "chapter_17/valid/void_pointer/conversion_by_assignment.c": {"return_code": 0}, "chapter_17/valid/void_pointer/explicit_cast.c": {"return_code": 0}, "chapter_17/valid/void_pointer/simple.c": {"return_code": 100}, "chapter_17/valid/void_pointer/memory_management_functions.c": {"return_code": 0}, "chapter_17/valid/void_pointer/common_pointer_type.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/addr_of_string.c": {"return_code": 0, "stdout": "Sample\tstring!\n\n"}, "chapter_16/valid/strings_as_lvalues/standard_library_calls.c": {"return_code": 0, "stdout": "Hello, World!\n"}, "chapter_16/valid/strings_as_lvalues/array_of_strings.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/cast_string_pointer.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/empty_string.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/pointer_operations.c": {"return_code": 0}, "chapter_16/valid/strings_as_lvalues/simple.c": {"return_code": 108}, "chapter_16/valid/strings_as_lvalues/adjacent_strings.c": {"return_code": 0, "stdout": "Hello, World\n"}, "chapter_16/valid/strings_as_lvalues/string_special_characters.c": {"return_code": 0, "stdout": "Hello\"world\nHello\\World\nLine\nbreak!\nTesting, 123.\n^@1 _\\]\n"}, "chapter_16/valid/strings_as_lvalues/strings_in_function_calls.c": {"return_code": 0}, "chapter_16/valid/libraries/return_char.c": {"return_code": 0}, "chapter_16/valid/libraries/char_arguments.c": {"return_code": 0}, "chapter_16/valid/libraries/global_char.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/array_init_special_chars.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/terminating_null_bytes.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/simple.c": {"return_code": 99}, "chapter_16/valid/strings_as_initializers/partial_initialize_via_string.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/adjacent_strings_in_initializer.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/transfer_by_eightbyte.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/literals_and_compound_initializers.c": {"return_code": 0}, "chapter_16/valid/strings_as_initializers/write_to_array.c": {"return_code": 0, "stdout": "abc\nabx\nHello\nWorld\nJello\n"}, "chapter_16/valid/strings_as_initializers/test_alignment.c": {"return_code": 0}, "chapter_16/valid/char_constants/return_char_constant.c": {"return_code": 99}, "chapter_16/valid/char_constants/escape_sequences.c": {"return_code": 0}, "chapter_16/valid/char_constants/control_characters.c": {"return_code": 0}, "chapter_16/valid/char_constants/char_constant_operations.c": {"return_code": 0}, "chapter_16/valid/chars/partial_initialization.c": {"return_code": 0}, "chapter_16/valid/chars/convert_by_assignment.c": {"return_code": 0}, "chapter_16/valid/chars/type_specifiers.c": {"return_code": 0}, "chapter_16/valid/chars/push_arg_on_page_boundary.c": {"return_code": 1}, "chapter_16/valid/chars/integer_promotion.c": {"return_code": 0}, "chapter_16/valid/chars/chained_casts.c": {"return_code": 0}, "chapter_16/valid/chars/return_char.c": {"return_code": 0}, "chapter_16/valid/chars/char_arguments.c": {"return_code": 0}, "chapter_16/valid/chars/char_expressions.c": {"return_code": 0}, "chapter_16/valid/chars/access_through_char_pointer.c": {"return_code": 0}, "chapter_16/valid/chars/common_type.c": {"return_code": 0}, "chapter_16/valid/chars/static_initializers.c": {"return_code": 0}, "chapter_16/valid/chars/explicit_casts.c": {"return_code": 0}, "chapter_9/valid/arguments_in_registers/parameter_shadows_own_function.c": {"return_code": 2}, "chapter_9/valid/arguments_in_registers/expression_args.c": {"return_code": 2}, "chapter_9/valid/arguments_in_registers/single_arg.c": {"return_code": 6}, "chapter_9/valid/arguments_in_registers/hello_world.c": {"return_code": 0, "stdout": "Hello, World!\n"}, "chapter_9/valid/arguments_in_registers/parameter_shadows_function.c": {"return_code": 3}, "chapter_9/valid/arguments_in_registers/parameters_are_preserved.c": {"return_code": 1}, "chapter_9/valid/arguments_in_registers/forward_decl_multi_arg.c": {"return_code": 1}, "chapter_9/valid/arguments_in_registers/fibonacci.c": {"return_code": 8}, "chapter_9/valid/arguments_in_registers/param_shadows_local_var.c": {"return_code": 20}, "chapter_9/valid/no_arguments/function_shadows_variable.c": {"return_code": 11}, "chapter_9/valid/no_arguments/use_function_in_expression.c": {"return_code": 21}, "chapter_9/valid/no_arguments/no_return_value.c": {"return_code": 3}, "chapter_9/valid/no_arguments/multiple_declarations.c": {"return_code": 3}, "chapter_9/valid/no_arguments/precedence.c": {"return_code": 0}, "chapter_9/valid/no_arguments/forward_decl.c": {"return_code": 3}, "chapter_9/valid/no_arguments/variable_shadows_function.c": {"return_code": 7}, "chapter_9/valid/libraries/system_call.c": {"return_code": 0, "stdout": "H"}, "chapter_9/valid/libraries/many_args.c": {"return_code": 115}, "chapter_9/valid/libraries/addition.c": {"return_code": 3}, "chapter_9/valid/libraries/no_function_calls/division.c": {"return_code": 1}, "chapter_9/valid/libraries/no_function_calls/local_stack_variables.c": {"return_code": 100}, "chapter_9/valid/extra_credit/compound_assign_function_result.c": {"return_code": 1}, "chapter_9/valid/extra_credit/goto_label_multiple_functions.c": {"return_code": 5}, "chapter_9/valid/extra_credit/goto_shared_name.c": {"return_code": 1}, "chapter_9/valid/stack_arguments/call_putchar.c": {"return_code": 8, "stdout": "A"}, "chapter_9/valid/stack_arguments/lots_of_arguments.c": {"return_code": 1}, "chapter_9/valid/stack_arguments/stack_alignment.c": {"return_code": 1}, "chapter_9/valid/stack_arguments/test_for_memory_leaks.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/logical.c": {"return_code": 0}, "chapter_12/valid/unsigned_expressions/arithmetic_wraparound.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/arithmetic_ops.c": {"return_code": 0}, "chapter_12/valid/unsigned_expressions/comparisons.c": {"return_code": 0}, "chapter_12/valid/unsigned_expressions/simple.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/static_variables.c": {"return_code": 1}, "chapter_12/valid/unsigned_expressions/locals.c": {"return_code": 0}, "chapter_12/valid/libraries/unsigned_args.c": {"return_code": 0}, "chapter_12/valid/libraries/unsigned_global_var.c": {"return_code": 1}, "chapter_12/valid/explicit_casts/same_size_conversion.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/extension.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/round_trip_casts.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/chained_casts.c": {"return_code": 0}, "chapter_12/valid/explicit_casts/truncate.c": {"return_code": 0}, "chapter_12/valid/type_specifiers/signed_type_specifiers.c": {"return_code": 0}, "chapter_12/valid/type_specifiers/unsigned_type_specifiers.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/convert_by_assignment.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/promote_constants.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/common_type.c": {"return_code": 0}, "chapter_12/valid/implicit_casts/static_initializers.c": {"return_code": 0}, "chapter_12/valid/extra_credit/switch_uint.c": {"return_code": 0}, "chapter_12/valid/extra_credit/compound_assign_uint.c": {"return_code": 1}, "chapter_12/valid/extra_credit/bitwise_unsigned_shift.c": {"return_code": 1}, "chapter_12/valid/extra_credit/bitwise_unsigned_ops.c": {"return_code": 1}, "chapter_5/valid/null_then_return.c": {"return_code": 0}, "chapter_5/valid/empty_function_body.c": {"return_code": 0}, "chapter_5/valid/short_circuit_or.c": {"return_code": 0}, "chapter_5/valid/assignment_in_initializer.c": {"return_code": 0}, "chapter_5/valid/non_short_circuit_or.c": {"return_code": 1}, "chapter_5/valid/null_statement.c": {"return_code": 0}, "chapter_5/valid/short_circuit_and_fail.c": {"return_code": 0}, "chapter_5/valid/local_var_missing_return.c": {"return_code": 0}, "chapter_5/valid/exp_then_declaration.c": {"return_code": 1}, "chapter_5/valid/add_variables.c": {"return_code": 3}, "chapter_5/valid/assign_val_in_initializer.c": {"return_code": 5}, "chapter_5/valid/assignment_lowest_precedence.c": {"return_code": 1}, "chapter_5/valid/allocate_temps_and_vars.c": {"return_code": 1}, "chapter_5/valid/use_assignment_result.c": {"return_code": 4}, "chapter_5/valid/use_val_in_own_initializer.c": {"return_code": 0}, "chapter_5/valid/unused_exp.c": {"return_code": 0}, "chapter_5/valid/return_var.c": {"return_code": 2}, "chapter_5/valid/mixed_precedence_assignment.c": {"return_code": 4}, "chapter_5/valid/assign.c": {"return_code": 2}, "chapter_5/valid/extra_credit/bitwise_shiftr_assign.c": {"return_code": 77}, "chapter_5/valid/extra_credit/bitwise_shiftl_variable.c": {"return_code": 24}, "chapter_5/valid/extra_credit/compound_bitwise_and.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_minus.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_multiply.c": {"return_code": 12}, "chapter_5/valid/extra_credit/compound_bitwise_xor.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_bitwise_or.c": {"return_code": 31}, "chapter_5/valid/extra_credit/compound_assignment_chained.c": {"return_code": 4}, "chapter_5/valid/extra_credit/compound_divide.c": {"return_code": 2}, "chapter_5/valid/extra_credit/compound_bitwise_shiftr.c": {"return_code": 102}, "chapter_5/valid/extra_credit/compound_assignment_use_result.c": {"return_code": 8}, "chapter_5/valid/extra_credit/compound_bitwise_shiftl.c": {"return_code": 48}, "chapter_5/valid/extra_credit/compound_plus.c": {"return_code": 4}, "chapter_5/valid/extra_credit/compound_mod.c": {"return_code": 2}, "chapter_5/valid/extra_credit/bitwise_and_vars.c": {"return_code": 1}, "chapter_7/valid/declaration_only.c": {"return_code": 1}, "chapter_7/valid/assign_to_self_2.c": {"return_code": 3}, "chapter_7/valid/hidden_then_visible.c": {"return_code": 1}, "chapter_7/valid/hidden_variable.c": {"return_code": 1}, "chapter_7/valid/assign_to_self.c": {"return_code": 4}, "chapter_7/valid/inner_uninitialized.c": {"return_code": 4}, "chapter_7/valid/multiple_vars_same_name.c": {"return_code": 2}, "chapter_7/valid/use_in_inner_scope.c": {"return_code": 3}, "chapter_7/valid/empty_blocks.c": {"return_code": 30}, "chapter_7/valid/nested_if.c": {"return_code": 1}, "chapter_7/valid/similar_var_names.c": {"return_code": 28}, "chapter_7/valid/extra_credit/goto_before_declaration.c": {"return_code": 0}, "chapter_7/valid/extra_credit/compound_subtract_in_block.c": {"return_code": 1}, "chapter_7/valid/extra_credit/goto_inner_scope.c": {"return_code": 1}, "chapter_4/valid/le_true.c": {"return_code": 2}, "chapter_4/valid/ne_true.c": {"return_code": 1}, "chapter_4/valid/ge_false.c": {"return_code": 0}, "chapter_4/valid/not_zero.c": {"return_code": 1}, "chapter_4/valid/precedence_2.c": {"return_code": 0}, "chapter_4/valid/ge_true.c": {"return_code": 2}, "chapter_4/valid/eq_precedence.c": {"return_code": 1}, "chapter_4/valid/eq_false.c": {"return_code": 0}, "chapter_4/valid/or_short_circuit.c": {"return_code": 1}, "chapter_4/valid/not_sum.c": {"return_code": 1}, "chapter_4/valid/precedence_4.c": {"return_code": 1}, "chapter_4/valid/and_short_circuit.c": {"return_code": 0}, "chapter_4/valid/precedence_3.c": {"return_code": 0}, "chapter_4/valid/compare_arithmetic_results.c": {"return_code": 1}, "chapter_4/valid/and_false.c": {"return_code": 0}, "chapter_4/valid/precedence_5.c": {"return_code": 1}, "chapter_4/valid/associativity.c": {"return_code": 1}, "chapter_4/valid/gt_true.c": {"return_code": 1}, "chapter_4/valid/lt_false.c": {"return_code": 0}, "chapter_4/valid/or_true.c": {"return_code": 3}, "chapter_4/valid/or_false.c": {"return_code": 0}, "chapter_4/valid/eq_true.c": {"return_code": 1}, "chapter_4/valid/ne_false.c": {"return_code": 0}, "chapter_4/valid/multi_short_circuit.c": {"return_code": 0}, "chapter_4/valid/gt_false.c": {"return_code": 0}, "chapter_4/valid/operate_on_booleans.c": {"return_code": 0}, "chapter_4/valid/not.c": {"return_code": 0}, "chapter_4/valid/le_false.c": {"return_code": 0}, "chapter_4/valid/nested_ops.c": {"return_code": 0}, "chapter_4/valid/precedence.c": {"return_code": 1}, "chapter_4/valid/not_sum_2.c": {"return_code": 0}, "chapter_4/valid/and_true.c": {"return_code": 1}, "chapter_4/valid/lt_true.c": {"return_code": 1}, "chapter_4/valid/extra_credit/bitwise_precedence.c": {"return_code": 1}, "chapter_3/valid/mod.c": {"return_code": 0}, "chapter_3/valid/unop_add.c": {"return_code": 0}, "chapter_3/valid/associativity_3.c": {"return_code": 8}, "chapter_3/valid/mult.c": {"return_code": 6}, "chapter_3/valid/sub.c": {"return_code": 255}, "chapter_3/valid/div_neg.c": {"return_code": 254}, "chapter_3/valid/unop_parens.c": {"return_code": 253}, "chapter_3/valid/add.c": {"return_code": 3}, "chapter_3/valid/associativity.c": {"return_code": 252}, "chapter_3/valid/associativity_2.c": {"return_code": 1}, "chapter_3/valid/div.c": {"return_code": 2}, "chapter_3/valid/sub_neg.c": {"return_code": 3}, "chapter_3/valid/associativity_and_precedence.c": {"return_code": 10}, "chapter_3/valid/parens.c": {"return_code": 14}, "chapter_3/valid/precedence.c": {"return_code": 14}, "chapter_3/valid/extra_credit/bitwise_shiftr.c": {"return_code": 62}, "chapter_3/valid/extra_credit/bitwise_and.c": {"return_code": 1}, "chapter_3/valid/extra_credit/bitwise_shiftl.c": {"return_code": 140}, "chapter_3/valid/extra_credit/bitwise_or.c": {"return_code": 3}, "chapter_3/valid/extra_credit/bitwise_shift_precedence.c": {"return_code": 0}, "chapter_3/valid/extra_credit/bitwise_xor.c": {"return_code": 6}, "chapter_3/valid/extra_credit/bitwise_shift_associativity_2.c": {"return_code": 16}, "chapter_3/valid/extra_credit/bitwise_shift_associativity.c": {"return_code": 66}, "chapter_3/valid/extra_credit/bitwise_precedence.c": {"return_code": 21}, "chapter_11/valid/long_expressions/long_args.c": {"return_code": 0}, "chapter_11/valid/long_expressions/logical.c": {"return_code": 0}, "chapter_11/valid/long_expressions/type_specifiers.c": {"return_code": 0}, "chapter_11/valid/long_expressions/multi_op.c": {"return_code": 1}, "chapter_11/valid/long_expressions/large_constants.c": {"return_code": 0}, "chapter_11/valid/long_expressions/arithmetic_ops.c": {"return_code": 0}, "chapter_11/valid/long_expressions/return_long.c": {"return_code": 1}, "chapter_11/valid/long_expressions/comparisons.c": {"return_code": 0}, "chapter_11/valid/long_expressions/simple.c": {"return_code": 1}, "chapter_11/valid/long_expressions/static_long.c": {"return_code": 1}, "chapter_11/valid/long_expressions/long_and_int_locals.c": {"return_code": 0}, "chapter_11/valid/long_expressions/assign.c": {"return_code": 1}, "chapter_11/valid/libraries/long_args.c": {"return_code": 0}, "chapter_11/valid/libraries/maintain_stack_alignment.c": {"return_code": 12}, "chapter_11/valid/libraries/return_long.c": {"return_code": 1}, "chapter_11/valid/libraries/long_global_var.c": {"return_code": 0}, "chapter_11/valid/explicit_casts/truncate.c": {"return_code": 0}, "chapter_11/valid/explicit_casts/sign_extend.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/convert_by_assignment.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/common_type.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/long_constants.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/convert_function_arguments.c": {"return_code": 0}, "chapter_11/valid/implicit_casts/convert_static_initializer.c": {"return_code": 0}, "chapter_11/valid/extra_credit/bitwise_long_op.c": {"return_code": 1}, "chapter_11/valid/extra_credit/compound_assign_to_int.c": {"return_code": 1}, "chapter_11/valid/extra_credit/compound_assign_to_long.c": {"return_code": 1}, "chapter_11/valid/extra_credit/switch_int.c": {"return_code": 1}, "chapter_11/valid/extra_credit/switch_long.c": {"return_code": 1}, "chapter_19/constant_folding/all_types/fold_truncate.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_cast_to_double.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_ulong.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_double.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_extensions_and_copies.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_long.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_uint.c": {"return_code": 0}, "chapter_19/constant_folding/all_types/fold_cast_from_double.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_unary.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_conditional_jump.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_binary.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_control_flow.c": {"return_code": 0}, "chapter_19/constant_folding/int_only/fold_exception.c": {"return_code": 0}, "chapter_19/unreachable_code_elimination/remove_useless_starting_label.c": {"return_code": 99}, "chapter_19/unreachable_code_elimination/dead_for_loop.c": {"return_code": 10}, "chapter_19/unreachable_code_elimination/keep_final_jump.c": {"return_code": 17}, "chapter_19/unreachable_code_elimination/remove_jump_keep_label.c": {"return_code": 10}, "chapter_19/unreachable_code_elimination/dead_branch_inside_loop.c": {"return_code": 19}, "chapter_19/unreachable_code_elimination/empty.c": {"return_code": 0}, "chapter_19/unreachable_code_elimination/infinite_loop.c": {"return_code": 11}, "chapter_19/unreachable_code_elimination/constant_if_else.c": {"return_code": 45}, "chapter_19/unreachable_code_elimination/dead_blocks_with_predecessors.c": {"return_code": 5}, "chapter_19/unreachable_code_elimination/remove_conditional_jumps.c": {"return_code": 1}, "chapter_19/unreachable_code_elimination/dead_after_return.c": {"return_code": 2}, "chapter_19/unreachable_code_elimination/empty_block.c": {"return_code": 1}, "chapter_19/unreachable_code_elimination/dead_after_if_else.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/pointer_arithmetic.c": {"return_code": 2}, "chapter_19/copy_propagation/all_types/store_doesnt_kill.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/propagate_into_type_conversions.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/redundant_double_copies.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/char_type_conversion.c": {"return_code": 1, "stdout": "CBA@"}, "chapter_19/copy_propagation/all_types/alias_analysis.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/copy_struct.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/redundant_struct_copies.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/propagate_null_pointer.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/propagate_all_types.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/funcall_kills_aliased.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/dont_propagate/static_are_aliased.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/dont_propagate/store_kills_aliased.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/dont_propagate/copy_to_offset.c": {"return_code": 3}, "chapter_19/copy_propagation/all_types/dont_propagate/dont_propagate_addr_of.c": {"return_code": 0}, "chapter_19/copy_propagation/all_types/dont_propagate/type_conversion.c": {"return_code": 1}, "chapter_19/copy_propagation/all_types/dont_propagate/zero_neg_zero_different.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/killed_then_redefined.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/different_paths_same_copy.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/multi_path_no_kill.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/redundant_copies.c": {"return_code": 20}, "chapter_19/copy_propagation/int_only/fig_19_8.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/propagate_into_complex_expressions.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/propagate_static.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/propagate_static_var.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/kill_and_add_copies.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/init_all_copies.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/propagate_params.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/nested_loops.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/constant_propagation.c": {"return_code": 6}, "chapter_19/copy_propagation/int_only/propagate_var.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/different_source_values_same_copy.c": {"return_code": 1}, "chapter_19/copy_propagation/int_only/dont_propagate/source_killed_on_one_path.c": {"return_code": 0, "stdout": "DA"}, "chapter_19/copy_propagation/int_only/dont_propagate/one_reaching_copy.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/dont_propagate/dest_killed.c": {"return_code": 4}, "chapter_19/copy_propagation/int_only/dont_propagate/no_copies_reach_entry.c": {"return_code": 4}, "chapter_19/copy_propagation/int_only/dont_propagate/listing_19_14.c": {"return_code": 101}, "chapter_19/copy_propagation/int_only/dont_propagate/add_all_blocks_to_worklist.c": {"return_code": 100}, "chapter_19/copy_propagation/int_only/dont_propagate/multi_values.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/dont_propagate/static_dst_killed.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/dont_propagate/static_src_killed.c": {"return_code": 0}, "chapter_19/copy_propagation/int_only/dont_propagate/source_killed.c": {"return_code": 0}, "chapter_19/dead_store_elimination/all_types/aliased_dead_at_exit.c": {"return_code": 1}, "chapter_19/dead_store_elimination/all_types/getaddr_doesnt_gen.c": {"return_code": 0}, "chapter_19/dead_store_elimination/all_types/copy_to_dead_struct.c": {"return_code": 4}, "chapter_19/dead_store_elimination/all_types/dont_elim/copytooffset_doesnt_kill.c": {"return_code": 101}, "chapter_19/dead_store_elimination/all_types/dont_elim/store_generates_dst.c": {"return_code": 4}, "chapter_19/dead_store_elimination/all_types/dont_elim/load_generates_pointer.c": {"return_code": 10}, "chapter_19/dead_store_elimination/all_types/dont_elim/load_through_pointer.c": {"return_code": 10}, "chapter_19/dead_store_elimination/all_types/dont_elim/pass_pointer_to_fun.c": {"return_code": 5}, "chapter_19/dead_store_elimination/all_types/dont_elim/never_kill_store.c": {"return_code": 4}, "chapter_19/dead_store_elimination/all_types/dont_elim/copyfromoffset_gen.c": {"return_code": 3}, "chapter_19/dead_store_elimination/int_only/fig_19_12.c": {"return_code": 9}, "chapter_19/dead_store_elimination/int_only/use_and_kill.c": {"return_code": 5}, "chapter_19/dead_store_elimination/int_only/dead_store_static_var.c": {"return_code": 1}, "chapter_19/dead_store_elimination/int_only/loop_dead_store.c": {"return_code": 51}, "chapter_19/dead_store_elimination/int_only/simple.c": {"return_code": 3}, "chapter_19/dead_store_elimination/int_only/elim_second_copy.c": {"return_code": 10}, "chapter_19/dead_store_elimination/int_only/dont_elim/static_vars_at_exit.c": {"return_code": 1}, "chapter_19/dead_store_elimination/int_only/dont_elim/used_one_path.c": {"return_code": 40}, "chapter_19/dead_store_elimination/int_only/dont_elim/dont_remove_funcall.c": {"return_code": 0, "stdout": "C"}, "chapter_19/dead_store_elimination/int_only/dont_elim/add_all_to_worklist.c": {"return_code": 0, "stdout": "L"}, "chapter_19/dead_store_elimination/int_only/dont_elim/loop.c": {"return_code": 54}, "chapter_19/dead_store_elimination/int_only/dont_elim/static_vars_fun.c": {"return_code": 5}, "chapter_19/whole_pipeline/all_types/unsigned_wraparound.c": {"return_code": 1}, "chapter_19/whole_pipeline/all_types/unsigned_compare.c": {"return_code": 1}, "chapter_19/whole_pipeline/all_types/signed_unsigned_conversion.c": {"return_code": 1}, "chapter_19/whole_pipeline/all_types/alias_analysis_change.c": {"return_code": 0}, "chapter_19/whole_pipeline/all_types/not_char.c": {"return_code": 1}, "chapter_19/whole_pipeline/all_types/const_fold_sign_extend.c": {"return_code": 1}, "chapter_19/whole_pipeline/all_types/char_round_trip.c": {"return_code": 1}, "chapter_19/whole_pipeline/all_types/const_fold_sign_extend_2.c": {"return_code": 1}, "chapter_19/whole_pipeline/int_only/dead_condition.c": {"return_code": 10}, "chapter_19/whole_pipeline/int_only/elim_and_copy_prop.c": {"return_code": 10}, "chapter_19/whole_pipeline/int_only/remainder_test.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/mixed_ints.c": {"return_code": 9}, "chapter_20/all_types/no_coalescing/dbl_trivially_colorable.c": {"return_code": 3}, "chapter_20/all_types/no_coalescing/spill_movz_dst.c": {"return_code": 29}, "chapter_20/all_types/no_coalescing/push_xmm.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/dbl_fun_call.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/stack_alignment.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/track_dbl_arg_registers.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/fourteen_pseudos_interfere.c": {"return_code": 0}, "chapter_20/all_types/no_coalescing/div_interference.c": {"return_code": 1}, "chapter_20/all_types/no_coalescing/test_spilling_dbls.c": {"return_code": 3}, "chapter_20/all_types/no_coalescing/store_pointer_in_register.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/same_instr_interference.c": {"return_code": 6}, "chapter_20/int_only/no_coalescing/spills_rewrites_compare.c": {"return_code": 3}, "chapter_20/int_only/no_coalescing/copy_and_separate_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/spills_and_rewrites.c": {"return_code": 23}, "chapter_20/int_only/no_coalescing/cmp_liveness.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/rewrite_large_multiply.c": {"return_code": 58}, "chapter_20/int_only/no_coalescing/spill_callee_saved.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/test_spill_metric.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/unary_interference.c": {"return_code": 10}, "chapter_20/int_only/no_coalescing/optimistic_coloring.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/track_arg_registers.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/many_pseudos_fewer_conflicts.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/same_instr_no_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/copy_no_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/force_spill.c": {"return_code": 9}, "chapter_20/int_only/no_coalescing/callee_saved_stack_alignment.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/idiv_interference.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/preserve_across_fun_call.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/use_all_hardregs.c": {"return_code": 0}, "chapter_20/int_only/no_coalescing/test_spill_metric_2.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/loop.c": {"return_code": 6}, "chapter_20/int_only/no_coalescing/trivially_colorable.c": {"return_code": 1}, "chapter_20/int_only/no_coalescing/cdq_interference.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/cdq_generates_ax.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/callee_saved_live_at_exit.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/coalesce_prevents_spill.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/george_coalesce.c": {"return_code": 1}, "chapter_20/int_only/with_coalescing/unary_generates_dst.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/briggs_coalesce.c": {"return_code": 2}, "chapter_20/int_only/with_coalescing/bin_generates_dst.c": {"return_code": 187}, "chapter_20/int_only/with_coalescing/briggs_coalesce_tmps.c": {"return_code": 1}, "chapter_20/int_only/with_coalescing/cmp_generates_operands.c": {"return_code": 1}, "chapter_20/int_only/with_coalescing/funcall_generates_args.c": {"return_code": 0}, "chapter_20/int_only/with_coalescing/eax_live_at_exit.c": {"return_code": 1}} \ No newline at end of file diff --git a/generate_expected_results.py b/generate_expected_results.py index 9e748a97..7e76182c 100755 --- a/generate_expected_results.py +++ b/generate_expected_results.py @@ -55,6 +55,8 @@ def main() -> None: # --all tells us to regenerate all expected results # by default just do the ones that have changed since last commit + # TODO option to remove entries from expected_result.json for files + # that no longer exist parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument("--since-commit", default=None) diff --git a/test_framework/tacky/copy_prop.py b/test_framework/tacky/copy_prop.py index f682770c..61680eff 100644 --- a/test_framework/tacky/copy_prop.py +++ b/test_framework/tacky/copy_prop.py @@ -4,7 +4,7 @@ import itertools import sys from pathlib import Path -from typing import Callable, List, Optional, Sequence, Union +from typing import Callable, List, Optional, Sequence, Union, Mapping from .. import basic from ..parser import asm @@ -214,38 +214,46 @@ def retval_test(self, expected_retval: Union[int, str], program_path: Path) -> N msg=f"Expected {expected_op} as return value, found {actual_retval} ({program_path})", ) - def arg_test(self, expected_args: Sequence[Optional[int]], program: Path) -> None: + def arg_test( + self, expected_args: Mapping[str, Sequence[Optional[int]]], program: Path + ) -> None: """Validate that propagate expected values into function arguments. The copy propagation pass should be able to determine the constant values of - some arguments to the "callee" function. Make sure we move these constants into - the corresponding parameter passing registers before calling "callee". + some arguments to some function calls. Make sure we move these constants into + the corresponding parameter passing registers before calling those functions. Args: - * expected_args: expected constant value of each argument - None if we don't expect to figure this out at compile time + * expected_args: mapping from function names to expected constant + value of each argument. + An argument's value is None if we don't expect to know it at compile time. * program_path: absolute path to source file""" - expected_ops: List[Optional[asm.Operand]] = [ - asm.Immediate(i) if i else None for i in expected_args - ] + + # convert constants to assembly operands + expected_ops: Mapping[str, List[Optional[asm.Operand]]] = { + f: [asm.Immediate(i) if i else None for i in args] + for f, args in expected_args.items() + } parsed_asm = self.run_and_parse(program) - # we assume that we're looking for arguments to function named "callee" - actual_args = find_args( - "callee", - parsed_asm, - arg_count=len(expected_args), - ) - for idx, (actual, expected) in enumerate( - itertools.zip_longest(actual_args, expected_ops) - ): - if expected is not None: - self.assertEqual( - actual, - expected, - msg=f"Expected argument {idx} to callee to be {expected}, found {actual}", - ) + # validate the args to each function call + # assume that each function is called only once in 'target' + for f, expected_f_args in expected_ops.items(): + actual_args = find_args( + f, + parsed_asm, + arg_count=len(expected_f_args), + ) + for idx, (actual, expected) in enumerate( + itertools.zip_longest(actual_args, expected_f_args) + ): + if expected is not None: + self.assertEqual( + actual, + expected, + msg=f"Expected argument {idx} to {f} to be {expected}, found {actual}", + ) def same_arg_test(self, program: Path) -> None: """Test that first and second arguments to callee are the same.""" @@ -329,45 +337,50 @@ def ok(i: asm.AsmItem) -> bool: # programs we'll validate with retval_test, and their expected return values RETVAL_TESTS = { # int-only - "complex_const_fold.c": -1, - "copy_prop_const_fold.c": 6, + "constant_propagation.c": 6, + "propagate_into_complex_expressions.c": 25, "fig_19_8.c": 4, "init_all_copies.c": 3, "killed_then_redefined.c": 2, - "loop.c": 10, - "multi_path.c": 3, + "different_paths_same_copy.c": 3, "multi_path_no_kill.c": 3, - "prop_static_var.c": 10, - "remainder_test.c": 1, + "propagate_static.c": 10, # other types "alias_analysis.c": 24, - "char_round_trip.c": 1, - "char_round_trip_2.c": -1, - "char_type_conversion.c": 1, - "const_fold_sign_extend.c": -1000, - "const_fold_sign_extend_2.c": -1000, - "const_fold_type_conversions.c": 83338, - "not_char.c": 1, - "propagate_doubles.c": 3000, + "propagate_into_type_conversions.c": 83826, + "propagate_all_types.c": 3500, "propagate_null_pointer.c": 0, - "signed_unsigned_conversion.c": -11, - "unsigned_compare.c": 1, - "unsigned_wraparound.c": 0, + "funcall_kills_aliased.c": 10, } -# programs we'll validate with arg_test, and their expected arguments -ARG_TESTS = {"propagate_fun_args.c": [None, 20], "kill_and_add_copies.c": [10, None]} +# programs we'll validate with arg_test, and mappings to callees with their expected arguments +ARG_TESTS = { + "kill_and_add_copies.c": {"callee": [10, None]}, + "nested_loops.c": { + "inner_loop1": [None, None, None, None, None, 100], + "inner_loop2": [None, None, None, None, None, 100], + "inner_loop3": [None, None, None, None, None, 100], + "validate": [None, None, None, None, None, 100], + }, +} # programs we'll validate with same_arg_test SAME_ARG_TESTS = [ "store_doesnt_kill.c", "copy_struct.c", - "multi_instance_same_copy.c", + "different_source_values_same_copy.c", + "propagate_static_var.c", "propagate_var.c", + "propagate_params.c", + "char_type_conversion.c", ] # programs we'll validate with redundant_copies_test -REDUNDANT_COPIES_TESTS = ["redundant_copies.c", "redundant_copies_2.c"] +REDUNDANT_COPIES_TESTS = [ + "redundant_copies.c", + "redundant_double_copies.c", + "redundant_struct_copies.c", +] # programs we'll validate with no_computations_test NO_COMPUTATIONS_TESTS = ["pointer_arithmetic.c"] diff --git a/test_framework/tacky/pipeline.py b/test_framework/tacky/pipeline.py index bf9384a3..8d7bdef4 100644 --- a/test_framework/tacky/pipeline.py +++ b/test_framework/tacky/pipeline.py @@ -18,6 +18,13 @@ class TestWholePipeline(common.TackyOptimizationTest): "dead_condition.c": 10, "elim_and_copy_prop.c": 10, "remainder_test.c": 1, + "unsigned_compare.c": 1, + "unsigned_wraparound.c": 0, + "const_fold_sign_extend.c": -1000, + "const_fold_sign_extend_2.c": -1000, + "char_round_trip.c": 1, + "signed_unsigned_conversion.c": -11, + "not_char.c": 1, } STORE_ELIMINATED = {"alias_analysis_change.c": [5, 10]} diff --git a/tests/chapter_19/copy_propagation/README.md b/tests/chapter_19/copy_propagation/README.md new file mode 100644 index 00000000..b63230f3 --- /dev/null +++ b/tests/chapter_19/copy_propagation/README.md @@ -0,0 +1,15 @@ +To validate that copies were propagated in a test program, the test script inspects the assembly for the `target` function. + +In some test programs, the copy propagation and constant folding passes make it possible to evaluate the return value at compile time. The test script expects these programs to include a `mov` instruction that copies the expected constant into EAX, followed by the function epilogue. + +In some programs, copy propagation should replace the arguments to certain function calls with constants. In other programs, copy propagation should propagate the same value two different function arguments. The test script validates these programs by checking which values are copied into the parameter-passing registers before the `call` instruction. + +Register coalescing, which we implement in Chapter 20, can make it appear that the same value is passed in two different parameter-passing reigsters, even if copy propagation wasn't performed. The tests are designed to prevent register coalescing in those cases, so they'll still test the intended cases after you complete Chapter 20. + +In one program (`redundant_copies.c`), removing a redundant copy makes a whole branch dead, allowing unreachable code elimination to remove that branch. The test script validates that this program contains no control-flow instructions. + +In `pointer_arithmetic.c`, the test script validates that we optimize away all computation instructions (e.g. arithmetic instructions like `imul` and type conversions like `movsx`). + +The programs in the `dont_propagate` directories cover cases where copies should _not_ be propagated. The test script doesn't inspect the assembly for these; it just validates that they behave correctly. + +To see what validation we perform for each test case, see `test_framework/tacky/copy_prop.py`. \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/alias_analysis.c b/tests/chapter_19/copy_propagation/all_types/alias_analysis.c index f149d52e..2ef48615 100644 --- a/tests/chapter_19/copy_propagation/all_types/alias_analysis.c +++ b/tests/chapter_19/copy_propagation/all_types/alias_analysis.c @@ -1,16 +1,41 @@ -void callee(int *ptr) { *ptr = -1; } +/* Test that alias analysis allows us to propagate some copies + * from variables whose address has been taken. */ +int callee(int *ptr) { + if (*ptr != 10) { + return 0; // failure + } + *ptr = -1; + return 1; +} + +int target(int *ptr1, int *ptr2) { + int i = 10; // generate i = 10 + int j = 20; // generate j = 20 + *ptr1 = callee(&i); // record i as a variable whose address is taken + // function call kills i = 10 + *ptr2 = i; -int target(void) { - int i = 10; - int j = 20; - callee(&i); - i = 4; + i = 4; // gen i = 4 - // look for movl $24, %eax (w/ constant fold enabled) - // can propagate i b/c there are no stores - // or function calls after i = 4 - // can propagate j b/c it's not aliased - return i + j; + // This should be rewritten as 'return 24'. + // We can propagate i b/c there are no stores + // or function calls after i = 4. + // We can propagate j b/c it's not aliased. + return i + j; } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + int callee_check1; + int callee_check2; + int result = target(&callee_check1, &callee_check2); + if (callee_check1 != 1) { + return 1; + } + if (callee_check2 != -1) { + return 2; + } + if (result != 24) { + return 3; + } + return 0; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/char_round_trip.c b/tests/chapter_19/copy_propagation/all_types/char_round_trip.c deleted file mode 100644 index 31c26b9e..00000000 --- a/tests/chapter_19/copy_propagation/all_types/char_round_trip.c +++ /dev/null @@ -1,7 +0,0 @@ -int target(void) { - int i = 257; - char c = i; - return (int)c; // -} - -int main(void) { return target() == 1; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/char_round_trip_2.c b/tests/chapter_19/copy_propagation/all_types/char_round_trip_2.c deleted file mode 100644 index bbacef31..00000000 --- a/tests/chapter_19/copy_propagation/all_types/char_round_trip_2.c +++ /dev/null @@ -1,8 +0,0 @@ -int target(void) { - int i = 255; - char c = (char)i; - i = (int)c; - return i; // -1 -} - -int main(void) { return target() == -1; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/char_type_conversion.c b/tests/chapter_19/copy_propagation/all_types/char_type_conversion.c index d135a69c..58eb4baf 100644 --- a/tests/chapter_19/copy_propagation/all_types/char_type_conversion.c +++ b/tests/chapter_19/copy_propagation/all_types/char_type_conversion.c @@ -1,3 +1,4 @@ +/* Test that we can propagate copies between char and signed char */ #ifdef SUPPRESS_WARNINGS #ifdef __clang__ #pragma clang diagnostic ignored "-Wconstant-conversion" @@ -6,13 +7,32 @@ #endif #endif -int target(void) { - char i = 200; - signed char j = i; - // w/ constant folding, should be able to reduce this to 1 - // this tests that we can propagate chars to replace sigend chars and vice - // versa they're effectively the same type - return i == j; +int putchar(int c); // from standard library + +void print_some_chars(char a, char b, char c, char d) { + putchar(a); + putchar(b); + putchar(c); + putchar(d); +} + +int callee(char c, signed char s) { + return c == s; +} + +int target(char c, signed char s) { + // first, call another function, with these arguments + // in different positions than in target or callee, so we can't + // coalesce them with the param-passing registers or each other + print_some_chars(67, 66, c, s); + + s = c; // generate s = c - we can do this because for the purposes of copy + // propagation, we consider char and signed char the same type + + // both arguments to callee should be the same + return callee(s, c); } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + return target(65, 64); +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/const_fold_sign_extend.c b/tests/chapter_19/copy_propagation/all_types/const_fold_sign_extend.c deleted file mode 100644 index 37843640..00000000 --- a/tests/chapter_19/copy_propagation/all_types/const_fold_sign_extend.c +++ /dev/null @@ -1,3 +0,0 @@ -long target(void) { return -1000; } - -int main(void) { return target() == -1000l; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/const_fold_sign_extend_2.c b/tests/chapter_19/copy_propagation/all_types/const_fold_sign_extend_2.c deleted file mode 100644 index 0055fe1f..00000000 --- a/tests/chapter_19/copy_propagation/all_types/const_fold_sign_extend_2.c +++ /dev/null @@ -1,3 +0,0 @@ -unsigned long target(void) { return -1000; } - -int main(void) { return target() == 18446744073709550616ul; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/const_fold_type_conversions.c b/tests/chapter_19/copy_propagation/all_types/const_fold_type_conversions.c deleted file mode 100644 index 261c66b8..00000000 --- a/tests/chapter_19/copy_propagation/all_types/const_fold_type_conversions.c +++ /dev/null @@ -1,12 +0,0 @@ -// check that we correctly propagate copies into type conversion instructions - -int target(void) { - unsigned char c = 250; - int i = c * 2; // 500 - double d = i * 1000.; // 500000.0 - unsigned long l = d / 6.0; // 83333 - d = l + 5.0; - return d; -} - -int main(void) { return target() == 83338; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/copy_struct.c b/tests/chapter_19/copy_propagation/all_types/copy_struct.c index bad43954..b1541f53 100644 --- a/tests/chapter_19/copy_propagation/all_types/copy_struct.c +++ b/tests/chapter_19/copy_propagation/all_types/copy_struct.c @@ -1,17 +1,25 @@ +/* Test that we can propagate copies of aggregate values */ struct s { - int x; - int y; + int x; + int y; }; -int callee(struct s a, struct s b) { return a.x + b.x; } +int callee(struct s a, struct s b) { + return a.x == 3 && a.y == 4 && b.x == 3 && b.y == 4; +} int target(void) { - struct s s1 = {1, 2}; - struct s s2 = {3, 4}; - s1 = s2; // generate s1 = s2 + struct s s1 = {1, 2}; + struct s s2 = {3, 4}; + s1 = s2; // generate s1 = s2 - // pass same value for both arguments - return callee(s1, s2); + // Make sure we pass the same value for both arguments. + // We don't need to worry that register coalescing + // will interfere with this test, + // because s1 and s2, as structures, won't be stored in registers. + return callee(s1, s2); } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + return target(); +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/dont_propagate/copy_to_offset.c b/tests/chapter_19/copy_propagation/all_types/dont_propagate/copy_to_offset.c index 23f8c94f..44f340dd 100644 --- a/tests/chapter_19/copy_propagation/all_types/dont_propagate/copy_to_offset.c +++ b/tests/chapter_19/copy_propagation/all_types/dont_propagate/copy_to_offset.c @@ -1,13 +1,14 @@ +/* Test that CopyToOffset kills its destination */ struct s { - int x; - int y; + int x; + int y; }; int main(void) { - static struct s s1 = {1, 2}; - struct s s2 = {3, 4}; - s1 = s2; // generate s1 = s2 - s2.x = 3; // kill s1 = s2 + static struct s s1 = {1, 2}; + struct s s2 = {3, 4}; + s1 = s2; // generate s1 = s2 + s2.x = 5; // kill s1 = s2 - return s1.x; + return s1.x; // make sure we don't propagate s2 into this return statement } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/dont_propagate/dont_propagate_addr_of.c b/tests/chapter_19/copy_propagation/all_types/dont_propagate/dont_propagate_addr_of.c index bcea1d14..993d8fc0 100644 --- a/tests/chapter_19/copy_propagation/all_types/dont_propagate/dont_propagate_addr_of.c +++ b/tests/chapter_19/copy_propagation/all_types/dont_propagate/dont_propagate_addr_of.c @@ -1,7 +1,7 @@ -int main(void) -{ - int x = 1; - int y = 2; - x = y; - return &x == &y; // don't rewrite as &y == &y +/* Test that we don't propagate copies into AddrOf instructions */ +int main(void) { + long x = 1; + long y = 2; + x = y; // gen x = y + return &x == &y; // don't rewrite as &y == &y } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/dont_propagate/funcall_kills_aliased.c b/tests/chapter_19/copy_propagation/all_types/dont_propagate/funcall_kills_aliased.c deleted file mode 100644 index 4e8c839b..00000000 --- a/tests/chapter_19/copy_propagation/all_types/dont_propagate/funcall_kills_aliased.c +++ /dev/null @@ -1,22 +0,0 @@ -double *ptr = 0; - -void save_ptr(double *to_save) -{ - ptr = to_save; -} - -void update_ptr(void) -{ - *ptr = 2.0; -} - -int main(void) -{ - double d = 10.0; - double *ptr = &d; - double *another_ptr = (double *)(int *)ptr; - save_ptr(another_ptr); - d = 1.0; - update_ptr(); - return d; -} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/dont_propagate/static_are_aliased.c b/tests/chapter_19/copy_propagation/all_types/dont_propagate/static_are_aliased.c index 7532daa0..d612a7cc 100644 --- a/tests/chapter_19/copy_propagation/all_types/dont_propagate/static_are_aliased.c +++ b/tests/chapter_19/copy_propagation/all_types/dont_propagate/static_are_aliased.c @@ -1,12 +1,23 @@ +/* Test that we consider all static variables aliased, + * so store kills copies to/from these variables */ int stat; int target(int *stat_ptr) { - stat = 10; - *stat_ptr = 8; - return stat; + int a = 0; + a = stat; // gen a = stat + *stat_ptr = 8; // kill a = stat + return a; // make sure we don't rewrite as 'return stat' } int main(void) { - int *ptr = &stat; - return target(ptr); + int *ptr = &stat; + stat = 5; + int result = target(ptr); + if (result != 5) { + return 1; // fail + } + if (stat != 8) { + return 2; // fail + } + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/dont_propagate/store_kills_aliased.c b/tests/chapter_19/copy_propagation/all_types/dont_propagate/store_kills_aliased.c index a50f0bfb..c5fe8968 100644 --- a/tests/chapter_19/copy_propagation/all_types/dont_propagate/store_kills_aliased.c +++ b/tests/chapter_19/copy_propagation/all_types/dont_propagate/store_kills_aliased.c @@ -1,61 +1,67 @@ -int aliased_src(int x) { - int y = x; // src is aliased - static int unused; - int *ptr = &unused; - if (x) { - ptr = &x; - } - *ptr = 100; - if (y != 12) { - return 1; - } - return 0; -} - -int aliased_dst(int flag) -{ - // store instructions kills any copies with aliased destination - int i = 10; - int j = 20; +/* Test that store instruction kills any copy + * whose source or destination is aliased + */ - // alias i and j - int *ptr1 = &i; - int *ptr2 = &j; - // kill i = 10 and j = 20 - int *ptr = flag ? ptr1 : ptr2; - *ptr = 100; +// Store kills copy w/ aliased src +int aliased_src(int flag, int x, int *ptr) { + int y = x; // gen y = x + if (flag) { + ptr = &x; // x is aliased + } + *ptr = 100; // kill y = x + return y; // make sure this isn't rewritten as 'return x' +} - // validate results +// Store kills copy w/ aliased dst +int aliased_dst(int flag, int x, int *ptr) { + int y = x; // gen y = x if (flag) { - // i should be 100, j should be unchanged - if (i != 100) { - return 2; - } - if (j != 20) { - return 3; - } - } else { - // j should be 100, i should be unchanged - if (j != 100) { - return 4; - } - if (i != 10) { - return 5; - } - - } - return 0; + ptr = &y; // y is aliased + } + *ptr = 100; // kill y = x + return y; // make sure this isn't rewritten as 'return x' } int main(void) { - int status = aliased_src(12); - if (status) { - return status; + int i = 0; + // first call aliased_src w/ flag = 0; + // Store instruction will update i + if (aliased_src(0, 1, &i) != 1) { + return 1; // fail + } + if (i != 100) { + return 2; // fail + } + + // call again w/ flag = 1; won't update i or return value + i = 0; + if (aliased_src(1, 2, &i) != 2) { + return 3; // fail } - status = aliased_dst(0); - if (status) { - return status; + if (i != 0) { + return 4; // fail } - return aliased_dst(1); + + // call aliased_dst with flag = 0; + // Store instruction will update i + if (aliased_dst(0, 5, &i) != 5) { + return 5; // fail + } + + if (i != 100) { + return 6; // fail + } + // call aliased_dst with flag = 1; + // Store won't update i, will update return value + i = 0; + if (aliased_dst(1, 5, &i) != 100) { + return 7; // fail + } + + if (i != 0) { + return 8; // fail + } + + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/dont_propagate/type_conversion.c b/tests/chapter_19/copy_propagation/all_types/dont_propagate/type_conversion.c index d0894611..fd4dfdaa 100644 --- a/tests/chapter_19/copy_propagation/all_types/dont_propagate/type_conversion.c +++ b/tests/chapter_19/copy_propagation/all_types/dont_propagate/type_conversion.c @@ -1,9 +1,16 @@ +/* Test that we don't propagate copies between values of different types, + * since that will lead to incorrect assembly generation (e.g. for comparisons + * and division). (If we had separate TACKY operators for signed vs unsigned + * comparisons/division/remainder operations instead of inferring signedness + * from TACKY operand types, it would be save to propagate these copies.) + */ int target(int i) { - unsigned int j = i; - // don't replace signed w/ unsigned value here - // NOTE: could handle this if we had separate signed/unsigned operators in - // TACKY - return (j > 100); + unsigned int j = i; + return (j / 100); // make sure we don't rewrite as i / 100 + // correct answer is 42949670, + // but if we propagate this copy we'll return -2 } -int main(void) { return target(-1); } \ No newline at end of file +int main(void) { + return target(-200) == 42949670; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/dont_propagate/zero_neg_zero_different.c b/tests/chapter_19/copy_propagation/all_types/dont_propagate/zero_neg_zero_different.c index d1840969..fff98513 100644 --- a/tests/chapter_19/copy_propagation/all_types/dont_propagate/zero_neg_zero_different.c +++ b/tests/chapter_19/copy_propagation/all_types/dont_propagate/zero_neg_zero_different.c @@ -1,15 +1,22 @@ +/* Make sure our copy propagation pass recognizes 0.0 and -0.0 + * as distinct values, even though they compare equal with standard + * floating-point comparison operators + * */ double copysign(double x, double y); double target(int flag) { - double result = 0.0; - if (flag) { - result = -0.0; - } - return result; // can't propagate because 0.0 and -0.0 are different! + double result = 0.0; // gen result = 0.0 + if (flag) { + result = -0.0; // gen result = -0.0 + } + + // can't propagate value of result because it has + // different values on different paths + return result; } int main(void) { - double pos_inf = 1 / target(0); - double neg_inf = 1 / target(1); - return pos_inf > neg_inf; + double pos_inf = 1 / target(0); + double neg_inf = 1 / target(1); + return pos_inf > neg_inf; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/funcall_kills_aliased.c b/tests/chapter_19/copy_propagation/all_types/funcall_kills_aliased.c new file mode 100644 index 00000000..8339e1e3 --- /dev/null +++ b/tests/chapter_19/copy_propagation/all_types/funcall_kills_aliased.c @@ -0,0 +1,71 @@ +/* Test that function calls kill all aliased variables, but not non-aliased + * variables */ + +double *globl_ptr = 0; + +void save_ptr(double *to_save) { + globl_ptr = to_save; +} + +void update_ptr(void) { + *globl_ptr = 4.0; +} + +// here, function call doesn't kill copy +int target(void) { + int x = 10; // gen x = 10 + update_ptr(); // doesn't kill x = 10 + + return x; // rewrite as 'return 10' +} + +// here, function call does kill copy +int kill_aliased(void) { + double d = 1.0; + double *ptr = &d; + save_ptr(ptr); + + if (*globl_ptr != 1.0) { + return 0; // fail + } + + d = 2.0; // gen d = 2.0 + + if (*globl_ptr != 2.0) { + return 0; // fail + } + + update_ptr(); // kill d = 2.0 + return d; // make sure we don't rewrite this as 'return 2.0' +} + +int main(void) { + double d = 0.0; + globl_ptr = &d; + + // call target, validate results + if (target() != 10) { + return 1; // fail + } + + // make sure target actually called update_ptr + if (d != 4.0) { + return 2; // fail + } + + // reset d + d = 0.0; + + // call kill_aliased + if (kill_aliased() != 4.0) { + return 3; // fail + } + + // make sure that didn't change d (since kill_aliased + // made globl_ptr point to a different value before updating through it) + if (d != 0.0) { + return 4; // fail + } + + return 0; // success +} diff --git a/tests/chapter_19/copy_propagation/all_types/pointer_arithmetic.c b/tests/chapter_19/copy_propagation/all_types/pointer_arithmetic.c index a4287302..699252dc 100644 --- a/tests/chapter_19/copy_propagation/all_types/pointer_arithmetic.c +++ b/tests/chapter_19/copy_propagation/all_types/pointer_arithmetic.c @@ -1,8 +1,20 @@ +/* Test that we propagate copies into AddPtr instructions */ int target(void) { - int nested[3][23] = {{0, 1}, {2}}; - // w/ constant folding and copy prop this doesn't require movslq or imul - // instructions - return nested[1][0]; + int nested[3][23] = {{0, 1}, {2}}; + + // we'll initially generate something like this: + // index0 = SignExtend(1) + // tmp2 = AddPtr(ptr=tmp1, index=index0, scale=92) + // index1 = SignExtend(0) + // tmp3 = AddPtr(ptr=tmp2, index=index1, scale=4) + // return tmp3 + // But after constant folding and copy propagation, both AddPtr + // instruction should have constant indices, so we won't need + // any imul instructions in the final assembly (like we normally would to + // implement AddPtr with a non-standard scale) + return nested[1][0]; } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + return target(); +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/propagate_all_types.c b/tests/chapter_19/copy_propagation/all_types/propagate_all_types.c new file mode 100644 index 00000000..d0ad0d85 --- /dev/null +++ b/tests/chapter_19/copy_propagation/all_types/propagate_all_types.c @@ -0,0 +1,40 @@ +/* Test that we can propagate all arithmetic types, including doubles, + * long and unsigned integers, and characters. + * */ + +#ifdef SUPPRESS_WARNINGS +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wconstant-conversion" +#else +#pragma GCC diagnostic ignored "-Woverflow" +#endif +#endif + +int target(void) { + // propagate doubles + double d = 1500.0; + double d2 = d; + + int sum = (int)(d + d2); // 3000 + + // propagate chars + char c = 250; // will be converted to -6 + char c2 = c; + sum = sum + (c2 + c); // 2988 + + // propagate unsigned char + unsigned char uc = -1; // will be converted to 255 + unsigned char uc2 = uc; + sum = sum + uc + uc2; // 3498 + + // propagate unsigned long + unsigned long ul = 18446744073709551615UL; // ULONG_MAX + unsigned long ul2 = ul + 3ul; // wraps around to 2 + sum = sum + ul2; // 3500 + + return sum; // rewrite as "return 3500" +} + +int main(void) { + return target() == 3500; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/propagate_doubles.c b/tests/chapter_19/copy_propagation/all_types/propagate_doubles.c deleted file mode 100644 index eb556d18..00000000 --- a/tests/chapter_19/copy_propagation/all_types/propagate_doubles.c +++ /dev/null @@ -1,7 +0,0 @@ -int target(void) { - double d = 1500.0; - double d2 = d; - return (int)d + d2; -} - -int main(void) { return target() == 3000; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/propagate_into_type_conversions.c b/tests/chapter_19/copy_propagation/all_types/propagate_into_type_conversions.c new file mode 100644 index 00000000..a7610c79 --- /dev/null +++ b/tests/chapter_19/copy_propagation/all_types/propagate_into_type_conversions.c @@ -0,0 +1,16 @@ +/* Test that we correctly propagate copies into type conversion instructions */ + +int target(void) { + unsigned char uc = 250; + int i = uc * 2; // 500 - tests ZeroExtend + double d = i * 1000.; // 500000.0 - tests IntToDouble + unsigned long ul = d / 6.0; // 83333 - tests DoubleToUInt + d = ul + 5.0; // 83338 - tests UIntToDouble + long l = -i; // -500 - tests SignExtend + char c = l; // 12 - tests Truncate + return d + i - c; // 83826 - tests DoubleToInt +} + +int main(void) { + return target() == 83826; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/propagate_null_pointer.c b/tests/chapter_19/copy_propagation/all_types/propagate_null_pointer.c index 0a5da0e9..41318ac6 100644 --- a/tests/chapter_19/copy_propagation/all_types/propagate_null_pointer.c +++ b/tests/chapter_19/copy_propagation/all_types/propagate_null_pointer.c @@ -1,10 +1,13 @@ -int *target(void) { - int *ptr = 0; - int *ptr2 = ptr; - return ptr2; +/* Test that we can propagate 0 between integer and + * different pointer types + * */ +long *target(void) { + int *ptr = 0; + long *ptr2 = (long *)ptr; + return ptr2; // this should be rewritten as 'return 0' } int main(void) { - int *result = target(); - return (!result); + long *result = target(); + return (!result); } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/redundant_double_copies.c b/tests/chapter_19/copy_propagation/all_types/redundant_double_copies.c new file mode 100644 index 00000000..86e086c8 --- /dev/null +++ b/tests/chapter_19/copy_propagation/all_types/redundant_double_copies.c @@ -0,0 +1,24 @@ +/* Test that we eliminate y = x and y = x if we can prove that x and y + * already have the same values. + * After copy propagation and cleanup unreachable code elimination, + * target should contain no control-flow instructions. + * Similar to int_only/redundant_copies.c but with doubles + * */ + +double target(int flag, int flag2, double y) { + double x = y; + + if (flag) { + y = x; // we can remove this because x and y already have the same + // value + } + if (flag2) { + x = y; // we can remove this because x and y already have the same + // value + } + return x + y; +} + +int main(void) { + return target(0, 1, 10.0) == 20.0; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/redundant_struct_copies.c b/tests/chapter_19/copy_propagation/all_types/redundant_struct_copies.c new file mode 100644 index 00000000..a84d8aed --- /dev/null +++ b/tests/chapter_19/copy_propagation/all_types/redundant_struct_copies.c @@ -0,0 +1,30 @@ +/* Test that we eliminate y = x and y = x if we can prove that x and y + * already have the same values. + * After copy propagation and cleanup unreachable code elimination, + * target should contain no control-flow instructions. + * Similar to int_only/redundant_copies.c but with structs + * */ + +struct s { + double d; + int i; +}; + +double target(int flag, int flag2, struct s y) { + struct s x = y; + + if (flag) { + y = x; // we can remove this because x and y already have the same + // value + } + if (flag2) { + x = y; // we can remove this because x and y already have the same + // value + } + return x.d + y.d + x.i + y.i; +} + +int main(void) { + struct s my_struct = {25.0, 5}; + return target(0, 1, my_struct) == 60.0; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/store_doesnt_kill.c b/tests/chapter_19/copy_propagation/all_types/store_doesnt_kill.c index 74e32a41..e0c161f0 100644 --- a/tests/chapter_19/copy_propagation/all_types/store_doesnt_kill.c +++ b/tests/chapter_19/copy_propagation/all_types/store_doesnt_kill.c @@ -1,12 +1,43 @@ -int callee(int *p1, int *p2) { return p1 == p2; } - -int target(void) { - int i = 0; - int *ptr = &i; - int *ptr2 = ptr; // generate copy ptr2 = ptr - *ptr = 10; // this does NOT kill copy - // make sure both args have same value, since we can replace ptr2 with ptr - return callee(ptr, ptr2); +/* Test that updating a value through a pointer does not kill that pointer */ + +void exit(int status); // from standard library + +void check_pointers(int a, int b, int *ptr1, int *ptr2) { + if (a != 100 || b != 101) { + exit(1); + } + + if (*ptr1 != 60 || *ptr2 != 61) { + exit(2); + } + return; +} + +int callee(int *p1, int *p2) { + if (p1 != p2) { + exit(3); + } + if (*p2 != 10) { + exit(4); + } + return 0; // success +} + +int target(int *ptr, int *ptr2) { + // first, call another function, with these arguments + // in different positions than in target or callee, so we can't + // coalesce them with the param-passing registers or each other + check_pointers(100, 101, ptr, ptr2); + + ptr2 = ptr; // generate copy + *ptr = 10; // Store(10, ptr) does NOT kill copy + + // both arguments to callee should be the same + return callee(ptr, ptr2); } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + int x = 60; + int y = 61; + return target(&x, &y); +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/unsigned_compare.c b/tests/chapter_19/copy_propagation/all_types/unsigned_compare.c deleted file mode 100644 index ddaa34c1..00000000 --- a/tests/chapter_19/copy_propagation/all_types/unsigned_compare.c +++ /dev/null @@ -1,4 +0,0 @@ -// really a consatnt-folding test -int target(void) { return (-1u > 100u); } - -int main(void) { return target(); } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/unsigned_wraparound.c b/tests/chapter_19/copy_propagation/all_types/unsigned_wraparound.c deleted file mode 100644 index 46cf8761..00000000 --- a/tests/chapter_19/copy_propagation/all_types/unsigned_wraparound.c +++ /dev/null @@ -1,6 +0,0 @@ -unsigned int target(void) { - unsigned int i = 10u - 11u; - return i % 5u; -} - -int main(void) { return target() == 0u; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/complex_const_fold.c b/tests/chapter_19/copy_propagation/int_only/complex_const_fold.c deleted file mode 100644 index 29a1d992..00000000 --- a/tests/chapter_19/copy_propagation/int_only/complex_const_fold.c +++ /dev/null @@ -1,7 +0,0 @@ -int target(void) { - int x = -100; - int y = x * 3 / 5; - return (y < 100 ? x % 3 : x / 4); -} - -int main(void) { return target() == -1; } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/constant_propagation.c b/tests/chapter_19/copy_propagation/int_only/constant_propagation.c new file mode 100644 index 00000000..a95cea7a --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/constant_propagation.c @@ -0,0 +1,12 @@ +/* A basic test of constant propagation in a function with no control flow + * structures + * */ +int target(void) { + int x = 3; + int y = x; + return x + y; // should become return 6 +} + +int main(void) { + return target(); +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/copy_prop_const_fold.c b/tests/chapter_19/copy_propagation/int_only/copy_prop_const_fold.c deleted file mode 100644 index 3ce77565..00000000 --- a/tests/chapter_19/copy_propagation/int_only/copy_prop_const_fold.c +++ /dev/null @@ -1,7 +0,0 @@ -int target(void) { - int x = 3; - int y = x; - return x + y; // look for movl $6, %eax -} - -int main(void) { return target(); } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/different_paths_same_copy.c b/tests/chapter_19/copy_propagation/int_only/different_paths_same_copy.c new file mode 100644 index 00000000..8b560aef --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/different_paths_same_copy.c @@ -0,0 +1,24 @@ +/* If two instances of the copy x = y appear on different paths to some use + * of x, we can propagate that copy. + * */ +int target(int flag) { + int x = 0; + if (flag) { + x = 3; + } else { + x = 3; + } + return x; // this should become 'return 3' +} + +int main(void) { + if (target(1) != 3) { + return 1; + } + + if (target(0) != 3) { + return 2; + } + + return 0; // success +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/different_source_values_same_copy.c b/tests/chapter_19/copy_propagation/int_only/different_source_values_same_copy.c new file mode 100644 index 00000000..62638cde --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/different_source_values_same_copy.c @@ -0,0 +1,38 @@ +/* We can propagate x = y if it appears on all paths to some use of x, + * even if y doesn't have the same value on all those paths. + * Based on Figure 19-5. + * */ + +int callee(int a, int b) { + return a + b; +} +int target(int flag) { + // use static variables here so we can't coalesce x and y + // into the same register, or into EDI and ESI, once we implement + // register coalescing; otherwise it might look like we've propagated + // x = y when we haven't + static int x; + static int y; + if (flag) { + y = 20; + x = y; + } else { + y = 100; + x = y; + } + // x = y reaches here, though with different values of y + return callee(x, y); +} + +int main(void) { + int result = target(0); + + if (result != 40) + return 1; + + result = target(1); + if (result != 20) + return 2; + + return 0; // success +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/add_all_blocks_to_worklist.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/add_all_blocks_to_worklist.c index 6e6e1e75..e03dfce9 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/add_all_blocks_to_worklist.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/add_all_blocks_to_worklist.c @@ -1,22 +1,31 @@ -int flag(void) -{ - return 1; -} +/* Test that we add every block to the worklist + * at the start of the iterative algoirthm + * */ + +int global; + +int flag = 1; -int bar(void) -{ - return 4; +int f(void) { + global = 100; + return 0; } -int main(void) -{ - int x = 1; - // all copies reach this block, so processing its predecessor - // won't change its incoming copies - // but we still gotta add it to worklist - if (flag()) - { - x = bar(); +int main(void) { + // Initially, we annotate every block with 'global = 0', + // which is the only copy in 'main'. + global = 0; + + // The copy 'global = 0' reaches this if statement. If we only add a block + // to the worklist when its predecessor's outgoing copies change, + // instead of adding every block to the initial worklist, we won't + // visit this block at all, and we won't see the call to f(), + // which kills this copy + if (flag) { + f(); // kill copy to global } - return x; -} \ No newline at end of file + + // If we didn't visit that if statement, we'll incorrectly + // rewrite this as 'return 0'. + return global; +} diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/dest_killed.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/dest_killed.c index 486e8446..602b0880 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/dest_killed.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/dest_killed.c @@ -1,11 +1,12 @@ -int foo(void) -{ +/* Test that updating a variable kills previous + * copies to that variable + * */ +int foo(void) { return 4; } -int main(void) -{ +int main(void) { int x = 3; - x = foo(); - return x; + x = foo(); // this kills x = 3 + return x; // don't propagate x = 3 } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/listing_19_14.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/listing_19_14.c new file mode 100644 index 00000000..964d1003 --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/listing_19_14.c @@ -0,0 +1,24 @@ +/* Test that function calls kill copies to static local variables; + * example from Listing 19-14 + * */ + +int indirect_update(void); + +int f(int new_total) { + static int total = 0; + total = new_total; // generate copy total = new_total + if (total > 100) + return 0; + total = 10; // generate total = 10 + indirect_update(); // kill total = 10 (b/c total is static) + return total; // can't rewrite as 'return 10' +} + +int indirect_update(void) { + f(101); // this will update 'total' + return 0; +} + +int main(void) { + return f(1); // expected return value: 101 +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/listing_20_15.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/listing_20_15.c deleted file mode 100644 index 1192d22b..00000000 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/listing_20_15.c +++ /dev/null @@ -1,23 +0,0 @@ -int indirect_update(void); - -int f(int new_total) -{ - static int total = 0; - total = new_total; - if (total > 100) - return 0; - total = 10; - indirect_update(); - return total; // can't propagate this -} - -int indirect_update(void) -{ - f(101); - return 0; -} - -int main(void) -{ - return f(1); -} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/multi_values.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/multi_values.c index 7fb8d242..c1a59a1b 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/multi_values.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/multi_values.c @@ -1,13 +1,27 @@ -int multi_path(int flag) -{ - int x = 3; +/* Test for meet operator: if different copies to a variable + * reach the ends of a block's predecessors, no copies to that variable + * reach that block + * */ + +int multi_path(int flag) { + int x = 3; // generate x = 3 if (flag) - x = 4; - // make sure it's not propagated - no assembly inspection needed + x = 4; // kill x = 3, generate x = 4 + + // One predecessor of our final block has outgoing copy x = 3, + // the other has outgoing copy x = 4. Their intersection is the empty set, + // so we can't propagate any value to this return statement. return x; } -int main(void) -{ - return multi_path(1) + multi_path(0); +int main(void) { + if (multi_path(1) != 4) { + return 1; + } + + if (multi_path(0) != 3) { + return 2; + } + + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/no_copies_reach_entry.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/no_copies_reach_entry.c index 22d006db..7ced5218 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/no_copies_reach_entry.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/no_copies_reach_entry.c @@ -1,10 +1,16 @@ -int foo(int a) -{ +/* Make sure we the set of reaching copies from ENTRY is empty */ +int target(int a, int flag) { + if (flag) { + // if we initialized ENTRY with the set of all copies in target, + // we'll think that a = 10 reaches this return statement, + // and incorrectly rewrite it as 'return 10' + return a; + } + + a = 10; // initialize ENTRY w/ empty set of copies, not including this one return a; - a = 10; // initialize ENTRY w/ empty set of copies, not including this one } -int main(void) -{ - return foo(4); +int main(void) { + return target(4, 1); } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/one_reaching_copy.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/one_reaching_copy.c index 75306b83..1c5f54b6 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/one_reaching_copy.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/one_reaching_copy.c @@ -1,21 +1,28 @@ -int flag(void) -{ - return 0; -} +/* If a copy appears on one path to a block but not on all + * paths to that block, it doesn't reach that block. + * */ -int number(void) -{ +int three(void) { return 3; } -int main(void) -{ +int target(int flag) { int x; - if (flag()) + if (flag) x = 10; else - x = number(); - // one predecessor contains copy x = 10, other predecessor contains no copies to x, - // so no copies reach start of this block + x = three(); + // one predecessor contains copy x = 10, other predecessor contains no + // copies to x, so no copies reach 'return x' return x; +} + +int main(void) { + if (target(1) != 10) { + return 1; + } + if (target(0) != 3) { + return 2; + } + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed.c index 67a61be2..d06f27b8 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed.c @@ -1,12 +1,15 @@ -int foo(void) -{ - return 10; -} +/* Basic test that updating the source of a copy kills that copy */ -int main(void) -{ - int x = foo(); - int y = x; // generate y = x - x = 4; // kill y = x - return y; // can't replace y with x here +int x = 10; + +int main(void) { + int y = x; // generate y = x + x = 4; // kill y = x + if (y != 10) { // can't replace y with x here + return 1; + } + if (x != 4) { + return 2; + } + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed_on_one_path.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed_on_one_path.c index a8fe56f8..875fc9ec 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed_on_one_path.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/source_killed_on_one_path.c @@ -1,12 +1,33 @@ -int f(int src, int flag) -{ - int x = src; // generate x = src - if (flag) - src = 10; // kill x = src - return x; +/* If a copy is generated on all paths to a block, + * and its source is updated on one path, + * it doesn't reach that block + * */ + +int putchar(int c); // from standard library + +int f(int src, int flag) { + int x = src; // generate x = src + if (flag) { + src = 65; // kill x = src + } + putchar(src); // use src so assignment doesn't get optimized away entirely + return x; // make sure we don't rewrite this as 'return src' } -int main(void) -{ - return f(5, 1) + f(3, 0); +int main(void) { + // first call f with flag = 0; + // validate return value, and make sure + // src is not updated + if (f(68, 0) != 68) { + return 1; + } + + // now call f with flag = 1; + // validate return value and make sure + // src is updated + if (f(70, 1) != 70) { + return 2; + } + + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_dst_killed.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_dst_killed.c index 80e439ae..da39d639 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_dst_killed.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_dst_killed.c @@ -1,14 +1,26 @@ +/* Function calls kill copies to variables with static storage duration */ int x; -int update_x(void) -{ +int update_x(void) { x = 4; return 0; } -int main(void) -{ - x = 3; - update_x(); - return x; // can't propagte b/c it's static +int target(void) { + x = 3; // generate x = 3 + update_x(); // kill x = 3 + return x; // can't propagte b/c it's static +} + +int main(void) { + // validate return value and value of x after function call + if (target() != 4) { + return 1; + } + + if (x != 4) { + return 2; + } + + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_src_killed.c b/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_src_killed.c index 6639b451..448a1fe1 100644 --- a/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_src_killed.c +++ b/tests/chapter_19/copy_propagation/int_only/dont_propagate/static_src_killed.c @@ -1,14 +1,29 @@ +/* Function calls kill copies where source value + * is a variable with static storage duration + * */ + int x = 1; -int f(void) -{ +int f(void) { x = 4; return 0; } -int main(void) -{ - int y = x; - f(); - return y; +int target(void) { + int y = x; // generate y = x + f(); // kill y = x + return y; // don't +} + +int main(void) { + if (target() != 1) { + return 1; + } + + // make sure x actually got updated + if (x != 4) { + return 2; + } + + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/fig_19_8.c b/tests/chapter_19/copy_propagation/int_only/fig_19_8.c index f0c0d839..166f85d1 100644 --- a/tests/chapter_19/copy_propagation/int_only/fig_19_8.c +++ b/tests/chapter_19/copy_propagation/int_only/fig_19_8.c @@ -1,21 +1,47 @@ -static int is_called; +/* Test case based on Figure 19-8: + * Make sure we run iterative algorithm until the results converge. + * */ +static int called_counter = 0; int callee(int i) { - is_called = 1; - return i == 4; + if (i == 3 && called_counter == 0) { + // we're on first loop iteration; iterate one more time + called_counter = 1; + return 1; + } + if (i == 4 && called_counter == 1) { + // we're on second loop iteration; stop + called_counter = 2; + return 0; + } + + // if we hit this point, something has gone wrong! + // set called_counter to indicate error, then terminate loop + called_counter = -1; + return 0; } int target(void) { - int y = 3; - int x; - do { - x = callee(y); - y = 4; - } while (x); - return y; // should become return 4 + int y = 3; + int keep_looping; + do { + // After analyzing each basic block once, + // it will look like we could rewrite this as + // x = callee(3), but once the algorithm converges + // we'll know that isn't safe. + keep_looping = callee(y); + y = 4; + } while (keep_looping); // loop should terminate after first iteration + return y; // should become return 4 } int main(void) { - int result = target(); - return result == 4 && is_called; + int result = target(); + if (result != 4) { + return 1; + } + if (called_counter != 2) { + return 2; + } + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/init_all_copies.c b/tests/chapter_19/copy_propagation/int_only/init_all_copies.c index 6ca5ca57..e4e36aea 100644 --- a/tests/chapter_19/copy_propagation/int_only/init_all_copies.c +++ b/tests/chapter_19/copy_propagation/int_only/init_all_copies.c @@ -1,26 +1,36 @@ -static int x = 0; +/* Test that we initialize each basic block with the set of all copies + * in the function + * */ -// test that we initialize each basic block w/ incoming set of all copies -int callee(void) { - x = x + 2; - return 0; -} -int count_down(void) { - static int i = 2; - i = i - 1; - return i; +int counter = 0; + +int increment_counter(void) { + counter = counter + 1; + return 0; } + int target(void) { - int y = 3; - do { - // when we first process this, one predecessor will having reaching copy y = - // 3 other predecessorw on't be processed yet - callee(); - } while (count_down()); - return y; // should become return 3 + int y = 3; + do { + // when we first process this block, + // y = 3 will reach it from one predecessor, and we won't have + // visited the other yet; make sure we still recognize + // that y = 3 reaches this block (and its successor) + increment_counter(); + } while (counter < 5); + return y; // this should become return 3 } int main(void) { - int result = target(); - return x == 4 && result == 3; + int result = target(); + if (result != 3) { + return 1; + } + + // make sure we looped the right number of times + if (counter != 5) { + return 2; + } + + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/kill_and_add_copies.c b/tests/chapter_19/copy_propagation/int_only/kill_and_add_copies.c index 1135cc87..c79ab588 100644 --- a/tests/chapter_19/copy_propagation/int_only/kill_and_add_copies.c +++ b/tests/chapter_19/copy_propagation/int_only/kill_and_add_copies.c @@ -1,18 +1,35 @@ -static int x = 0; // make x static so it's not impacted by dead store elim +/* Test how we handle copies in the transfer function: + * x = src should generate a copy _and_ kill previous copies + * where x is the source or destination + * */ +static int globvar; -int set_x(void) { - x = 4; - return 1; +int set_globvar(int i) { + globvar = i; + return 0; } -int callee(int a, int b) { return a + b; } +int callee(int a, int b) { + return a + b; +} -int target(void) { - set_x(); - int y = x; // gen y = x; - x = 10; // kill y = x, gen x = 10 - // make sure we propagate x = 10 but not y = x - return callee(x, y); // becomes use(10, y) +int target(int param) { + int x = param; + // should be able to propagate param into var but we don't explicitly + // check that here + set_globvar(x); + int y = x; // gen y = x; + x = 10; // kill x = param and y = x, gen x = 10 + // make sure we propagate x = 10 but not y = x + return callee(x, y); // becomes callee(10, y) } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + if (target(4) != 14) { + return 1; + } + if (globvar != 4) { // make sure we passed the right value to set_globvar + return 2; + } + return 0; // success +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/killed_then_redefined.c b/tests/chapter_19/copy_propagation/int_only/killed_then_redefined.c index c7f50594..f775f436 100644 --- a/tests/chapter_19/copy_propagation/int_only/killed_then_redefined.c +++ b/tests/chapter_19/copy_propagation/int_only/killed_then_redefined.c @@ -1,10 +1,32 @@ -int callee(void) { return 3; } +/* If two identical copies to x appear on the path to some use of x, + * and the first one is killed, make sure we can still propagate the second. + * */ + +int x = 0; +int y = 0; + +int callee(void) { + y = x * 2; // make sure x still has the right value at this point + return 5; +} int target(void) { - int x = 2; - x = callee(); - x = 2; - return x; // look for movl $2, %eax + x = 2; // gen x = 2 + x = callee(); // kill x = 2 + x = 2; // gen x = 2 again + return x; // should become "return 2" } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + int result = target(); + if (result != 2) { + return 1; + } + if (y != 4) { // make sure we called callee() + return 2; + } + if (x != 2) { + return 3; + } + return 0; // success +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/loop.c b/tests/chapter_19/copy_propagation/int_only/loop.c deleted file mode 100644 index ce97e9f4..00000000 --- a/tests/chapter_19/copy_propagation/int_only/loop.c +++ /dev/null @@ -1,28 +0,0 @@ -int count_down(void) { - static int i = 10; - i = i - 1; - return i; -} - -int sum = 0; - -int callee(void) { return 5; } - -int use(int i) { return sum = sum + i; } - -int target(void) { - int y = 10; // gen y = 10 - int x = y; // gen x = y - while (count_down()) { - x = callee(); // kill x = y - use(x); - x = y; // gen x = y - } - - return x; // should become "return 10" -} - -int main(void) { - int result = target(); - return result == 10 && sum == 45; -} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/multi_instance_same_copy.c b/tests/chapter_19/copy_propagation/int_only/multi_instance_same_copy.c deleted file mode 100644 index a1b08c8e..00000000 --- a/tests/chapter_19/copy_propagation/int_only/multi_instance_same_copy.c +++ /dev/null @@ -1,31 +0,0 @@ -int callee(int a, int b) { return a + b; } -int target(int flag) { - int x; - int y; - if (flag) { - y = 10; - x = y; - } else { - y = 20; - x = y; - } - // x = y reaches here, though with different values of y - // compare to Figure 20-6 - // should return y (which is rip-relative) - // one catch - what if they decide to be clever and use movl %eax, _y(%rip) - // instead? (GCC does) maybe we don't need to worry about that - return callee(x, y); -} - -int main(void) { - int result = target(0); - - if (result != 40) - return 0; - - result = target(1); - if (result != 20) - return 0; - - return 1; -} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/multi_path.c b/tests/chapter_19/copy_propagation/int_only/multi_path.c deleted file mode 100644 index 61532b36..00000000 --- a/tests/chapter_19/copy_propagation/int_only/multi_path.c +++ /dev/null @@ -1,11 +0,0 @@ -int target(int flag) { - int x = 0; - if (flag) { - x = 3; - } else { - x = 3; - } - return x; // look for movl $3, %eax -} - -int main(void) { return target(1) + target(0); } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/multi_path_no_kill.c b/tests/chapter_19/copy_propagation/int_only/multi_path_no_kill.c index 94272274..14f9178a 100644 --- a/tests/chapter_19/copy_propagation/int_only/multi_path_no_kill.c +++ b/tests/chapter_19/copy_propagation/int_only/multi_path_no_kill.c @@ -1,19 +1,29 @@ - +/* If there are multiple paths from x = 3 to a use of x, but the copy + * isn't killed on any of those paths, we can propagate it. + * */ int var = 0; int callee(void) { - var = var + 1; - return 0; + var = var + 1; + return 0; } int target(int flag) { - int x = 3; - if (flag) - callee(); - return x; // look for movl $3, %eax + int x = 3; + if (flag) + callee(); + return x; // should become return 3 } int main(void) { - int result = target(0); - result = result + target(1); - return result == 6 && var == 1; + if (target(0) != 3) { + return 1; + } + if (target(1) != 3) { + return 2; + } + // make sure callee was called once + if (var != 1) { + return 3; + } + return 0; // success } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/nested_loops.c b/tests/chapter_19/copy_propagation/int_only/nested_loops.c new file mode 100644 index 00000000..0351e01f --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/nested_loops.c @@ -0,0 +1,134 @@ +/* A test case that takes even longer than fig_19_8.c to converge; + * some blocks need to be visited three times before the algorithm converges. + * */ + +static int outer_flag = 0; +static int inner_flag = 1; + +// functions to validate args and control number of loop iterations +int inner_loop1(int a, int b, int c, int d, int e, int f) { + // this should be the second loop iteration, so b, c, and e should be + // updated, but a, d, and f shouldn't + if (a != 1 || b != 11 || c != 12 || d != 4 || e != 20 || f != 100) { + return 0; // fail + } + return 1; // success +} + +int inner_loop2(int a, int b, int c, int d, int e, int f) { + if (outer_flag == 0) { + // first call: no variables have been updated + if (a != 1 || b != 2 || c != 3 || d != 4 || e != 5 || f != 100) { + return 0; // fail + } + } else { + // second call: a, b, c, and e have been updated + if (a != 10 || b != 11 || c != 12 || d != 4 || e != 20 || f != 100) { + return 0; // fail + } + } + + return 1; // success +} + +int inner_loop3(int a, int b, int c, int d, int e, int f) { + if (outer_flag == 0) { + if (inner_flag == 2) { + // first call to this function: only b has been updated + if (a != 1 || b != 11 || c != 3 || d != 4 || e != 5 || f != 100) { + return 0; // fail + } + } else { + // second iteration through inner loop: b and c have been updated + if (a != 1 || b != 11 || c != 12 || d != 4 || e != 5 || f != 100) { + return 0; // fail + } + } + } else { + // second time through outer loop: a, b, c, and e have been updated + if (a != 10 || b != 11 || c != 12 || d != 4 || e != 20 || f != 100) { + return 0; // fail + } + } + + return 1; // success +} + +int inner_loop4(int a, int b, int c, int d, int e, int f) { + // this never runs + // use all parameters to silence compiler warnings + return a + b + c + d + e + f; +} + +int validate(int a, int b, int c, int d, int e, int f) { + // a, b, c, and e have been updated + if (a != 10 || b != 11 || c != 12 || d != 4 || e != 20 || f != 100) { + return 0; // fail + } + return 1; // success +} + +int target(void) { + // we can propagate f throughout whole function, but nothing else + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 100; + + // go through outer loop twice + while (outer_flag < 2) { + // skip this loop on first outer iteration, run on second + while (inner_flag < 1) { + if (!inner_loop1(a, b, c, d, e, f)) { + return 1; // fail + } + a = 10; + inner_flag = 1; + } + + // do this loop once per outer iteration + while (inner_flag < 2) { + if (!inner_loop2(a, b, c, d, e, f)) { + return 2; // fail + } + b = 11; + // set inner_flag to 2 so this loop doesn't run again but next loop + // runs twice + inner_flag = 2; + } + + // do this loop twice per outer iteration + while (inner_flag < 4) { + if (!inner_loop3(a, b, c, d, e, f)) { + return 3; // fail + } + // increment inner_flag so this loop runs twice + inner_flag = inner_flag + 1; + c = 12; + } + + // skip this loop both times + while (inner_flag < 4) { + inner_loop4(a, b, c, d, e, f); + d = 13; + } + + e = 20; + f = 100; + outer_flag = outer_flag + 1; + // reset inner flag + inner_flag = 0; + } + + if (!validate(a, b, c, d, e, f)) { // we can propagate f into this call + return 4; + } + + return 0; // success +} + +int main(void) { + return target(); +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/prop_static_var.c b/tests/chapter_19/copy_propagation/int_only/prop_static_var.c deleted file mode 100644 index 6f6fef0a..00000000 --- a/tests/chapter_19/copy_propagation/int_only/prop_static_var.c +++ /dev/null @@ -1,14 +0,0 @@ -int x = 0; - -int target(void) { - // we can propagate value of x, even though it has static storage duration, - // b/c no intervening reads/writes - x = 10; - int y = x; - return y; // should become "return 10" -} - -int main(void) { - int result = target(); - return result == 10 && x == 10; -} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/propagate_fun_args.c b/tests/chapter_19/copy_propagation/int_only/propagate_fun_args.c deleted file mode 100644 index 15639bd3..00000000 --- a/tests/chapter_19/copy_propagation/int_only/propagate_fun_args.c +++ /dev/null @@ -1,15 +0,0 @@ -int callee(int a, int b) { return a * b; } - -int target(int a, int b) { - int x = 10; // generate x = 10 - int y = 20; // generate y = 20 - x = a + b; // kill x = 10 - // should become callee(x, 20) - // look for movl $20, %esi - // dst of addl should be source of movl to edi (or, should be rdi) - // NOTE: mention that tests assume no function inlining... - // or just have separate compilation unit to prevent that - return callee(x, y); -} - -int main(void) { return target(5, 6); } \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/propagate_into_complex_expressions.c b/tests/chapter_19/copy_propagation/int_only/propagate_into_complex_expressions.c new file mode 100644 index 00000000..3fa4e906 --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/propagate_into_complex_expressions.c @@ -0,0 +1,13 @@ +/* Test that we can propagate values from copies + * into unary expressions, binary expressions, + * and conditional jumps. + * */ +int target(void) { + int x = 100; + int y = -x * 3 + 300; + return (y ? x % 3 : x / 4); +} + +int main(void) { + return target() == 25; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/propagate_params.c b/tests/chapter_19/copy_propagation/int_only/propagate_params.c new file mode 100644 index 00000000..f9a91ceb --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/propagate_params.c @@ -0,0 +1,43 @@ +/* Test that we can propagate copies both to and from function parameters; + * similar to propagate_var, but with paramters instead of variables. + * */ +int callee(int a, int b) { + return a * b; +} +int f(void) { + return 3; +} +int globl = 0; +int set_globvar(void) { + globl = 4; + return 0; +} +int target(int a, int b) { + b = a; // propagate copy from a to b + + // call another function before callee so we can't coalesce a into EDI + // or b into ESI; otherwise, once we implement register coalescing, + // it will look like we've propagated the copy even if we haven't + set_globvar(); + // look for: same value passed in ESI, EDI + int product = callee(a, b); + + // now update b while a is live, so we can't coalesce them + // into the same register; otherwise it will look like we've propagated + // the copy even if we haven't + b = f(); + return (product + a - b); // return 5 * 5 + 5 - 3 ==> 27 +} + +int main(void) { + if (target(5, 6) != 27) { + return 1; + } + + // make sure we called set_globvar + if (globl != 4) { + return 2; + } + + return 0; // success +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/propagate_static.c b/tests/chapter_19/copy_propagation/int_only/propagate_static.c new file mode 100644 index 00000000..eda6db44 --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/propagate_static.c @@ -0,0 +1,21 @@ +/* Test that we can propagate copies to variables with static storage + * duration */ +int x = 0; + +int target(void) { + // we can propagate value of x, even though it has static storage duration, + // b/c no intervening reads/writes + x = 10; + return x; // should become "return 10" +} + +int main(void) { + int result = target(); + if (result != 10) { + return 1; + } + if (x != 10) { + return 2; + } + return 0; // success +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/propagate_static_var.c b/tests/chapter_19/copy_propagation/int_only/propagate_static_var.c new file mode 100644 index 00000000..69a6ae46 --- /dev/null +++ b/tests/chapter_19/copy_propagation/int_only/propagate_static_var.c @@ -0,0 +1,39 @@ +/* Propagate a copy where the source value is a variable with static storage + * duration, in a function with no control flow strucures. + * */ +int callee(int a, int b) { + return a + b; +} + +int target(void) { + static int x = 3; + + // y also needs to be static so we can't coalesce + // it into ESI once we implement register coalescing; + // otherwise it may look like we've propagated a copy + // when we haven't + static int y = 0; + + y = x; // make sure we propagate this into function call + + // look for: same value passed in ESI, EDI + int sum = callee(x, y); + + // increment x to make sure we're not just propagating + // x's initial value. (If we are, we'll get the wrong result on + // the second call to target + x = x + 1; + return sum; +} + +int main(void) { + // make sure target gives correct result + if (target() != 6) { + return 1; + } + // invoke again after x has been incremented + if (target() != 8) { + return 2; + } + return 0; // success +} diff --git a/tests/chapter_19/copy_propagation/int_only/propagate_var.c b/tests/chapter_19/copy_propagation/int_only/propagate_var.c index 80ce87c6..2fa62278 100644 --- a/tests/chapter_19/copy_propagation/int_only/propagate_var.c +++ b/tests/chapter_19/copy_propagation/int_only/propagate_var.c @@ -1,14 +1,47 @@ -int callee(int a, int b) { return a + b; } +/* Test that we can propagate copies where the source value is + * a variable, in a function with no control flow strucures. + * */ +int callee(int a, int b) { + return a + b; +} int f(void) { - return 3; + return 3; +} + +int globl = 0; +int set_globvar(void) { + globl = 4; + return 0; } + int target(void) { - int x = f(); - int y = x; - // look for: same value passed in ESI, EDI - // NOTE: this could be accomplished using either copy propagation - // or copy coalescing in register allocator - return callee(x, y); + int x = f(); + int y = x; // propagate this copy into function call + + // call another function before callee so we can't coalesce x into EDI + // or y into ESI; otherwise it will look like we've propagated x as + // a function argument even if we haven't + set_globvar(); + + // look for: same value passed in ESI, EDI + int sum = callee(x, y); + + // now update y while x is live, so we can't coalesce them + // into the same register; otherwise it will look like we've propagated x as + // a function argument even if we haven't + y = f(); + return (sum + x * y); // return 6 + 9 ==> 15 } -int main(void) { return target(); } +int main(void) { + // make sure target gives correct result + if (target() != 15) { + return 1; + } + + // make sure we called set_globvar + if (globl != 4) { + return 2; + } + return 0; // success +} diff --git a/tests/chapter_19/copy_propagation/int_only/redundant_copies.c b/tests/chapter_19/copy_propagation/int_only/redundant_copies.c index 721f3f6d..9129d5bd 100644 --- a/tests/chapter_19/copy_propagation/int_only/redundant_copies.c +++ b/tests/chapter_19/copy_propagation/int_only/redundant_copies.c @@ -1,13 +1,23 @@ -int callee(void) { return 3; } +/* Test that we eliminate y = x and y = x if we can prove that x and y + * already have the same values. + * After copy propagation and cleanup unreachable code elimination, + * target should contain no control-flow instructions + * */ -int target(int flag, int y) { - int x = y; +int target(int flag, int flag2, int y) { + int x = y; - // make sure we optimize out jump/label here b/c y = x is redundnat - if (flag) { - y = x; - } - return y; + if (flag) { + y = x; // we can remove this because x and y already have the same + // value + } + if (flag2) { + x = y; // we can remove this because x and y already have the same + // value + } + return x + y; } -int main(void) { return target(0, 10); } \ No newline at end of file +int main(void) { + return target(0, 1, 10); // should return 20 +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/int_only/redundant_copies_2.c b/tests/chapter_19/copy_propagation/int_only/redundant_copies_2.c deleted file mode 100644 index ea611f43..00000000 --- a/tests/chapter_19/copy_propagation/int_only/redundant_copies_2.c +++ /dev/null @@ -1,22 +0,0 @@ -#if defined SUPPRESS_WARNINGS -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" -#endif - - -int callee(void) { - return 3; -} - -int target(int flag, int y) { - int x = y; - - // make sure we optimize out jump/label here b/c y = x is redundant - if (flag) { - x = y; - } - return y; -} - -int main(void) { - return target(0, 10); -} \ No newline at end of file diff --git a/tests/chapter_19/unreachable_code_elimination/dead_blocks_with_predecessors.c b/tests/chapter_19/unreachable_code_elimination/dead_blocks_with_predecessors.c index 72608243..f783ca69 100644 --- a/tests/chapter_19/unreachable_code_elimination/dead_blocks_with_predecessors.c +++ b/tests/chapter_19/unreachable_code_elimination/dead_blocks_with_predecessors.c @@ -20,6 +20,7 @@ int target(void) { for (; x < 10; x = x + 1) { x = x + callee(); } + return x; } int main(void) { diff --git a/tests/chapter_19/whole_pipeline/all_types/char_round_trip.c b/tests/chapter_19/whole_pipeline/all_types/char_round_trip.c new file mode 100644 index 00000000..0548def7 --- /dev/null +++ b/tests/chapter_19/whole_pipeline/all_types/char_round_trip.c @@ -0,0 +1,13 @@ +// test constant folding of type conversions between char and int; +// this may already be covered elsewhere +int target(void) { + int i = 257; + char c = i; + i = 255; + char c2 = i; + return (int)c == 1 && (int) c2 == -1; +} + +int main(void) { + return target(); +} \ No newline at end of file diff --git a/tests/chapter_19/whole_pipeline/all_types/const_fold_sign_extend.c b/tests/chapter_19/whole_pipeline/all_types/const_fold_sign_extend.c new file mode 100644 index 00000000..382db8f6 --- /dev/null +++ b/tests/chapter_19/whole_pipeline/all_types/const_fold_sign_extend.c @@ -0,0 +1,7 @@ +long target(void) { + return -1000; +} + +int main(void) { + return target() == -1000l; +} \ No newline at end of file diff --git a/tests/chapter_19/whole_pipeline/all_types/const_fold_sign_extend_2.c b/tests/chapter_19/whole_pipeline/all_types/const_fold_sign_extend_2.c new file mode 100644 index 00000000..07ccc13f --- /dev/null +++ b/tests/chapter_19/whole_pipeline/all_types/const_fold_sign_extend_2.c @@ -0,0 +1,7 @@ +unsigned long target(void) { + return -1000; +} + +int main(void) { + return target() == 18446744073709550616ul; +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/not_char.c b/tests/chapter_19/whole_pipeline/all_types/not_char.c similarity index 72% rename from tests/chapter_19/copy_propagation/all_types/not_char.c rename to tests/chapter_19/whole_pipeline/all_types/not_char.c index 483f6c3d..5e3e52ec 100644 --- a/tests/chapter_19/copy_propagation/all_types/not_char.c +++ b/tests/chapter_19/whole_pipeline/all_types/not_char.c @@ -7,8 +7,10 @@ #endif int target(void) { - char x = 256; - return !x; + char x = 256; + return !x; } -int main(void) { return target(); } \ No newline at end of file +int main(void) { + return target(); +} \ No newline at end of file diff --git a/tests/chapter_19/copy_propagation/all_types/signed_unsigned_conversion.c b/tests/chapter_19/whole_pipeline/all_types/signed_unsigned_conversion.c similarity index 51% rename from tests/chapter_19/copy_propagation/all_types/signed_unsigned_conversion.c rename to tests/chapter_19/whole_pipeline/all_types/signed_unsigned_conversion.c index 44eff58b..6de1a618 100644 --- a/tests/chapter_19/copy_propagation/all_types/signed_unsigned_conversion.c +++ b/tests/chapter_19/whole_pipeline/all_types/signed_unsigned_conversion.c @@ -2,9 +2,11 @@ // copy propagation unsigned int target(void) { - int i = -1; - unsigned int u = (unsigned)i; - return u - 10; + int i = -1; + unsigned int u = (unsigned)i; + return u - 10; } -int main(void) { return target() == 4294967285u; } \ No newline at end of file +int main(void) { + return target() == 4294967285u; +} \ No newline at end of file diff --git a/tests/chapter_19/whole_pipeline/all_types/unsigned_compare.c b/tests/chapter_19/whole_pipeline/all_types/unsigned_compare.c new file mode 100644 index 00000000..95721634 --- /dev/null +++ b/tests/chapter_19/whole_pipeline/all_types/unsigned_compare.c @@ -0,0 +1,8 @@ +// really a consatnt-folding test +int target(void) { + return (-1u > 100u); +} + +int main(void) { + return target(); +} \ No newline at end of file diff --git a/tests/chapter_19/whole_pipeline/all_types/unsigned_wraparound.c b/tests/chapter_19/whole_pipeline/all_types/unsigned_wraparound.c new file mode 100644 index 00000000..5101e41f --- /dev/null +++ b/tests/chapter_19/whole_pipeline/all_types/unsigned_wraparound.c @@ -0,0 +1,8 @@ +unsigned int target(void) { + unsigned int i = 10u - 11u; + return i % 5u; +} + +int main(void) { + return target() == 0u; +} \ No newline at end of file