diff options
Diffstat (limited to 'tools/mir_opt_test/main.cpp')
-rw-r--r-- | tools/mir_opt_test/main.cpp | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/tools/mir_opt_test/main.cpp b/tools/mir_opt_test/main.cpp new file mode 100644 index 00000000..80a627f3 --- /dev/null +++ b/tools/mir_opt_test/main.cpp @@ -0,0 +1,246 @@ +/* + */ +#include <path.h> +#include <target_version.hpp> +#include "test_desc.h" +#include <hir_conv/main_bindings.hpp> +#include <mir/operations.hpp> +#include <mir/main_bindings.hpp> +#include <mir/mir.hpp> +#include <trans/monomorphise.hpp> // used as a MIR clone +#include <debug_inner.hpp> + +#ifdef _WIN32 +# define NOGDI // Don't include GDI functions (defines some macros that collide with mrustc ones) +# include <Windows.h> +#else +# include <dirent.h> +# include <sys/stat.h> +#endif + +TargetVersion gTargetVersion = TargetVersion::Rustc1_29; + +struct Options +{ + helpers::path test_dir; + + bool parse(int argc, char* argv[]); + void print_usage() const; + void print_help() const; +}; + +namespace { + MIR::FunctionPointer clone_mir(const StaticTraitResolve& resolve, const MIR::FunctionPointer& fcn); + bool compare_mir(const MIR::Function& exp, const MIR::Function& have, const HIR::SimplePath& path); +} + +int main(int argc, char* argv[]) +{ + debug_init_phases("MIRTEST_DEBUG", { + "Parse", + "Cleanup", + "Validate", + "Run Tests", + }); + + Options opts; + if( !opts.parse(argc, argv) ) + { + return 1; + } + + ::std::vector<MirOptTestFile> test_files; + { + auto ph = DebugTimedPhase("Parse"); +#ifdef _WIN32 + WIN32_FIND_DATA find_data; + auto mask = opts.test_dir / "*.rs"; + HANDLE find_handle = FindFirstFile( mask.str().c_str(), &find_data ); + if( find_handle == INVALID_HANDLE_VALUE ) { + ::std::cerr << "Unable to find files matching " << mask << ::std::endl; + return 1; + } + do + { + auto test_file_path = opts.test_dir / find_data.cFileName; +#else + auto* dp = opendir(opts.test_dir.str().c_str()); + if( dp == nullptr ) { + ::std::cerr << "Unable to open directory " << opts.test_dir << ::std::endl; + } + while( const auto* dent = readdir(dp) ) + { + if( dent->d_name[0] == '.' ) + continue ; + auto test_file_path = opts.test_dir / dent->d_name; + struct stat sb; + stat(test_file_path.str().c_str(), &sb); + if( (sb.st_mode & S_IFMT) != S_IFREG) { + continue ; + } +#endif + try + { + test_files.push_back( MirOptTestFile::load_from_file(test_file_path) ); + } + catch(const ::std::exception& e) + { + ::std::cerr << "Exception: " << e.what() << " when loading test " << test_file_path << ::std::endl; + } +#ifndef _WIN32 + } + closedir(dp); +#else + } while( FindNextFile(find_handle, &find_data) ); + FindClose(find_handle); +#endif + } + + { + auto ph = DebugTimedPhase("Cleanup"); + for(auto& f : test_files) + { + ConvertHIR_Bind(*f.m_crate); + } + } + + { + auto ph = DebugTimedPhase("Validate"); + for(auto& f : test_files) + { + MIR_CheckCrate(*f.m_crate); + } + } + + for(auto& f : test_files) + { + auto ph = DebugTimedPhase("Run Tests"); + for(const auto& test : f.m_tests) + { + const auto& in_fcn = f.m_crate->get_function_by_path(Span(), test.input_function); + const auto& exp_mir = *f.m_crate->get_function_by_path(Span(), test.output_template_function).m_code.m_mir; + + StaticTraitResolve resolve(*f.m_crate); + // TODO: Generics? + auto cloned_mir = clone_mir(resolve, in_fcn.m_code.m_mir); + + MIR_Optimise(resolve, test.input_function, *cloned_mir, in_fcn.m_args, in_fcn.m_return); + + compare_mir(exp_mir, *cloned_mir, test.input_function); + } + } + + return 0; +} + +bool Options::parse(int argc, char* argv[]) +{ + for(int i = 1; i < argc; i ++) + { + auto arg = helpers::string_view(argv[i], strlen(argv[i])); + if( arg[0] != '-' ) + { + if( !this->test_dir.is_valid() ) + { + this->test_dir = static_cast<std::string>(arg); + } + else + { + this->print_usage(); + return false; + } + } + else if( arg[1] != '-' ) + { + switch(arg[1]) + { + case 'h': + this->print_help(); + exit(0); + default: + this->print_usage(); + return false; + } + } + else + { + if( arg == "--help" ) + { + this->print_help(); + exit(0); + } + else + { + this->print_usage(); + return false; + } + } + } + return true; +} + +void Options::print_usage() const +{ +} +void Options::print_help() const +{ +} + +namespace { + MIR::FunctionPointer clone_mir(const StaticTraitResolve& resolve, const MIR::FunctionPointer& fcn) + { + return Trans_Monomorphise(resolve, {}, fcn); + } + bool compare_mir(const MIR::Function& exp, const MIR::Function& have, const HIR::SimplePath& path) + { + if( exp.locals.size() != have.locals.size() ) { + std::cerr << path << " Mismatch in local count: exp " << exp.locals.size() << " != " << have.locals.size() << std::endl; + return false; + } + for(size_t i = 0; i < exp.locals.size(); i ++) + { + if( exp.locals[i] != have.locals[i] ) + { + std::cerr << path << " Local " << i << " mismatch: exp " << exp.locals[i] << " != " << have.locals[i] << std::endl; + return false; + } + } + + if( exp.drop_flags != have.drop_flags ) { + std::cerr << path << " Mismatch in drop flags" << std::endl; + return false; + } + + if( exp.blocks.size() != have.blocks.size() ) { + std::cerr << path << " Mismatch in block count: exp " << exp.blocks.size() << " != " << have.blocks.size() << std::endl; + return false; + } + for(size_t bb_idx = 0; bb_idx < exp.blocks.size(); bb_idx ++) + { + const auto& bb_e = exp.blocks[bb_idx]; + const auto& bb_h = have.blocks[bb_idx]; + + if( bb_e.statements.size() != bb_h.statements.size() ) { + std::cerr << path << " BB" << bb_idx << " Mismatch in statement count: exp " << bb_e.statements.size() << " != " << bb_h.statements.size() << std::endl; + return false; + } + for(size_t stmt_idx = 0; stmt_idx < bb_e.statements.size(); stmt_idx ++) + { + const auto& stmt_e = bb_e.statements[stmt_idx]; + const auto& stmt_h = bb_h.statements[stmt_idx]; + if( stmt_e != stmt_h ) { + std::cerr << path << " BB" << bb_idx << "/" << stmt_idx << " Mismatched statements: exp " << stmt_e << " != " << stmt_h << std::endl; + return false; + } + } + + if( bb_e.terminator != bb_h.terminator ) + { + std::cerr << path << " BB" << bb_idx << "/TERM Mismatched terminator: exp " << bb_e.terminator << " != " << bb_h.terminator << std::endl; + return false; + } + } + std::cerr << path << " EQUAL" << std::endl; + return true; + } +}
\ No newline at end of file |