1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::common::*;

use super::*;

#[derive(Debug)]
pub struct CheckPlain<M> {
    pattern: M,
}
impl<M> CheckPlain<M>
where
    M: MatcherMut,
{
    pub fn new(pattern: M) -> Self {
        Self { pattern }
    }
}
impl<M> Spanned for CheckPlain<M>
where
    M: MatcherMut,
{
    fn span(&self) -> SourceSpan {
        self.pattern.span()
    }
}
impl<M> Rule for CheckPlain<M>
where
    M: MatcherMut,
{
    fn kind(&self) -> Check {
        Check::Plain
    }

    fn apply<'input, 'context, C>(&self, context: &mut C) -> DiagResult<Matches<'input>>
    where
        C: Context<'input, 'context> + ?Sized,
    {
        let input = context.search_block();
        let result = self.pattern.try_match_mut(input, context)?;

        match &result {
            MatchResult {
                ty,
                info: Some(info),
            } if ty.is_ok() => {
                context.cursor_mut().set_start(info.span.end());
            }
            _ => (),
        }
        Ok(result.into())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::pattern::matcher::*;

    #[test]
    fn check_plain_test() -> DiagResult<()> {
        let mut context = TestContext::new();
        context.with_checks("CHECK: @inc4").with_input(
            "
define void @sub1(i32* %p, i32 %v) {
entry:
        %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v)
        ret void
}

define void @inc4(i64* %p) {
entry:
        %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1)
        ret void
}
",
        );
        let mut mctx = context.match_context();
        let pattern = SubstringMatcher::new(
            Span::new(SourceSpan::from(8..12), Cow::Borrowed("@inc4")),
            &mctx.config,
        )
        .expect("expected pattern to be valid");
        let rule = CheckPlain::new(pattern);
        let matches = rule
            .apply(&mut mctx)
            .expect("expected non-fatal application of rule");
        let matched = TestResult::from_matches(matches, &mctx).into_result()?;
        assert_eq!(matched[0].span.offset(), 153);
        assert_eq!(matched[0].span.len(), 5);
        let input = mctx.search();
        assert_eq!(input.as_str(matched[0].matched_range()), "@inc4");
        assert_eq!(input.buffer()[mctx.cursor().start()], b'(');

        Ok(())
    }
}