diff options
Diffstat (limited to 'lib/compiler/src')
| -rw-r--r-- | lib/compiler/src/beam_bool.erl | 75 | ||||
| -rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 42 | 
2 files changed, 81 insertions, 36 deletions
| diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl index 5a4621dc37..a452d30b61 100644 --- a/lib/compiler/src/beam_bool.erl +++ b/lib/compiler/src/beam_bool.erl @@ -126,44 +126,53 @@ bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) ->  		%% There was a reference to a boolean expression  		%% from inside a protected block (try/catch), to  		%% a boolean expression outside. -		  throw:protected_barrier -> +		throw:protected_barrier ->  		    failed; -		  %% The 'xor' operator was used. We currently don't -		  %% find it worthwile to translate 'xor' operators -		  %% (the code would be clumsy). -		  throw:'xor' -> +		%% The 'xor' operator was used. We currently don't +		%% find it worthwile to translate 'xor' operators +		%% (the code would be clumsy). +		throw:'xor' ->  		    failed; -		  %% The block does not contain a boolean expression, -		  %% but only a call to a guard BIF. -		  %% For instance: ... when element(1, T) -> - 		  throw:not_boolean_expr -> +		%% The block does not contain a boolean expression, +		%% but only a call to a guard BIF. +		%% For instance: ... when element(1, T) -> +		throw:not_boolean_expr ->   		    failed; -		  %% The block contains a 'move' instruction that could -		  %% not be handled. - 		  throw:move -> +		%% The block contains a 'move' instruction that could +		%% not be handled. +		throw:move ->   		    failed; -		  %% The optimization is not safe. (A register -		  %% used by the instructions following the -		  %% optimized code is either not assigned a -		  %% value at all or assigned a different value.) -		  throw:all_registers_not_killed -> +		%% The optimization is not safe. (A register +		%% used by the instructions following the +		%% optimized code is either not assigned a +		%% value at all or assigned a different value.) +		throw:all_registers_not_killed ->  		    failed; -		  throw:registers_used -> +		throw:registers_used ->  		    failed; -		  %% A protected block refered to the value -		  %% returned by another protected block, -		  %% probably because the Core Erlang code -		  %% used nested try/catches in the guard. -		  %% (v3_core never produces nested try/catches -		  %% in guards, so it must have been another -		  %% Core Erlang translator.) -		  throw:protected_violation -> +		%% A protected block refered to the value +		%% returned by another protected block, +		%% probably because the Core Erlang code +		%% used nested try/catches in the guard. +		%% (v3_core never produces nested try/catches +		%% in guards, so it must have been another +		%% Core Erlang translator.) +		throw:protected_violation -> +		    failed; + +		%% Failed to work out the live registers for a GC +		%% BIF. For example, if the number of live registers +		%% needed to be 4 because {x,3} was a source register, +		%% but {x,2} was not known to be initialized, this +		%% exception would be thrown. +		throw:gc_bif_alloc_failure ->  		    failed +  	    end      end. @@ -665,10 +674,16 @@ put_reg_1(V, [], I) -> [{I,V}].  fetch_reg(V, [{I,V}|_]) -> {x,I};  fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs). -live_regs(Regs) -> -    foldl(fun ({I,_}, _) -> -		  I -	  end, -1, Regs)+1. +live_regs([{_,reserved}|_]) -> +    %% We are not sure that this register is initialized, so we must +    %% abort the optimization. +    throw(gc_bif_alloc_failure); +live_regs([{I,_}]) -> +    I+1; +live_regs([{_,_}|Regs]) -> +    live_regs(Regs); +live_regs([]) -> +    0.  %%% diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 82817a987a..09716d0866 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -2072,17 +2072,47 @@ maybe_replace_var_1(E, #sub{t=Tdb}) ->  		false ->  		    E;  		true -> -		    cerl_trees:map(fun(C) -> -					   case cerl:is_c_alias(C) of -					       false -> C; -					       true -> cerl:alias_pat(C) -					   end -				   end, T0) +		    %% The pattern was a tuple. Now we must make sure +		    %% that the elements of the tuple are suitable. In +		    %% particular, we don't want binary or map +		    %% construction here, since that means that the +		    %% binary or map will be constructed in the 'case' +		    %% argument. That is wasteful for binaries. Even +		    %% worse is that any map pattern that use the ':=' +		    %% operator will fail when used in map +		    %% construction (only the '=>' operator is allowed +		    %% when constructing a map from scratch). +		    ToData = fun coerce_to_data/1, +		    try +			cerl_trees:map(ToData, T0) +		    catch +			throw:impossible -> +			    %% Something unsuitable was found (map or +			    %% or binary). Keep the variable. +			    E +		    end  	    end;  	error ->  	    E      end. +%% coerce_to_data(Core) -> Core' +%%  Coerce an element originally from a pattern to an data item or or +%%  variable. Throw an 'impossible' exception if non-data Core Erlang +%%  terms such as binary construction or map construction are +%%  encountered. + +coerce_to_data(C) -> +    case cerl:is_c_alias(C) of +	false -> +	    case cerl:is_data(C) orelse cerl:is_c_var(C) of +		true -> C; +		false -> throw(impossible) +	    end; +	true -> +	    coerce_to_data(cerl:alias_pat(C)) +    end. +  %% case_opt_lit(Literal, Clauses0, LitExpr) ->  %%           {ok,[],Clauses} | error  %%  The current part of the case expression is a literal. That | 
