aboutsummaryrefslogtreecommitdiffstats
path: root/lib/debugger/src/dbg_iload.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/debugger/src/dbg_iload.erl')
-rw-r--r--lib/debugger/src/dbg_iload.erl91
1 files changed, 70 insertions, 21 deletions
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index f83684b605..917f213e60 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -72,8 +72,7 @@ store_module(Mod, File, Binary, Db) ->
exit({Mod,too_old_beam_file});
{raw_abstract_v1,Code0} ->
Code = interpret_file_attribute(Code0),
- {_,_,Forms0,_} = sys_pre_expand:module(Code, []),
- Forms0
+ standard_transforms(Code)
end,
dbg_idb:insert(Db, mod_file, File),
dbg_idb:insert(Db, defs, []),
@@ -94,6 +93,11 @@ store_module(Mod, File, Binary, Db) ->
dbg_idb:insert(Db, mod_bin, NewBinary),
dbg_idb:insert(Db, mod_raw, <<Src/binary,0:8>>). %% Add eos
+standard_transforms(Forms0) ->
+ Forms = erl_expand_records:module(Forms0, []),
+ erl_internal:add_predefined_functions(Forms).
+
+
%% Adjust line numbers using the file/2 attribute.
%% Also take the absolute value of line numbers.
%% This simple fix will make the marker point at the correct line
@@ -102,7 +106,6 @@ store_module(Mod, File, Binary, Db) ->
interpret_file_attribute(Code) ->
epp:interpret_file_attribute(Code).
-
abstr(Bin) when is_binary(Bin) -> binary_to_term(Bin);
abstr(Term) -> Term.
@@ -124,8 +127,9 @@ store_forms([{function,_,Name,Arity,Cs0}|Fs], Mod, Db, Exp) ->
store_forms(Fs, Mod, Db, Exp);
store_forms([{attribute,_,_Name,_Val}|Fs], Mod, Db, Exp) ->
store_forms(Fs, Mod, Db, Exp);
-store_forms([F|_], _Mod, _Db, _Exp) ->
- exit({unknown_form,F});
+store_forms([_|Fs], Mod, Db, Exp) ->
+ %% Ignore other forms such as {eof,_} or {warning,_}.
+ store_forms(Fs, Mod, Db, Exp);
store_forms([], _, _, _) ->
ok.
@@ -218,10 +222,34 @@ pattern({op,_,'+',{float,Anno,I}}) ->
pattern({bin,Anno,Grp}) ->
Grp1 = pattern_list(bin_expand_strings(Grp)),
{bin,ln(Anno),Grp1};
-pattern({bin_element,Anno,Expr,Size,Type}) ->
- Expr1 = pattern(Expr),
- Size1 = expr(Size, false),
- {bin_element,ln(Anno),Expr1,Size1,Type}.
+pattern({bin_element,Anno,Expr0,Size0,Type0}) ->
+ {Size1,Type} = make_bit_type(Anno, Size0, Type0),
+ Expr1 = pattern(Expr0),
+ Expr = coerce_to_float(Expr1, Type0),
+ Size = pattern(Size1),
+ {bin_element,ln(Anno),Expr,Size,Type};
+%% Evaluate compile-time expressions.
+pattern({op,_,'++',{nil,_},R}) ->
+ pattern(R);
+pattern({op,_,'++',{cons,Li,H,T},R}) ->
+ pattern({cons,Li,H,{op,Li,'++',T,R}});
+pattern({op,_,'++',{string,Li,L},R}) ->
+ pattern(string_to_conses(Li, L, R));
+pattern({op,_Line,_Op,_A}=Op) ->
+ pattern(erl_eval:partial_eval(Op));
+pattern({op,_Line,_Op,_L,_R}=Op) ->
+ pattern(erl_eval:partial_eval(Op)).
+
+string_to_conses(Anno, Cs, Tail) ->
+ lists:foldr(fun (C, T) -> {cons,Anno,{char,Anno,C},T} end, Tail, Cs).
+
+coerce_to_float({value,Anno,Int}=E, [float|_]) when is_integer(Int) ->
+ try
+ {value,Anno,float(Int)}
+ catch
+ error:badarg -> E
+ end;
+coerce_to_float(E, _) -> E.
%% These patterns are processed "in parallel" for purposes of variable
%% definition etc.
@@ -299,11 +327,12 @@ gexpr({map,Anno,E0,Fs0}) ->
gexpr({bin,Anno,Flds0}) ->
Flds = gexpr_list(bin_expand_strings(Flds0)),
{bin,ln(Anno),Flds};
-gexpr({bin_element,Anno,Expr0,Size0,Type}) ->
+gexpr({bin_element,Anno,Expr0,Size0,Type0}) ->
+ {Size1,Type} = make_bit_type(Anno, Size0, Type0),
Expr = gexpr(Expr0),
- Size = gexpr(Size0),
+ Size = gexpr(Size1),
{bin_element,ln(Anno),Expr,Size,Type};
-%%% The previous passes have added the module name 'erlang' to
+%%% The erl_expand_records pass has added the module name 'erlang' to
%%% all BIF calls, even in guards.
gexpr({call,Anno,{remote,_,{atom,_,erlang},{atom,_,self}},[]}) ->
{dbg,ln(Anno),self,[]};
@@ -383,18 +412,21 @@ expr({'receive',Anno,Cs0,To0,ToEs0}, Lc) ->
ToEs1 = exprs(ToEs0, Lc),
Cs1 = icr_clauses(Cs0, Lc),
{'receive',ln(Anno),Cs1,To1,ToEs1};
-expr({'fun',Anno,{clauses,Cs0},{_,_,Name}}, _Lc) when is_atom(Name) ->
+expr({'fun',Anno,{clauses,Cs0}}, _Lc) ->
%% New R10B-2 format (abstract_v2).
Cs = fun_clauses(Cs0),
+ Name = new_fun_name(),
{make_fun,ln(Anno),Name,Cs};
-expr({'fun',Anno,{function,F,A},{_Index,_OldUniq,Name}}, _Lc) ->
+expr({'fun',Anno,{function,F,A}}, _Lc) ->
%% New R8 format (abstract_v2).
Line = ln(Anno),
As = new_vars(A, Line),
+ Name = new_fun_name(),
Cs = [{clause,Line,As,[],[{local_call,Line,F,As,true}]}],
{make_fun,Line,Name,Cs};
-expr({named_fun,Anno,FName,Cs0,{_,_,Name}}, _Lc) when is_atom(Name) ->
+expr({named_fun,Anno,FName,Cs0}, _Lc) ->
Cs = fun_clauses(Cs0),
+ Name = new_fun_name(),
{make_named_fun,ln(Anno),Name,FName,Cs};
expr({'fun',Anno,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Lc)
when 0 =< A, A =< 255 ->
@@ -508,17 +540,26 @@ expr({op,Anno,Op,L0,R0}, _Lc) ->
expr({bin,Anno,Grp}, _Lc) ->
Grp1 = expr_list(bin_expand_strings(Grp)),
{bin,ln(Anno),Grp1};
-expr({bin_element,Anno,Expr,Size,Type}, _Lc) ->
- Expr1 = expr(Expr, false),
- Size1 = expr(Size, false),
- {bin_element,ln(Anno),Expr1,Size1,Type};
-expr(Other, _Lc) ->
- exit({?MODULE,{unknown_expr,Other}}).
+expr({bin_element,Anno,Expr0,Size0,Type0}, _Lc) ->
+ {Size1,Type} = make_bit_type(Anno, Size0, Type0),
+ Expr = expr(Expr0, false),
+ Size = expr(Size1, false),
+ {bin_element,ln(Anno),Expr,Size,Type}.
consify([A|As]) ->
{cons,0,A,consify(As)};
consify([]) -> {value,0,[]}.
+make_bit_type(Line, default, Type0) ->
+ case erl_bits:set_bit_type(default, Type0) of
+ {ok,all,Bt} -> {{atom,Line,all},erl_bits:as_list(Bt)};
+ {ok,undefined,Bt} -> {{atom,Line,undefined},erl_bits:as_list(Bt)};
+ {ok,Size,Bt} -> {{integer,Line,Size},erl_bits:as_list(Bt)}
+ end;
+make_bit_type(_Line, Size, Type0) -> %Integer or 'all'
+ {ok,Size,Bt} = erl_bits:set_bit_type(Size, Type0),
+ {Size,erl_bits:as_list(Bt)}.
+
%% The debugger converts both strings "abc" and lists [67, 68, 69]
%% into {value, Line, [67, 68, 69]}, making it impossible to later
%% distingish one or the other inside binaries when evaluating. To
@@ -594,6 +635,14 @@ new_vars(N, L, Vs) when N > 0 ->
new_vars(N-1, L, [V|Vs]);
new_vars(0, _, Vs) -> Vs.
+new_fun_name() ->
+ {F,A} = get(current_function),
+ I = get(fun_count),
+ put(fun_count, I+1),
+ Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(A) ++
+ "-fun-" ++ integer_to_list(I) ++ "-",
+ list_to_atom(Name).
+
ln(Anno) ->
erl_anno:line(Anno).