diff options
Diffstat (limited to 'lib/compiler/test/beam_validator_SUITE.erl')
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl new file mode 100644 index 0000000000..ef8feb8a27 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -0,0 +1,375 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(beam_validator_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + beam_files/1,compiler_bug/1,stupid_but_valid/1, + xrange/1,yrange/1,stack/1,call_last/1,merge_undefined/1, + uninit/1,unsafe_catch/1, + dead_code/1,mult_labels/1, + overwrite_catchtag/1,overwrite_trytag/1,accessing_tags/1,bad_catch_try/1, + cons_guard/1, + freg_range/1,freg_uninit/1,freg_state/1, + bin_match/1,bin_aligned/1,bad_dsetel/1, + state_after_fault_in_catch/1,no_exception_in_catch/1, + undef_label/1,illegal_instruction/1]). + +-include("test_server.hrl"). + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = test_server:timetrap(?t:minutes(10)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> + test_lib:recompile(?MODULE), + [beam_files,compiler_bug,stupid_but_valid, + xrange,yrange,stack,call_last,merge_undefined, + uninit,unsafe_catch, + dead_code,mult_labels, + overwrite_catchtag,overwrite_trytag,accessing_tags,bad_catch_try, + cons_guard, + freg_range,freg_uninit,freg_state, + bin_match,bin_aligned, + bad_dsetel,state_after_fault_in_catch,no_exception_in_catch, + undef_label,illegal_instruction]. + +beam_files(Config) when is_list(Config) -> + ?line {ok,Cwd} = file:get_cwd(), + ?line Parent = filename:dirname(Cwd), + ?line Wc = filename:join([Parent,"*","*.beam"]), + %% Must have at least two files here, or there will could be + %% a grammatical error in the output of the io:format/2 call below. ;-) + ?line [_,_|_] = Fs = filelib:wildcard(Wc), + ?line io:format("~p files\n", [length(Fs)]), + beam_files_1(Fs, 0). + +beam_files_1([F|Fs], Errors) -> + ?line case beam_validator:file(F) of + ok -> + beam_files_1(Fs, Errors); + {error,Es} -> + io:format("File: ~s", [F]), + io:format("Error: ~p\n", [Es]), + beam_files_1(Fs, Errors+1) + end; +beam_files_1([], 0) -> ok; +beam_files_1([], Errors) -> + ?line io:format("~p error(s)", [Errors]), + ?line ?t:fail(). + +compiler_bug(Config) when is_list(Config) -> + %% Check that the compiler returns an error if we try to + %% assemble one of the bad '.S' files. + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "stack"), + ?line error = compile:file(File, [asm,report_errors,binary,time]), + ok. + +%% The following code is stupid but it should compile. +stupid_but_valid(Config) when is_list(Config) -> + AnAtom = nisse, + ?line try setelement(5, setelement(6, AnAtom, value), another_value) of + Term -> ?line ?t:fail({what_happened,Term}) + catch + error:badarg -> ok + end, + ok. + +xrange(Config) when is_list(Config) -> + Errors = do_val(xrange, Config), + ?line + [{{t,sum_1,2}, + {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4, + {uninitialized_reg,{x,-1}}}}, + {{t,sum_2,2}, + {{bif,'+',{f,0},[{x,0},{x,1024}],{x,0}},4, + {uninitialized_reg,{x,1024}}}}, + {{t,sum_3,2}, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4, + {invalid_store,{x,-1},number}}}, + {{t,sum_4,2}, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,1024}},4,limit}}] = Errors, + ok. + +yrange(Config) when is_list(Config) -> + Errors = do_val(yrange, Config), + ?line + [{{t,sum_1,2}, + {{move,{x,1},{y,-1}},5, + {invalid_store,{y,-1},term}}}, + {{t,sum_2,2}, + {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},8, + {uninitialized_reg,{y,1024}}}}, + {{t,sum_3,2}, + {{move,{x,1},{y,1024}},5,limit}}, + {{t,sum_4,2}, + {{move,{x,1},{y,-1}},5, + {invalid_store,{y,-1},term}}}] = Errors, + ok. + +stack(Config) when is_list(Config) -> + Errors = do_val(stack, Config), + ?line [{{t,a,2},{return,11,{stack_frame,2}}}, + {{t,b,2},{{deallocate,2},4,{allocated,none}}}, + {{t,c,2},{{deallocate,2},12,{allocated,none}}}, + {{t,d,2}, + {{allocate,2,2},5,{existing_stack_frame,{size,2}}}}, + {{t,e,2},{{deallocate,5},6,{allocated,2}}}, + {{t,bad_1,0},{{allocate_zero,2,10},4,{{x,9},not_live}}}, + {{t,bad_2,0},{{move,{y,0},{x,0}},5,{unassigned,{y,0}}}}] = Errors, + ok. + +call_last(Config) when is_list(Config) -> + Errors = do_val(call_last, Config), + ?line [{{t,a,1},{{call_last,1,{f,8},2},11,{allocated,1}}}, + {{t,b,1}, + {{call_ext_last,2,{extfunc,lists,seq,2},2}, + 11, + {allocated,1}}}] = Errors, + ok. + +merge_undefined(Config) when is_list(Config) -> + Errors = do_val(merge_undefined, Config), + ?line [{{t,handle_call,2}, + {{call_ext,2,{extfunc,debug,filter,2}}, + 22, + {uninitialized_reg,{y,0}}}}] = Errors, + ok. + +uninit(Config) when is_list(Config) -> + Errors = do_val(uninit, Config), + ?line + [{{t,sum_1,2}, + {{move,{y,0},{x,0}},5,{uninitialized_reg,{y,0}}}}, + {{t,sum_2,2}, + {{call,1,{f,10}},6,{uninitialized_reg,{y,0}}}}, + {{t,sum_3,2}, + {{bif,'+',{f,0},[{x,0},{y,0}],{x,0}}, + 7, + {unassigned,{y,0}}}}] = Errors, + ok. + +unsafe_catch(Config) when is_list(Config) -> + Errors = do_val(unsafe_catch, Config), + ?line + [{{t,small,2}, + {{bs_put_integer,{f,0},{integer,16},1, + {field_flags,[aligned,unsigned,big]},{y,0}}, + 20, + {unassigned,{y,0}}}}] = Errors, + ok. + +dead_code(Config) when is_list(Config) -> + [] = do_val(dead_code, Config), + ok. + +mult_labels(Config) when is_list(Config) -> + [] = do_val(erl_prim_loader, Config, ".beam"), + ok. + +overwrite_catchtag(Config) when is_list(Config) -> + Errors = do_val(overwrite_catchtag, Config), + ?line + [{{overwrite_catchtag,foo,1}, + {{move,{x,0},{y,0}},6,{catchtag,_}}}] = Errors, + ok. + +overwrite_trytag(Config) when is_list(Config) -> + Errors = do_val(overwrite_trytag, Config), + ?line + [{{overwrite_trytag,foo,1}, + {{kill,{y,2}},9,{trytag,_}}}] = Errors, + ok. + +accessing_tags(Config) when is_list(Config) -> + Errors = do_val(accessing_tags, Config), + ?line + [{{accessing_tags,foo,1}, + {{move,{y,0},{x,0}},6,{catchtag,_}}}, + {{accessing_tags,bar,1}, + {{move,{y,0},{x,0}},6,{trytag,_}}}] = Errors, + ok. + +bad_catch_try(Config) when is_list(Config) -> + Errors = do_val(bad_catch_try, Config), + ?line [{{bad_catch_try,bad_1,1}, + {{'catch',{x,0},{f,3}}, + 5,{invalid_store,{x,0},{catchtag,[3]}}}}, + {{bad_catch_try,bad_2,1}, + {{catch_end,{x,9}}, + 8,{source_not_y_reg,{x,9}}}}, + {{bad_catch_try,bad_3,1}, + {{catch_end,{y,1}},9,{bad_type,{atom,kalle}}}}, + {{bad_catch_try,bad_4,1}, + {{'try',{x,0},{f,15}},5,{invalid_store,{x,0},{trytag,[15]}}}}, + {{bad_catch_try,bad_5,1}, + {{try_case,{y,1}},12,{bad_type,term}}}, + {{bad_catch_try,bad_6,1}, + {{try_end,{y,1}},8,{bad_type,{integer,1}}}}] = Errors, + ok. + +cons_guard(Config) when is_list(Config) -> + Errors = do_val(cons, Config), + ?line + [{{cons,foo,1}, + {{get_list,{x,0},{x,1},{x,2}}, + 5, + {bad_type,{needed,cons},{actual,term}}}}] = Errors, + ok. + +freg_range(Config) when is_list(Config) -> + Errors = do_val(freg_range, Config), + ?line + [{{t,sum_1,2}, + {{bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}}, + 5, + {bad_source,{fr,-1}}}}, + {{t,sum_2,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}}, + 6, + {uninitialized_reg,{fr,1024}}}}, + {{t,sum_3,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}}, + 7, + {bad_target,{fr,-1}}}}, + {{t,sum_4,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}}, + 7, + limit}}] = Errors, + ok. + +freg_uninit(Config) when is_list(Config) -> + Errors = do_val(freg_uninit, Config), + ?line + [{{t,sum_1,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 6, + {uninitialized_reg,{fr,1}}}}, + {{t,sum_2,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 9, + {uninitialized_reg,{fr,0}}}}] = Errors, + ok. + +freg_state(Config) when is_list(Config) -> + Errors = do_val(freg_state, Config), + ?line + [{{t,sum_1,2}, + {{bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 6, + {bad_floating_point_state,undefined}}}, + {{t,sum_2,2}, + {{fmove,{fr,0},{x,0}}, + 8, + {bad_floating_point_state,cleared}}}, + {{t,sum_3,2}, + {{bif,'-',{f,0},[{x,1},{x,0}],{x,1}}, + 8, + {unsafe_instruction,{float_error_state,cleared}}}}, + {{t,sum_4,2}, + {{fcheckerror,{f,0}}, + 4, + {bad_floating_point_state,undefined}}}, + {{t,sum_5,2}, + {fclearerror,5,{bad_floating_point_state,cleared}}}] = Errors, + ok. + +bin_match(Config) when is_list(Config) -> + Errors = do_val(bin_match, Config), + ?line + [{{t,t,1},{{bs_save,0},4,no_bs_match_state}}, + {{t,x,1},{{bs_restore,1},16,{no_save_point,1}}}] = Errors, + ok. + +bin_aligned(Config) when is_list(Config) -> + Errors = do_val(bin_aligned, Config), + ?line + [{{t,decode,1}, + {{bs_put_integer,{f,0}, + {integer,5}, + 1, + {field_flags,[unsigned,big,aligned]}, + {integer,0}}, + 10, + {aligned_flag_set,{bits,3}}}}] = Errors, + ok. + +bad_dsetel(Config) when is_list(Config) -> + Errors = do_val(bad_dsetel, Config), + ?line + [{{t,t,1}, + {{set_tuple_element,{x,1},{x,0},1}, + 15, + illegal_context_for_set_tuple_element}}] = Errors, + ok. + +state_after_fault_in_catch(Config) when is_list(Config) -> + Errors = do_val(state_after_fault_in_catch, Config), + [{{t,foo,1}, + {{move,{x,1},{x,0}},10,{uninitialized_reg,{x,1}}}}, + {{state_after_fault_in_catch,if_end,1}, + {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}}, + {{state_after_fault_in_catch,case_end,1}, + {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}}, + {{state_after_fault_in_catch,badmatch,1}, + {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}}] = Errors, + ok. + +no_exception_in_catch(Config) when is_list(Config) -> + Errors = do_val(no_exception_in_catch, Config), + [{{no_exception_in_catch,nested_of_1,4}, + {{move,{x,3},{x,0}},91,{uninitialized_reg,{x,3}}}}] = Errors, + ok. + +undef_label(Config) when is_list(Config) -> + Errors = do_val(undef_label, Config), + [{{undef_label,t,1},{undef_labels,[42]}}, + {{undef_label,x,1},{return,4,no_entry_label}}] = Errors, + ok. + +illegal_instruction(Config) when is_list(Config) -> + Errors = do_val(illegal_instruction, Config), + [{{illegal_instruction,t,1}, + {{my_illegal_instruction,{x,0}},4,unknown_instruction}}, + {{'_',x,1},{bad_func_info,1,illegal_instruction}}, + {{'_',y,0},{[],0,illegal_instruction}}] = Errors, + ok. + + + +%%%------------------------------------------------------------------------- + +do_val(Name, Config) -> + do_val(Name, Config, ".S"). + +do_val(Name, Config, Type) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, atom_to_list(Name)++Type), + ?line case beam_validator:file(File) of + {error,Errors} -> + ?line io:format("~p:~n~s", + [File,beam_validator:format_error(Errors)]), + Errors; + ok -> [] + end. |