diff options
Diffstat (limited to 'lib/debugger/src/dbg_iload.erl')
-rw-r--r-- | lib/debugger/src/dbg_iload.erl | 91 |
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). |