1use std::fmt;
44
45use super::{ClauseData, Language, SourceLocation};
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
72#[repr(C)]
73pub enum DirectiveKind {
74 Parallel = 0,
79 ParallelFor = 1,
81 ParallelForSimd = 2,
83 ParallelSections = 3,
85 ParallelWorkshare = 4,
87 ParallelLoop = 5,
89 ParallelMasked = 6,
91 ParallelMaster = 7,
93
94 For = 10,
99 ForSimd = 11,
101 Sections = 12,
103 Section = 13,
105 Single = 14,
107 Workshare = 15,
109 Loop = 16,
111
112 Simd = 20,
117 DeclareSimd = 21,
119
120 Task = 30,
125 Taskloop = 31,
127 TaskloopSimd = 32,
129 Taskyield = 33,
131 Taskwait = 34,
133 Taskgroup = 35,
135
136 Target = 40,
141 TargetData = 41,
143 TargetEnterData = 42,
145 TargetExitData = 43,
147 TargetUpdate = 44,
149 TargetParallel = 45,
151 TargetParallelFor = 46,
153 TargetParallelForSimd = 47,
155 TargetParallelLoop = 48,
157 TargetSimd = 49,
159 TargetTeams = 50,
161 TargetTeamsDistribute = 51,
163 TargetTeamsDistributeSimd = 52,
165 TargetTeamsDistributeParallelFor = 53,
167 TargetTeamsDistributeParallelForSimd = 54,
169 TargetTeamsLoop = 55,
171
172 Teams = 60,
177 TeamsDistribute = 61,
179 TeamsDistributeSimd = 62,
181 TeamsDistributeParallelFor = 63,
183 TeamsDistributeParallelForSimd = 64,
185 TeamsLoop = 65,
187
188 Barrier = 70,
193 Critical = 71,
195 Atomic = 72,
197 Flush = 73,
199 Ordered = 74,
201 Master = 75,
203 Masked = 76,
205
206 DeclareReduction = 80,
211 DeclareMapper = 81,
213 DeclareTarget = 82,
215 DeclareVariant = 83,
217
218 Distribute = 90,
223 DistributeSimd = 91,
225 DistributeParallelFor = 92,
227 DistributeParallelForSimd = 93,
229
230 Metadirective = 100,
235
236 Threadprivate = 110,
241 Allocate = 111,
243 Requires = 112,
245 Scan = 113,
247 Depobj = 114,
249 Nothing = 115,
251 Error = 116,
253
254 Unknown = 255,
256}
257
258impl fmt::Display for DirectiveKind {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 match self {
261 DirectiveKind::Parallel => write!(f, "parallel"),
263 DirectiveKind::ParallelFor => write!(f, "parallel for"),
264 DirectiveKind::ParallelForSimd => write!(f, "parallel for simd"),
265 DirectiveKind::ParallelSections => write!(f, "parallel sections"),
266 DirectiveKind::ParallelWorkshare => write!(f, "parallel workshare"),
267 DirectiveKind::ParallelLoop => write!(f, "parallel loop"),
268 DirectiveKind::ParallelMasked => write!(f, "parallel masked"),
269 DirectiveKind::ParallelMaster => write!(f, "parallel master"),
270
271 DirectiveKind::For => write!(f, "for"),
273 DirectiveKind::ForSimd => write!(f, "for simd"),
274 DirectiveKind::Sections => write!(f, "sections"),
275 DirectiveKind::Section => write!(f, "section"),
276 DirectiveKind::Single => write!(f, "single"),
277 DirectiveKind::Workshare => write!(f, "workshare"),
278 DirectiveKind::Loop => write!(f, "loop"),
279
280 DirectiveKind::Simd => write!(f, "simd"),
282 DirectiveKind::DeclareSimd => write!(f, "declare simd"),
283
284 DirectiveKind::Task => write!(f, "task"),
286 DirectiveKind::Taskloop => write!(f, "taskloop"),
287 DirectiveKind::TaskloopSimd => write!(f, "taskloop simd"),
288 DirectiveKind::Taskyield => write!(f, "taskyield"),
289 DirectiveKind::Taskwait => write!(f, "taskwait"),
290 DirectiveKind::Taskgroup => write!(f, "taskgroup"),
291
292 DirectiveKind::Target => write!(f, "target"),
294 DirectiveKind::TargetData => write!(f, "target data"),
295 DirectiveKind::TargetEnterData => write!(f, "target enter data"),
296 DirectiveKind::TargetExitData => write!(f, "target exit data"),
297 DirectiveKind::TargetUpdate => write!(f, "target update"),
298 DirectiveKind::TargetParallel => write!(f, "target parallel"),
299 DirectiveKind::TargetParallelFor => write!(f, "target parallel for"),
300 DirectiveKind::TargetParallelForSimd => write!(f, "target parallel for simd"),
301 DirectiveKind::TargetParallelLoop => write!(f, "target parallel loop"),
302 DirectiveKind::TargetSimd => write!(f, "target simd"),
303 DirectiveKind::TargetTeams => write!(f, "target teams"),
304 DirectiveKind::TargetTeamsDistribute => write!(f, "target teams distribute"),
305 DirectiveKind::TargetTeamsDistributeSimd => write!(f, "target teams distribute simd"),
306 DirectiveKind::TargetTeamsDistributeParallelFor => {
307 write!(f, "target teams distribute parallel for")
308 }
309 DirectiveKind::TargetTeamsDistributeParallelForSimd => {
310 write!(f, "target teams distribute parallel for simd")
311 }
312 DirectiveKind::TargetTeamsLoop => write!(f, "target teams loop"),
313
314 DirectiveKind::Teams => write!(f, "teams"),
316 DirectiveKind::TeamsDistribute => write!(f, "teams distribute"),
317 DirectiveKind::TeamsDistributeSimd => write!(f, "teams distribute simd"),
318 DirectiveKind::TeamsDistributeParallelFor => {
319 write!(f, "teams distribute parallel for")
320 }
321 DirectiveKind::TeamsDistributeParallelForSimd => {
322 write!(f, "teams distribute parallel for simd")
323 }
324 DirectiveKind::TeamsLoop => write!(f, "teams loop"),
325
326 DirectiveKind::Barrier => write!(f, "barrier"),
328 DirectiveKind::Critical => write!(f, "critical"),
329 DirectiveKind::Atomic => write!(f, "atomic"),
330 DirectiveKind::Flush => write!(f, "flush"),
331 DirectiveKind::Ordered => write!(f, "ordered"),
332 DirectiveKind::Master => write!(f, "master"),
333 DirectiveKind::Masked => write!(f, "masked"),
334
335 DirectiveKind::DeclareReduction => write!(f, "declare reduction"),
337 DirectiveKind::DeclareMapper => write!(f, "declare mapper"),
338 DirectiveKind::DeclareTarget => write!(f, "declare target"),
339 DirectiveKind::DeclareVariant => write!(f, "declare variant"),
340
341 DirectiveKind::Distribute => write!(f, "distribute"),
343 DirectiveKind::DistributeSimd => write!(f, "distribute simd"),
344 DirectiveKind::DistributeParallelFor => write!(f, "distribute parallel for"),
345 DirectiveKind::DistributeParallelForSimd => {
346 write!(f, "distribute parallel for simd")
347 }
348
349 DirectiveKind::Metadirective => write!(f, "metadirective"),
351
352 DirectiveKind::Threadprivate => write!(f, "threadprivate"),
354 DirectiveKind::Allocate => write!(f, "allocate"),
355 DirectiveKind::Requires => write!(f, "requires"),
356 DirectiveKind::Scan => write!(f, "scan"),
357 DirectiveKind::Depobj => write!(f, "depobj"),
358 DirectiveKind::Nothing => write!(f, "nothing"),
359 DirectiveKind::Error => write!(f, "error"),
360
361 DirectiveKind::Unknown => write!(f, "unknown"),
362 }
363 }
364}
365
366impl DirectiveKind {
367 pub fn is_parallel(&self) -> bool {
369 matches!(
370 self,
371 DirectiveKind::Parallel
372 | DirectiveKind::ParallelFor
373 | DirectiveKind::ParallelForSimd
374 | DirectiveKind::ParallelSections
375 | DirectiveKind::ParallelWorkshare
376 | DirectiveKind::ParallelLoop
377 | DirectiveKind::ParallelMasked
378 | DirectiveKind::ParallelMaster
379 )
380 }
381
382 pub fn is_worksharing(&self) -> bool {
384 matches!(
385 self,
386 DirectiveKind::For
387 | DirectiveKind::ForSimd
388 | DirectiveKind::Sections
389 | DirectiveKind::Section
390 | DirectiveKind::Single
391 | DirectiveKind::Workshare
392 )
393 }
394
395 pub fn is_simd(&self) -> bool {
397 matches!(
398 self,
399 DirectiveKind::Simd
400 | DirectiveKind::DeclareSimd
401 | DirectiveKind::ForSimd
402 | DirectiveKind::ParallelForSimd
403 | DirectiveKind::TaskloopSimd
404 | DirectiveKind::TargetSimd
405 | DirectiveKind::TargetParallelForSimd
406 | DirectiveKind::TargetTeamsDistributeSimd
407 | DirectiveKind::TargetTeamsDistributeParallelForSimd
408 | DirectiveKind::TeamsDistributeSimd
409 | DirectiveKind::TeamsDistributeParallelForSimd
410 | DirectiveKind::DistributeSimd
411 | DirectiveKind::DistributeParallelForSimd
412 )
413 }
414
415 pub fn is_task(&self) -> bool {
417 matches!(
418 self,
419 DirectiveKind::Task
420 | DirectiveKind::Taskloop
421 | DirectiveKind::TaskloopSimd
422 | DirectiveKind::Taskyield
423 | DirectiveKind::Taskwait
424 | DirectiveKind::Taskgroup
425 )
426 }
427
428 pub fn is_target(&self) -> bool {
430 matches!(
431 self,
432 DirectiveKind::Target
433 | DirectiveKind::TargetData
434 | DirectiveKind::TargetEnterData
435 | DirectiveKind::TargetExitData
436 | DirectiveKind::TargetUpdate
437 | DirectiveKind::TargetParallel
438 | DirectiveKind::TargetParallelFor
439 | DirectiveKind::TargetParallelForSimd
440 | DirectiveKind::TargetParallelLoop
441 | DirectiveKind::TargetSimd
442 | DirectiveKind::TargetTeams
443 | DirectiveKind::TargetTeamsDistribute
444 | DirectiveKind::TargetTeamsDistributeSimd
445 | DirectiveKind::TargetTeamsDistributeParallelFor
446 | DirectiveKind::TargetTeamsDistributeParallelForSimd
447 | DirectiveKind::TargetTeamsLoop
448 )
449 }
450
451 pub fn is_teams(&self) -> bool {
453 matches!(
454 self,
455 DirectiveKind::Teams
456 | DirectiveKind::TeamsDistribute
457 | DirectiveKind::TeamsDistributeSimd
458 | DirectiveKind::TeamsDistributeParallelFor
459 | DirectiveKind::TeamsDistributeParallelForSimd
460 | DirectiveKind::TeamsLoop
461 | DirectiveKind::TargetTeams
462 | DirectiveKind::TargetTeamsDistribute
463 | DirectiveKind::TargetTeamsDistributeSimd
464 | DirectiveKind::TargetTeamsDistributeParallelFor
465 | DirectiveKind::TargetTeamsDistributeParallelForSimd
466 | DirectiveKind::TargetTeamsLoop
467 )
468 }
469
470 pub fn is_loop(&self) -> bool {
472 matches!(
473 self,
474 DirectiveKind::For
475 | DirectiveKind::ForSimd
476 | DirectiveKind::Loop
477 | DirectiveKind::ParallelFor
478 | DirectiveKind::ParallelForSimd
479 | DirectiveKind::ParallelLoop
480 | DirectiveKind::Simd
481 | DirectiveKind::Taskloop
482 | DirectiveKind::TaskloopSimd
483 | DirectiveKind::Distribute
484 | DirectiveKind::DistributeSimd
485 | DirectiveKind::DistributeParallelFor
486 | DirectiveKind::DistributeParallelForSimd
487 )
488 }
489
490 pub fn is_synchronization(&self) -> bool {
492 matches!(
493 self,
494 DirectiveKind::Barrier
495 | DirectiveKind::Critical
496 | DirectiveKind::Atomic
497 | DirectiveKind::Flush
498 | DirectiveKind::Ordered
499 | DirectiveKind::Master
500 | DirectiveKind::Masked
501 )
502 }
503
504 pub fn is_declare(&self) -> bool {
506 matches!(
507 self,
508 DirectiveKind::DeclareReduction
509 | DirectiveKind::DeclareMapper
510 | DirectiveKind::DeclareTarget
511 | DirectiveKind::DeclareVariant
512 | DirectiveKind::DeclareSimd
513 )
514 }
515
516 pub fn has_structured_block(&self) -> bool {
518 !matches!(
519 self,
520 DirectiveKind::Barrier
521 | DirectiveKind::Taskyield
522 | DirectiveKind::Taskwait
523 | DirectiveKind::Flush
524 | DirectiveKind::TargetEnterData
525 | DirectiveKind::TargetExitData
526 | DirectiveKind::TargetUpdate
527 | DirectiveKind::Threadprivate
528 | DirectiveKind::DeclareSimd
529 | DirectiveKind::DeclareReduction
530 | DirectiveKind::DeclareMapper
531 | DirectiveKind::DeclareTarget
532 | DirectiveKind::DeclareVariant
533 | DirectiveKind::Scan
534 | DirectiveKind::Depobj
535 | DirectiveKind::Nothing
536 | DirectiveKind::Error
537 | DirectiveKind::Section
538 )
539 }
540}
541
542#[derive(Debug, Clone, PartialEq)]
596pub struct DirectiveIR {
597 kind: DirectiveKind,
599
600 name: String,
608
609 clauses: Box<[ClauseData]>,
616
617 location: SourceLocation,
619
620 language: Language,
622}
623
624impl DirectiveIR {
625 pub fn new(
650 kind: DirectiveKind,
651 name: &str,
652 clauses: Vec<ClauseData>,
653 location: SourceLocation,
654 language: Language,
655 ) -> Self {
656 Self {
657 kind,
658 name: name.to_string(),
659 clauses: clauses.into_boxed_slice(),
660 location,
661 language,
662 }
663 }
664
665 pub fn simple(
679 kind: DirectiveKind,
680 name: &str,
681 location: SourceLocation,
682 language: Language,
683 ) -> Self {
684 Self::new(kind, name, vec![], location, language)
685 }
686
687 pub fn parallel(
703 default: Option<super::DefaultKind>,
704 location: SourceLocation,
705 language: Language,
706 ) -> Self {
707 let mut clauses = vec![];
708 if let Some(kind) = default {
709 clauses.push(ClauseData::Default(kind));
710 }
711 Self::new(
712 DirectiveKind::Parallel,
713 "parallel",
714 clauses,
715 location,
716 language,
717 )
718 }
719
720 pub fn for_loop(
735 schedule: super::ScheduleKind,
736 chunk_size: Option<super::Expression>,
737 location: SourceLocation,
738 language: Language,
739 ) -> Self {
740 let clauses = vec![ClauseData::Schedule {
741 kind: schedule,
742 modifiers: vec![],
743 chunk_size,
744 }];
745 Self::new(DirectiveKind::For, "for", clauses, location, language)
746 }
747
748 pub fn barrier(location: SourceLocation, language: Language) -> Self {
759 Self::simple(DirectiveKind::Barrier, "barrier", location, language)
760 }
761
762 pub fn taskwait(location: SourceLocation, language: Language) -> Self {
764 Self::simple(DirectiveKind::Taskwait, "taskwait", location, language)
765 }
766
767 pub fn taskyield(location: SourceLocation, language: Language) -> Self {
769 Self::simple(DirectiveKind::Taskyield, "taskyield", location, language)
770 }
771
772 pub fn kind(&self) -> DirectiveKind {
778 self.kind
779 }
780
781 pub fn name(&self) -> &str {
794 &self.name
795 }
796
797 pub fn clauses(&self) -> &[ClauseData] {
799 &self.clauses
800 }
801
802 pub fn location(&self) -> SourceLocation {
804 self.location
805 }
806
807 pub fn language(&self) -> Language {
809 self.language
810 }
811
812 pub fn has_clause<F>(&self, predicate: F) -> bool
830 where
831 F: Fn(&ClauseData) -> bool,
832 {
833 self.clauses.iter().any(predicate)
834 }
835
836 pub fn find_clause<F>(&self, predicate: F) -> Option<&ClauseData>
838 where
839 F: Fn(&ClauseData) -> bool,
840 {
841 self.clauses.iter().find(|c| predicate(c))
842 }
843
844 pub fn count_clauses<F>(&self, predicate: F) -> usize
846 where
847 F: Fn(&ClauseData) -> bool,
848 {
849 self.clauses.iter().filter(|c| predicate(c)).count()
850 }
851
852 pub fn filter_clauses<F>(&self, predicate: F) -> Vec<&ClauseData>
854 where
855 F: Fn(&ClauseData) -> bool,
856 {
857 self.clauses.iter().filter(|c| predicate(c)).collect()
858 }
859}
860
861impl fmt::Display for DirectiveIR {
862 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
863 write!(f, "{}{}", self.language.pragma_prefix(), self.kind)?;
865
866 for clause in self.clauses.iter() {
868 write!(f, " {clause}")?;
869 }
870
871 Ok(())
872 }
873}
874
875#[cfg(test)]
880mod tests {
881 use super::*;
882 use crate::ir::{ClauseItem, DefaultKind, Identifier, ReductionOperator};
883
884 #[test]
886 fn test_directive_kind_display() {
887 assert_eq!(DirectiveKind::Parallel.to_string(), "parallel");
888 assert_eq!(DirectiveKind::ParallelFor.to_string(), "parallel for");
889 assert_eq!(DirectiveKind::For.to_string(), "for");
890 assert_eq!(DirectiveKind::Target.to_string(), "target");
891 assert_eq!(
892 DirectiveKind::TargetTeamsDistributeParallelForSimd.to_string(),
893 "target teams distribute parallel for simd"
894 );
895 }
896
897 #[test]
898 fn test_directive_kind_is_parallel() {
899 assert!(DirectiveKind::Parallel.is_parallel());
900 assert!(DirectiveKind::ParallelFor.is_parallel());
901 assert!(DirectiveKind::ParallelForSimd.is_parallel());
902 assert!(!DirectiveKind::For.is_parallel());
903 assert!(!DirectiveKind::Target.is_parallel());
904 }
905
906 #[test]
907 fn test_directive_kind_is_worksharing() {
908 assert!(DirectiveKind::For.is_worksharing());
909 assert!(DirectiveKind::Sections.is_worksharing());
910 assert!(DirectiveKind::Single.is_worksharing());
911 assert!(!DirectiveKind::Parallel.is_worksharing());
912 }
913
914 #[test]
915 fn test_directive_kind_is_simd() {
916 assert!(DirectiveKind::Simd.is_simd());
917 assert!(DirectiveKind::ForSimd.is_simd());
918 assert!(DirectiveKind::ParallelForSimd.is_simd());
919 assert!(!DirectiveKind::For.is_simd());
920 assert!(!DirectiveKind::Parallel.is_simd());
921 }
922
923 #[test]
924 fn test_directive_kind_is_task() {
925 assert!(DirectiveKind::Task.is_task());
926 assert!(DirectiveKind::Taskloop.is_task());
927 assert!(DirectiveKind::Taskyield.is_task());
928 assert!(!DirectiveKind::Parallel.is_task());
929 }
930
931 #[test]
932 fn test_directive_kind_is_target() {
933 assert!(DirectiveKind::Target.is_target());
934 assert!(DirectiveKind::TargetData.is_target());
935 assert!(DirectiveKind::TargetTeams.is_target());
936 assert!(!DirectiveKind::Teams.is_target());
937 assert!(!DirectiveKind::Parallel.is_target());
938 }
939
940 #[test]
941 fn test_directive_kind_is_teams() {
942 assert!(DirectiveKind::Teams.is_teams());
943 assert!(DirectiveKind::TeamsDistribute.is_teams());
944 assert!(DirectiveKind::TargetTeams.is_teams());
945 assert!(!DirectiveKind::Target.is_teams());
946 }
947
948 #[test]
949 fn test_directive_kind_is_loop() {
950 assert!(DirectiveKind::For.is_loop());
951 assert!(DirectiveKind::Loop.is_loop());
952 assert!(DirectiveKind::Simd.is_loop());
953 assert!(!DirectiveKind::Parallel.is_loop());
954 assert!(!DirectiveKind::Barrier.is_loop());
955 }
956
957 #[test]
958 fn test_directive_kind_is_synchronization() {
959 assert!(DirectiveKind::Barrier.is_synchronization());
960 assert!(DirectiveKind::Critical.is_synchronization());
961 assert!(DirectiveKind::Atomic.is_synchronization());
962 assert!(!DirectiveKind::Parallel.is_synchronization());
963 }
964
965 #[test]
966 fn test_directive_kind_is_declare() {
967 assert!(DirectiveKind::DeclareReduction.is_declare());
968 assert!(DirectiveKind::DeclareTarget.is_declare());
969 assert!(DirectiveKind::DeclareSimd.is_declare());
970 assert!(!DirectiveKind::Parallel.is_declare());
971 }
972
973 #[test]
974 fn test_directive_kind_has_structured_block() {
975 assert!(DirectiveKind::Parallel.has_structured_block());
976 assert!(DirectiveKind::For.has_structured_block());
977 assert!(DirectiveKind::Critical.has_structured_block());
978 assert!(!DirectiveKind::Barrier.has_structured_block());
979 assert!(!DirectiveKind::Taskyield.has_structured_block());
980 assert!(!DirectiveKind::DeclareTarget.has_structured_block());
981 }
982
983 #[test]
985 fn test_directive_ir_new() {
986 let dir = DirectiveIR::new(
987 DirectiveKind::Parallel,
988 "parallel",
989 vec![],
990 SourceLocation::new(10, 1),
991 Language::C,
992 );
993
994 assert_eq!(dir.kind(), DirectiveKind::Parallel);
995 assert_eq!(dir.clauses().len(), 0);
996 assert_eq!(dir.location(), SourceLocation::new(10, 1));
997 assert_eq!(dir.language(), Language::C);
998 }
999
1000 #[test]
1001 fn test_directive_ir_with_clauses() {
1002 let clauses = vec![
1003 ClauseData::Default(DefaultKind::Shared),
1004 ClauseData::Private {
1005 items: vec![ClauseItem::Identifier(Identifier::new("x"))],
1006 },
1007 ];
1008
1009 let dir = DirectiveIR::new(
1010 DirectiveKind::Parallel,
1011 "parallel",
1012 clauses,
1013 SourceLocation::start(),
1014 Language::C,
1015 );
1016
1017 assert_eq!(dir.clauses().len(), 2);
1018 }
1019
1020 #[test]
1021 fn test_directive_ir_has_clause() {
1022 let dir = DirectiveIR::new(
1023 DirectiveKind::Parallel,
1024 "parallel",
1025 vec![ClauseData::Default(DefaultKind::Shared)],
1026 SourceLocation::start(),
1027 Language::C,
1028 );
1029
1030 assert!(dir.has_clause(|c| matches!(c, ClauseData::Default(_))));
1031 assert!(!dir.has_clause(|c| matches!(c, ClauseData::Private { .. })));
1032 }
1033
1034 #[test]
1035 fn test_directive_ir_find_clause() {
1036 let dir = DirectiveIR::new(
1037 DirectiveKind::Parallel,
1038 "parallel",
1039 vec![
1040 ClauseData::Default(DefaultKind::Shared),
1041 ClauseData::Private { items: vec![] },
1042 ],
1043 SourceLocation::start(),
1044 Language::C,
1045 );
1046
1047 let found = dir.find_clause(|c| matches!(c, ClauseData::Default(_)));
1048 assert!(found.is_some());
1049 assert!(matches!(found.unwrap(), ClauseData::Default(_)));
1050 }
1051
1052 #[test]
1053 fn test_directive_ir_count_clauses() {
1054 let dir = DirectiveIR::new(
1055 DirectiveKind::Parallel,
1056 "parallel",
1057 vec![
1058 ClauseData::Private { items: vec![] },
1059 ClauseData::Default(DefaultKind::Shared),
1060 ClauseData::Private { items: vec![] },
1061 ],
1062 SourceLocation::start(),
1063 Language::C,
1064 );
1065
1066 assert_eq!(
1067 dir.count_clauses(|c| matches!(c, ClauseData::Private { .. })),
1068 2
1069 );
1070 assert_eq!(
1071 dir.count_clauses(|c| matches!(c, ClauseData::Default(_))),
1072 1
1073 );
1074 }
1075
1076 #[test]
1077 fn test_directive_ir_filter_clauses() {
1078 let dir = DirectiveIR::new(
1079 DirectiveKind::Parallel,
1080 "parallel",
1081 vec![
1082 ClauseData::Private { items: vec![] },
1083 ClauseData::Default(DefaultKind::Shared),
1084 ClauseData::Private { items: vec![] },
1085 ],
1086 SourceLocation::start(),
1087 Language::C,
1088 );
1089
1090 let private_clauses = dir.filter_clauses(|c| matches!(c, ClauseData::Private { .. }));
1091 assert_eq!(private_clauses.len(), 2);
1092 }
1093
1094 #[test]
1095 fn test_directive_ir_display() {
1096 let dir = DirectiveIR::new(
1097 DirectiveKind::Parallel,
1098 "parallel",
1099 vec![ClauseData::Default(DefaultKind::Shared)],
1100 SourceLocation::start(),
1101 Language::C,
1102 );
1103
1104 let display = dir.to_string();
1105 assert!(display.contains("pragma"));
1106 assert!(display.contains("omp"));
1107 assert!(display.contains("parallel"));
1108 assert!(display.contains("default"));
1109 }
1110
1111 #[test]
1112 fn test_directive_ir_display_with_reduction() {
1113 let clauses = vec![ClauseData::Reduction {
1114 operator: ReductionOperator::Add,
1115 items: vec![ClauseItem::Identifier(Identifier::new("sum"))],
1116 }];
1117
1118 let dir = DirectiveIR::new(
1119 DirectiveKind::ParallelFor,
1120 "parallel for",
1121 clauses,
1122 SourceLocation::start(),
1123 Language::C,
1124 );
1125
1126 let display = dir.to_string();
1127 assert!(display.contains("parallel for"));
1128 assert!(display.contains("reduction"));
1129 assert!(display.contains("+"));
1130 assert!(display.contains("sum"));
1131 }
1132
1133 #[test]
1134 fn test_directive_ir_clone() {
1135 let dir1 = DirectiveIR::new(
1136 DirectiveKind::Parallel,
1137 "parallel",
1138 vec![ClauseData::Default(DefaultKind::Shared)],
1139 SourceLocation::start(),
1140 Language::C,
1141 );
1142
1143 let dir2 = dir1.clone();
1144 assert_eq!(dir1, dir2);
1145 }
1146
1147 #[test]
1148 fn test_directive_ir_equality() {
1149 let dir1 = DirectiveIR::new(
1150 DirectiveKind::Parallel,
1151 "parallel",
1152 vec![],
1153 SourceLocation::start(),
1154 Language::C,
1155 );
1156
1157 let dir2 = DirectiveIR::new(
1158 DirectiveKind::Parallel,
1159 "parallel",
1160 vec![],
1161 SourceLocation::start(),
1162 Language::C,
1163 );
1164
1165 let dir3 = DirectiveIR::new(
1166 DirectiveKind::For,
1167 "for",
1168 vec![],
1169 SourceLocation::start(),
1170 Language::C,
1171 );
1172
1173 assert_eq!(dir1, dir2);
1174 assert_ne!(dir1, dir3);
1175 }
1176
1177 #[test]
1179 fn test_directive_kind_longest_name() {
1180 let kind = DirectiveKind::TargetTeamsDistributeParallelForSimd;
1181 assert_eq!(
1182 kind.to_string(),
1183 "target teams distribute parallel for simd"
1184 );
1185 assert!(kind.is_target());
1186 assert!(kind.is_teams());
1187 assert!(kind.is_simd());
1188 }
1189
1190 #[test]
1192 fn test_directive_kind_deprecated() {
1193 let kind = DirectiveKind::ParallelMaster;
1194 assert_eq!(kind.to_string(), "parallel master");
1195 assert!(kind.is_parallel());
1196 }
1197
1198 #[test]
1200 fn test_directive_ir_no_clauses() {
1201 let dir = DirectiveIR::new(
1202 DirectiveKind::Barrier,
1203 "barrier",
1204 vec![],
1205 SourceLocation::start(),
1206 Language::C,
1207 );
1208
1209 assert_eq!(dir.clauses().len(), 0);
1210 assert!(!dir.has_clause(|_| true));
1211 }
1212}