@@ -87,31 +87,94 @@ const Node* get_quoted_value(const Node* instruction) {
8787 return NULL ;
8888}
8989
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 ;
95110 }
96111 return NULL ;
97112}
98113
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 ;
105128 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+ }
107167 break ;
108- default : return value ;
168+ }
169+ default : break ;
109170 }
171+ break ;
110172 }
173+ return node ;
111174}
112175
113176const IntLiteral * resolve_to_int_literal (const Node * node ) {
114- node = resolve_value (node );
177+ node = resolve_node_to_definition (node , default_node_resolve_config () );
115178 if (!node )
116179 return NULL ;
117180 if (node -> tag == IntLiteral_TAG )
@@ -120,7 +183,7 @@ const IntLiteral* resolve_to_int_literal(const Node* node) {
120183}
121184
122185const FloatLiteral * resolve_to_float_literal (const Node * node ) {
123- node = resolve_value (node );
186+ node = resolve_node_to_definition (node , default_node_resolve_config () );
124187 if (!node )
125188 return NULL ;
126189 if (node -> tag == FloatLiteral_TAG )
@@ -139,19 +202,6 @@ const char* get_string_literal(IrArena* arena, const Node* node) {
139202 if (!node )
140203 return NULL ;
141204 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- }
155205 case PrimOp_TAG : {
156206 switch (node -> payload .prim_op .op ) {
157207 case lea_op : {
0 commit comments