@@ -6,20 +6,24 @@ use crate::hir::{PtrPrintMap};
66// NOTE: Effect very intentionally does not support Eq or PartialEq; we almost never want to check
77// bit equality of types in the compiler but instead check subtyping, intersection, union, etc.
88#[ derive( Copy , Clone , Debug ) ]
9- // TODO(Jacob): Update this comment
10- /// The main work horse of intraprocedural type inference and specialization. The main interfaces
9+ /// The main work horse of effect inference and specialization. The main interfaces
1110/// will look like:
1211///
1312/// * is effect A a subset of effect B
1413/// * union/meet effect A and effect B
1514///
1615/// Most questions can be rewritten in terms of these operations.
17- // TODO(Jacob): Convert from read_bits and write_bits to just bits
18- // Rename this struct to be about a memory location, with another struct
19- // of Effects that combines the two.
16+
17+ // TODO(Jacob): Fix up comments for Effect and EffectPair
18+ // Make it clear why we need both of these. Effect handles all lattice operations
19+ // EffectPair is our typical use case because we care about having both read and write effects
2020pub struct Effect {
21+ bits : u64
22+ }
23+
24+ pub struct EffectPair {
2125 /// Unlike ZJIT's type system, effects do not have a notion of subclasses.
22- /// Instead of specializations, the Effects struct contains two bitsets.
26+ /// Instead of specializations, the Effects struct contains two Effect bitsets.
2327 /// We have read and write bitsets, both representing the same lattice.
2428 ///
2529 /// TODO(Jacob): Provide an example about why we split based on read / write
@@ -28,31 +32,37 @@ pub struct Effect {
2832 /// This should include top, bottom, and how you move up or down in between
2933 ///
3034 /// These fields should not be directly read or written except by internal `Effect` APIs.
31- read_bits : u64 ,
32- write_bits : u64
35+ read_bits : Effect ,
36+ write_bits : Effect
3337}
3438
3539include ! ( "hir_effect.inc.rs" ) ;
3640
37- /// Print adaptor for [`Effect`]. See [`PtrPrintMap`].
41+
42+ /// Print adaptor for [`BitSet`]. See [`PtrPrintMap`].
3843pub struct EffectPrinter < ' a > {
3944 inner : Effect ,
4045 ptr_map : & ' a PtrPrintMap ,
4146}
4247
43- // TODO(Jacob): Port from types to effects
4448impl < ' a > std:: fmt:: Display for EffectPrinter < ' a > {
4549 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
46- let ty = self . inner ;
50+ let effect = self . inner ;
51+ // TODO(Jacob): Is it better to have 2*n in terms of list traversals, or allocate 1 bitset?
52+ // We could just remove this first loop through and make the function simpler. This seems better to me?
53+ //
54+ // If there's an exact match, write and return
4755 for ( name, pattern) in bits:: AllBitPatterns {
48- if ty. bits == pattern {
56+ if effect. bits == pattern {
57+ // TODO(Jacob): Figure out if this is horrible rust
4958 write ! ( f, "{name}" ) ?;
50- return write_spec ( f , self ) ;
59+ return Ok ( ( ) ) ;
5160 }
5261 }
53- #TODO ( Jacob ) : Convert to debug assert
54- assert ! ( bits:: AllBitPatterns . is_sorted_by( |( _, left) , ( _, right) | left > right) ) ;
55- let mut bits = ty. bits ;
62+ // Otherwise, find the most descriptive sub-effect write it, and mask out the handled bits.
63+ // Most descriptive means "highest number of bits set while remaining fully contained within `effect`"
64+ debug_assert ! ( bits:: AllBitPatterns . is_sorted_by( |( _, left) , ( _, right) | left > right) ) ;
65+ let mut bits = effect. bits ;
5666 let mut sep = "" ;
5767 for ( name, pattern) in bits:: AllBitPatterns {
5868 if bits == 0 { break ; }
@@ -62,11 +72,14 @@ impl<'a> std::fmt::Display for EffectPrinter<'a> {
6272 bits &= !pattern;
6373 }
6474 }
65- assert_eq ! ( bits, 0 , "Should have eliminated all bits by iterating over all patterns" ) ;
66- write_spec ( f , self )
75+ debug_assert_eq ! ( bits, 0 , "Should have eliminated all bits by iterating over all patterns" ) ;
76+ Ok ( ( ) )
6777 }
6878}
6979
80+ // TODO(Jacob): Add EffectPairPrinter that just calls out to EffectPrinter twice
81+ // TODO(Jacob): Add functions for effect pair. print differing effects in the pair
82+
7083impl std:: fmt:: Display for Effect {
7184 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
7285 self . print ( & PtrPrintMap :: identity ( ) ) . fmt ( f)
@@ -76,48 +89,36 @@ impl std::fmt::Display for Effect {
7689impl Effect {
7790 // TODO(Jacob): Double check this comment below that was pulled from types
7891 /// Private. Only for creating effect globals.
79- const fn from_bits ( read_bits : u64 , write_bits : u64 ) -> Effect {
92+ const fn from_bits ( bits : u64 ) -> Effect {
8093 Effect {
81- read_bits,
82- write_bits,
94+ bits
8395 }
8496 }
8597
8698 pub fn union ( & self , other : Effect ) -> Effect {
87- let read_bits = self . read_bits | other. read_bits ;
88- let write_bits = self . write_bits | other. write_bits ;
89- Effect :: from_bits ( read_bits, write_bits)
99+ Effect :: from_bits ( self . bits | other. bits )
90100 }
91101
92- pub fn intersection ( & self , other : Effect ) -> Effect {
93- let read_bits = self . read_bits & other. read_bits ;
94- let write_bits = self . write_bits & other. write_bits ;
95- Effect :: from_bits ( read_bits, write_bits)
102+ pub fn intersect ( & self , other : Effect ) -> Effect {
103+ Effect :: from_bits ( self . bits & other. bits )
96104 }
97105
98- pub fn overlaps ( & self , other : Effect ) -> bool {
99- ! self . intersection ( other) . bit_equal ( effects :: None )
106+ pub fn exclude ( & self , other : Effect ) -> Effect {
107+ Effect :: from_bits ( self . bits - ( self . bits & other. bits ) )
100108 }
101109
102110 // TODO(Jacob): Rewrite comment and see if this is intended to be used or not. We don't have subtypes...
103111 /// Check bit equality of two `Type`s. Do not use! You are probably looking for [`Effect::includes`].
104112 pub fn bit_equal ( & self , other : Effect ) -> bool {
105- self . read_bits == other. read_bits && self . write_bits == other . write_bits
113+ self . bits == other. bits
106114 }
107115
108116 pub fn includes ( & self , other : Effect ) -> bool {
109- let union = Effect :: union ( self , other) ;
110- Effect :: bit_equal ( self , union)
111- }
112-
113- pub fn includes_read ( & self , other : Effect ) -> bool {
114- let union = Effect :: union ( self , other) ;
115- self . read_bits == union. read_bits
117+ self . bit_equal ( Effect :: union ( self , other) )
116118 }
117119
118- pub fn includes_write ( & self , other : Effect ) -> bool {
119- let union = Effect :: union ( self , other) ;
120- self . write_bits == union. write_bits
120+ pub fn overlaps ( & self , other : Effect ) -> bool {
121+ !self . intersect ( other) . bit_equal ( effects:: None )
121122 }
122123
123124 pub fn print ( self , ptr_map : & PtrPrintMap ) -> EffectPrinter < ' _ > {
0 commit comments