|
| 1 | +#include <stdio.h> |
1 | 2 | #include <stdlib.h> |
2 | 3 |
|
3 | 4 | #include "llvm.h" |
@@ -719,8 +720,6 @@ LLVMValueRef codegen_expr_assignment(CodeGenContext *ctx, AstNode *node) { |
719 | 720 | // Final fallback: use value type |
720 | 721 | if (!element_type) { |
721 | 722 | element_type = value_type; |
722 | | - fprintf(stderr, "Warning: Could not determine pointer element type, " |
723 | | - "using value type\n"); |
724 | 723 | } |
725 | 724 |
|
726 | 725 | // Convert value to match element type if needed |
@@ -948,6 +947,165 @@ LLVMValueRef codegen_expr_index(CodeGenContext *ctx, AstNode *node) { |
948 | 947 | return NULL; |
949 | 948 | } |
950 | 949 |
|
| 950 | + // **NEW: Special handling for indexing member access (struct.field[index])** |
| 951 | + if (node->expr.index.object->type == AST_EXPR_MEMBER) { |
| 952 | + AstNode *member_expr = node->expr.index.object; |
| 953 | + const char *field_name = member_expr->expr.member.member; |
| 954 | + |
| 955 | + // Generate the member access to get the pointer |
| 956 | + LLVMValueRef pointer = codegen_expr_struct_access(ctx, member_expr); |
| 957 | + if (!pointer) { |
| 958 | + fprintf(stderr, "Error: Failed to resolve member access for indexing\n"); |
| 959 | + return NULL; |
| 960 | + } |
| 961 | + |
| 962 | + // Generate the index expression |
| 963 | + LLVMValueRef index = codegen_expr(ctx, node->expr.index.index); |
| 964 | + if (!index) { |
| 965 | + return NULL; |
| 966 | + } |
| 967 | + |
| 968 | + LLVMTypeRef pointer_type = LLVMTypeOf(pointer); |
| 969 | + LLVMTypeKind pointer_kind = LLVMGetTypeKind(pointer_type); |
| 970 | + |
| 971 | + // The member access should have returned a pointer |
| 972 | + if (pointer_kind != LLVMPointerTypeKind) { |
| 973 | + fprintf(stderr, "Error: Member '%s' is not a pointer type for indexing\n", |
| 974 | + field_name); |
| 975 | + return NULL; |
| 976 | + } |
| 977 | + |
| 978 | + // Find the struct that contains this field to get element type info |
| 979 | + LLVMTypeRef element_type = NULL; |
| 980 | + |
| 981 | + // Build a list of field names in the chain (in reverse order) |
| 982 | + const char *field_chain[32]; |
| 983 | + int chain_length = 0; |
| 984 | + AstNode *current_node = member_expr; |
| 985 | + |
| 986 | + while (current_node && current_node->type == AST_EXPR_MEMBER && |
| 987 | + chain_length < 32) { |
| 988 | + field_chain[chain_length++] = current_node->expr.member.member; |
| 989 | + current_node = current_node->expr.member.object; |
| 990 | + } |
| 991 | + |
| 992 | + // Reverse the chain to get the correct order |
| 993 | + for (int i = 0; i < chain_length / 2; i++) { |
| 994 | + const char *temp = field_chain[i]; |
| 995 | + field_chain[i] = field_chain[chain_length - 1 - i]; |
| 996 | + field_chain[chain_length - 1 - i] = temp; |
| 997 | + } |
| 998 | + |
| 999 | + // Find the base identifier |
| 1000 | + AstNode *base_obj = member_expr->expr.member.object; |
| 1001 | + while (base_obj->type == AST_EXPR_MEMBER) { |
| 1002 | + base_obj = base_obj->expr.member.object; |
| 1003 | + } |
| 1004 | + |
| 1005 | + if (base_obj->type == AST_EXPR_IDENTIFIER) { |
| 1006 | + const char *base_name = base_obj->expr.identifier.name; |
| 1007 | + LLVM_Symbol *base_sym = find_symbol(ctx, base_name); |
| 1008 | + |
| 1009 | + if (base_sym) { |
| 1010 | + // Find the initial struct type |
| 1011 | + StructInfo *current_struct = NULL; |
| 1012 | + LLVMTypeRef sym_type = base_sym->type; |
| 1013 | + LLVMTypeKind sym_kind = LLVMGetTypeKind(sym_type); |
| 1014 | + |
| 1015 | + if (sym_kind == LLVMPointerTypeKind && base_sym->element_type) { |
| 1016 | + // It's a pointer to struct |
| 1017 | + for (StructInfo *info = ctx->struct_types; info; info = info->next) { |
| 1018 | + if (info->llvm_type == base_sym->element_type) { |
| 1019 | + current_struct = info; |
| 1020 | + break; |
| 1021 | + } |
| 1022 | + } |
| 1023 | + } else if (sym_kind == LLVMStructTypeKind) { |
| 1024 | + // Direct struct type |
| 1025 | + for (StructInfo *info = ctx->struct_types; info; info = info->next) { |
| 1026 | + if (info->llvm_type == sym_type) { |
| 1027 | + current_struct = info; |
| 1028 | + break; |
| 1029 | + } |
| 1030 | + } |
| 1031 | + } |
| 1032 | + |
| 1033 | + // Trace through the field chain |
| 1034 | + for (int i = 0; i < chain_length && current_struct; i++) { |
| 1035 | + const char *current_field_name = field_chain[i]; |
| 1036 | + int field_idx = get_field_index(current_struct, current_field_name); |
| 1037 | + |
| 1038 | + if (field_idx < 0) { |
| 1039 | + fprintf(stderr, "Error: Field '%s' not found in struct '%s'\n", |
| 1040 | + current_field_name, current_struct->name); |
| 1041 | + break; |
| 1042 | + } |
| 1043 | + |
| 1044 | + // If this is the last field in the chain, get its element type |
| 1045 | + if (i == chain_length - 1) { |
| 1046 | + element_type = current_struct->field_element_types[field_idx]; |
| 1047 | + break; |
| 1048 | + } |
| 1049 | + |
| 1050 | + // Otherwise, move to the next struct in the chain |
| 1051 | + LLVMTypeRef field_type = current_struct->field_types[field_idx]; |
| 1052 | + LLVMTypeKind field_kind = LLVMGetTypeKind(field_type); |
| 1053 | + |
| 1054 | + if (field_kind == LLVMStructTypeKind) { |
| 1055 | + // Field is a struct - find its info |
| 1056 | + StructInfo *next_struct = NULL; |
| 1057 | + for (StructInfo *info = ctx->struct_types; info; |
| 1058 | + info = info->next) { |
| 1059 | + if (info->llvm_type == field_type) { |
| 1060 | + next_struct = info; |
| 1061 | + break; |
| 1062 | + } |
| 1063 | + } |
| 1064 | + current_struct = next_struct; |
| 1065 | + } else if (field_kind == LLVMPointerTypeKind) { |
| 1066 | + // Field is a pointer - get what it points to |
| 1067 | + LLVMTypeRef pointee = |
| 1068 | + current_struct->field_element_types[field_idx]; |
| 1069 | + if (pointee && LLVMGetTypeKind(pointee) == LLVMStructTypeKind) { |
| 1070 | + // Find the struct info for the pointee |
| 1071 | + StructInfo *next_struct = NULL; |
| 1072 | + for (StructInfo *info = ctx->struct_types; info; |
| 1073 | + info = info->next) { |
| 1074 | + if (info->llvm_type == pointee) { |
| 1075 | + next_struct = info; |
| 1076 | + break; |
| 1077 | + } |
| 1078 | + } |
| 1079 | + current_struct = next_struct; |
| 1080 | + } else { |
| 1081 | + // Not a struct pointer, can't continue |
| 1082 | + break; |
| 1083 | + } |
| 1084 | + } else { |
| 1085 | + // Field is not a struct or pointer, can't continue |
| 1086 | + break; |
| 1087 | + } |
| 1088 | + } |
| 1089 | + } |
| 1090 | + } |
| 1091 | + |
| 1092 | + if (!element_type) { |
| 1093 | + fprintf( |
| 1094 | + stderr, |
| 1095 | + "Error: Could not determine pointer element type for indexing '%s'\n", |
| 1096 | + field_name); |
| 1097 | + return NULL; |
| 1098 | + } |
| 1099 | + |
| 1100 | + // Build GEP for pointer arithmetic |
| 1101 | + LLVMValueRef element_ptr = LLVMBuildGEP2( |
| 1102 | + ctx->builder, element_type, pointer, &index, 1, "member_ptr_element"); |
| 1103 | + |
| 1104 | + // Load the actual value |
| 1105 | + return LLVMBuildLoad2(ctx->builder, element_type, element_ptr, |
| 1106 | + "member_element_val"); |
| 1107 | + } |
| 1108 | + |
951 | 1109 | // Generate the object being indexed |
952 | 1110 | LLVMValueRef object = codegen_expr(ctx, node->expr.index.object); |
953 | 1111 | if (!object) { |
@@ -1081,53 +1239,6 @@ LLVMValueRef codegen_expr_index(CodeGenContext *ctx, AstNode *node) { |
1081 | 1239 | cast_node->expr.cast.type->type_data.pointer.pointee_type; |
1082 | 1240 | pointee_type = codegen_type(ctx, pointee_node); |
1083 | 1241 | } |
1084 | | - } else if (node->expr.index.object->type == AST_EXPR_MEMBER) { |
1085 | | - AstNode *member_expr = node->expr.index.object; |
1086 | | - const char *field_name = member_expr->expr.member.member; |
1087 | | - |
1088 | | - // Need to get the base object to find which struct this field belongs to |
1089 | | - AstNode *base_obj = member_expr->expr.member.object; |
1090 | | - |
1091 | | - if (base_obj->type == AST_EXPR_IDENTIFIER) { |
1092 | | - const char *base_name = base_obj->expr.identifier.name; |
1093 | | - LLVM_Symbol *base_sym = find_symbol(ctx, base_name); |
1094 | | - |
1095 | | - if (base_sym) { |
1096 | | - // Determine the struct type |
1097 | | - LLVMTypeRef base_type = base_sym->type; |
1098 | | - StructInfo *struct_info = NULL; |
1099 | | - |
1100 | | - // If base is a pointer to struct, get the pointee type |
1101 | | - if (LLVMGetTypeKind(base_type) == LLVMPointerTypeKind && |
1102 | | - base_sym->element_type) { |
1103 | | - // Find struct info by its LLVM type |
1104 | | - for (StructInfo *info = ctx->struct_types; info; |
1105 | | - info = info->next) { |
1106 | | - if (info->llvm_type == base_sym->element_type) { |
1107 | | - struct_info = info; |
1108 | | - break; |
1109 | | - } |
1110 | | - } |
1111 | | - } else { |
1112 | | - // Direct struct type |
1113 | | - for (StructInfo *info = ctx->struct_types; info; |
1114 | | - info = info->next) { |
1115 | | - if (info->llvm_type == base_type) { |
1116 | | - struct_info = info; |
1117 | | - break; |
1118 | | - } |
1119 | | - } |
1120 | | - } |
1121 | | - |
1122 | | - if (struct_info) { |
1123 | | - int field_idx = get_field_index(struct_info, field_name); |
1124 | | - if (field_idx >= 0) { |
1125 | | - // Use the element type stored for this field |
1126 | | - pointee_type = struct_info->field_element_types[field_idx]; |
1127 | | - } |
1128 | | - } |
1129 | | - } |
1130 | | - } |
1131 | 1242 | } |
1132 | 1243 |
|
1133 | 1244 | // CRITICAL: Don't fall back to i8! This causes the bug. |
|
0 commit comments