tenseleyflow/bencch / c4a171d

Browse files

Add bench core compiler types

Authored by espadonne
SHA
c4a171d5a095f4ad8af146f45b77278baa9ce125
Parents
9cfbbed
Tree
e9472dd

4 changed files

StatusFile+-
A bench-core/Cargo.toml 5 0
A bench-core/src/lib.rs 248 0
M bench/Cargo.toml 1 0
M bench/src/compiler.rs 123 5
bench-core/Cargo.tomladded
@@ -0,0 +1,5 @@
1
+[package]
2
+name = "bencch-core"
3
+version = "0.1.0"
4
+edition = "2021"
5
+description = "Bench-owned compiler-facing types for bencch"
bench-core/src/lib.rsadded
@@ -0,0 +1,248 @@
1
+use std::collections::{BTreeMap, BTreeSet};
2
+use std::fmt;
3
+use std::path::PathBuf;
4
+
5
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6
+pub enum OptLevel {
7
+    O0,
8
+    O1,
9
+    O2,
10
+    O3,
11
+    Ofast,
12
+}
13
+
14
+impl OptLevel {
15
+    pub fn parse_flag(flag: &str) -> Option<Self> {
16
+        match flag.to_ascii_lowercase().as_str() {
17
+            "o0" => Some(Self::O0),
18
+            "o1" => Some(Self::O1),
19
+            "o2" => Some(Self::O2),
20
+            "o3" => Some(Self::O3),
21
+            "ofast" => Some(Self::Ofast),
22
+            _ => None,
23
+        }
24
+    }
25
+
26
+    pub fn as_flag(&self) -> &'static str {
27
+        match self {
28
+            Self::O0 => "-O0",
29
+            Self::O1 => "-O1",
30
+            Self::O2 => "-O2",
31
+            Self::O3 => "-O3",
32
+            Self::Ofast => "-Ofast",
33
+        }
34
+    }
35
+
36
+    pub fn as_str(&self) -> &'static str {
37
+        match self {
38
+            Self::O0 => "O0",
39
+            Self::O1 => "O1",
40
+            Self::O2 => "O2",
41
+            Self::O3 => "O3",
42
+            Self::Ofast => "Ofast",
43
+        }
44
+    }
45
+}
46
+
47
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48
+pub enum Stage {
49
+    Preprocess,
50
+    Tokens,
51
+    Ast,
52
+    Sema,
53
+    Ir,
54
+    OptIr,
55
+    Mir,
56
+    Regalloc,
57
+    Asm,
58
+    Obj,
59
+    Run,
60
+}
61
+
62
+impl Stage {
63
+    pub const ALL: [Stage; 11] = [
64
+        Stage::Preprocess,
65
+        Stage::Tokens,
66
+        Stage::Ast,
67
+        Stage::Sema,
68
+        Stage::Ir,
69
+        Stage::OptIr,
70
+        Stage::Mir,
71
+        Stage::Regalloc,
72
+        Stage::Asm,
73
+        Stage::Obj,
74
+        Stage::Run,
75
+    ];
76
+
77
+    pub fn parse(name: &str) -> Option<Self> {
78
+        match name.trim().to_ascii_lowercase().as_str() {
79
+            "preprocess" => Some(Self::Preprocess),
80
+            "tokens" => Some(Self::Tokens),
81
+            "ast" => Some(Self::Ast),
82
+            "sema" => Some(Self::Sema),
83
+            "ir" => Some(Self::Ir),
84
+            "optir" => Some(Self::OptIr),
85
+            "mir" => Some(Self::Mir),
86
+            "regalloc" => Some(Self::Regalloc),
87
+            "asm" => Some(Self::Asm),
88
+            "obj" => Some(Self::Obj),
89
+            "run" => Some(Self::Run),
90
+            _ => None,
91
+        }
92
+    }
93
+
94
+    pub fn as_str(&self) -> &'static str {
95
+        match self {
96
+            Self::Preprocess => "preprocess",
97
+            Self::Tokens => "tokens",
98
+            Self::Ast => "ast",
99
+            Self::Sema => "sema",
100
+            Self::Ir => "ir",
101
+            Self::OptIr => "optir",
102
+            Self::Mir => "mir",
103
+            Self::Regalloc => "regalloc",
104
+            Self::Asm => "asm",
105
+            Self::Obj => "obj",
106
+            Self::Run => "run",
107
+        }
108
+    }
109
+}
110
+
111
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112
+pub enum FailureStage {
113
+    Preprocess,
114
+    Lexer,
115
+    Parser,
116
+    Sema,
117
+    Ir,
118
+    Obj,
119
+    Run,
120
+}
121
+
122
+impl FailureStage {
123
+    pub fn parse(name: &str) -> Option<Self> {
124
+        match name.trim().to_ascii_lowercase().as_str() {
125
+            "preprocess" => Some(Self::Preprocess),
126
+            "lexer" | "tokens" => Some(Self::Lexer),
127
+            "parser" | "parse" | "ast" => Some(Self::Parser),
128
+            "sema" => Some(Self::Sema),
129
+            "ir" | "optir" => Some(Self::Ir),
130
+            "obj" | "asm" => Some(Self::Obj),
131
+            "run" => Some(Self::Run),
132
+            _ => None,
133
+        }
134
+    }
135
+
136
+    pub fn as_str(&self) -> &'static str {
137
+        match self {
138
+            Self::Preprocess => "preprocess",
139
+            Self::Lexer => "lexer",
140
+            Self::Parser => "parser",
141
+            Self::Sema => "sema",
142
+            Self::Ir => "ir",
143
+            Self::Obj => "obj",
144
+            Self::Run => "run",
145
+        }
146
+    }
147
+}
148
+
149
+#[derive(Debug, Clone)]
150
+pub struct CaptureRequest {
151
+    pub input: PathBuf,
152
+    pub requested: BTreeSet<Stage>,
153
+    pub opt_level: OptLevel,
154
+}
155
+
156
+impl CaptureRequest {
157
+    pub fn new(input: impl Into<PathBuf>) -> Self {
158
+        Self {
159
+            input: input.into(),
160
+            requested: BTreeSet::new(),
161
+            opt_level: OptLevel::O0,
162
+        }
163
+    }
164
+
165
+    pub fn with_stage(mut self, stage: Stage) -> Self {
166
+        self.requested.insert(stage);
167
+        self
168
+    }
169
+
170
+    pub fn with_all_stages(mut self) -> Self {
171
+        self.requested.extend(Stage::ALL);
172
+        self
173
+    }
174
+
175
+    pub fn with_opt_level(mut self, opt_level: OptLevel) -> Self {
176
+        self.opt_level = opt_level;
177
+        self
178
+    }
179
+}
180
+
181
+#[derive(Debug, Clone)]
182
+pub struct CaptureResult {
183
+    pub input: PathBuf,
184
+    pub opt_level: OptLevel,
185
+    pub stages: BTreeMap<Stage, CapturedStage>,
186
+}
187
+
188
+impl CaptureResult {
189
+    pub fn get(&self, stage: Stage) -> Option<&CapturedStage> {
190
+        self.stages.get(&stage)
191
+    }
192
+}
193
+
194
+#[derive(Debug, Clone)]
195
+pub struct CaptureFailure {
196
+    pub input: PathBuf,
197
+    pub opt_level: OptLevel,
198
+    pub stage: FailureStage,
199
+    pub detail: String,
200
+    pub stages: BTreeMap<Stage, CapturedStage>,
201
+}
202
+
203
+impl CaptureFailure {
204
+    pub fn partial_result(&self) -> CaptureResult {
205
+        CaptureResult {
206
+            input: self.input.clone(),
207
+            opt_level: self.opt_level,
208
+            stages: self.stages.clone(),
209
+        }
210
+    }
211
+}
212
+
213
+impl fmt::Display for CaptureFailure {
214
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215
+        write!(f, "{}: {}", self.stage.as_str(), self.detail)
216
+    }
217
+}
218
+
219
+impl std::error::Error for CaptureFailure {}
220
+
221
+#[derive(Debug, Clone)]
222
+pub enum CapturedStage {
223
+    Text(String),
224
+    Run(RunCapture),
225
+}
226
+
227
+impl CapturedStage {
228
+    pub fn as_text(&self) -> Option<&str> {
229
+        match self {
230
+            Self::Text(text) => Some(text),
231
+            Self::Run(_) => None,
232
+        }
233
+    }
234
+
235
+    pub fn as_run(&self) -> Option<&RunCapture> {
236
+        match self {
237
+            Self::Text(_) => None,
238
+            Self::Run(run) => Some(run),
239
+        }
240
+    }
241
+}
242
+
243
+#[derive(Debug, Clone)]
244
+pub struct RunCapture {
245
+    pub exit_code: i32,
246
+    pub stdout: String,
247
+    pub stderr: String,
248
+}
bench/Cargo.tomlmodified
@@ -9,4 +9,5 @@ name = "afs-tests"
99
 path = "src/main.rs"
