use std::os;
use extra::getopts;
+use extra::getopts::groups::{optopt, optflag, reqopt};
use extra::test;
use common::config;
use common::mode_compile_fail;
use common::mode_pretty;
use common::mode_debug_info;
+use common::mode_codegen;
use common::mode;
use util::logv;
}
pub fn parse_config(args: ~[~str]) -> config {
- let opts =
- ~[getopts::reqopt("compile-lib-path"),
- getopts::reqopt("run-lib-path"),
- getopts::reqopt("rustc-path"), getopts::reqopt("src-base"),
- getopts::reqopt("build-base"), getopts::reqopt("aux-base"),
- getopts::reqopt("stage-id"),
- getopts::reqopt("mode"), getopts::optflag("ignored"),
- getopts::optopt("runtool"), getopts::optopt("rustcflags"),
- getopts::optflag("verbose"),
- getopts::optopt("logfile"),
- getopts::optflag("jit"),
- getopts::optflag("newrt"),
- getopts::optopt("target"),
- getopts::optopt("adb-path"),
- getopts::optopt("adb-test-dir")
+
+ let groups : ~[getopts::groups::OptGroup] =
+ ~[reqopt("", "compile-lib-path", "path to host shared libraries", "PATH"),
+ reqopt("", "run-lib-path", "path to target shared libraries", "PATH"),
+ reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH"),
+ optopt("", "clang-path", "path to executable for codegen tests", "PATH"),
+ optopt("", "llvm-bin-path", "path to directory holding llvm binaries", "DIR"),
+ reqopt("", "src-base", "directory to scan for test files", "PATH"),
+ reqopt("", "build-base", "directory to deposit test outputs", "PATH"),
+ reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"),
+ reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
+ reqopt("", "mode", "which sort of compile tests to run",
+ "(compile-fail|run-fail|run-pass|pretty|debug-info)"),
+ optflag("", "ignored", "run tests marked as ignored / xfailed"),
+ optopt("", "runtool", "supervisor program to run tests under \
+ (eg. emulator, valgrind)", "PROGRAM"),
+ optopt("", "rustcflags", "flags to pass to rustc", "FLAGS"),
+ optflag("", "verbose", "run tests verbosely, showing all output"),
+ optopt("", "logfile", "file to log test execution to", "FILE"),
+ optflag("", "jit", "run tests under the JIT"),
+ optflag("", "newrt", "run tests on the new runtime / scheduler"),
+ optopt("", "target", "the target to build for", "TARGET"),
+ optopt("", "adb-path", "path to the android debugger", "PATH"),
+ optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"),
+ optflag("h", "help", "show this message"),
];
assert!(!args.is_empty());
+ let argv0 = copy args[0];
let args_ = args.tail();
+ if args[1] == ~"-h" || args[1] == ~"--help" {
+ let message = fmt!("Usage: %s [OPTIONS] [TESTNAME...]", argv0);
+ io::println(getopts::groups::usage(message, groups));
+ fail!()
+ }
+
let matches =
- &match getopts::getopts(args_, opts) {
+ &match getopts::groups::getopts(args_, groups) {
Ok(m) => m,
Err(f) => fail!(getopts::fail_str(f))
};
+ if getopts::opt_present(matches, "h") || getopts::opt_present(matches, "help") {
+ let message = fmt!("Usage: %s [OPTIONS] [TESTNAME...]", argv0);
+ io::println(getopts::groups::usage(message, groups));
+ fail!()
+ }
+
fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
Path(getopts::opt_str(m, nm))
}
compile_lib_path: getopts::opt_str(matches, "compile-lib-path"),
run_lib_path: getopts::opt_str(matches, "run-lib-path"),
rustc_path: opt_path(matches, "rustc-path"),
+ clang_path: getopts::opt_maybe_str(matches, "clang-path").map(|s| Path(*s)),
+ llvm_bin_path: getopts::opt_maybe_str(matches, "llvm-bin-path").map(|s| Path(*s)),
src_base: opt_path(matches, "src-base"),
build_base: opt_path(matches, "build-base"),
aux_base: opt_path(matches, "aux-base"),
~"run-pass" => mode_run_pass,
~"pretty" => mode_pretty,
~"debug-info" => mode_debug_info,
+ ~"codegen" => mode_codegen,
_ => fail!("invalid mode")
}
}
mode_run_pass => ~"run-pass",
mode_pretty => ~"pretty",
mode_debug_info => ~"debug-info",
+ mode_codegen => ~"codegen",
}
}
mode_run_fail => run_rfail_test(&config, &props, &testfile),
mode_run_pass => run_rpass_test(&config, &props, &testfile),
mode_pretty => run_pretty_test(&config, &props, &testfile),
- mode_debug_info => run_debuginfo_test(&config, &props, &testfile)
+ mode_debug_info => run_debuginfo_test(&config, &props, &testfile),
+ mode_codegen => run_codegen_test(&config, &props, &testfile)
}
}
}
}
}
+
+// codegen tests (vs. clang)
+
+fn make_o_name(config: &config, testfile: &Path) -> Path {
+ output_base_name(config, testfile).with_filetype("o")
+}
+
+fn append_suffix_to_stem(p: &Path, suffix: &str) -> Path {
+ if suffix.len() == 0 {
+ copy *p
+ } else {
+ let stem = p.filestem().get();
+ p.with_filestem(stem + "-" + suffix)
+ }
+}
+
+fn compile_test_and_save_bitcode(config: &config, props: &TestProps,
+ testfile: &Path) -> ProcRes {
+ let link_args = ~[~"-L", aux_output_dir_name(config, testfile).to_str()];
+ let llvm_args = ~[~"-c", ~"--lib", ~"--save-temps"];
+ let args = make_compile_args(config, props,
+ link_args + llvm_args,
+ make_o_name, testfile);
+ compose_and_run_compiler(config, props, testfile, args, None)
+}
+
+fn compile_cc_with_clang_and_save_bitcode(config: &config, _props: &TestProps,
+ testfile: &Path) -> ProcRes {
+ let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
+ let bitcodefile = append_suffix_to_stem(&bitcodefile, "clang");
+ let ProcArgs = ProcArgs {
+ prog: config.clang_path.get_ref().to_str(),
+ args: ~[~"-c",
+ ~"-emit-llvm",
+ ~"-o", bitcodefile.to_str(),
+ testfile.with_filetype("cc").to_str() ]
+ };
+ compose_and_run(config, testfile, ProcArgs, ~[], "", None)
+}
+
+fn extract_function_from_bitcode(config: &config, _props: &TestProps,
+ fname: &str, testfile: &Path,
+ suffix: &str) -> ProcRes {
+ let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
+ let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
+ let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
+ let ProcArgs = ProcArgs {
+ prog: config.llvm_bin_path.get_ref().push("llvm-extract").to_str(),
+ args: ~[~"-func=" + fname,
+ ~"-o=" + extracted_bc.to_str(),
+ bitcodefile.to_str() ]
+ };
+ compose_and_run(config, testfile, ProcArgs, ~[], "", None)
+}
+
+fn disassemble_extract(config: &config, _props: &TestProps,
+ testfile: &Path, suffix: &str) -> ProcRes {
+ let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
+ let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
+ let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
+ let extracted_ll = extracted_bc.with_filetype("ll");
+ let ProcArgs = ProcArgs {
+ prog: config.llvm_bin_path.get_ref().push("llvm-dis").to_str(),
+ args: ~[~"-o=" + extracted_ll.to_str(),
+ extracted_bc.to_str() ]
+ };
+ compose_and_run(config, testfile, ProcArgs, ~[], "", None)
+}
+
+
+fn run_codegen_test(config: &config, props: &TestProps, testfile: &Path) {
+
+ if config.llvm_bin_path.is_none() {
+ fatal(~"missing --llvm-bin-path");
+ }
+
+ if config.clang_path.is_none() {
+ fatal(~"missing --clang-path");
+ }
+
+ let mut ProcRes = compile_test_and_save_bitcode(config, props, testfile);
+ if ProcRes.status != 0 {
+ fatal_ProcRes(~"compilation failed!", &ProcRes);
+ }
+
+ ProcRes = extract_function_from_bitcode(config, props, "test", testfile, "");
+ if ProcRes.status != 0 {
+ fatal_ProcRes(~"extracting 'test' function failed", &ProcRes);
+ }
+
+ ProcRes = disassemble_extract(config, props, testfile, "");
+ if ProcRes.status != 0 {
+ fatal_ProcRes(~"disassembling extract failed", &ProcRes);
+ }
+
+
+ let mut ProcRes = compile_cc_with_clang_and_save_bitcode(config, props, testfile);
+ if ProcRes.status != 0 {
+ fatal_ProcRes(~"compilation failed!", &ProcRes);
+ }
+
+ ProcRes = extract_function_from_bitcode(config, props, "test", testfile, "clang");
+ if ProcRes.status != 0 {
+ fatal_ProcRes(~"extracting 'test' function failed", &ProcRes);
+ }
+
+ ProcRes = disassemble_extract(config, props, testfile, "clang");
+ if ProcRes.status != 0 {
+ fatal_ProcRes(~"disassembling extract failed", &ProcRes);
+ }
+
+
+
+}
+