1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2017-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% Purpose : Optimize bit syntax matching. 21 22 23-module(sys_core_bsm). 24-export([module/2]). 25 26-include("core_parse.hrl"). 27 28-spec module(cerl:c_module(), [compile:option()]) -> {'ok', cerl:c_module()}. 29 30module(#c_module{defs=Ds}=Mod, _Opts) -> 31 {ok,Mod#c_module{defs=function(Ds)}}. 32 33function([{#c_var{name={F,Arity}}=Name,B0}|Fs]) -> 34 try cerl_trees:map(fun bsm_reorder/1, B0) of 35 B -> [{Name,B} | function(Fs)] 36 catch 37 Class:Error:Stack -> 38 io:fwrite("Function: ~w/~w\n", [F,Arity]), 39 erlang:raise(Class, Error, Stack) 40 end; 41function([]) -> 42 []. 43 44%%% Reorder bit syntax matching to faciliate optimization in further passes. 45 46bsm_reorder(#c_case{arg=#c_var{}=V}=Case) -> 47 bsm_reorder_1([V], Case); 48bsm_reorder(#c_case{arg=#c_values{es=Es}}=Case) -> 49 bsm_reorder_1(Es, Case); 50bsm_reorder(Core) -> 51 Core. 52 53bsm_reorder_1(Vs0, #c_case{clauses=Cs0}=Case) -> 54 case bsm_leftmost(Cs0) of 55 Pos when Pos > 0, Pos =/= none -> 56 Vs = core_lib:make_values(move_from_col(Pos, Vs0)), 57 Cs = [C#c_clause{pats=move_from_col(Pos, Ps)} 58 || #c_clause{pats=Ps}=C <- Cs0], 59 Case#c_case{arg=Vs,clauses=Cs}; 60 _ -> 61 Case 62 end. 63 64move_from_col(Pos, L) -> 65 {First,[Col|Rest]} = lists:split(Pos - 1, L), 66 [Col|First] ++ Rest. 67 68%% bsm_leftmost(Cs) -> none | ArgumentNumber 69%% Find the leftmost argument that matches a nonempty binary. 70%% Return either 'none' or the argument number (1-N). 71 72bsm_leftmost(Cs) -> 73 bsm_leftmost_1(Cs, none). 74 75bsm_leftmost_1([_|_], 1) -> 76 1; 77bsm_leftmost_1([#c_clause{pats=Ps}|Cs], Pos) -> 78 bsm_leftmost_2(Ps, Cs, 1, Pos); 79bsm_leftmost_1([], Pos) -> Pos. 80 81bsm_leftmost_2(_, Cs, Pos, Pos) -> 82 bsm_leftmost_1(Cs, Pos); 83bsm_leftmost_2([#c_binary{segments=[_|_]}|_], Cs, N, _) -> 84 bsm_leftmost_1(Cs, N); 85bsm_leftmost_2([_|Ps], Cs, N, Pos) -> 86 bsm_leftmost_2(Ps, Cs, N+1, Pos); 87bsm_leftmost_2([], Cs, _, Pos) -> 88 bsm_leftmost_1(Cs, Pos). 89