Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/arm-codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ void cfg_flatten(void)
}

/* prepare 'argc' and 'argv', then proceed to 'main' function */
elf_offset += 24;
elf_offset += 32; /* 6 insns for main call + 2 for exit */

for (func = FUNC_LIST.head; func; func = func->next) {
/* reserve stack */
Expand Down Expand Up @@ -488,7 +488,11 @@ void code_generate(void)
emit(__add_r(__AL, __r8, __r12, __r8));
emit(__lw(__AL, __r0, __r8, 0));
emit(__add_i(__AL, __r1, __r8, 4));
emit(__b(__AL, MAIN_BB->elf_offset - elf_code->size));
emit(__bl(__AL, MAIN_BB->elf_offset - elf_code->size));

/* exit with main's return value */
emit(__mov_i(__AL, __r7, 1));
emit(__svc());

for (int i = 0; i < ph2_ir_idx; i++) {
ph2_ir = PH2_IR_FLATTEN[i];
Expand Down
172 changes: 156 additions & 16 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,122 @@ bool read_preproc_directive(void)

void read_parameter_list_decl(func_t *func, int anon);

/* Forward declaration for ternary handling used by initializers */
void read_ternary_operation(block_t *parent, basic_block_t **bb);

/* Parse array initializer to determine size for implicit arrays and
* optionally emit initialization code.
*/
void parse_array_init(var_t *var,
block_t *parent,
basic_block_t **bb,
int emit_code)
{
int elem_size = var->type->size;
int count = 0;
var_t *base_addr = NULL;

/* Store values if we need to emit code later for implicit arrays */
var_t *stored_vals[256]; /* Max 256 elements for now */
int is_implicit = (var->array_size == 0);

/* If emitting code and size is known, arrays are already addresses */
if (emit_code && !is_implicit) {
/* Arrays are already addresses, no need for OP_address_of */
base_addr = var;
}

lex_expect(T_open_curly);
if (!lex_peek(T_close_curly, NULL)) {
for (;;) {
/* Parse element expression */
read_expr(parent, bb);
read_ternary_operation(parent, bb);
var_t *val = opstack_pop();

/* Store value for implicit arrays */
if (is_implicit && emit_code && count < 256)
stored_vals[count] = val;

if (emit_code && !is_implicit && count < var->array_size) {
/* Emit code for explicit size arrays */
var_t target;
memset(&target, 0, sizeof(target));
target.type = var->type;
target.is_ptr = 0;
var_t *v = resize_var(parent, bb, val, &target);

/* Compute element address: base + count*elem_size */
var_t *elem_addr = base_addr;
if (count > 0) {
var_t *offset = require_var(parent);
gen_name_to(offset->var_name);
offset->init_val = count * elem_size;
add_insn(parent, *bb, OP_load_constant, offset, NULL, NULL,
0, NULL);

var_t *addr = require_var(parent);
gen_name_to(addr->var_name);
add_insn(parent, *bb, OP_add, addr, base_addr, offset, 0,
NULL);
elem_addr = addr;
}

/* Write element */
add_insn(parent, *bb, OP_write, NULL, elem_addr, v, elem_size,
NULL);
}

count++;
if (!lex_accept(T_comma))
break;
if (lex_peek(T_close_curly, NULL))
break;
}
}
lex_expect(T_close_curly);

/* For implicit size arrays, set the size and emit code */
if (is_implicit) {
if (var->is_ptr > 0)
var->is_ptr = 0;
var->array_size = count;

/* Now emit the code since we know the size */
if (emit_code && count > 0) {
base_addr = var; /* Arrays are already addresses */

for (int i = 0; i < count && i < 256; i++) {
var_t target;
memset(&target, 0, sizeof(target));
target.type = var->type;
target.is_ptr = 0;
var_t *v = resize_var(parent, bb, stored_vals[i], &target);

/* Compute element address */
var_t *elem_addr = base_addr;
if (i > 0) {
var_t *offset = require_var(parent);
gen_name_to(offset->var_name);
offset->init_val = i * elem_size;
add_insn(parent, *bb, OP_load_constant, offset, NULL, NULL,
0, NULL);

var_t *addr = require_var(parent);
gen_name_to(addr->var_name);
add_insn(parent, *bb, OP_add, addr, base_addr, offset, 0,
NULL);
elem_addr = addr;
}

/* Write element */
add_insn(parent, *bb, OP_write, NULL, elem_addr, v, elem_size,
NULL);
}
}
}
}

void read_inner_var_decl(var_t *vd, int anon, int is_param)
{
vd->init_val = 0;
Expand Down Expand Up @@ -885,7 +1001,6 @@ void read_char_param(block_t *parent, basic_block_t *bb)
}

void read_logical(opcode_t op, block_t *parent, basic_block_t **bb);
void read_ternary_operation(block_t *parent, basic_block_t **bb);
void read_func_parameters(func_t *func, block_t *parent, basic_block_t **bb)
{
int param_num = 0;
Expand Down Expand Up @@ -969,6 +1084,7 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
read_literal_param(parent, *bb);
else if (lex_peek(T_char, NULL))
read_char_param(parent, *bb);

else if (lex_peek(T_numeric, NULL))
read_numeric_param(parent, *bb, is_neg);
else if (lex_accept(T_log_not)) {
Expand Down Expand Up @@ -3068,11 +3184,17 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
add_insn(parent, bb, OP_allocat, var, NULL, NULL, 0, NULL);
add_symbol(bb, var);
if (lex_accept(T_assign)) {
read_expr(parent, &bb);
read_ternary_operation(parent, &bb);
if (lex_peek(T_open_curly, NULL) &&
(var->array_size > 0 || var->is_ptr > 0)) {
parse_array_init(var, parent, &bb,
1); /* Always emit code */
} else {
read_expr(parent, &bb);
read_ternary_operation(parent, &bb);

rs1 = resize_var(parent, &bb, opstack_pop(), var);
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
rs1 = resize_var(parent, &bb, opstack_pop(), var);
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
}
}
while (lex_accept(T_comma)) {
var_t *nv;
Expand All @@ -3086,11 +3208,16 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
add_insn(parent, bb, OP_allocat, nv, NULL, NULL, 0, NULL);
add_symbol(bb, nv);
if (lex_accept(T_assign)) {
read_expr(parent, &bb);
read_ternary_operation(parent, &bb);
if (lex_peek(T_open_curly, NULL) &&
(nv->array_size > 0 || nv->is_ptr > 0)) {
parse_array_init(nv, parent, &bb, 1);
} else {
read_expr(parent, &bb);
read_ternary_operation(parent, &bb);

rs1 = resize_var(parent, &bb, opstack_pop(), nv);
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
rs1 = resize_var(parent, &bb, opstack_pop(), nv);
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
}
}
}
lex_expect(T_semicolon);
Expand Down Expand Up @@ -3150,11 +3277,18 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
add_insn(parent, bb, OP_allocat, var, NULL, NULL, 0, NULL);
add_symbol(bb, var);
if (lex_accept(T_assign)) {
read_expr(parent, &bb);
read_ternary_operation(parent, &bb);
if (lex_peek(T_open_curly, NULL) &&
(var->array_size > 0 || var->is_ptr > 0)) {
parse_array_init(
var, parent, &bb,
1); /* FIXED: Emit code for locals in functions */
} else {
read_expr(parent, &bb);
read_ternary_operation(parent, &bb);

rs1 = resize_var(parent, &bb, opstack_pop(), var);
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
rs1 = resize_var(parent, &bb, opstack_pop(), var);
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
}
}
while (lex_accept(T_comma)) {
var_t *nv;
Expand All @@ -3168,10 +3302,16 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
add_insn(parent, bb, OP_allocat, nv, NULL, NULL, 0, NULL);
add_symbol(bb, nv);
if (lex_accept(T_assign)) {
read_expr(parent, &bb);
if (lex_peek(T_open_curly, NULL) &&
(nv->array_size > 0 || nv->is_ptr > 0)) {
parse_array_init(nv, parent, &bb,
1); /* FIXED: Emit code for locals */
} else {
read_expr(parent, &bb);

rs1 = resize_var(parent, &bb, opstack_pop(), nv);
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
rs1 = resize_var(parent, &bb, opstack_pop(), nv);
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
}
}
}
lex_expect(T_semicolon);
Expand Down
34 changes: 16 additions & 18 deletions src/riscv-codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,11 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
void cfg_flatten(void)
{
func_t *func = find_func("__syscall");
func->bbs->elf_offset = 48; /* offset of start + exit in codegen */
/* Prologue ~ 6 instructions (24 bytes). Place __syscall right after. */
func->bbs->elf_offset = 24;

elf_offset = 84; /* offset of start + exit + syscall in codegen */
/* Reserve space for prologue (24) + syscall trampoline (36) = 60 bytes. */
elf_offset = 60;
GLOBAL_FUNC->bbs->elf_offset = elf_offset;

for (ph2_ir_t *ph2_ir = GLOBAL_FUNC->bbs->ph2_ir_list.head; ph2_ir;
Expand Down Expand Up @@ -437,24 +439,17 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
void code_generate(void)
{
elf_data_start = elf_code_start + elf_offset;
func_t *func;

/* start */
/* start: save original sp in s0; allocate global stack; run init */
emit(__addi(__s0, __sp, 0));
emit(__lui(__t0, rv_hi(GLOBAL_FUNC->stack_size)));
emit(__addi(__t0, __t0, rv_lo(GLOBAL_FUNC->stack_size)));
emit(__sub(__sp, __sp, __t0));
emit(__addi(__gp, __sp, 0));
emit(__addi(__gp, __sp, 0)); /* Set up global pointer */
emit(__jal(__ra, GLOBAL_FUNC->bbs->elf_offset - elf_code->size));

/* exit */
emit(__lui(__t0, rv_hi(GLOBAL_FUNC->stack_size)));
emit(__addi(__t0, __t0, rv_lo(GLOBAL_FUNC->stack_size)));
emit(__add(__gp, __gp, __t0));
emit(__addi(__sp, __gp, 0));
emit(__addi(__a0, __a0, 0));
emit(__addi(__a7, __zero, 93));
emit(__ecall());

/* syscall */
/* syscall trampoline for __syscall - must be at offset 24 */
emit(__addi(__a7, __a0, 0));
emit(__addi(__a0, __a1, 0));
emit(__addi(__a1, __a2, 0));
Expand All @@ -471,12 +466,15 @@ void code_generate(void)
emit_ph2_ir(ph2_ir);

/* prepare 'argc' and 'argv', then proceed to 'main' function */
emit(__lui(__t0, rv_hi(GLOBAL_FUNC->stack_size)));
emit(__addi(__t0, __t0, rv_lo(GLOBAL_FUNC->stack_size)));
emit(__add(__t0, __gp, __t0));
/* use original sp saved in s0 to get argc/argv */
emit(__addi(__t0, __s0, 0));
emit(__lw(__a0, __t0, 0));
emit(__addi(__a1, __t0, 4));
emit(__jal(__zero, MAIN_BB->elf_offset - elf_code->size));
emit(__jal(__ra, MAIN_BB->elf_offset - elf_code->size));

/* exit with main's return value in a0 */
emit(__addi(__a7, __zero, 93));
emit(__ecall());

for (int i = 0; i < ph2_ir_idx; i++) {
ph2_ir = PH2_IR_FLATTEN[i];
Expand Down
2 changes: 1 addition & 1 deletion src/ssa.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ void new_name(block_t *block, var_t **var)
var_t *get_stack_top_subscript_var(var_t *var)
{
if (var->base->rename.stack_idx < 1)
fatal("Index is less than 1");
return var; /* fallback: use base when no prior definition */

int sub = var->base->rename.stack[var->base->rename.stack_idx - 1];
for (int i = 0; i < var->base->subscripts_idx; i++) {
Expand Down
73 changes: 73 additions & 0 deletions tests/driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3683,4 +3683,77 @@ int main() {
}
EOF

# Local array initializers - verify compilation and correct values
# Test 1: Implicit size array with single element
try_ 1 << 'EOF'
int main() {
int a[] = {1};
return a[0]; /* Should return 1 */
}
EOF

# Test 2: Explicit size array with single element
try_ 42 << 'EOF'
int main() {
int a[1] = {42};
return a[0]; /* Should return 42 */
}
EOF

# Test 3: Multiple elements - verify all are initialized
try_ 6 << 'EOF'
int main() {
int a[3] = {1, 2, 3};
return a[0] + a[1] + a[2]; /* Should return 1+2+3=6 */
}
EOF

# Test 4: Character array initialization
try_ 97 << 'EOF'
int main() {
char s[] = {'a', 'b', 'c'};
return s[0]; /* Should return ASCII value of 'a' = 97 */
}
EOF

# Test 5: Empty initializer (all zeros)
try_ 0 << 'EOF'
int main() {
int a[5] = {};
return a[0] + a[1] + a[2] + a[3] + a[4]; /* Should return 0 */
}
EOF

# Test 6: Partial initialization (remaining should be zero)
try_ 15 << 'EOF'
int main() {
int a[5] = {5, 10};
return a[0] + a[1] + a[2] + a[3] + a[4]; /* Should return 5+10+0+0+0=15 */
}
EOF

# Test 7: Pass initialized array to function
try_ 30 << 'EOF'
int sum(int *p, int n) {
int total = 0;
for (int i = 0; i < n; i++)
total += p[i];
return total;
}
int main() {
int a[] = {5, 10, 15};
return sum(a, 3); /* Should return 5+10+15=30 */
}
EOF

# Test 8: Nested scope with array initialization
try_ 100 << 'EOF'
int main() {
{
int values[] = {25, 25, 25, 25};
return values[0] + values[1] + values[2] + values[3];
}
}
EOF

echo OK