1010
 
1111
 [dependencies]
12
+bencch-core = { path = "../bench-core" }
1213
 armfortas = { path = "../.." }
bench/src/compiler.rsmodified
@@ -1,9 +1,9 @@
1
+use std::collections::{BTreeMap, BTreeSet};
12
 use std::path::{Path, PathBuf};
23
 
3
-pub use armfortas::driver::OptLevel;
4
-pub use armfortas::testing::{
5
-    capture_from_path, CaptureFailure, CaptureRequest, CaptureResult, CapturedStage,
6
-    FailureStage, RunCapture, Stage,
4
+pub use bencch_core::{
5
+    CaptureFailure, CaptureRequest, CaptureResult, CapturedStage, FailureStage, OptLevel,
6
+    RunCapture, Stage,
77
 };
88
 
99
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -26,12 +26,130 @@ pub fn compile_output(
2626
         emit_obj: matches!(mode, EmitMode::Obj),
2727
         emit_ir: false,
2828
         preprocess_only: false,
29
-        opt_level,
29
+        opt_level: into_driver_opt_level(opt_level),
3030
     };
3131
 
3232
     armfortas::driver::compile(&opts)
3333
 }
3434
 
35
+pub fn capture_from_path(request: &CaptureRequest) -> Result<CaptureResult, CaptureFailure> {
36
+    let arm_request = armfortas::testing::CaptureRequest {
37
+        input: request.input.clone(),
38
+        requested: request
39
+            .requested
40
+            .iter()
41
+            .copied()
42
+            .map(into_arm_stage)
43
+            .collect::<BTreeSet<_>>(),
44
+        opt_level: into_driver_opt_level(request.opt_level),
45
+    };
46
+
47
+    armfortas::testing::capture_from_path(&arm_request)
48
+        .map(into_bench_capture_result)
49
+        .map_err(into_bench_capture_failure)
50
+}
51
+
52
+fn into_driver_opt_level(opt_level: OptLevel) -> armfortas::driver::OptLevel {
53
+    match opt_level {
54
+        OptLevel::O0 => armfortas::driver::OptLevel::O0,
55
+        OptLevel::O1 => armfortas::driver::OptLevel::O1,
56
+        OptLevel::O2 => armfortas::driver::OptLevel::O2,
57
+        OptLevel::O3 => armfortas::driver::OptLevel::O3,
58
+        OptLevel::Ofast => armfortas::driver::OptLevel::Ofast,
59
+    }
60
+}
61
+
62
+fn from_driver_opt_level(opt_level: armfortas::driver::OptLevel) -> OptLevel {
63
+    match opt_level {
64
+        armfortas::driver::OptLevel::O0 => OptLevel::O0,
65
+        armfortas::driver::OptLevel::O1 => OptLevel::O1,
66
+        armfortas::driver::OptLevel::O2 => OptLevel::O2,
67
+        armfortas::driver::OptLevel::O3 => OptLevel::O3,
68
+        armfortas::driver::OptLevel::Ofast => OptLevel::Ofast,
69
+    }
70
+}
71
+
72
+fn into_arm_stage(stage: Stage) -> armfortas::testing::Stage {
73
+    match stage {
74
+        Stage::Preprocess => armfortas::testing::Stage::Preprocess,
75
+        Stage::Tokens => armfortas::testing::Stage::Tokens,
76
+        Stage::Ast => armfortas::testing::Stage::Ast,
77
+        Stage::Sema => armfortas::testing::Stage::Sema,
78
+        Stage::Ir => armfortas::testing::Stage::Ir,
79
+        Stage::OptIr => armfortas::testing::Stage::OptIr,
80
+        Stage::Mir => armfortas::testing::Stage::Mir,
81
+        Stage::Regalloc => armfortas::testing::Stage::Regalloc,
82
+        Stage::Asm => armfortas::testing::Stage::Asm,
83
+        Stage::Obj => armfortas::testing::Stage::Obj,
84
+        Stage::Run => armfortas::testing::Stage::Run,
85
+    }
86
+}
87
+
88
+fn from_arm_stage(stage: armfortas::testing::Stage) -> Stage {
89
+    match stage {
90
+        armfortas::testing::Stage::Preprocess => Stage::Preprocess,
91
+        armfortas::testing::Stage::Tokens => Stage::Tokens,
92
+        armfortas::testing::Stage::Ast => Stage::Ast,
93
+        armfortas::testing::Stage::Sema => Stage::Sema,
94
+        armfortas::testing::Stage::Ir => Stage::Ir,
95
+        armfortas::testing::Stage::OptIr => Stage::OptIr,
96
+        armfortas::testing::Stage::Mir => Stage::Mir,
97
+        armfortas::testing::Stage::Regalloc => Stage::Regalloc,
98
+        armfortas::testing::Stage::Asm => Stage::Asm,
99
+        armfortas::testing::Stage::Obj => Stage::Obj,
100
+        armfortas::testing::Stage::Run => Stage::Run,
101
+    }
102
+}
103
+
104
+fn from_arm_failure_stage(stage: armfortas::testing::FailureStage) -> FailureStage {
105
+    match stage {
106
+        armfortas::testing::FailureStage::Preprocess => FailureStage::Preprocess,
107
+        armfortas::testing::FailureStage::Lexer => FailureStage::Lexer,
108
+        armfortas::testing::FailureStage::Parser => FailureStage::Parser,
109
+        armfortas::testing::FailureStage::Sema => FailureStage::Sema,
110
+        armfortas::testing::FailureStage::Ir => FailureStage::Ir,
111
+        armfortas::testing::FailureStage::Obj => FailureStage::Obj,
112
+        armfortas::testing::FailureStage::Run => FailureStage::Run,
113
+    }
114
+}
115
+
116
+fn from_arm_captured_stage(stage: armfortas::testing::CapturedStage) -> CapturedStage {
117
+    match stage {
118
+        armfortas::testing::CapturedStage::Text(text) => CapturedStage::Text(text),
119
+        armfortas::testing::CapturedStage::Run(run) => CapturedStage::Run(RunCapture {
120
+            exit_code: run.exit_code,
121
+            stdout: run.stdout,
122
+            stderr: run.stderr,
123
+        }),
124
+    }
125
+}
126
+
127
+fn into_bench_capture_result(result: armfortas::testing::CaptureResult) -> CaptureResult {
128
+    CaptureResult {
129
+        input: result.input,
130
+        opt_level: from_driver_opt_level(result.opt_level),
131
+        stages: result
132
+            .stages
133
+            .into_iter()
134
+            .map(|(stage, captured)| (from_arm_stage(stage), from_arm_captured_stage(captured)))
135
+            .collect::<BTreeMap<_, _>>(),
136
+    }
137
+}
138
+
139
+fn into_bench_capture_failure(failure: armfortas::testing::CaptureFailure) -> CaptureFailure {
140
+    CaptureFailure {
141
+        input: failure.input,
142
+        opt_level: from_driver_opt_level(failure.opt_level),
143
+        stage: from_arm_failure_stage(failure.stage),
144
+        detail: failure.detail,
145
+        stages: failure
146
+            .stages
147
+            .into_iter()
148
+            .map(|(stage, captured)| (from_arm_stage(stage), from_arm_captured_stage(captured)))
149
+            .collect::<BTreeMap<_, _>>(),
150
+    }
151
+}
152
+
35153
 #[cfg(test)]
36154
 pub mod test_support {
37155
     pub use armfortas::ir::inst::{