pub struct DirectiveIR { /* private fields */ }
Expand description
Complete IR representation of an OpenMP directive
This is the top-level structure that combines all IR components:
- Directive type (kind)
- Semantic clause data
- Source location
- Language context
- Optional metadata for special directives
§Examples
let dir = DirectiveIR::new(
DirectiveKind::Parallel,
"parallel",
vec![ClauseData::Default(DefaultKind::Shared)],
SourceLocation::new(10, 1),
Language::C,
);
assert_eq!(dir.kind(), DirectiveKind::Parallel);
assert_eq!(dir.clauses().len(), 1);
assert!(dir.kind().is_parallel());
§Learning: Box for Large Structures
Since DirectiveIR
can contain a large Vec<ClauseData>
, and ClauseData
variants can themselves be large, we use Box<[ClauseData]>
instead of
Vec<ClauseData>
for the final immutable representation. This:
- Reduces struct size (Box is one pointer)
- Signals immutability (boxed slice can’t grow/shrink)
- Saves memory (no extra capacity like Vec)
We still accept Vec
in constructors for convenience, then convert to Box.
§Memory Model (Safety Fix)
IMPORTANT: This struct now stores an owned name: String
to prevent use-after-free bugs.
Why?
- Directive names from line continuations are stored in
Cow::Owned
- Previously, IR borrowed from this
Cow
via'a
lifetime - When
Directive
dropped,Cow::Owned
was freed → dangling pointers - Solution: DirectiveIR now owns the normalized directive name
Performance: Minimal overhead (~50ns String allocation). See docs/PERFORMANCE_ANALYSIS.md
.
Implementations§
Source§impl<'a> DirectiveIR
impl<'a> DirectiveIR
Sourcepub fn new(
kind: DirectiveKind,
name: &str,
clauses: Vec<ClauseData>,
location: SourceLocation,
language: Language,
) -> Self
pub fn new( kind: DirectiveKind, name: &str, clauses: Vec<ClauseData>, location: SourceLocation, language: Language, ) -> Self
Create a new directive IR
§Example
let clauses = vec![
ClauseData::Reduction {
operator: ReductionOperator::Add,
items: vec![Identifier::new("sum").into()],
},
];
let dir = DirectiveIR::new(
DirectiveKind::ParallelFor,
"parallel for",
clauses,
SourceLocation::new(42, 1),
Language::C,
);
assert_eq!(dir.kind(), DirectiveKind::ParallelFor);
assert_eq!(dir.name(), "parallel for");
Sourcepub fn simple(
kind: DirectiveKind,
name: &str,
location: SourceLocation,
language: Language,
) -> Self
pub fn simple( kind: DirectiveKind, name: &str, location: SourceLocation, language: Language, ) -> Self
Create a simple directive with no clauses
§Example
let dir = DirectiveIR::simple(DirectiveKind::Barrier, "barrier", SourceLocation::start(), Language::C);
assert_eq!(dir.clauses().len(), 0);
Sourcepub fn parallel(
default: Option<DefaultKind>,
location: SourceLocation,
language: Language,
) -> Self
pub fn parallel( default: Option<DefaultKind>, location: SourceLocation, language: Language, ) -> Self
Create a parallel directive with common clauses
Convenience constructor for the most common OpenMP pattern.
§Example
let dir = DirectiveIR::parallel(
Some(DefaultKind::Shared),
SourceLocation::start(),
Language::C
);
assert!(dir.has_clause(|c| c.is_default()));
Sourcepub fn for_loop(
schedule: ScheduleKind,
chunk_size: Option<Expression>,
location: SourceLocation,
language: Language,
) -> Self
pub fn for_loop( schedule: ScheduleKind, chunk_size: Option<Expression>, location: SourceLocation, language: Language, ) -> Self
Create a for loop directive with schedule
§Example
let dir = DirectiveIR::for_loop(
ScheduleKind::Static,
None,
SourceLocation::start(),
Language::C
);
assert!(dir.has_clause(|c| c.is_schedule()));
Sourcepub fn barrier(location: SourceLocation, language: Language) -> Self
pub fn barrier(location: SourceLocation, language: Language) -> Self
Create a barrier directive (always simple)
§Example
let dir = DirectiveIR::barrier(SourceLocation::start(), Language::C);
assert_eq!(dir.kind(), DirectiveKind::Barrier);
assert_eq!(dir.clauses().len(), 0);
Sourcepub fn taskwait(location: SourceLocation, language: Language) -> Self
pub fn taskwait(location: SourceLocation, language: Language) -> Self
Create a taskwait directive (always simple)
Sourcepub fn taskyield(location: SourceLocation, language: Language) -> Self
pub fn taskyield(location: SourceLocation, language: Language) -> Self
Create a taskyield directive (always simple)
Sourcepub fn kind(&self) -> DirectiveKind
pub fn kind(&self) -> DirectiveKind
Get the directive kind
Sourcepub fn name(&self) -> &str
pub fn name(&self) -> &str
Get the normalized directive name
This returns the directive name as it appears in the source, after normalization (e.g., line continuations collapsed).
§Example
let dir = DirectiveIR::simple(DirectiveKind::ParallelFor, "parallel for", SourceLocation::start(), Language::C);
assert_eq!(dir.name(), "parallel for");
Sourcepub fn clauses(&self) -> &[ClauseData]
pub fn clauses(&self) -> &[ClauseData]
Get the clauses
Sourcepub fn location(&self) -> SourceLocation
pub fn location(&self) -> SourceLocation
Get the source location
Sourcepub fn has_clause<F>(&self, predicate: F) -> bool
pub fn has_clause<F>(&self, predicate: F) -> bool
Check if this directive has a specific clause type
§Example
let dir = DirectiveIR::new(
DirectiveKind::Parallel,
"parallel",
vec![ClauseData::Default(DefaultKind::Shared)],
SourceLocation::start(),
Language::C,
);
assert!(dir.has_clause(|c| matches!(c, ClauseData::Default(_))));
assert!(!dir.has_clause(|c| matches!(c, ClauseData::Private { .. })));
Sourcepub fn find_clause<F>(&self, predicate: F) -> Option<&ClauseData>
pub fn find_clause<F>(&self, predicate: F) -> Option<&ClauseData>
Find first clause matching predicate
Sourcepub fn count_clauses<F>(&self, predicate: F) -> usize
pub fn count_clauses<F>(&self, predicate: F) -> usize
Count clauses matching predicate
Sourcepub fn filter_clauses<F>(&self, predicate: F) -> Vec<&ClauseData>
pub fn filter_clauses<F>(&self, predicate: F) -> Vec<&ClauseData>
Get all clauses matching predicate
Source§impl DirectiveIR
impl DirectiveIR
Sourcepub fn validate(&self) -> Result<(), Vec<ValidationError>>
pub fn validate(&self) -> Result<(), Vec<ValidationError>>
Validate this directive and its clauses
§Example
use roup::ir::{DirectiveIR, DirectiveKind, ClauseData, DefaultKind, Language, SourceLocation};
let ir = DirectiveIR::new(
DirectiveKind::Parallel,
"parallel",
vec![ClauseData::Default(DefaultKind::Shared)],
SourceLocation::start(),
Language::C,
);
// This will validate successfully
assert!(ir.validate().is_ok());
Trait Implementations§
Source§impl Clone for DirectiveIR
impl Clone for DirectiveIR
Source§fn clone(&self) -> DirectiveIR
fn clone(&self) -> DirectiveIR
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more