Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
propagate comments forward for no_bs_start_match2 validation errors
(See the parent commit for some a primer on the problem and test cases.) This commit is refactors a fix for a `beam_validator` failure we are currently solving by hard-coding a register. In the test case: parse_float2(<<".", Rest/binary>>) -> parse_digits2([], Rest); parse_float2(Bin) -> {[], Bin}. parse_digits2(Foo, Bin) -> parse_digits2(Foo, [], Bin). parse_digits2(Foo, Bar, Bin) -> parse_digits2(Foo, Bar, Bin, []). parse_digits2( Foo, Bar, <<Digit/integer, Rest/binary>>, Acc) when is_integer(Digit) andalso Digit >= 48 andalso Digit =< 57 -> parse_digits2(Foo, Bar, Rest, [Digit | Acc]); parse_digits2(_Foo, _Bar, Rest, Acc) -> {lists:reverse(Acc), Rest}. Prior to this commit, `beam_validator` gave the following validation error: {{'kfun__tx_funs__-allowed_bs_match_digit_parser2_test/0-fun-0-__33998213', tx_funs__parse_float2,1}, {{call_only,2,{f,7}},10,no_bs_start_match2}}} Which happens because `parse_float2/1` calls `parse_digits2/2` with an argument which is annotated as accepting a match context, but the parameter in `parse_digits2/2` is not yet annotated as accepting a match context. In order to fix this scenario, we would need to determine which parameter of `parse_digits2/2` (and later which of `parse_digits2/3` needs to accept a match context, since that information is not available in the `beam_validator` failure message. Lets look at the disasm for that function: {function,tx_funs__parse_float2,1,4, [{label,3}, {line, [{location, "/home/michael/dev-tools/code/khepri/test/tx_funs.erl", 279}]}, {func_info, {atom, 'kfun__tx_funs__-allowed_bs_match_digit_parser2_test/0-fun-0-__33998213'}, {atom,tx_funs__parse_float2}, 1}, {label,4}, {'%',{var_info,{x,0},[accepts_match_context]}}, {bs_start_match4,{atom,no_fail},1,{x,0},{x,0}}, {test,bs_match_string, {f,5}, [{x,0},8,{string,<<".">>}]}, {move,{x,0},{x,1}}, {move,nil,{x,0}}, {call_only,2,{f,7}}, {label,5}, {bs_get_tail,{x,0},{x,0},1}, {test_heap,3,1}, {put_tuple2,{x,0},{list,[nil,{x,0}]}}, return]} We want to pull forward the annotation (5th instruction, 1-indexed) for `{x,0}` to the definition of the function being called ({f,7}). First we lookup the function code for the failing function by Name and Arity (`find_comments_for_call/4`), then determine the typing of the branch in which the call occurs: in this case by scanning the instructions between {label,4} (the start of the branch) and instruction 10 (the call_only; we get this index from the `beam_validator` failure message), gathering annotations and following {move,Src,Dst} instructions. Once we have the annotations leading up to the call, we can add them to right after the callee's entrypoint. The `merge_comments/2` and `add_comments_to_code/4` functions have been refactored to allow merging in multiple comments at once, which may be necessary if we're propagating the typing for multiple parameters.
- Loading branch information