Skip to content

Commit ed76357

Browse files
committed
revised "node resolving" code
1 parent 14161c6 commit ed76357

File tree

2 files changed

+88
-29
lines changed

2 files changed

+88
-29
lines changed

include/shady/ir.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ String get_value_name_safe(const Node*);
117117
void set_variable_name(Node* var, String);
118118

119119
const Node* get_quoted_value(const Node* instruction);
120-
121120
const IntLiteral* resolve_to_int_literal(const Node* node);
122121
int64_t get_int_literal_value(IntLiteral, bool sign_extend);
123122
const FloatLiteral* resolve_to_float_literal(const Node* node);
@@ -149,6 +148,16 @@ void set_abstraction_body (Node* abs, const Node* body);
149148
const Node* get_let_instruction(const Node* let);
150149
const Node* get_let_tail(const Node* let);
151150

151+
typedef struct {
152+
bool enter_loads;
153+
bool allow_incompatible_types;
154+
bool assume_globals_immutability;
155+
} NodeResolveConfig;
156+
NodeResolveConfig default_node_resolve_config();
157+
const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config);
158+
159+
const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config);
160+
152161
//////////////////////////////// Constructors ////////////////////////////////
153162

154163
/// For typing things that don't return at all

src/shady/node.c

Lines changed: 78 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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

113176
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());
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

122185
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());
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

Comments
 (0)