Skip to content

Commit 4478ded

Browse files
committed
auto merge of #7623 : graydon/rust/codegen-compiletests, r=pcwalton
This is some initial sketch-work for #7461 though it will depend on #7459 to be useful for anything. For the time being, just infrastructure.
2 parents f92b75a + bbdbd3c commit 4478ded

File tree

10 files changed

+715
-274
lines changed

10 files changed

+715
-274
lines changed

configure

+1
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ do
731731
make_dir $h/test/perf
732732
make_dir $h/test/pretty
733733
make_dir $h/test/debug-info
734+
make_dir $h/test/codegen
734735
make_dir $h/test/doc-tutorial
735736
make_dir $h/test/doc-tutorial-ffi
736737
make_dir $h/test/doc-tutorial-macros

mk/tests.mk

+18-1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
246246
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
247247
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
248248
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-exec \
249+
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
249250
check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
250251
check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
251252

@@ -430,6 +431,8 @@ CFAIL_RS := $(wildcard $(S)src/test/compile-fail/*.rs)
430431
BENCH_RS := $(wildcard $(S)src/test/bench/*.rs)
431432
PRETTY_RS := $(wildcard $(S)src/test/pretty/*.rs)
432433
DEBUGINFO_RS := $(wildcard $(S)src/test/debug-info/*.rs)
434+
CODEGEN_RS := $(wildcard $(S)src/test/codegen/*.rs)
435+
CODEGEN_CC := $(wildcard $(S)src/test/codegen/*.cc)
433436

434437
# perf tests are the same as bench tests only they run under
435438
# a performance monitor.
@@ -443,6 +446,7 @@ BENCH_TESTS := $(BENCH_RS)
443446
PERF_TESTS := $(PERF_RS)
444447
PRETTY_TESTS := $(PRETTY_RS)
445448
DEBUGINFO_TESTS := $(DEBUGINFO_RS)
449+
CODEGEN_TESTS := $(CODEGEN_RS) $(CODEGEN_CC)
446450

447451
CTEST_SRC_BASE_rpass = run-pass
448452
CTEST_BUILD_BASE_rpass = run-pass
@@ -479,10 +483,19 @@ CTEST_BUILD_BASE_debuginfo = debug-info
479483
CTEST_MODE_debuginfo = debug-info
480484
CTEST_RUNTOOL_debuginfo = $(CTEST_RUNTOOL)
481485

486+
CTEST_SRC_BASE_codegen = codegen
487+
CTEST_BUILD_BASE_codegen = codegen
488+
CTEST_MODE_codegen = codegen
489+
CTEST_RUNTOOL_codegen = $(CTEST_RUNTOOL)
490+
482491
ifeq ($(CFG_GDB),)
483492
CTEST_DISABLE_debuginfo = "no gdb found"
484493
endif
485494

495+
ifeq ($(CFG_CLANG),)
496+
CTEST_DISABLE_codegen = "no clang found"
497+
endif
498+
486499
ifeq ($(CFG_OSTYPE),apple-darwin)
487500
CTEST_DISABLE_debuginfo = "gdb on darwing needs root"
488501
endif
@@ -507,6 +520,8 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
507520
--compile-lib-path $$(HLIB$(1)_H_$(3)) \
508521
--run-lib-path $$(TLIB$(1)_T_$(2)_H_$(3)) \
509522
--rustc-path $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
523+
--clang-path $(if $(CFG_CLANG),$(CFG_CLANG),clang) \
524+
--llvm-bin-path $(CFG_LLVM_INST_DIR_$(CFG_BUILD_TRIPLE))/bin \
510525
--aux-base $$(S)src/test/auxiliary/ \
511526
--stage-id stage$(1)-$(2) \
512527
--target $(2) \
@@ -522,6 +537,7 @@ CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
522537
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
523538
CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
524539
CTEST_DEPS_debuginfo_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_TESTS)
540+
CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
525541

526542
endef
527543

@@ -565,7 +581,7 @@ endif
565581

566582
endef
567583

568-
CTEST_NAMES = rpass rpass-full rfail cfail bench perf debuginfo
584+
CTEST_NAMES = rpass rpass-full rfail cfail bench perf debuginfo codegen
569585

570586
$(foreach host,$(CFG_HOST_TRIPLES), \
571587
$(eval $(foreach target,$(CFG_TARGET_TRIPLES), \
@@ -674,6 +690,7 @@ TEST_GROUPS = \
674690
bench \
675691
perf \
676692
debuginfo \
693+
codegen \
677694
doc \
678695
$(foreach docname,$(DOC_TEST_NAMES),doc-$(docname)) \
679696
pretty \

src/compiletest/common.rs

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub enum mode {
1515
mode_run_pass,
1616
mode_pretty,
1717
mode_debug_info,
18+
mode_codegen
1819
}
1920

2021
pub struct config {
@@ -27,6 +28,12 @@ pub struct config {
2728
// The rustc executable
2829
rustc_path: Path,
2930

31+
// The clang executable
32+
clang_path: Option<Path>,
33+
34+
// The llvm binaries path
35+
llvm_bin_path: Option<Path>,
36+
3037
// The directory containing the tests to run
3138
src_base: Path,
3239

src/compiletest/compiletest.rs

+48-18
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern mod extra;
1919
use std::os;
2020

2121
use extra::getopts;
22+
use extra::getopts::groups::{optopt, optflag, reqopt};
2223
use extra::test;
2324

2425
use common::config;
@@ -27,6 +28,7 @@ use common::mode_run_fail;
2728
use common::mode_compile_fail;
2829
use common::mode_pretty;
2930
use common::mode_debug_info;
31+
use common::mode_codegen;
3032
use common::mode;
3133
use util::logv;
3234

@@ -45,31 +47,54 @@ pub fn main() {
4547
}
4648

4749
pub fn parse_config(args: ~[~str]) -> config {
48-
let opts =
49-
~[getopts::reqopt("compile-lib-path"),
50-
getopts::reqopt("run-lib-path"),
51-
getopts::reqopt("rustc-path"), getopts::reqopt("src-base"),
52-
getopts::reqopt("build-base"), getopts::reqopt("aux-base"),
53-
getopts::reqopt("stage-id"),
54-
getopts::reqopt("mode"), getopts::optflag("ignored"),
55-
getopts::optopt("runtool"), getopts::optopt("rustcflags"),
56-
getopts::optflag("verbose"),
57-
getopts::optopt("logfile"),
58-
getopts::optflag("jit"),
59-
getopts::optflag("newrt"),
60-
getopts::optopt("target"),
61-
getopts::optopt("adb-path"),
62-
getopts::optopt("adb-test-dir")
50+
51+
let groups : ~[getopts::groups::OptGroup] =
52+
~[reqopt("", "compile-lib-path", "path to host shared libraries", "PATH"),
53+
reqopt("", "run-lib-path", "path to target shared libraries", "PATH"),
54+
reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH"),
55+
optopt("", "clang-path", "path to executable for codegen tests", "PATH"),
56+
optopt("", "llvm-bin-path", "path to directory holding llvm binaries", "DIR"),
57+
reqopt("", "src-base", "directory to scan for test files", "PATH"),
58+
reqopt("", "build-base", "directory to deposit test outputs", "PATH"),
59+
reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"),
60+
reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
61+
reqopt("", "mode", "which sort of compile tests to run",
62+
"(compile-fail|run-fail|run-pass|pretty|debug-info)"),
63+
optflag("", "ignored", "run tests marked as ignored / xfailed"),
64+
optopt("", "runtool", "supervisor program to run tests under \
65+
(eg. emulator, valgrind)", "PROGRAM"),
66+
optopt("", "rustcflags", "flags to pass to rustc", "FLAGS"),
67+
optflag("", "verbose", "run tests verbosely, showing all output"),
68+
optopt("", "logfile", "file to log test execution to", "FILE"),
69+
optflag("", "jit", "run tests under the JIT"),
70+
optflag("", "newrt", "run tests on the new runtime / scheduler"),
71+
optopt("", "target", "the target to build for", "TARGET"),
72+
optopt("", "adb-path", "path to the android debugger", "PATH"),
73+
optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"),
74+
optflag("h", "help", "show this message"),
6375
];
6476

6577
assert!(!args.is_empty());
78+
let argv0 = copy args[0];
6679
let args_ = args.tail();
80+
if args[1] == ~"-h" || args[1] == ~"--help" {
81+
let message = fmt!("Usage: %s [OPTIONS] [TESTNAME...]", argv0);
82+
println(getopts::groups::usage(message, groups));
83+
fail!()
84+
}
85+
6786
let matches =
68-
&match getopts::getopts(args_, opts) {
87+
&match getopts::groups::getopts(args_, groups) {
6988
Ok(m) => m,
7089
Err(f) => fail!(getopts::fail_str(f))
7190
};
7291

92+
if getopts::opt_present(matches, "h") || getopts::opt_present(matches, "help") {
93+
let message = fmt!("Usage: %s [OPTIONS] [TESTNAME...]", argv0);
94+
println(getopts::groups::usage(message, groups));
95+
fail!()
96+
}
97+
7398
fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
7499
Path(getopts::opt_str(m, nm))
75100
}
@@ -78,6 +103,8 @@ pub fn parse_config(args: ~[~str]) -> config {
78103
compile_lib_path: getopts::opt_str(matches, "compile-lib-path"),
79104
run_lib_path: getopts::opt_str(matches, "run-lib-path"),
80105
rustc_path: opt_path(matches, "rustc-path"),
106+
clang_path: getopts::opt_maybe_str(matches, "clang-path").map(|s| Path(*s)),
107+
llvm_bin_path: getopts::opt_maybe_str(matches, "llvm-bin-path").map(|s| Path(*s)),
81108
src_base: opt_path(matches, "src-base"),
82109
build_base: opt_path(matches, "build-base"),
83110
aux_base: opt_path(matches, "aux-base"),
@@ -159,6 +186,7 @@ pub fn str_mode(s: ~str) -> mode {
159186
~"run-pass" => mode_run_pass,
160187
~"pretty" => mode_pretty,
161188
~"debug-info" => mode_debug_info,
189+
~"codegen" => mode_codegen,
162190
_ => fail!("invalid mode")
163191
}
164192
}
@@ -170,6 +198,7 @@ pub fn mode_str(mode: mode) -> ~str {
170198
mode_run_pass => ~"run-pass",
171199
mode_pretty => ~"pretty",
172200
mode_debug_info => ~"debug-info",
201+
mode_codegen => ~"codegen",
173202
}
174203
}
175204

@@ -187,8 +216,9 @@ pub fn test_opts(config: &config) -> test::TestOpts {
187216
logfile: copy config.logfile,
188217
run_tests: true,
189218
run_benchmarks: false,
190-
save_results: None,
191-
compare_results: None
219+
ratchet_metrics: None,
220+
ratchet_noise_percent: None,
221+
save_metrics: None,
192222
}
193223
}
194224

src/compiletest/runtest.rs

+117-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ pub fn run(config: config, testfile: ~str) {
3939
mode_run_fail => run_rfail_test(&config, &props, &testfile),
4040
mode_run_pass => run_rpass_test(&config, &props, &testfile),
4141
mode_pretty => run_pretty_test(&config, &props, &testfile),
42-
mode_debug_info => run_debuginfo_test(&config, &props, &testfile)
42+
mode_debug_info => run_debuginfo_test(&config, &props, &testfile),
43+
mode_codegen => run_codegen_test(&config, &props, &testfile)
4344
}
4445
}
4546

@@ -835,3 +836,118 @@ fn _arm_push_aux_shared_library(config: &config, testfile: &Path) {
835836
}
836837
}
837838
}
839+
840+
// codegen tests (vs. clang)
841+
842+
fn make_o_name(config: &config, testfile: &Path) -> Path {
843+
output_base_name(config, testfile).with_filetype("o")
844+
}
845+
846+
fn append_suffix_to_stem(p: &Path, suffix: &str) -> Path {
847+
if suffix.len() == 0 {
848+
copy *p
849+
} else {
850+
let stem = p.filestem().get();
851+
p.with_filestem(stem + "-" + suffix)
852+
}
853+
}
854+
855+
fn compile_test_and_save_bitcode(config: &config, props: &TestProps,
856+
testfile: &Path) -> ProcRes {
857+
let link_args = ~[~"-L", aux_output_dir_name(config, testfile).to_str()];
858+
let llvm_args = ~[~"-c", ~"--lib", ~"--save-temps"];
859+
let args = make_compile_args(config, props,
860+
link_args + llvm_args,
861+
make_o_name, testfile);
862+
compose_and_run_compiler(config, props, testfile, args, None)
863+
}
864+
865+
fn compile_cc_with_clang_and_save_bitcode(config: &config, _props: &TestProps,
866+
testfile: &Path) -> ProcRes {
867+
let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
868+
let bitcodefile = append_suffix_to_stem(&bitcodefile, "clang");
869+
let ProcArgs = ProcArgs {
870+
prog: config.clang_path.get_ref().to_str(),
871+
args: ~[~"-c",
872+
~"-emit-llvm",
873+
~"-o", bitcodefile.to_str(),
874+
testfile.with_filetype("cc").to_str() ]
875+
};
876+
compose_and_run(config, testfile, ProcArgs, ~[], "", None)
877+
}
878+
879+
fn extract_function_from_bitcode(config: &config, _props: &TestProps,
880+
fname: &str, testfile: &Path,
881+
suffix: &str) -> ProcRes {
882+
let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
883+
let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
884+
let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
885+
let ProcArgs = ProcArgs {
886+
prog: config.llvm_bin_path.get_ref().push("llvm-extract").to_str(),
887+
args: ~[~"-func=" + fname,
888+
~"-o=" + extracted_bc.to_str(),
889+
bitcodefile.to_str() ]
890+
};
891+
compose_and_run(config, testfile, ProcArgs, ~[], "", None)
892+
}
893+
894+
fn disassemble_extract(config: &config, _props: &TestProps,
895+
testfile: &Path, suffix: &str) -> ProcRes {
896+
let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
897+
let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
898+
let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
899+
let extracted_ll = extracted_bc.with_filetype("ll");
900+
let ProcArgs = ProcArgs {
901+
prog: config.llvm_bin_path.get_ref().push("llvm-dis").to_str(),
902+
args: ~[~"-o=" + extracted_ll.to_str(),
903+
extracted_bc.to_str() ]
904+
};
905+
compose_and_run(config, testfile, ProcArgs, ~[], "", None)
906+
}
907+
908+
909+
fn run_codegen_test(config: &config, props: &TestProps, testfile: &Path) {
910+
911+
if config.llvm_bin_path.is_none() {
912+
fatal(~"missing --llvm-bin-path");
913+
}
914+
915+
if config.clang_path.is_none() {
916+
fatal(~"missing --clang-path");
917+
}
918+
919+
let mut ProcRes = compile_test_and_save_bitcode(config, props, testfile);
920+
if ProcRes.status != 0 {
921+
fatal_ProcRes(~"compilation failed!", &ProcRes);
922+
}
923+
924+
ProcRes = extract_function_from_bitcode(config, props, "test", testfile, "");
925+
if ProcRes.status != 0 {
926+
fatal_ProcRes(~"extracting 'test' function failed", &ProcRes);
927+
}
928+
929+
ProcRes = disassemble_extract(config, props, testfile, "");
930+
if ProcRes.status != 0 {
931+
fatal_ProcRes(~"disassembling extract failed", &ProcRes);
932+
}
933+
934+
935+
let mut ProcRes = compile_cc_with_clang_and_save_bitcode(config, props, testfile);
936+
if ProcRes.status != 0 {
937+
fatal_ProcRes(~"compilation failed!", &ProcRes);
938+
}
939+
940+
ProcRes = extract_function_from_bitcode(config, props, "test", testfile, "clang");
941+
if ProcRes.status != 0 {
942+
fatal_ProcRes(~"extracting 'test' function failed", &ProcRes);
943+
}
944+
945+
ProcRes = disassemble_extract(config, props, testfile, "clang");
946+
if ProcRes.status != 0 {
947+
fatal_ProcRes(~"disassembling extract failed", &ProcRes);
948+
}
949+
950+
951+
952+
}
953+

src/libextra/json.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use std::to_str;
2727
use serialize::Encodable;
2828
use serialize;
2929
use sort::Sort;
30+
use treemap::TreeMap;
3031

3132
/// Represents a json value
3233
pub enum Json {
@@ -1225,7 +1226,7 @@ impl Ord for Json {
12251226
}
12261227

12271228
/// A trait for converting values to JSON
1228-
trait ToJson {
1229+
pub trait ToJson {
12291230
/// Converts the value of `self` to an instance of JSON
12301231
fn to_json(&self) -> Json;
12311232
}
@@ -1330,7 +1331,17 @@ impl<A:ToJson> ToJson for ~[A] {
13301331
fn to_json(&self) -> Json { List(self.map(|elt| elt.to_json())) }
13311332
}
13321333

1333-
impl<A:ToJson + Copy> ToJson for HashMap<~str, A> {
1334+
impl<A:ToJson> ToJson for HashMap<~str, A> {
1335+
fn to_json(&self) -> Json {
1336+
let mut d = HashMap::new();
1337+
for self.iter().advance |(key, value)| {
1338+
d.insert(copy *key, value.to_json());
1339+
}
1340+
Object(~d)
1341+
}
1342+
}
1343+
1344+
impl<A:ToJson> ToJson for TreeMap<~str, A> {
13341345
fn to_json(&self) -> Json {
13351346
let mut d = HashMap::new();
13361347
for self.iter().advance |(key, value)| {

0 commit comments

Comments
 (0)