@@ -227,7 +227,8 @@ impl<'ctx> LLVMBackend<'ctx> {
227227 // Clear block, value, and phi maps for this function
228228 self . block_map . clear ( ) ;
229229 self . phi_map . clear ( ) ;
230- // Note: We keep function parameters in value_map from declare_function
230+ self . value_map . clear ( ) ; // Clear value_map between functions
231+ self . type_map . clear ( ) ; // Clear type_map between functions
231232
232233 // Map function parameters to HIR value IDs and store their types
233234 for ( i, param) in func. signature . params . iter ( ) . enumerate ( ) {
@@ -236,13 +237,21 @@ impl<'ctx> LLVMBackend<'ctx> {
236237 self . type_map . insert ( param. id , param. ty . clone ( ) ) ;
237238 }
238239
239- // Map constant values and special instruction values to LLVM values
240+ // Map constant values, parameters, and special instruction values to LLVM values
240241 for ( value_id, value) in & func. values {
241242 match & value. kind {
242243 HirValueKind :: Constant ( constant) => {
243244 let llvm_constant = self . compile_constant ( constant) ?;
244245 self . value_map . insert ( * value_id, llvm_constant) ;
245246 }
247+ HirValueKind :: Parameter ( param_index) => {
248+ // SSA creates new value IDs for parameters with HirValueKind::Parameter
249+ // Map these to the actual LLVM function parameters
250+ if let Some ( param_value) = fn_value. get_nth_param ( * param_index) {
251+ self . value_map . insert ( * value_id, param_value) ;
252+ self . type_map . insert ( * value_id, value. ty . clone ( ) ) ;
253+ }
254+ }
246255 HirValueKind :: Instruction => {
247256 // For instruction values that appear in func.values (like undef structs),
248257 // create an undef value of the appropriate type
@@ -671,6 +680,8 @@ impl<'ctx> LLVMBackend<'ctx> {
671680 self . builder . build_alloca ( llvm_ty, "alloca" ) ?
672681 } ;
673682 self . value_map . insert ( * result, alloca. into ( ) ) ;
683+ // Record the type as a pointer to the allocated type
684+ self . type_map . insert ( * result, HirType :: Ptr ( Box :: new ( ty. clone ( ) ) ) ) ;
674685 }
675686
676687 HirInstruction :: GetElementPtr { result, ty, ptr, indices } => {
@@ -697,7 +708,7 @@ impl<'ctx> LLVMBackend<'ctx> {
697708
698709 // ========== Aggregate Operations ==========
699710 HirInstruction :: ExtractValue { result, ty, aggregate, indices } => {
700- let mut current_value = self . get_value ( * aggregate) ?;
711+ let agg_value = self . get_value ( * aggregate) ?;
701712
702713 // Extract value from struct or array using chained extraction
703714 // LLVM's build_extract_value only takes a single index, so we need to
@@ -708,43 +719,95 @@ impl<'ctx> LLVMBackend<'ctx> {
708719 ) ) ;
709720 }
710721
711- // Apply each index in sequence for nested extraction
712- for ( i, & index) in indices. iter ( ) . enumerate ( ) {
713- let is_last = i == indices. len ( ) - 1 ;
714- let name = if is_last {
715- "extract"
722+ // Check if aggregate is a pointer (e.g., from Alloca)
723+ // In this case, we use GEP + Load instead of ExtractValue
724+ if agg_value. is_pointer_value ( ) {
725+ // ty is the result type (the field type), not the aggregate type
726+ // We need to get the aggregate type from the HIR value info
727+ let result_ty = self . translate_type ( ty) ?;
728+ let ptr = agg_value. into_pointer_value ( ) ;
729+
730+ // For pointer-based struct access, we need the aggregate type.
731+ // We can get this from the instruction that produced the pointer.
732+ // For now, get it from the type_map
733+ let agg_hir_type = self . type_map . get ( aggregate) . cloned ( ) ;
734+
735+ let pointee_type = if let Some ( HirType :: Ptr ( inner) ) = agg_hir_type {
736+ self . translate_type ( & inner) ?
737+ } else if let Some ( hir_ty) = agg_hir_type {
738+ // If it's not a pointer type in HIR but is a pointer value,
739+ // the type might already be the struct type
740+ self . translate_type ( & hir_ty) ?
716741 } else {
717- & format ! ( "extract_nested_{}" , i)
742+ // Fallback: try to infer from the result type
743+ // This won't work correctly, but provides a fallback
744+ result_ty
718745 } ;
719746
720- // Try to extract from struct
721- if let Ok ( struct_val) = TryInto :: < inkwell:: values:: StructValue > :: try_into ( current_value) {
722- let extracted = self . builder . build_extract_value (
723- struct_val,
724- index,
725- name
726- ) ?;
727- current_value = extracted. as_basic_value_enum ( ) ;
728- } else if let Ok ( array_val) = TryInto :: < inkwell:: values:: ArrayValue > :: try_into ( current_value) {
729- // For arrays, we can also use extract_value
730- let extracted = self . builder . build_extract_value (
731- array_val,
732- index,
733- name
734- ) ?;
735- current_value = extracted. as_basic_value_enum ( ) ;
736- } else {
737- return Err ( CompilerError :: CodeGen (
738- format ! ( "ExtractValue can only be used on struct or array types, got: {:?}" , current_value. get_type( ) )
739- ) ) ;
747+ // Build GEP indices: first index is always 0 to dereference the pointer
748+ // then follow with the struct field indices
749+ let mut gep_indices: Vec < inkwell:: values:: IntValue > = vec ! [
750+ self . context. i32_type( ) . const_int( 0 , false )
751+ ] ;
752+ for & idx in indices {
753+ gep_indices. push ( self . context . i32_type ( ) . const_int ( idx as u64 , false ) ) ;
740754 }
741- }
742755
743- self . value_map . insert ( * result, current_value) ;
756+ // GEP to get address of the field
757+ let field_ptr = unsafe {
758+ self . builder . build_gep (
759+ pointee_type,
760+ ptr,
761+ & gep_indices,
762+ "field_ptr"
763+ ) ?
764+ } ;
765+
766+ // Load the field value using the result type
767+ let loaded = self . builder . build_load ( result_ty, field_ptr, "field_load" ) ?;
768+ self . value_map . insert ( * result, loaded) ;
769+ } else {
770+ // Original behavior: work on value types
771+ let mut current_value = agg_value;
772+
773+ // Apply each index in sequence for nested extraction
774+ for ( i, & index) in indices. iter ( ) . enumerate ( ) {
775+ let is_last = i == indices. len ( ) - 1 ;
776+ let name = if is_last {
777+ "extract"
778+ } else {
779+ & format ! ( "extract_nested_{}" , i)
780+ } ;
781+
782+ // Try to extract from struct
783+ if let Ok ( struct_val) = TryInto :: < inkwell:: values:: StructValue > :: try_into ( current_value) {
784+ let extracted = self . builder . build_extract_value (
785+ struct_val,
786+ index,
787+ name
788+ ) ?;
789+ current_value = extracted. as_basic_value_enum ( ) ;
790+ } else if let Ok ( array_val) = TryInto :: < inkwell:: values:: ArrayValue > :: try_into ( current_value) {
791+ // For arrays, we can also use extract_value
792+ let extracted = self . builder . build_extract_value (
793+ array_val,
794+ index,
795+ name
796+ ) ?;
797+ current_value = extracted. as_basic_value_enum ( ) ;
798+ } else {
799+ return Err ( CompilerError :: CodeGen (
800+ format ! ( "ExtractValue can only be used on struct or array types, got: {:?}" , current_value. get_type( ) )
801+ ) ) ;
802+ }
803+ }
804+
805+ self . value_map . insert ( * result, current_value) ;
806+ }
744807 }
745808
746809 HirInstruction :: InsertValue { result, ty, aggregate, value, indices } => {
747- let mut current_agg = self . get_value ( * aggregate) ?;
810+ let current_agg = self . get_value ( * aggregate) ?;
748811 let val = self . get_value ( * value) ?;
749812
750813 if indices. is_empty ( ) {
@@ -753,12 +816,38 @@ impl<'ctx> LLVMBackend<'ctx> {
753816 ) ) ;
754817 }
755818
756- // For nested insertion, we need to:
757- // 1. Extract the nested aggregate at indices[0..n-1]
758- // 2. Insert value at the final index
759- // 3. Insert the modified nested aggregate back
760- if indices. len ( ) == 1 {
761- // Simple case: single-level insertion
819+ // Check if aggregate is a pointer (e.g., from Alloca)
820+ // In this case, we use GEP + Store instead of InsertValue
821+ if current_agg. is_pointer_value ( ) {
822+ let llvm_ty = self . translate_type ( ty) ?;
823+ let ptr = current_agg. into_pointer_value ( ) ;
824+
825+ // Build GEP indices: first index is always 0 to dereference the pointer
826+ // then follow with the struct field indices
827+ let mut gep_indices: Vec < inkwell:: values:: IntValue > = vec ! [
828+ self . context. i32_type( ) . const_int( 0 , false )
829+ ] ;
830+ for & idx in indices {
831+ gep_indices. push ( self . context . i32_type ( ) . const_int ( idx as u64 , false ) ) ;
832+ }
833+
834+ // GEP to get address of the field
835+ let field_ptr = unsafe {
836+ self . builder . build_gep (
837+ llvm_ty,
838+ ptr,
839+ & gep_indices,
840+ "field_ptr"
841+ ) ?
842+ } ;
843+
844+ // Store the value
845+ self . builder . build_store ( field_ptr, val) ?;
846+
847+ // The result is the original pointer (for chaining)
848+ self . value_map . insert ( * result, current_agg) ;
849+ } else if indices. len ( ) == 1 {
850+ // Simple case: single-level insertion on a value
762851 let inserted = if let Ok ( struct_val) = TryInto :: < inkwell:: values:: StructValue > :: try_into ( current_agg) {
763852 self . builder . build_insert_value (
764853 struct_val,
0 commit comments