Skip to content

Commit d6796d0

Browse files
authored
Improve documentation of the filetest run command (#1645)
* Improve output display of RunCommand The previous use of Debug for displaying `print` and `run` results was less than clear. * Avoid checking the types of vectors during trampoline construction Because DataValue only understands `V128` vectors, we avoid type-checking vector values when constructing the trampoline arguments. * Improve the documentation of the filetest `run` command Adds an up-to-date example of how to use the `run` and `print` directives and includes an actual use of the new directives in a SIMD arithmetic filetest.
1 parent c284ffe commit d6796d0

4 files changed

Lines changed: 72 additions & 43 deletions

File tree

cranelift/docs/testing.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,21 @@ Cranelift IR right before binary machine code emission.
320320

321321
Compile and execute a function.
322322

323-
Add a `; run` directive after each function that should be executed. These
324-
functions must have the signature `() -> bNN` where `bNN` is some sort of
325-
boolean, e.g. `b1` or `b32`. A `true` value is interpreted as a successful
326-
test execution, whereas a `false` value is interpreted as a failed test.
323+
This test command allows several directives:
324+
- to print the result of running a function to stdout, add a `print`
325+
directive and call the preceding function with arguments (see `%foo` in
326+
the example below); remember to enable `--nocapture` if running these
327+
tests through Cargo
328+
- to check the result of a function, add a `run` directive and call the
329+
preceding function with a comparison (`==` or `!=`) (see `%bar` below)
330+
- for backwards compatibility, to check the result of a function with a
331+
`() -> b*` signature, only the `run` directive is required, with no
332+
invocation or comparison (see `%baz` below); a `true` value is
333+
interpreted as a successful test execution, whereas a `false` value is
334+
interpreted as a failed test.
327335

328336
Currently a `target` is required but is only used to indicate whether the host
329-
platform can run the test, and currently only the architecture is filtered. The
337+
platform can run the test and currently only the architecture is filtered. The
330338
host platform's native target will be used to actually compile the test.
331339

332340
Example:
@@ -335,8 +343,25 @@ Example:
335343
test run
336344
target x86_64
337345
338-
function %trivial_test() -> b1 {
339-
ebb0:
346+
; how to print the results of a function
347+
function %foo() -> i32 {
348+
block0:
349+
v0 = iconst.i32 42
350+
return v0
351+
}
352+
; print: %foo()
353+
354+
; how to check the results of a function
355+
function %bar(i32) -> i32 {
356+
block0(v0:i32):
357+
v1 = iadd_imm v0, 1
358+
return v1
359+
}
360+
; run: %bar(1) == 2
361+
362+
; legacy method of checking the results of a function
363+
function %baz() -> b1 {
364+
block0:
340365
v0 = bconst.b1 true
341366
return v0
342367
}

cranelift/filetests/filetests/isa/x86/simd-arithmetic-run.clif

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,21 @@ test run
22
set enable_simd
33
target x86_64 skylake
44

5-
function %iadd_i32x4() -> b1 {
6-
block0:
7-
v0 = vconst.i32x4 [1 1 1 1]
8-
v1 = vconst.i32x4 [1 2 3 4]
5+
function %iadd_i32x4(i32x4, i32x4) -> i32x4 {
6+
block0(v0:i32x4, v1:i32x4):
97
v2 = iadd v0, v1
10-
11-
v3 = extractlane v2, 0
12-
v4 = icmp_imm eq v3, 2
13-
14-
v5 = extractlane v2, 3
15-
v6 = icmp_imm eq v5, 5
16-
; TODO replace extractlanes with vector comparison
17-
18-
v7 = band v4, v6
19-
return v7
8+
return v2
209
}
21-
; run
10+
; run: %iadd_i32x4([1 1 1 1], [1 2 3 4]) == [2 3 4 5]
2211

23-
function %iadd_i8x16_with_overflow() -> b1 {
12+
function %iadd_i8x16_with_overflow() -> i8x16 {
2413
block0:
2514
v0 = vconst.i8x16 [255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255]
2615
v1 = vconst.i8x16 [2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
2716
v2 = iadd v0, v1
28-
29-
v3 = extractlane v2, 0
30-
v4 = icmp_imm eq v3, 1
31-
; TODO replace extractlane with vector comparison
32-
33-
return v4
17+
return v2
3418
}
35-
; run
19+
; run: %iadd_i8x16_with_overflow() == [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
3620

3721
function %isub_i32x4_rex() -> b1 {
3822
block0:

cranelift/filetests/src/function_runner.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,8 @@ impl UnboxedValues {
189189

190190
// Store the argument values into `values_vec`.
191191
for ((arg, slot), param) in arguments.iter().zip(&mut values_vec).zip(&signature.params) {
192-
assert_eq!(
193-
arg.ty(),
194-
param.value_type,
192+
assert!(
193+
arg.ty() == param.value_type || arg.is_vector(),
195194
"argument type mismatch: {} != {}",
196195
arg.ty(),
197196
param.value_type

cranelift/reader/src/run_command.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl RunCommand {
3434
match self {
3535
RunCommand::Print(invoke) => {
3636
let actual = invoke_fn(&invoke.args);
37-
println!("{:?} -> {:?}", invoke, actual)
37+
println!("{} -> {}", invoke, DisplayDataValues(&actual))
3838
}
3939
RunCommand::Run(invoke, compare, expected) => {
4040
let actual = invoke_fn(&invoke.args);
@@ -43,7 +43,8 @@ impl RunCommand {
4343
Comparison::NotEquals => *expected != actual,
4444
};
4545
if !matched {
46-
return Err(format!("Failed test: {:?}, actual: {:?}", self, actual));
46+
let actual = DisplayDataValues(&actual);
47+
return Err(format!("Failed test: {}, actual: {}", self, actual));
4748
}
4849
}
4950
}
@@ -56,14 +57,8 @@ impl Display for RunCommand {
5657
match self {
5758
RunCommand::Print(invocation) => write!(f, "print: {}", invocation),
5859
RunCommand::Run(invocation, comparison, expected) => {
59-
write!(f, "run: {} {} ", invocation, comparison)?;
60-
if expected.len() == 1 {
61-
write!(f, "{}", expected[0])
62-
} else {
63-
write!(f, "[")?;
64-
write_data_value_list(f, expected)?;
65-
write!(f, "]")
66-
}
60+
let expected = DisplayDataValues(expected);
61+
write!(f, "run: {} {} {}", invocation, comparison, expected)
6762
}
6863
}
6964
}
@@ -125,6 +120,14 @@ impl DataValue {
125120
DataValue::V128(_) => ir::types::I8X16,
126121
}
127122
}
123+
124+
/// Return true if the value is a vector (i.e. `DataValue::V128`).
125+
pub fn is_vector(&self) -> bool {
126+
match self {
127+
DataValue::V128(_) => true,
128+
_ => false,
129+
}
130+
}
128131
}
129132

130133
/// Helper for creating [From] implementations for [DataValue]
@@ -163,6 +166,24 @@ impl Display for DataValue {
163166
}
164167
}
165168

169+
/// Helper structure for printing bracket-enclosed vectors of [DataValue]s.
170+
/// - for empty vectors, display `[]`
171+
/// - for single item vectors, display `42`, e.g.
172+
/// - for multiple item vectors, display `[42, 43, 44]`, e.g.
173+
struct DisplayDataValues<'a>(&'a [DataValue]);
174+
175+
impl<'a> Display for DisplayDataValues<'a> {
176+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
177+
if self.0.len() == 1 {
178+
write!(f, "{}", self.0[0])
179+
} else {
180+
write!(f, "[")?;
181+
write_data_value_list(f, &self.0)?;
182+
write!(f, "]")
183+
}
184+
}
185+
}
186+
166187
/// Helper function for displaying `Vec<DataValue>`.
167188
fn write_data_value_list(f: &mut Formatter<'_>, list: &[DataValue]) -> fmt::Result {
168189
match list.len() {

0 commit comments

Comments
 (0)