Skip to main content

vicis_core/ir/module/global_variable/
parser.rs

1use crate::ir::{
2    module::{global_variable::GlobalVariable, linkage, name, unnamed_addr},
3    types,
4    types::Types,
5    util::spaces,
6    value,
7};
8use nom::{
9    branch::alt,
10    bytes::complete::tag,
11    character::complete::{char, digit1},
12    combinator::opt,
13    error::VerboseError,
14    sequence::preceded,
15    IResult,
16};
17
18// @<GlobalVarName> = [Linkage] [PreemptionSpecifier] [Visibility]
19//                    [DLLStorageClass] [ThreadLocal]
20//                    [(unnamed_addr|local_unnamed_addr)] [AddrSpace]
21//                    [ExternallyInitialized]
22//                    <global | constant> <Type> [<InitializerConstant>]
23//                    [, section "name"] [, comdat [($name)]]
24//                    [, align <Alignment>] (, !name !N)*
25
26pub fn parse<'a>(
27    source: &'a str,
28    types: &Types,
29) -> IResult<&'a str, GlobalVariable, VerboseError<&'a str>> {
30    let (source, name) = preceded(spaces, preceded(char('@'), name::parse))(source)?;
31    let (source, _) = preceded(spaces, char('='))(source)?;
32    let (source, linkage) = opt(preceded(spaces, linkage::parse))(source)?;
33    let (source, unnamed_addr) = opt(preceded(spaces, unnamed_addr::parse))(source)?;
34    let (source, kind) = preceded(spaces, alt((tag("global"), tag("constant"))))(source)?;
35    let (source, ty) = types::parse(source, types)?;
36    let (source, init) = parse_init(source, types, ty)?;
37    let (source, align) = opt(preceded(
38        spaces,
39        preceded(
40            char(','),
41            preceded(spaces, preceded(tag("align"), preceded(spaces, digit1))),
42        ),
43    ))(source)?;
44    Ok((
45        source,
46        GlobalVariable {
47            name,
48            linkage,
49            unnamed_addr,
50            is_constant: kind == "constant",
51            ty,
52            init,
53            align: align.map_or(0, |align| align.parse::<u32>().unwrap()),
54        },
55    ))
56}
57
58pub fn parse_init<'a>(
59    source: &'a str,
60    types: &Types,
61    ty: types::Type,
62) -> IResult<&'a str, Option<value::ConstantData>, VerboseError<&'a str>> {
63    if let Ok((source, init)) = value::parser::parse_constant(source, types, ty) {
64        return Ok((source, Some(init)));
65    }
66    Ok((source, None))
67}
68
69pub fn parse_global_type_and_const<'a>(
70    source: &'a str,
71    types: &Types,
72) -> IResult<&'a str, (types::Type, value::ConstantData), VerboseError<&'a str>> {
73    let (source, ty) = types::parse(source, types)?;
74    let (source, konst) = value::parser::parse_constant(source, types, ty)?;
75    Ok((source, (ty, konst)))
76}