@@ -87,31 +87,94 @@ const Node* get_quoted_value(const Node* instruction) {
87
87
return NULL ;
88
88
}
89
89
90
- const Node * resolve_decl (const Node * decl ) {
91
- switch (decl -> tag ) {
92
- case Constant_TAG : return get_quoted_value (decl -> payload .constant .instruction );
93
- case GlobalVariable_TAG : /* TODO: when adding immutable globals */
94
- default : break ;
90
+ const Node * resolve_ptr_to_value (const Node * ptr , NodeResolveConfig config ) {
91
+ while (ptr ) {
92
+ ptr = resolve_node_to_definition (ptr , config );
93
+ switch (ptr -> tag ) {
94
+ case PrimOp_TAG : {
95
+ switch (ptr -> payload .prim_op .op ) {
96
+ case convert_op : { // allow address space conversions
97
+ ptr = first (ptr -> payload .prim_op .operands );
98
+ continue ;
99
+ }
100
+ default : break ;
101
+ }
102
+ }
103
+ case GlobalVariable_TAG :
104
+ if (config .assume_globals_immutability )
105
+ return ptr -> payload .global_variable .init ;
106
+ break ;
107
+ default : break ;
108
+ }
109
+ ptr = NULL ;
95
110
}
96
111
return NULL ;
97
112
}
98
113
99
- const Node * resolve_value (const Node * value ) {
100
- while (true) {
101
- if (!value )
102
- return NULL ;
103
- assert (is_value (value ));
104
- switch (value -> tag ) {
114
+ NodeResolveConfig default_node_resolve_config () {
115
+ return (NodeResolveConfig ) {
116
+ .enter_loads = true,
117
+ .allow_incompatible_types = false,
118
+ .assume_globals_immutability = false,
119
+ };
120
+ }
121
+
122
+ const Node * resolve_node_to_definition (const Node * node , NodeResolveConfig config ) {
123
+ while (node ) {
124
+ switch (node -> tag ) {
125
+ case Constant_TAG :
126
+ node = node -> payload .constant .instruction ;
127
+ continue ;
105
128
case RefDecl_TAG :
106
- value = resolve_decl (value -> payload .ref_decl .decl );
129
+ node = node -> payload .ref_decl .decl ;
130
+ continue ;
131
+ case Variable_TAG : {
132
+ if (node -> payload .var .pindex != 0 )
133
+ break ;
134
+ const Node * abs = node -> payload .var .abs ;
135
+ if (!abs || abs -> tag != Case_TAG )
136
+ break ;
137
+ const Node * user = abs -> payload .case_ .structured_construct ;
138
+ if (user -> tag != Let_TAG )
139
+ break ;
140
+ node = user -> payload .let .instruction ;
141
+ continue ;
142
+ }
143
+ case PrimOp_TAG : {
144
+ switch (node -> payload .prim_op .op ) {
145
+ case quote_op : {
146
+ node = first (node -> payload .prim_op .operands );;
147
+ continue ;
148
+ }
149
+ case load_op : {
150
+ if (config .enter_loads ) {
151
+ const Node * source = first (node -> payload .prim_op .operands );
152
+ const Node * result = resolve_ptr_to_value (source , config );
153
+ if (!result )
154
+ break ;
155
+ node = result ;
156
+ continue ;
157
+ }
158
+ }
159
+ case reinterpret_op : {
160
+ if (config .allow_incompatible_types ) {
161
+ node = first (node -> payload .prim_op .operands );
162
+ continue ;
163
+ }
164
+ }
165
+ default : break ;
166
+ }
107
167
break ;
108
- default : return value ;
168
+ }
169
+ default : break ;
109
170
}
171
+ break ;
110
172
}
173
+ return node ;
111
174
}
112
175
113
176
const IntLiteral * resolve_to_int_literal (const Node * node ) {
114
- node = resolve_value (node );
177
+ node = resolve_node_to_definition (node , default_node_resolve_config () );
115
178
if (!node )
116
179
return NULL ;
117
180
if (node -> tag == IntLiteral_TAG )
@@ -120,7 +183,7 @@ const IntLiteral* resolve_to_int_literal(const Node* node) {
120
183
}
121
184
122
185
const FloatLiteral * resolve_to_float_literal (const Node * node ) {
123
- node = resolve_value (node );
186
+ node = resolve_node_to_definition (node , default_node_resolve_config () );
124
187
if (!node )
125
188
return NULL ;
126
189
if (node -> tag == FloatLiteral_TAG )
@@ -139,19 +202,6 @@ const char* get_string_literal(IrArena* arena, const Node* node) {
139
202
if (!node )
140
203
return NULL ;
141
204
switch (node -> tag ) {
142
- case Constant_TAG : return get_string_literal (arena , get_quoted_value (node -> payload .constant .instruction ));
143
- case RefDecl_TAG : return get_string_literal (arena , node -> payload .ref_decl .decl );
144
- case Variable_TAG : {
145
- if (node -> payload .var .pindex != 0 )
146
- return NULL ;
147
- const Node * abs = node -> payload .var .abs ;
148
- if (!abs || abs -> tag != Case_TAG )
149
- return NULL ;
150
- const Node * user = abs -> payload .case_ .structured_construct ;
151
- if (user -> tag != Let_TAG )
152
- return NULL ;
153
- return get_string_literal (arena , user -> payload .let .instruction );
154
- }
155
205
case PrimOp_TAG : {
156
206
switch (node -> payload .prim_op .op ) {
157
207
case lea_op : {
0 commit comments