diff --git a/docs/testing.rst b/docs/testing.rst index 9a59f2c7be..f58a413033 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -336,3 +336,11 @@ that instruction is compared to the directive:: [R#200c,%x8] v11 = isub v1, v2 ; bin: 40628433 return } + +If any instructions are unencoded (indicated with a `[-]` encoding field), they +will be encoded using the same mechanism as the legalizer uses. However, +illegal instructions for the ISA won't be expanded into other instruction +sequences. Instead the test will fail. + +Value locations must be present if they are required to compute the binary +bits. Missing value locations will cause the test to crash. diff --git a/filetests/isa/riscv/binary32.cton b/filetests/isa/riscv/binary32.cton index 0d2805681a..c2f117f5da 100644 --- a/filetests/isa/riscv/binary32.cton +++ b/filetests/isa/riscv/binary32.cton @@ -6,7 +6,7 @@ function int32() { ebb0: [-,%x5] v1 = iconst.i32 1 [-,%x6] v2 = iconst.i32 2 - [R#0c,%x7] v10 = iadd v1, v2 ; bin: 006283b3 + [-,%x7] v10 = iadd v1, v2 ; bin: 006283b3 [R#200c,%x8] v11 = isub v1, v2 ; bin: 40628433 [R#10c] v12 = imul v1, v2 return diff --git a/src/filetest/binemit.rs b/src/filetest/binemit.rs index 2c6a725431..16c2613b20 100644 --- a/src/filetest/binemit.rs +++ b/src/filetest/binemit.rs @@ -3,7 +3,7 @@ //! The `binemit` test command generates binary machine code for every instruction in the input //! functions and compares the results to the expected output. -use std::borrow::{Borrow, Cow}; +use std::borrow::Cow; use std::fmt::Write; use cretonne::binemit; use cretonne::ir; @@ -60,7 +60,7 @@ impl SubTest for TestBinEmit { } fn is_mutating(&self) -> bool { - false + true } fn needs_isa(&self) -> bool { @@ -71,7 +71,7 @@ impl SubTest for TestBinEmit { let isa = context.isa.expect("binemit needs an ISA"); // TODO: Run a verifier pass over the code first to detect any bad encodings or missing/bad // value locations. The current error reporting is just crashing... - let func = func.borrow(); + let mut func = func.into_owned(); let mut sink = TextSink { text: String::new() }; @@ -85,6 +85,22 @@ impl SubTest for TestBinEmit { comment.text)) } }; + + // Compute an encoding for `inst` if one wasn't provided. + if !func.encodings + .get(inst) + .map(|e| e.is_legal()) + .unwrap_or(false) { + match isa.encode(&func.dfg, &func.dfg[inst]) { + Ok(enc) => *func.encodings.ensure(inst) = enc, + Err(_) => { + return Err(format!("{} can't be encoded: {}", + inst, + func.dfg.display_inst(inst))) + } + } + } + sink.text.clear(); isa.emit_inst(&func, inst, &mut sink); let have = sink.text.trim();