Skip to content

Commit 460498e

Browse files
committed
rust: configuration list compilers and instructions explicitly
1 parent 777954d commit 460498e

File tree

6 files changed

+363
-314
lines changed

6 files changed

+363
-314
lines changed

rust/bear/src/bin/main.rs

Lines changed: 91 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl Application {
8080
let event_source = EventFileReader::try_from(input)?;
8181
let semantic_recognition = SemanticRecognition::try_from(&config)?;
8282
let semantic_transform = SemanticTransform::from(&config.output);
83-
let output_writer = OutputWriter::configure(&output, &config.output);
83+
let output_writer = OutputWriter::configure(&output, &config.output)?;
8484
let result = Application::Semantic {
8585
event_source,
8686
semantic_recognition,
@@ -124,7 +124,7 @@ impl Application {
124124
let entries = event_source
125125
.generate()
126126
.flat_map(|execution| semantic_recognition.apply(execution))
127-
.map(|semantic| semantic_transform.apply(semantic));
127+
.flat_map(|semantic| semantic_transform.apply(semantic));
128128
// Consume the entries and write them to the output file.
129129
// The exit code is based on the result of the output writer.
130130
match output_writer.run(entries) {
@@ -162,17 +162,16 @@ impl TryFrom<&config::Main> for SemanticRecognition {
162162
_ => vec![],
163163
};
164164
let compilers_to_exclude = match &config.output {
165-
config::Output::Clang { filter, .. } => filter.compilers.with_paths.clone(),
166-
_ => vec![],
167-
};
168-
let arguments_to_exclude = match &config.output {
169-
config::Output::Clang { filter, .. } => filter.compilers.with_arguments.clone(),
165+
config::Output::Clang { compilers, .. } => compilers
166+
.into_iter()
167+
.filter(|compiler| compiler.ignore == config::Ignore::Always)
168+
.map(|compiler| compiler.path.clone())
169+
.collect(),
170170
_ => vec![],
171171
};
172172
let tool = semantic::tools::Builder::new()
173173
.compilers_to_recognize(compilers_to_include.as_slice())
174174
.compilers_to_exclude(compilers_to_exclude.as_slice())
175-
.compilers_to_exclude_by_arguments(arguments_to_exclude.as_slice())
176175
.build();
177176

178177
Ok(SemanticRecognition {
@@ -218,24 +217,18 @@ impl SemanticRecognition {
218217
/// Modifies the compiler flags based on the configuration. Ignores non-compiler calls.
219218
enum SemanticTransform {
220219
NoTransform,
221-
Transform {
222-
arguments_to_add: Vec<String>,
223-
arguments_to_remove: Vec<String>,
224-
},
220+
Transform { compilers: Vec<config::Compiler> },
225221
}
226222

227223
impl From<&config::Output> for SemanticTransform {
228224
fn from(config: &config::Output) -> Self {
229225
match config {
230-
config::Output::Clang { transform, .. } => {
231-
if transform.arguments_to_add.is_empty() && transform.arguments_to_remove.is_empty()
232-
{
226+
config::Output::Clang { compilers, .. } => {
227+
if compilers.is_empty() {
233228
SemanticTransform::NoTransform
234229
} else {
235-
SemanticTransform::Transform {
236-
arguments_to_add: transform.arguments_to_add.clone(),
237-
arguments_to_remove: transform.arguments_to_remove.clone(),
238-
}
230+
let compilers = compilers.clone();
231+
SemanticTransform::Transform { compilers }
239232
}
240233
}
241234
config::Output::Semantic { .. } => SemanticTransform::NoTransform,
@@ -244,53 +237,95 @@ impl From<&config::Output> for SemanticTransform {
244237
}
245238

246239
impl SemanticTransform {
247-
fn apply(&self, input: semantic::Meaning) -> semantic::Meaning {
248-
match input {
240+
fn apply(&self, input: semantic::Meaning) -> Option<semantic::Meaning> {
241+
match &input {
249242
semantic::Meaning::Compiler {
250243
compiler,
251-
working_dir,
252244
passes,
253-
} if matches!(self, SemanticTransform::Transform { .. }) => {
254-
let passes_transformed = passes
255-
.into_iter()
256-
.map(|pass| self.transform_pass(pass))
257-
.collect();
258-
259-
semantic::Meaning::Compiler {
260-
compiler,
261-
working_dir,
262-
passes: passes_transformed,
245+
working_dir,
246+
} => match self.lookup(&compiler) {
247+
Some(config::Compiler {
248+
ignore: config::Ignore::Always,
249+
..
250+
}) => None,
251+
Some(config::Compiler {
252+
ignore: config::Ignore::Conditional,
253+
arguments,
254+
..
255+
}) => {
256+
if Self::filter(arguments, passes) {
257+
None
258+
} else {
259+
Some(input)
260+
}
261+
}
262+
Some(config::Compiler {
263+
ignore: config::Ignore::Never,
264+
arguments,
265+
..
266+
}) => {
267+
let new_passes = SemanticTransform::execute(arguments, passes);
268+
Some(semantic::Meaning::Compiler {
269+
compiler: compiler.clone(),
270+
working_dir: working_dir.clone(),
271+
passes: new_passes,
272+
})
263273
}
274+
None => Some(input),
275+
},
276+
_ => Some(input),
277+
}
278+
}
279+
280+
// TODO: allow multiple matches for the same compiler
281+
fn lookup(&self, compiler: &std::path::Path) -> Option<&config::Compiler> {
282+
match self {
283+
SemanticTransform::Transform { compilers } => {
284+
compilers.iter().find(|c| c.path == compiler)
264285
}
265-
_ => input,
286+
_ => None,
266287
}
267288
}
268289

269-
fn transform_pass(&self, pass: semantic::CompilerPass) -> semantic::CompilerPass {
270-
match pass {
271-
semantic::CompilerPass::Compile {
272-
source,
273-
output,
274-
flags,
275-
} => match self {
276-
SemanticTransform::Transform {
277-
arguments_to_add,
278-
arguments_to_remove,
290+
fn filter(arguments: &config::Arguments, passes: &[semantic::CompilerPass]) -> bool {
291+
let match_flags = arguments.match_.as_slice();
292+
passes.iter().any(|pass| match pass {
293+
semantic::CompilerPass::Compile { flags, .. } => {
294+
flags.iter().any(|flag| match_flags.contains(flag))
295+
}
296+
_ => false,
297+
})
298+
}
299+
300+
fn execute(
301+
arguments: &config::Arguments,
302+
passes: &[semantic::CompilerPass],
303+
) -> Vec<semantic::CompilerPass> {
304+
let arguments_to_remove = arguments.remove.as_slice();
305+
let arguments_to_add = arguments.add.as_slice();
306+
307+
let mut new_passes = Vec::with_capacity(passes.len());
308+
for pass in passes {
309+
match pass {
310+
semantic::CompilerPass::Compile {
311+
source,
312+
output,
313+
flags,
279314
} => {
280-
let flags_transformed = flags
281-
.into_iter()
282-
.filter(|flag| !arguments_to_remove.contains(flag))
283-
.chain(arguments_to_add.iter().cloned())
284-
.collect();
285-
semantic::CompilerPass::Compile {
286-
source,
287-
output,
288-
flags: flags_transformed,
289-
}
315+
let mut new_flags = flags.clone();
316+
new_flags.retain(|flag| !arguments_to_remove.contains(flag));
317+
new_flags.extend(arguments_to_add.iter().cloned());
318+
new_passes.push(semantic::CompilerPass::Compile {
319+
source: source.clone(),
320+
output: output.clone(),
321+
flags: new_flags,
322+
});
290323
}
291-
_ => panic!("This is a bug! Please report it to the developers."),
292-
},
293-
_ => pass,
324+
semantic::CompilerPass::Preprocess => {
325+
new_passes.push(semantic::CompilerPass::Preprocess)
326+
}
327+
}
294328
}
329+
new_passes
295330
}
296331
}

0 commit comments

Comments
 (0)