Skip to content

Commit c684f74

Browse files
committed
Fix global struct array init and runtime access
This commit addresses two critical issues with global struct arrays: 1. Global struct arrays were missing the is_global flag, causing them to be treated as local variables during code generation. This led to segmentation faults when accessing them at runtime since they were incorrectly loaded from the stack pointer (sp) instead of the global pointer (gp). 2. Global struct array initialization values were being parsed but ignored. The parser was only consuming the tokens without generating the necessary OP_load_constant instructions to initialize the values at runtime. This fixes the test case where `struct point gpts1[] = { {3, 4} }` would return 0 instead of the expected 7 when accessing gpts1[0].x+gpts1[0].y.
1 parent 4e99f5a commit c684f74

File tree

1 file changed

+36
-10
lines changed

1 file changed

+36
-10
lines changed

src/parser.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -738,18 +738,43 @@ void parse_array_init(var_t *var,
738738
var_t *field_val_raw = NULL;
739739

740740
if (parent == GLOBAL_BLOCK) {
741-
/* Global scope: only accept constants */
742-
if (lex_peek(T_numeric, NULL)) {
743-
lex_accept(T_numeric);
744-
/* Skip the value - we can't initialize at
745-
* global scope yet */
746-
} else if (lex_peek(T_minus, NULL)) {
747-
lex_accept(T_minus);
748-
lex_accept(T_numeric);
741+
/* Global scope: accept constants and emit loads
742+
* if emit_code is true */
743+
if (lex_peek(T_numeric, NULL) ||
744+
lex_peek(T_minus, NULL)) {
745+
int is_neg = 0;
746+
if (lex_accept(T_minus))
747+
is_neg = 1;
748+
char numtok[MAX_ID_LEN];
749+
lex_ident(T_numeric, numtok);
750+
int num_val = read_numeric_constant(numtok);
751+
if (is_neg)
752+
num_val = -num_val;
753+
754+
if (emit_code) {
755+
field_val_raw = require_var(parent);
756+
gen_name_to(field_val_raw->var_name);
757+
field_val_raw->init_val = num_val;
758+
add_insn(parent, *bb, OP_load_constant,
759+
field_val_raw, NULL, NULL, 0,
760+
NULL);
761+
}
762+
} else if (lex_peek(T_char, NULL)) {
763+
char chtok[5];
764+
lex_ident(T_char, chtok);
765+
766+
if (emit_code) {
767+
field_val_raw =
768+
require_typed_var(parent, TY_char);
769+
gen_name_to(field_val_raw->var_name);
770+
field_val_raw->init_val = chtok[0];
771+
add_insn(parent, *bb, OP_load_constant,
772+
field_val_raw, NULL, NULL, 0,
773+
NULL);
774+
}
749775
} else if (lex_peek(T_string, NULL)) {
750776
lex_accept(T_string);
751-
} else if (lex_peek(T_char, NULL)) {
752-
lex_accept(T_char);
777+
/* Strings not supported in struct fields */
753778
} else {
754779
error(
755780
"Global array initialization requires "
@@ -3996,6 +4021,7 @@ void read_global_statement(void)
39964021

39974022
/* one or more declarators */
39984023
var_t *var = require_typed_var(block, decl_type);
4024+
var->is_global = true; /* Global struct variable */
39994025
read_partial_var_decl(var, NULL);
40004026
add_insn(block, GLOBAL_FUNC->bbs, OP_allocat, var, NULL, NULL, 0,
40014027
NULL);

0 commit comments

Comments
 (0)