|
1 | 1 | # Generate hir_effect.inc.rs. To do this, we build up a DAG that |
2 | | -# represents a slice of the ZJIT effect hierarchy. |
| 2 | +# represents the ZJIT effect hierarchy. |
| 3 | +# TODO(Jacob): Make sure this function works after all the types and effects replacements |
3 | 4 |
|
4 | 5 | require 'set' |
5 | 6 |
|
6 | | -# Type represents not just a Ruby class but a named union of other types. |
7 | | -class Type |
8 | | - attr_accessor :name, :subtypes |
| 7 | +# Effect represents not just a Ruby class but a named union of other effects. |
| 8 | +class Effect |
| 9 | + attr_accessor :name, :subeffects |
9 | 10 |
|
10 | | - def initialize name, subtypes=nil |
| 11 | + def initialize name, subeffects=nil |
11 | 12 | @name = name |
12 | | - @subtypes = subtypes || [] |
| 13 | + @subeffects = subeffects || [] |
13 | 14 | end |
14 | 15 |
|
15 | | - def all_subtypes |
16 | | - subtypes.flat_map { |subtype| subtype.all_subtypes } + subtypes |
| 16 | + def all_subeffects |
| 17 | + subeffects.flat_map { |subeffect| subeffect.all_subeffects } + subeffects |
17 | 18 | end |
18 | 19 |
|
19 | | - def subtype name |
20 | | - result = Type.new name |
21 | | - @subtypes << result |
| 20 | + def subeffect name |
| 21 | + result = Effect.new name |
| 22 | + @subeffects << result |
22 | 23 | result |
23 | 24 | end |
24 | 25 | end |
25 | 26 |
|
26 | 27 | # Helper to generate graphviz. |
27 | | -def to_graphviz_rec type |
28 | | - type.subtypes.each {|subtype| |
29 | | - puts type.name + "->" + subtype.name + ";" |
| 28 | +def to_graphviz_rec effect |
| 29 | + effect.subeffects.each {|subeffect| |
| 30 | + puts effect.name + "->" + subeffect.name + ";" |
30 | 31 | } |
31 | | - type.subtypes.each {|subtype| |
32 | | - to_graphviz_rec subtype |
| 32 | + effect.subeffect.each {|subeffect| |
| 33 | + to_graphviz_rec subeffect |
33 | 34 | } |
34 | 35 | end |
35 | 36 |
|
36 | 37 | # Generate graphviz. |
37 | | -def to_graphviz type |
| 38 | +def to_graphviz effect |
38 | 39 | puts "digraph G {" |
39 | | - to_graphviz_rec type |
| 40 | + to_graphviz_rec effect |
40 | 41 | puts "}" |
41 | 42 | end |
42 | 43 |
|
43 | | -# ===== Start generating the type DAG ===== |
| 44 | +# ===== Start generating the effect DAG ===== |
44 | 45 |
|
45 | | -# Start at Any. All types are subtypes of Any. |
46 | | -any = Type.new "Any" |
| 46 | +# Start at Any. All effects are subeffects of Any. |
| 47 | +any = Effect.new 'Any' |
47 | 48 | # Build the effect universe. |
48 | | -allocator = any.subtype "Allocator" |
49 | | -control = any.subtype "Control" |
50 | | -memory = any.subtype "Memory" |
51 | | -other = memory.subtype "Other" |
52 | | -frame = memory.subtype "Frame" |
53 | | -pc = frame.subtype "PC" |
54 | | -locals = frame.subtype "Locals" |
55 | | -stack = frame.subtype "Stack" |
| 49 | +allocator = any.subeffect 'Allocator' |
| 50 | +control = any.subeffect 'Control' |
| 51 | +memory = any.subeffect 'Memory' |
| 52 | +other = memory.subeffect 'Other' |
| 53 | +frame = memory.subeffect 'Frame' |
| 54 | +pc = frame.subeffect 'PC' |
| 55 | +locals = frame.subeffect 'Locals' |
| 56 | +stack = frame.subeffect 'Stack' |
56 | 57 |
|
57 | 58 | # Use the smallest unsigned value needed to describe all effect bits |
58 | 59 | # If it becomes an issue, this can be generated but for now we do it manually |
59 | | -$int_label = "u8" |
60 | | - |
61 | | -# Define a new type that can be subclassed (most of them). |
62 | | -# If c_name is given, mark the rb_cXYZ object as equivalent to this exact type. |
63 | | -def base_type name, c_name: nil |
64 | | - type = $object.subtype name |
65 | | - exact = type.subtype(name+"Exact") |
66 | | - subclass = type.subtype(name+"Subclass") |
| 60 | +$int_label = 'u8' |
| 61 | + |
| 62 | +# Define a new effect that can be subclassed (most of them). |
| 63 | +# If c_name is given, mark the rb_cXYZ object as equivalent to this exact effect. |
| 64 | +def base_effect name, c_name: nil |
| 65 | + effect = $object.subeffect name |
| 66 | + exact = effect.subeffect(name+'Exact') |
| 67 | + subclass = effect.subeffect(name+'Subclass') |
67 | 68 | if c_name |
68 | 69 | $exact_c_names[exact.name] = c_name |
69 | 70 | $inexact_c_names[subclass.name] = c_name |
70 | 71 | end |
71 | 72 | $builtin_exact << exact.name |
72 | 73 | $subclass << subclass.name |
73 | | - [type, exact] |
| 74 | + [effect, exact] |
74 | 75 | end |
75 | 76 |
|
76 | | -# Define a new type that cannot be subclassed. |
77 | | -# If c_name is given, mark the rb_cXYZ object as equivalent to this type. |
78 | | -def final_type name, base: $object, c_name: nil |
| 77 | +# Define a new effect that cannot be subclassed. |
| 78 | +# If c_name is given, mark the rb_cXYZ object as equivalent to this effect. |
| 79 | +def final_effect name, base: $object, c_name: nil |
79 | 80 | if c_name |
80 | 81 | $exact_c_names[name] = c_name |
81 | 82 | end |
82 | | - type = base.subtype name |
83 | | - $builtin_exact << type.name |
84 | | - type |
| 83 | + effect = base.subeffect name |
| 84 | + $builtin_exact << effect.name |
| 85 | + effect |
85 | 86 | end |
86 | 87 |
|
87 | | -# Assign individual bits to type leaves and union bit patterns to nodes with subtypes |
| 88 | +# Assign individual bits to effect leaves and union bit patterns to nodes with subeffects |
88 | 89 | num_bits = 0 |
89 | 90 | $bits = {"Empty" => ["0#{$int_label}"]} |
90 | 91 | $numeric_bits = {"Empty" => 0} |
91 | | -Set[any, *any.all_subtypes].sort_by(&:name).each {|type| |
92 | | - subtypes = type.subtypes |
93 | | - if subtypes.empty? |
| 92 | +Set[any, *any.all_subeffects].sort_by(&:name).each {|effect| |
| 93 | + subeffects = effect.subeffects |
| 94 | + if subeffects.empty? |
94 | 95 | # Assign bits for leaves |
95 | | - $bits[type.name] = ["1#{$int_label} << #{num_bits}"] |
96 | | - $numeric_bits[type.name] = 1 << num_bits |
| 96 | + $bits[effect.name] = ["1#{$int_label} << #{num_bits}"] |
| 97 | + $numeric_bits[effect.name] = 1 << num_bits |
97 | 98 | num_bits += 1 |
98 | 99 | else |
99 | 100 | # Assign bits for unions |
100 | | - $bits[type.name] = subtypes.map(&:name).sort |
| 101 | + $bits[effect.name] = subeffects.map(&:name).sort |
101 | 102 | end |
102 | 103 | } |
103 | | -[*any.all_subtypes, any].each {|type| |
104 | | - subtypes = type.subtypes |
105 | | - unless subtypes.empty? |
106 | | - $numeric_bits[type.name] = subtypes.map {|ty| $numeric_bits[ty.name]}.reduce(&:|) |
| 104 | +[*any.all_subeffects, any].each {|effect| |
| 105 | + subeffects = effect.subeffects |
| 106 | + unless subeffects.empty? |
| 107 | + $numeric_bits[effect.name] = subeffects.map {|ty| $numeric_bits[ty.name]}.reduce(&:|) |
107 | 108 | end |
108 | 109 | } |
109 | 110 |
|
110 | | -# Unions are for names of groups of type bit patterns that don't fit neatly |
| 111 | +# Unions are for names of groups of effect bit patterns that don't fit neatly |
111 | 112 | # into the Ruby class hierarchy. For example, we might want to refer to a union |
112 | 113 | # of TrueClassExact|FalseClassExact by the name BoolExact even though a "bool" |
113 | 114 | # doesn't exist as a class in Ruby. |
114 | | -def add_union name, type_names |
115 | | - type_names = type_names.sort |
116 | | - $bits[name] = type_names |
117 | | - $numeric_bits[name] = type_names.map {|type_name| $numeric_bits[type_name]}.reduce(&:|) |
| 115 | +def add_union name, effect_names |
| 116 | + effect_names = effect_names.sort |
| 117 | + $bits[name] = effect_names |
| 118 | + $numeric_bits[name] = effect_names.map {|effect_name| $numeric_bits[effect_name]}.reduce(&:|) |
118 | 119 | end |
119 | 120 |
|
120 | 121 | # ===== Finished generating the DAG; write Rust code ===== |
121 | 122 |
|
122 | 123 | puts "// This file is @generated by src/hir/gen_hir_effect.rb." |
123 | 124 | puts "mod bits {" |
124 | | -$bits.keys.sort.map {|type_name| |
125 | | - subtypes = $bits[type_name].join(" | ") |
126 | | - puts " pub const #{type_name}: #{$int_label} = #{subtypes};" |
| 125 | +$bits.keys.sort.map {|effect_name| |
| 126 | + subeffects = $bits[effect_name].join(" | ") |
| 127 | + puts " pub const #{effect_name}: #{$int_label} = #{subeffects};" |
127 | 128 | } |
128 | 129 | puts " pub const AllBitPatterns: [(&str, #{$int_label}); #{$bits.size}] = [" |
129 | 130 | # Sort the bit patterns by decreasing value so that we can print the densest |
130 | | -# possible to-string representation of a Type. For example, CSigned instead of |
| 131 | +# possible to-string representation of an Effect. For example, CSigned instead of |
131 | 132 | # CInt8|CInt16|... |
132 | | -$numeric_bits.sort_by {|key, val| -val}.each {|type_name, _| |
133 | | - puts " (\"#{type_name}\", #{type_name})," |
| 133 | +$numeric_bits.sort_by {|key, val| -val}.each {|effect_name, _| |
| 134 | + puts " (\"#{effect_name}\", #{effect_name})," |
134 | 135 | } |
135 | 136 | puts " ];" |
136 | 137 | puts " pub const NumEffectBits: #{$int_label} = #{num_bits}; |
137 | 138 | }" |
138 | 139 |
|
139 | 140 | puts "pub mod effect_sets { |
140 | 141 | use super::*;" |
141 | | -$bits.keys.sort.map {|type_name| |
142 | | - puts " pub const #{type_name}: EffectSet = EffectSet::from_bits(bits::#{type_name});" |
| 142 | +$bits.keys.sort.map {|effect_name| |
| 143 | + puts " pub const #{effect_name}: EffectSet = EffectSet::from_bits(bits::#{effect_name});" |
143 | 144 | } |
144 | 145 | puts "}" |
145 | 146 |
|
146 | 147 |
|
147 | 148 | # puts "pub mod effects { |
148 | 149 | # use super::*;" |
149 | | -# $bits.keys.sort.map {|type_name| |
150 | | -# puts " pub const #{type_name}: EffectSet = EffectSet::from_bits(bits::#{type_name});" |
| 150 | +# $bits.keys.sort.map {|effect_name| |
| 151 | +# puts " pub const #{effect_name}: EffectSet = EffectSet::from_bits(bits::#{effect_name});" |
151 | 152 | # } |
152 | 153 | # puts "}" |
0 commit comments