@@ -353,6 +353,32 @@ static const Node* reinterpret_cast_helper(BodyBuilder* bb, const Node* ptr, con
353
353
return ptr ;
354
354
}
355
355
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
+
356
382
static const Node * _infer_primop (Context * ctx , const Node * node , const Type * expected_type ) {
357
383
assert (node -> tag == PrimOp_TAG );
358
384
IrArena * a = ctx -> rewriter .dst_arena ;
@@ -392,10 +418,7 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp
392
418
assert (type_args .count <= 1 );
393
419
new_operands [0 ] = infer (ctx , old_operands .nodes [0 ], NULL );
394
420
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 ));
399
422
type_args = empty (a );
400
423
}
401
424
goto rebuild ;
@@ -404,13 +427,11 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp
404
427
assert (old_operands .count == 2 );
405
428
assert (type_args .count <= 1 );
406
429
new_operands [0 ] = infer (ctx , old_operands .nodes [0 ], NULL );
407
- const Type * ptr_type = get_unqualified_type (new_operands [0 ]-> type );
408
430
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 ));
412
432
type_args = empty (a );
413
433
}
434
+ const Type * ptr_type = get_unqualified_type (new_operands [0 ]-> type );
414
435
assert (ptr_type -> tag == PtrType_TAG );
415
436
const Type * element_t = ptr_type -> payload .ptr_type .pointed_type ;
416
437
assert (element_t );
@@ -493,7 +514,7 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp
493
514
.operands = new_ops
494
515
})));
495
516
496
- if (was_untyped ) {
517
+ if (was_untyped && is_physical_as ( get_pointer_type_address_space ( src_ptr )) ) {
497
518
const Type * result_t = type_untyped_ptr (base_datatype , unit_type (a ));
498
519
result = gen_reinterpret_cast (bb , result_t , result );
499
520
}
0 commit comments