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
use crate::{
    ir::{
        attribute::{IntegerAttribute, TypeAttribute},
        Attribute, Identifier,
    },
    Context,
};

const ATTRIBUTE_COUNT: usize = 3;

// spell-checker: disable

/// alloca options.
#[derive(Debug, Default, Clone, Copy)]
pub struct AllocaOptions<'c> {
    align: Option<IntegerAttribute<'c>>,
    elem_type: Option<TypeAttribute<'c>>,
    inalloca: bool,
}

impl<'c> AllocaOptions<'c> {
    /// Creates load/store options.
    pub fn new() -> Self {
        Self::default()
    }

    /// Sets the alignment.
    pub fn align(mut self, align: Option<IntegerAttribute<'c>>) -> Self {
        self.align = align;
        self
    }

    /// Sets the elem_type, not needed if the returned pointer is not opaque.
    pub fn elem_type(mut self, elem_type: Option<TypeAttribute<'c>>) -> Self {
        self.elem_type = elem_type;
        self
    }

    /// Sets the inalloca flag.
    pub fn inalloca(mut self, inalloca: bool) -> Self {
        self.inalloca = inalloca;
        self
    }

    pub(super) fn into_attributes(
        self,
        context: &'c Context,
    ) -> Vec<(Identifier<'c>, Attribute<'c>)> {
        let mut attributes = Vec::with_capacity(ATTRIBUTE_COUNT);

        if let Some(align) = self.align {
            attributes.push((Identifier::new(context, "alignment"), align.into()));
        }

        if let Some(elem_type) = self.elem_type {
            attributes.push((Identifier::new(context, "elem_type"), elem_type.into()));
        }

        if self.inalloca {
            attributes.push((
                Identifier::new(context, "inalloca"),
                Attribute::unit(context),
            ));
        }

        attributes
    }
}