aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/compiler/src/beam_a.erl3
-rw-r--r--lib/compiler/src/beam_block.erl10
-rw-r--r--lib/compiler/src/beam_record.erl2
-rw-r--r--lib/compiler/src/beam_type.erl13
-rw-r--r--lib/compiler/src/beam_utils.erl54
5 files changed, 47 insertions, 35 deletions
diff --git a/lib/compiler/src/beam_a.erl b/lib/compiler/src/beam_a.erl
index 6f09dc4be4..7df2edd714 100644
--- a/lib/compiler/src/beam_a.erl
+++ b/lib/compiler/src/beam_a.erl
@@ -58,7 +58,8 @@ rename_instrs([{call_only,A,F}|Is]) ->
rename_instrs([{call_ext_only,A,F}|Is]) ->
[{call_ext,A,F},return|rename_instrs(Is)];
rename_instrs([{'%live',_}|Is]) ->
- %% When compiling from old .S files.
+ %% Ignore old type of live annotation. Only happens when compiling
+ %% from very old .S files.
rename_instrs(Is);
rename_instrs([I|Is]) ->
[rename_instr(I)|rename_instrs(Is)];
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index 570fc05ae5..c8fea2069a 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -41,7 +41,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is4 = move_allocates(Is3),
Is5 = beam_utils:live_opt(Is4),
Is6 = opt_blocks(Is5),
- Is7 = beam_utils:delete_live_annos(Is6),
+ Is7 = beam_utils:delete_annos(Is6),
Is = opt_allocs(Is7),
%% Done.
@@ -137,7 +137,7 @@ embed_lines([], Acc) -> Acc.
opt_blocks([{block,Bl0}|Is]) ->
%% The live annotation at the beginning is not useful.
- [{'%live',_,_}|Bl] = Bl0,
+ [{'%anno',_}|Bl] = Bl0,
[{block,opt_block(Bl)}|opt_blocks(Is)];
opt_blocks([I|Is]) ->
[I|opt_blocks(Is)];
@@ -196,7 +196,7 @@ move_allocates([I|Is]) ->
[I|move_allocates(Is)];
move_allocates([]) -> [].
-move_allocates_1([{'%def',_}|Is], Acc) ->
+move_allocates_1([{'%anno',_}|Is], Acc) ->
move_allocates_1(Is, Acc);
move_allocates_1([I|Is], [{set,[],[],{alloc,Live0,Info}}|Acc]=Acc0) ->
case alloc_may_pass(I) of
@@ -243,7 +243,7 @@ opt([{set,_,_,{line,_}}=Line1,
opt([{set,Ds0,Ss,Op}|Is0]) ->
{Ds,Is} = opt_moves(Ds0, Is0),
[{set,Ds,Ss,Op}|opt(Is)];
-opt([{'%live',_,_}=I|Is]) ->
+opt([{'%anno',_}=I|Is]) ->
[I|opt(Is)];
opt([]) -> [].
@@ -525,7 +525,7 @@ x_live([], Regs) -> Regs.
%% Given a reversed instruction stream, determine the
%% the registers that are defined.
-defined_regs([{'%def',Def}|_], Regs) ->
+defined_regs([{'%anno',{def,Def}}|_], Regs) ->
Def bor Regs;
defined_regs([{set,Ds,_,{alloc,Live,_}}|_], Regs) ->
x_live(Ds, Regs bor ((1 bsl Live) - 1));
diff --git a/lib/compiler/src/beam_record.erl b/lib/compiler/src/beam_record.erl
index db1053e48c..58a6de6775 100644
--- a/lib/compiler/src/beam_record.erl
+++ b/lib/compiler/src/beam_record.erl
@@ -71,7 +71,7 @@ rewrite([{test,test_arity,Fail,[Src,N]}=TA,
I = {test,is_tagged_tuple,Fail,[Src,N,Atom]},
rewrite(Is, Idx, Def, [I|Acc])
end;
-rewrite([{block,[{'%def',Def}|Bl]}|Is], Idx, _Def, Acc) ->
+rewrite([{block,[{'%anno',{def,Def}}|Bl]}|Is], Idx, _Def, Acc) ->
rewrite(Is, Idx, Def, [{block,Bl}|Acc]);
rewrite([{label,L}=I|Is], Idx0, Def, Acc) ->
Idx = beam_utils:index_label(L, Acc, Idx0),
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 14fe22fd27..3b6bf49961 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -40,7 +40,7 @@ function({function,Name,Arity,CLabel,Asm0}) ->
Asm1 = beam_utils:live_opt(Asm0),
Asm2 = opt(Asm1, [], tdb_new()),
Asm3 = beam_utils:live_opt(Asm2),
- Asm = beam_utils:delete_live_annos(Asm3),
+ Asm = beam_utils:delete_annos(Asm3),
{function,Name,Arity,CLabel,Asm}
catch
Class:Error:Stack ->
@@ -300,7 +300,7 @@ clearerror([], OrigIs) -> [{set,[],[],fclearerror}|OrigIs].
%% Combine two blocks and eliminate any move instructions that assign
%% to registers that are killed later in the block.
%%
-merge_blocks(B1, [{'%live',_,_}|B2]) ->
+merge_blocks(B1, [{'%anno',_}|B2]) ->
merge_blocks_1(B1++[{set,[],[],stop_here}|B2]).
merge_blocks_1([{set,[],_,stop_here}|Is]) -> Is;
@@ -355,7 +355,7 @@ flt_need_heap_2({set,_,_,{alloc,_,_}}, H, Fl) ->
{flt_alloc(H, Fl),0,0};
flt_need_heap_2({set,_,_,{set_tuple_element,_}}, H, Fl) ->
{flt_alloc(H, Fl),0,0};
-flt_need_heap_2({'%live',_,_}, H, Fl) ->
+flt_need_heap_2({'%anno',_}, H, Fl) ->
{flt_alloc(H, Fl),0,0};
%% All other instructions are "neutral". We just pass them.
flt_need_heap_2(_, H, Fl) ->
@@ -382,7 +382,7 @@ build_alloc(Words, Floats) -> {alloc,[{words,Words},{floats,Floats}]}.
%% is not continous at an allocation function (e.g. if {x,0} and {x,2}
%% are live, but not {x,1}).
-flt_liveness([{'%live',_Live,Regs}=LiveInstr|Is]) ->
+flt_liveness([{'%anno',{used,Regs}}=LiveInstr|Is]) ->
flt_liveness_1(Is, Regs, [LiveInstr]).
flt_liveness_1([{set,Ds,Ss,{alloc,Live0,Alloc}}|Is], Regs0, Acc) ->
@@ -394,7 +394,7 @@ flt_liveness_1([{set,Ds,Ss,{alloc,Live0,Alloc}}|Is], Regs0, Acc) ->
flt_liveness_1([{set,Ds,_,_}=I|Is], Regs0, Acc) ->
Regs = x_live(Ds, Regs0),
flt_liveness_1(Is, Regs, [I|Acc]);
-flt_liveness_1([{'%live',_,_}], _Regs, Acc) ->
+flt_liveness_1([{'%anno',_}], _Regs, Acc) ->
reverse(Acc).
init_regs(Live) ->
@@ -418,7 +418,8 @@ x_live([], Regs) -> Regs.
%% Update the type database to account for executing an instruction.
%%
%% First the cases for instructions inside basic blocks.
-update({'%live',_,_}, Ts) -> Ts;
+update({'%anno',_}, Ts) ->
+ Ts;
update({set,[D],[S],move}, Ts) ->
tdb_copy(S, D, Ts);
update({set,[D],[{integer,I},Reg],{bif,element,_}}, Ts0) ->
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index a2795e625f..b9ce3befaf 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -25,7 +25,7 @@
is_not_used/3,usage/3,
empty_label_index/0,index_label/3,index_labels/1,replace_labels/4,
code_at/2,bif_to_test/3,is_pure_test/1,
- live_opt/1,delete_live_annos/1,combine_heap_needs/2,
+ live_opt/1,delete_annos/1,combine_heap_needs/2,
anno_defs/1,
split_even/1
]).
@@ -95,7 +95,7 @@ is_killed_block({x,X}, [{set,_,_,{alloc,Live,_}}|_]) ->
X >= Live;
is_killed_block(R, [{set,Ds,Ss,_Op}|Is]) ->
not member(R, Ss) andalso (member(R, Ds) orelse is_killed_block(R, Is));
-is_killed_block(R, [{'%live',_,Regs}|Is]) ->
+is_killed_block(R, [{'%anno',{used,Regs}}|Is]) ->
case R of
{x,X} when (Regs bsr X) band 1 =:= 0 -> true;
_ -> is_killed_block(R, Is)
@@ -270,7 +270,7 @@ is_pure_test({test,Op,_,Ops}) ->
%% Go through the instruction sequence in reverse execution
%% order, keep track of liveness and remove 'move' instructions
%% whose destination is a register that will not be used.
-%% Also insert {'%live',Live,Regs} annotations at the beginning
+%% Also insert {used,Regs} annotations at the beginning
%% and end of each block.
-spec live_opt([instruction()]) -> [instruction()].
@@ -285,22 +285,22 @@ live_opt(Is0) ->
Bef ++ [Fi|live_opt(reverse(Is), 0, D, [])].
-%% delete_live_annos([Instruction]) -> [Instruction].
-%% Delete all live annotations.
+%% delete_annos([Instruction]) -> [Instruction].
+%% Delete all annotations.
--spec delete_live_annos([instruction()]) -> [instruction()].
+-spec delete_annos([instruction()]) -> [instruction()].
-delete_live_annos([{block,Bl0}|Is]) ->
- case delete_live_annos(Bl0) of
- [] -> delete_live_annos(Is);
- [_|_]=Bl -> [{block,Bl}|delete_live_annos(Is)]
+delete_annos([{block,Bl0}|Is]) ->
+ case delete_annos(Bl0) of
+ [] -> delete_annos(Is);
+ [_|_]=Bl -> [{block,Bl}|delete_annos(Is)]
end;
-delete_live_annos([{'%live',_,_}|Is]) ->
- delete_live_annos(Is);
-delete_live_annos([I|Is]) ->
- [I|delete_live_annos(Is)];
-delete_live_annos([]) -> [].
-
+delete_annos([{'%anno',_}|Is]) ->
+ delete_annos(Is);
+delete_annos([I|Is]) ->
+ [I|delete_annos(Is)];
+delete_annos([]) -> [].
+
%% combine_heap_needs(HeapNeed1, HeapNeed2) -> HeapNeed
%% Combine the heap need for two allocation instructions.
@@ -316,7 +316,7 @@ combine_heap_needs(H1, H2) ->
%% anno_defs(Instructions) -> Instructions'
-%% Add {'%def',RegisterBitmap} annotations to the beginning of
+%% Add {def,RegisterBitmap} annotations to the beginning of
%% each block. Iff bit X is set in the the bitmap, it means
%% that {x,X} is defined when the block is entered.
@@ -658,7 +658,7 @@ check_liveness_ret(_, _, St) -> {killed,St}.
%% alloc_used - Used only in an allocate instruction
%% used - Reg is explicitly used by an instruction
%%
-%% '%live' annotations are not allowed.
+%% Annotations are not allowed.
%%
%% (Unknown instructions will cause an exception.)
@@ -855,9 +855,9 @@ live_opt([{test,bs_start_match2,Fail,Live,[Src,_],_}=I|Is], _, D, Acc) ->
%% Other instructions.
live_opt([{block,Bl0}|Is], Regs0, D, Acc) ->
- Live0 = {'%live',live_regs(Regs0),Regs0},
+ Live0 = make_anno({used,Regs0}),
{Bl,Regs} = live_opt_block(reverse(Bl0), Regs0, D, [Live0]),
- Live = {'%live',live_regs(Regs),Regs},
+ Live = make_anno({used,Regs}),
live_opt(Is, Regs, D, [{block,[Live|Bl]}|Acc]);
live_opt([build_stacktrace=I|Is], _, D, Acc) ->
live_opt(Is, live_call(1), D, [I|Acc]);
@@ -971,7 +971,7 @@ live_opt_block([{set,Ds,Ss,Op0}|Is], Regs0, D, Acc) ->
_ ->
live_opt_block(Is, Regs, D, [I|Acc])
end;
-live_opt_block([{'%live',_,_}|Is], Regs, D, Acc) ->
+live_opt_block([{'%anno',_}|Is], Regs, D, Acc) ->
live_opt_block(Is, Regs, D, Acc);
live_opt_block([], Regs, _, Acc) -> {Acc,Regs}.
@@ -1046,7 +1046,7 @@ defs([{bif,_,{f,Fail},_Src,Dst}=I|Is], Regs0, D) ->
[I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
defs([{block,Block0}|Is], Regs0, D0) ->
{Block,Regs,D} = defs_list(Block0, Regs0, D0),
- [{block,[{'%def',Regs0}|Block]}|defs(Is, Regs, D)];
+ [{block,[make_anno({def,Regs0})|Block]}|defs(Is, Regs, D)];
defs([{bs_init,{f,L},_,_,_,Dst}=I|Is], Regs0, D) ->
Regs = def_regs([Dst], Regs0),
[I|defs(Is, Regs, update_regs(L, Regs, D))];
@@ -1236,3 +1236,13 @@ update_regs(L, Regs0, D) ->
all_defined(Live, Regs) ->
All = (1 bsl Live) - 1,
Regs band All =:= All.
+
+%%%
+%%% Utilities.
+%%%
+
+%% make_anno(Anno) -> WrappedAnno.
+%% Wrap an annotation term.
+
+make_anno(Anno) ->
+ {'%anno',Anno}.