@@ -430,11 +430,69 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
430
430
431
431
fn load ( & mut self , ty : & ' ll Type , ptr : & ' ll Value , align : Align ) -> & ' ll Value {
432
432
trace ! ( "Load {ty:?} {:?}" , ptr) ;
433
- let ptr = self . pointercast ( ptr, self . cx . type_ptr_to ( ty) ) ;
433
+ // `ty` is the LLVM type of the data we want to load from memory (e.g., i64).
434
+ // `ptr` is the LLVM value representing the memory address (e.g., could be an
435
+ // i8* or already an i64*).
436
+
437
+ let original_ptr_llty = self . cx . val_ty ( ptr) ;
438
+
439
+ // For LLVMBuildLoad in LLVM 7, the pointer operand must be PointeeType*, and
440
+ // PointeeType is what will be loaded. So, `ptr` must be cast to `ty*`.
441
+ let required_ptr_llty_for_load = self . cx . type_ptr_to ( ty) ;
442
+
443
+ trace ! (
444
+ "Builder::load: Type to load: {:?}, Original ptr type: {:?}, Required ptr type for load: {:?}, align={:?}" ,
445
+ ty,
446
+ original_ptr_llty,
447
+ required_ptr_llty_for_load,
448
+ align. bytes( )
449
+ ) ;
450
+
451
+ // Sanity check: ptr must be a pointer type.
452
+ assert_eq ! (
453
+ self . cx. type_kind( original_ptr_llty) ,
454
+ TypeKind :: Pointer ,
455
+ "Attempting to load from a non-pointer LLVM value. Original type: {:?}. Required load type: {:?}" ,
456
+ original_ptr_llty,
457
+ ty
458
+ ) ;
459
+
460
+ let final_ptr_for_llvm_load = if original_ptr_llty == required_ptr_llty_for_load {
461
+ // The pointer is already correctly typed (e.g., loading i64 from an i64*).
462
+ ptr
463
+ } else {
464
+ // The pointer type needs adjustment (e.g., ptr is an i8*, but we need to load an i64).
465
+ // We must bitcast ptr to required_ptr_llty_for_load (e.g., i64*).
466
+ debug ! (
467
+ "Builder::load: Pointer type mismatch. \
468
+ Type to load: {:?}, Original pointer type: {:?}, Required pointer type for load: {:?}. \
469
+ Injecting bitcast for pointer operand.",
470
+ ty, original_ptr_llty, required_ptr_llty_for_load
471
+ ) ;
472
+ self . bitcast ( ptr, required_ptr_llty_for_load)
473
+ } ;
474
+
475
+ // Now, final_ptr_for_llvm_load is guaranteed to be of type `ty*`.
476
+ // The LLVM 7 `LLVMBuildLoad` C-API infers the type of the value to be loaded
477
+ // from the pointee type of its pointer argument.
434
478
unsafe {
435
- let load = llvm:: LLVMBuildLoad ( self . llbuilder , ptr, UNNAMED ) ;
436
- llvm:: LLVMSetAlignment ( load, align. bytes ( ) as c_uint ) ;
437
- load
479
+ let load_instr = llvm:: LLVMBuildLoad ( self . llbuilder , final_ptr_for_llvm_load, UNNAMED ) ;
480
+
481
+ // Sanity check: the type of the loaded value should match `ty`.
482
+ let actual_loaded_llty = self . cx . val_ty ( load_instr) ;
483
+ if actual_loaded_llty != ty {
484
+ bug ! (
485
+ "Builder::load: LLVMBuildLoad produced a value of type ({:?}) which does not match the expected `ty` parameter ({:?}). \
486
+ Pointer type passed to LLVMBuildLoad was: {:?}, after casting from original: {:?}.",
487
+ actual_loaded_llty,
488
+ ty,
489
+ final_ptr_for_llvm_load,
490
+ original_ptr_llty
491
+ ) ;
492
+ }
493
+
494
+ llvm:: LLVMSetAlignment ( load_instr, align. bytes ( ) as c_uint ) ;
495
+ load_instr
438
496
}
439
497
}
440
498
0 commit comments