Skip to content

Commit 12f714d

Browse files
author
TheDevConnor
committed
fixed some minor issues with 2d matrix accessing for bytes not fully fixed for very large inputs
1 parent 159c8fc commit 12f714d

2 files changed

Lines changed: 142 additions & 47 deletions

File tree

src/helper/help.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
/** Enable debug logs for arena allocator (comment to disable) */
2929
#define DEBUG_ARENA_ALLOC 1
3030

31-
#define Luma_Compiler_version "v0.1.2"
31+
#define Luma_Compiler_version "v0.1.3"
3232

3333
/** Error codes returned by the compiler */
3434
typedef enum {

src/llvm/expr.c

Lines changed: 141 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,16 @@ LLVMValueRef codegen_expr_assignment(CodeGenContext *ctx, AstNode *node) {
600600
if (target->type == AST_EXPR_IDENTIFIER) {
601601
LLVM_Symbol *sym = find_symbol(ctx, target->expr.identifier.name);
602602
if (sym && !sym->is_function) {
603+
// NEW: If assigning a cast expression, update element type
604+
if (node->expr.assignment.value->type == AST_EXPR_CAST) {
605+
AstNode *cast_node = node->expr.assignment.value;
606+
LLVMTypeRef new_element_type =
607+
extract_element_type_from_ast(ctx, cast_node->expr.cast.type);
608+
if (new_element_type) {
609+
sym->element_type = new_element_type;
610+
}
611+
}
612+
603613
LLVMBuildStore(ctx->builder, value, sym->value);
604614
return value;
605615
}
@@ -874,7 +884,8 @@ LLVMValueRef codegen_expr_array(CodeGenContext *ctx, AstNode *node) {
874884

875885
AstNode **elements = node->expr.array.elements;
876886
size_t element_count = node->expr.array.element_count;
877-
size_t target_size = node->expr.array.target_size; // NEW: Get target size for padding
887+
size_t target_size =
888+
node->expr.array.target_size; // NEW: Get target size for padding
878889

879890
if (element_count == 0) {
880891
fprintf(stderr, "Error: Empty array literals not supported\n");
@@ -889,17 +900,19 @@ LLVMValueRef codegen_expr_array(CodeGenContext *ctx, AstNode *node) {
889900
}
890901

891902
LLVMTypeRef element_type = LLVMTypeOf(first_element);
892-
893-
// NEW: Use target_size if set (for padding), otherwise use actual element_count
903+
904+
// NEW: Use target_size if set (for padding), otherwise use actual
905+
// element_count
894906
size_t actual_array_size = (target_size > 0) ? target_size : element_count;
895907
LLVMTypeRef array_type = LLVMArrayType(element_type, actual_array_size);
896908

897909
// Check if all elements are constants
898910
bool all_constants = LLVMIsConstant(first_element);
899-
911+
900912
// NEW: Allocate for the FULL size (including padding)
901913
LLVMValueRef *element_values = (LLVMValueRef *)arena_alloc(
902-
ctx->arena, sizeof(LLVMValueRef) * actual_array_size, alignof(LLVMValueRef));
914+
ctx->arena, sizeof(LLVMValueRef) * actual_array_size,
915+
alignof(LLVMValueRef));
903916

904917
element_values[0] = first_element;
905918

@@ -931,11 +944,11 @@ LLVMValueRef codegen_expr_array(CodeGenContext *ctx, AstNode *node) {
931944
// NEW: Pad remaining elements with zeros if target_size > element_count
932945
if (target_size > element_count) {
933946
LLVMValueRef zero_value = LLVMConstNull(element_type);
934-
947+
935948
for (size_t i = element_count; i < target_size; i++) {
936949
element_values[i] = zero_value;
937950
}
938-
951+
939952
// If we're padding, we can't be all constants unless zeros count
940953
// (which they do, so keep checking)
941954
// zero_value is always constant, so all_constants remains unchanged
@@ -1172,25 +1185,31 @@ LLVMValueRef codegen_expr_index(CodeGenContext *ctx, AstNode *node) {
11721185
// Direct array value indexing (from array literals)
11731186
LLVMTypeRef element_type = LLVMGetElementType(object_type);
11741187

1175-
// We need to store the array and get a pointer to it for GEP
1188+
// Allocate with proper alignment for the array type
11761189
LLVMValueRef array_alloca =
11771190
LLVMBuildAlloca(ctx->builder, object_type, "temp_array");
1178-
LLVMBuildStore(ctx->builder, object, array_alloca);
11791191

1180-
// Create GEP indices: [0, index] for array access
1192+
// Store with proper alignment - CRITICAL for i64 arrays!
1193+
LLVMValueRef store_inst =
1194+
LLVMBuildStore(ctx->builder, object, array_alloca);
1195+
// For i64 arrays, we need 8-byte alignment
1196+
LLVMSetAlignment(store_inst, 8);
1197+
1198+
// Use InBoundsGEP for safety
11811199
LLVMValueRef indices[2];
11821200
indices[0] = LLVMConstInt(LLVMInt32TypeInContext(ctx->context), 0, false);
11831201
indices[1] = index;
11841202

11851203
LLVMValueRef element_ptr =
1186-
LLVMBuildGEP2(ctx->builder, object_type, array_alloca, indices, 2,
1187-
"array_element_ptr");
1204+
LLVMBuildInBoundsGEP2(ctx->builder, object_type, array_alloca, indices,
1205+
2, "array_element_ptr");
11881206

1189-
// CRITICAL FIX: Always load the element value
1190-
// If it's an inner array, load it so the next indexing operation
1191-
// receives an array value (not a pointer)
1192-
return LLVMBuildLoad2(ctx->builder, element_type, element_ptr,
1193-
"array_element");
1207+
// Load with proper alignment
1208+
LLVMValueRef load_inst = LLVMBuildLoad2(ctx->builder, element_type,
1209+
element_ptr, "array_element");
1210+
LLVMSetAlignment(load_inst, 8);
1211+
1212+
return load_inst;
11941213

11951214
} else if (object_kind == LLVMPointerTypeKind) {
11961215
// Handle pointer indexing - check if it's a symbol first for better type
@@ -1241,38 +1260,114 @@ LLVMValueRef codegen_expr_index(CodeGenContext *ctx, AstNode *node) {
12411260
}
12421261
}
12431262
} else if (node->expr.index.object->type == AST_EXPR_INDEX) {
1244-
// Second-level indexing: ptr[i][j]
1245-
// Trace back to find the base variable
1246-
AstNode *base_node = node->expr.index.object;
1247-
while (base_node->type == AST_EXPR_INDEX) {
1248-
base_node = base_node->expr.index.object;
1263+
// Second-level indexing: either arr[i][j] for arrays OR ptr[i][j] for
1264+
// pointers We need to handle these differently!
1265+
1266+
// First, let's check what the FIRST indexing returns
1267+
// Generate it to see if we get an array value or a pointer
1268+
LLVMValueRef first_index_result =
1269+
codegen_expr(ctx, node->expr.index.object);
1270+
if (!first_index_result) {
1271+
return NULL;
12491272
}
1250-
if (base_node->type == AST_EXPR_IDENTIFIER) {
1251-
const char *base_var_name = base_node->expr.identifier.name;
1252-
LLVM_Symbol *base_sym = find_symbol(ctx, base_var_name);
1253-
if (base_sym && base_sym->element_type) {
1254-
// For multi-dimensional arrays, the element type after first index
1255-
// would be a pointer to the inner type
1256-
if (LLVMGetTypeKind(base_sym->element_type) == LLVMPointerTypeKind) {
1257-
// This needs more sophisticated handling for multi-dimensional
1258-
// arrays
1259-
pointee_type = LLVMInt64TypeInContext(ctx->context); // fallback
1273+
1274+
LLVMTypeRef first_result_type = LLVMTypeOf(first_index_result);
1275+
LLVMTypeKind first_result_kind = LLVMGetTypeKind(first_result_type);
1276+
1277+
// CASE 1: First indexing returned an ARRAY value (nested array literal)
1278+
// Example: directions[d] where directions is [[int; 2]; 8]
1279+
if (first_result_kind == LLVMArrayTypeKind) {
1280+
// This is a nested array access - the first index gave us an array
1281+
// Now index into that array
1282+
LLVMTypeRef inner_element_type = LLVMGetElementType(first_result_type);
1283+
1284+
// Store the array value so we can GEP into it
1285+
LLVMValueRef temp_alloca = LLVMBuildAlloca(
1286+
ctx->builder, first_result_type, "nested_array_temp");
1287+
1288+
// CRITICAL: Store with proper alignment for i64 arrays
1289+
LLVMValueRef store_inst =
1290+
LLVMBuildStore(ctx->builder, first_index_result, temp_alloca);
1291+
LLVMSetAlignment(store_inst, 8);
1292+
1293+
// Use InBoundsGEP with proper indices
1294+
LLVMValueRef gep_indices[2];
1295+
gep_indices[0] =
1296+
LLVMConstInt(LLVMInt32TypeInContext(ctx->context), 0, false);
1297+
gep_indices[1] = index;
1298+
1299+
LLVMValueRef element_ptr =
1300+
LLVMBuildInBoundsGEP2(ctx->builder, first_result_type, temp_alloca,
1301+
gep_indices, 2, "nested_element_ptr");
1302+
1303+
// Load with proper alignment
1304+
LLVMValueRef load_inst = LLVMBuildLoad2(
1305+
ctx->builder, inner_element_type, element_ptr, "nested_element");
1306+
LLVMSetAlignment(load_inst, 8);
1307+
1308+
return load_inst;
1309+
}
1310+
1311+
// CASE 2: First indexing returned a POINTER (double pointer like **byte)
1312+
else if (first_result_kind == LLVMPointerTypeKind) {
1313+
// This is pointer indexing: grid[r][c] where grid is **byte
1314+
// first_index_result is the result of grid[r], which is a *byte
1315+
1316+
// Trace back to find the base variable for type info
1317+
AstNode *base_node = node->expr.index.object;
1318+
while (base_node->type == AST_EXPR_INDEX) {
1319+
base_node = base_node->expr.index.object;
1320+
}
1321+
1322+
if (base_node->type == AST_EXPR_IDENTIFIER) {
1323+
const char *base_var_name = base_node->expr.identifier.name;
1324+
LLVM_Symbol *base_sym = find_symbol(ctx, base_var_name);
1325+
1326+
if (base_sym && base_sym->element_type) {
1327+
// For **byte, element_type is *byte (pointer to byte)
1328+
// We need to dereference once more to get byte
1329+
if (LLVMGetTypeKind(base_sym->element_type) ==
1330+
LLVMPointerTypeKind) {
1331+
// Check the base variable name to infer the final type
1332+
if (strstr(base_var_name, "byte") ||
1333+
strstr(base_var_name, "char")) {
1334+
pointee_type = LLVMInt8TypeInContext(ctx->context);
1335+
} else if (strstr(base_var_name, "int") &&
1336+
!strstr(base_var_name, "byte")) {
1337+
pointee_type = LLVMInt64TypeInContext(ctx->context);
1338+
} else if (strstr(base_var_name, "double")) {
1339+
pointee_type = LLVMDoubleTypeInContext(ctx->context);
1340+
} else if (strstr(base_var_name, "float")) {
1341+
pointee_type = LLVMFloatTypeInContext(ctx->context);
1342+
} else {
1343+
pointee_type = LLVMInt8TypeInContext(ctx->context);
1344+
}
1345+
} else {
1346+
pointee_type = base_sym->element_type;
1347+
}
12601348
} else {
1261-
pointee_type = base_sym->element_type;
1262-
}
1263-
} else {
1264-
// Old name-based fallback
1265-
if (strstr(base_var_name, "double")) {
1266-
pointee_type = LLVMDoubleTypeInContext(ctx->context);
1267-
} else if (strstr(base_var_name, "float")) {
1268-
pointee_type = LLVMFloatTypeInContext(ctx->context);
1269-
} else if (strstr(base_var_name, "int") &&
1270-
!strstr(base_var_name, "char")) {
1271-
pointee_type = LLVMInt64TypeInContext(ctx->context);
1272-
} else if (strstr(base_var_name, "char") ||
1273-
strstr(base_var_name, "_buf")) {
1274-
pointee_type = LLVMInt8TypeInContext(ctx->context);
1349+
// Fallback based on variable name
1350+
if (strstr(base_var_name, "byte") ||
1351+
strstr(base_var_name, "char")) {
1352+
pointee_type = LLVMInt8TypeInContext(ctx->context);
1353+
} else if (strstr(base_var_name, "double")) {
1354+
pointee_type = LLVMDoubleTypeInContext(ctx->context);
1355+
} else if (strstr(base_var_name, "float")) {
1356+
pointee_type = LLVMFloatTypeInContext(ctx->context);
1357+
} else if (strstr(base_var_name, "int")) {
1358+
pointee_type = LLVMInt64TypeInContext(ctx->context);
1359+
} else {
1360+
pointee_type = LLVMInt8TypeInContext(ctx->context);
1361+
}
12751362
}
1363+
1364+
// Now we have the pointer from first indexing and the element type
1365+
// Do the second level of pointer indexing
1366+
LLVMValueRef element_ptr =
1367+
LLVMBuildGEP2(ctx->builder, pointee_type, first_index_result,
1368+
&index, 1, "ptr_ptr_element");
1369+
return LLVMBuildLoad2(ctx->builder, pointee_type, element_ptr,
1370+
"ptr_ptr_element_val");
12761371
}
12771372
}
12781373
} else if (node->expr.index.object->type == AST_EXPR_CAST) {

0 commit comments

Comments
 (0)