Skip to content

Commit 0cdb0d6

Browse files
committed
infer: be more lenient about source ptrs in untyped mode
1 parent 2d863a7 commit 0cdb0d6

File tree

1 file changed

+30
-9
lines changed

1 file changed

+30
-9
lines changed

src/shady/passes/infer.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,32 @@ static const Node* reinterpret_cast_helper(BodyBuilder* bb, const Node* ptr, con
353353
return ptr;
354354
}
355355

356+
static void fix_source_pointer(BodyBuilder* bb, const Node** operand, const Type* element_type) {
357+
IrArena* a = element_type->arena;
358+
const Type* original_operand_t = get_unqualified_type((*operand)->type);
359+
assert(original_operand_t->tag == PtrType_TAG);
360+
if (is_physical_ptr_type(original_operand_t)) {
361+
// typed loads - normalise to typed ptrs instead by generating an extra cast!
362+
const Type *ptr_type = original_operand_t;
363+
ptr_type = type_untyped_ptr(ptr_type, element_type);
364+
*operand = reinterpret_cast_helper(bb, *operand, ptr_type);
365+
} else {
366+
// we can't insert a cast but maybe we can make this work
367+
do {
368+
const Type* pointee = get_pointer_type_element(get_unqualified_type((*operand)->type));
369+
if (pointee == element_type)
370+
return;
371+
pointee = get_maybe_nominal_type_body(pointee);
372+
if (pointee->tag == RecordType_TAG) {
373+
*operand = gen_lea(bb, *operand, int32_literal(a, 0), singleton(int32_literal(a, 0)));
374+
continue;
375+
}
376+
// TODO arrays
377+
assert(false);
378+
} while(true);
379+
}
380+
}
381+
356382
static const Node* _infer_primop(Context* ctx, const Node* node, const Type* expected_type) {
357383
assert(node->tag == PrimOp_TAG);
358384
IrArena* a = ctx->rewriter.dst_arena;
@@ -392,10 +418,7 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp
392418
assert(type_args.count <= 1);
393419
new_operands[0] = infer(ctx, old_operands.nodes[0], NULL);
394420
if (type_args.count == 1) {
395-
// typed loads - normalise to typed ptrs instead by generating an extra cast!
396-
const Type* ptr_type = get_unqualified_type(new_operands[0]->type);
397-
ptr_type = type_untyped_ptr(ptr_type, first(type_args));
398-
new_operands[0] = reinterpret_cast_helper(bb, new_operands[0], ptr_type);
421+
fix_source_pointer(bb, &new_operands[0], first(type_args));
399422
type_args = empty(a);
400423
}
401424
goto rebuild;
@@ -404,13 +427,11 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp
404427
assert(old_operands.count == 2);
405428
assert(type_args.count <= 1);
406429
new_operands[0] = infer(ctx, old_operands.nodes[0], NULL);
407-
const Type* ptr_type = get_unqualified_type(new_operands[0]->type);
408430
if (type_args.count == 1) {
409-
// typed loads - normalise to typed ptrs instead by generating an extra cast!
410-
ptr_type = type_untyped_ptr(ptr_type, first(type_args));
411-
new_operands[0] = reinterpret_cast_helper(bb, new_operands[0], ptr_type);
431+
fix_source_pointer(bb, &new_operands[0], first(type_args));
412432
type_args = empty(a);
413433
}
434+
const Type* ptr_type = get_unqualified_type(new_operands[0]->type);
414435
assert(ptr_type->tag == PtrType_TAG);
415436
const Type* element_t = ptr_type->payload.ptr_type.pointed_type;
416437
assert(element_t);
@@ -493,7 +514,7 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp
493514
.operands = new_ops
494515
})));
495516

496-
if (was_untyped) {
517+
if (was_untyped && is_physical_as(get_pointer_type_address_space(src_ptr))) {
497518
const Type* result_t = type_untyped_ptr(base_datatype, unit_type(a));
498519
result = gen_reinterpret_cast(bb, result_t, result);
499520
}

0 commit comments

Comments
 (0)