use rucc_base::Symbol;
use rucc_diag::Span;
use crate::ast::{AsmOperandList, StrId, StrList, SymbolList};
use crate::expr::ExprId;
pub type AsmId = rucc_base::Idx<Asm>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Asm {
pub template: StrId,
pub outputs: AsmOperandList,
pub inputs: AsmOperandList,
pub clobbers: StrList,
pub labels: SymbolList,
pub quals: AsmQuals,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AsmOperand {
pub name: Option<Symbol>,
pub constraint: StrId,
pub value: ExprId,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct AsmQuals(u8);
impl AsmQuals {
pub const NONE: AsmQuals = AsmQuals(0);
pub const VOLATILE: AsmQuals = AsmQuals(1);
pub const INLINE: AsmQuals = AsmQuals(2);
pub const GOTO: AsmQuals = AsmQuals(4);
#[inline]
#[must_use]
pub const fn has(self, other: AsmQuals) -> bool {
self.0 & other.0 == other.0
}
#[inline]
#[must_use]
pub const fn with(self, other: AsmQuals) -> AsmQuals {
AsmQuals(self.0 | other.0)
}
#[inline]
#[must_use]
pub const fn is_none(self) -> bool {
self.0 == 0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn qualifier_sets_add_up() {
let q = AsmQuals::NONE.with(AsmQuals::VOLATILE).with(AsmQuals::GOTO);
assert!(q.has(AsmQuals::VOLATILE));
assert!(q.has(AsmQuals::GOTO));
assert!(!q.has(AsmQuals::INLINE));
assert!(AsmQuals::NONE.is_none());
}
}