cranelift_fuzzgen/
print.rs1use cranelift::codegen::data_value::DataValue;
2use cranelift::codegen::ir::Function;
3use cranelift::prelude::settings::SettingKind;
4use cranelift::prelude::*;
5use std::fmt;
6
7use crate::TestCaseInput;
8
9#[derive(Debug)]
10enum TestCaseKind {
11 Compile,
12 Run,
13}
14
15pub struct PrintableTestCase<'a> {
17 kind: TestCaseKind,
18 isa: &'a isa::OwnedTargetIsa,
19 functions: &'a [Function],
20 inputs: &'a [TestCaseInput],
22}
23
24impl<'a> PrintableTestCase<'a> {
25 pub fn compile(isa: &'a isa::OwnedTargetIsa, functions: &'a [Function]) -> Self {
27 Self {
28 kind: TestCaseKind::Compile,
29 isa,
30 functions,
31 inputs: &[],
32 }
33 }
34
35 pub fn run(
39 isa: &'a isa::OwnedTargetIsa,
40 functions: &'a [Function],
41 inputs: &'a [TestCaseInput],
42 ) -> Self {
43 Self {
44 kind: TestCaseKind::Run,
45 isa,
46 functions,
47 inputs,
48 }
49 }
50
51 pub fn main(&self) -> &Function {
53 &self.functions[0]
54 }
55}
56
57impl<'a> fmt::Debug for PrintableTestCase<'a> {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 match self.kind {
60 TestCaseKind::Compile => {
61 writeln!(f, ";; Compile test case\n")?;
62 writeln!(f, "test compile")?;
63 }
64 TestCaseKind::Run => {
65 writeln!(f, ";; Run test case\n")?;
66 writeln!(f, "test interpret")?;
67 writeln!(f, "test run")?;
68 }
69 };
70
71 write_non_default_flags(f, self.isa.flags())?;
72
73 write!(f, "target {} ", self.isa.triple().architecture)?;
74 write_non_default_isa_flags(f, &self.isa)?;
75 write!(f, "\n\n")?;
76
77 for func in self.functions.iter().rev() {
80 writeln!(f, "{func}\n")?;
81 }
82
83 if !self.inputs.is_empty() {
84 writeln!(
85 f,
86 "; Note: the results in the below test cases are simply a placeholder and probably will be wrong\n"
87 )?;
88 }
89
90 for input in self.inputs.iter() {
91 let returns = &self.main().signature.returns;
96 let placeholder_output = returns
97 .iter()
98 .map(|param| DataValue::read_from_slice_ne(&[0; 16][..], param.value_type))
99 .map(|val| format!("{val}"))
100 .collect::<Vec<_>>()
101 .join(", ");
102
103 let test_condition = match returns.len() {
105 0 => String::new(),
106 1 => format!(" == {placeholder_output}"),
107 _ => format!(" == [{placeholder_output}]"),
108 };
109
110 let args = input
111 .iter()
112 .map(|val| format!("{val}"))
113 .collect::<Vec<_>>()
114 .join(", ");
115
116 writeln!(f, "; run: {}({}){}", self.main().name, args, test_condition)?;
117 }
118
119 Ok(())
120 }
121}
122
123fn write_non_default_flags(f: &mut fmt::Formatter<'_>, flags: &settings::Flags) -> fmt::Result {
125 let default_flags = settings::Flags::new(settings::builder());
126 for (default, flag) in default_flags.iter().zip(flags.iter()) {
127 assert_eq!(default.name, flag.name);
128
129 if default.value_string() != flag.value_string() {
130 writeln!(f, "set {}={}", flag.name, flag.value_string())?;
131 }
132 }
133
134 Ok(())
135}
136
137fn write_non_default_isa_flags(
139 f: &mut fmt::Formatter<'_>,
140 isa: &isa::OwnedTargetIsa,
141) -> fmt::Result {
142 let default_isa = isa::lookup(isa.triple().clone())
143 .unwrap()
144 .finish(isa.flags().clone())
145 .unwrap();
146
147 for (default, flag) in default_isa.isa_flags().iter().zip(isa.isa_flags()) {
148 assert_eq!(default.name, flag.name);
149
150 if default.value_string() == flag.value_string() {
152 continue;
153 }
154
155 if flag.kind() == SettingKind::Bool && flag.value_string() == "true" {
158 write!(f, "{} ", flag.name)?;
159 } else {
160 write!(f, "{}={} ", flag.name, flag.value_string())?;
161 }
162 }
163
164 Ok(())
165}