Skip to content

Commit 1479440

Browse files
committed
Preserve pointer semantics for array literals
Introduce helpers to centralize array-literal scalar decay. Temporary array compound literals are detected and converted to a scalar only when a scalar is actually required; otherwise the expression yields the temporary array’s address, preserving pointer semantics. Update binary ops, direct/compound assignments, function-call arguments, and ternary results to use the unified helper instead of ad-hoc collapsing. This fixes cases where array literals were reduced to their first element in pointer contexts, while keeping struct and plain scalar behavior unchanged. Addresses #299 (array compound literals).
1 parent a9f4cbc commit 1479440

File tree

1 file changed

+102
-37
lines changed

1 file changed

+102
-37
lines changed

src/parser.c

Lines changed: 102 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ void parse_array_init(var_t *var,
4646
basic_block_t **bb,
4747
bool emit_code);
4848
void parse_array_compound_literal(var_t *var,
49-
block_t *parent,
50-
basic_block_t **bb,
51-
bool emit_code);
49+
block_t *parent,
50+
basic_block_t **bb,
51+
bool emit_code);
5252

5353
label_t *find_label(char *name)
5454
{
@@ -1334,9 +1334,9 @@ void parse_array_init(var_t *var,
13341334
}
13351335

13361336
void parse_array_compound_literal(var_t *var,
1337-
block_t *parent,
1338-
basic_block_t **bb,
1339-
bool emit_code)
1337+
block_t *parent,
1338+
basic_block_t **bb,
1339+
bool emit_code)
13401340
{
13411341
int elem_size = var->type->size;
13421342
int count = 0;
@@ -1354,8 +1354,8 @@ void parse_array_compound_literal(var_t *var,
13541354
target.type = var->type;
13551355
target.ptr_level = 0;
13561356
var_t *store_val = resize_var(parent, bb, value, &target);
1357-
var_t *elem_addr = compute_element_address(
1358-
parent, bb, var, count, elem_size);
1357+
var_t *elem_addr =
1358+
compute_element_address(parent, bb, var, count, elem_size);
13591359
add_insn(parent, *bb, OP_write, NULL, elem_addr, store_val,
13601360
elem_size, NULL);
13611361
}
@@ -1369,6 +1369,35 @@ void parse_array_compound_literal(var_t *var,
13691369
lex_expect(T_close_curly);
13701370
var->array_size = count;
13711371
}
1372+
static bool is_array_literal_temp(var_t *var)
1373+
{
1374+
return var && var->array_size > 0 && var->var_name[0] == '.';
1375+
}
1376+
1377+
static var_t *scalarize_array_literal(block_t *parent,
1378+
basic_block_t **bb,
1379+
var_t *array_var,
1380+
type_t *hint_type)
1381+
{
1382+
if (!is_array_literal_temp(array_var))
1383+
return array_var;
1384+
1385+
type_t *elem_type = hint_type ? hint_type : array_var->type;
1386+
if (!elem_type)
1387+
elem_type = TY_int;
1388+
1389+
int elem_size = elem_type->size;
1390+
if (elem_size <= 0)
1391+
elem_size = TY_int->size;
1392+
1393+
var_t *scalar = require_typed_var(parent, elem_type);
1394+
scalar->ptr_level = 0;
1395+
gen_name_to(scalar->var_name);
1396+
scalar->init_val = array_var->init_val;
1397+
1398+
add_insn(parent, *bb, OP_read, scalar, array_var, NULL, elem_size, NULL);
1399+
return scalar;
1400+
}
13721401
void read_inner_var_decl(var_t *vd, bool anon, bool is_param)
13731402
{
13741403
/* Preserve typedef pointer level - don't reset if already inherited */
@@ -1661,7 +1690,16 @@ void read_func_parameters(func_t *func, block_t *parent, basic_block_t **bb)
16611690
read_ternary_operation(parent, bb);
16621691

16631692
param = opstack_pop();
1664-
1693+
if (func) {
1694+
if (param_num < func->num_params) {
1695+
var_t *target = &func->param_defs[param_num];
1696+
if (!target->ptr_level && !target->array_size)
1697+
param = scalarize_array_literal(parent, bb, param,
1698+
target->type);
1699+
} else if (func->va_args) {
1700+
param = scalarize_array_literal(parent, bb, param, TY_int);
1701+
}
1702+
}
16651703
/* Handle parameter type conversion for direct calls.
16661704
* Indirect calls currently don't provide function instance.
16671705
*/
@@ -2904,6 +2942,16 @@ void read_expr(block_t *parent, basic_block_t **bb)
29042942
continue; /* skip normal processing */
29052943
}
29062944

2945+
bool rs1_is_ptr_like = rs1 && (rs1->ptr_level || rs1->array_size);
2946+
bool rs2_is_ptr_like = rs2 && (rs2->ptr_level || rs2->array_size);
2947+
2948+
if (is_array_literal_temp(rs1) && !rs2_is_ptr_like)
2949+
rs1 = scalarize_array_literal(parent, bb, rs1,
2950+
rs2 && rs2->type ? rs2->type : NULL);
2951+
2952+
if (is_array_literal_temp(rs2) && !rs1_is_ptr_like)
2953+
rs2 = scalarize_array_literal(parent, bb, rs2,
2954+
rs1 && rs1->type ? rs1->type : NULL);
29072955
/* Constant folding for binary operations */
29082956
if (rs1 && rs2 && rs1->init_val && !rs1->ptr_level && !rs1->is_global &&
29092957
rs2->init_val && !rs2->ptr_level && !rs2->is_global) {
@@ -3524,7 +3572,7 @@ void finalize_logical(opcode_t op,
35243572

35253573
void read_ternary_operation(block_t *parent, basic_block_t **bb)
35263574
{
3527-
var_t *vd, *rs1;
3575+
var_t *vd;
35283576

35293577
if (!lex_accept(T_question))
35303578
return;
@@ -3549,17 +3597,39 @@ void read_ternary_operation(block_t *parent, basic_block_t **bb)
35493597
abort();
35503598
}
35513599

3552-
rs1 = opstack_pop();
3553-
vd = require_var(parent);
3554-
gen_name_to(vd->var_name);
3555-
add_insn(parent, then_, OP_assign, vd, rs1, NULL, 0, NULL);
3600+
var_t *true_val = opstack_pop();
35563601

35573602
/* false branch */
35583603
read_expr(parent, &else_);
35593604
bb_connect(*bb, else_, ELSE);
3605+
var_t *false_val = opstack_pop();
3606+
bool true_array = is_array_literal_temp(true_val);
3607+
bool false_array = is_array_literal_temp(false_val);
35603608

3561-
rs1 = opstack_pop();
3562-
add_insn(parent, else_, OP_assign, vd, rs1, NULL, 0, NULL);
3609+
if (true_array && !false_array)
3610+
true_val = scalarize_array_literal(parent, &then_, true_val,
3611+
false_val ? false_val->type : NULL);
3612+
3613+
if (false_array && !true_array)
3614+
false_val = scalarize_array_literal(parent, &else_, false_val,
3615+
true_val ? true_val->type : NULL);
3616+
3617+
vd = require_var(parent);
3618+
gen_name_to(vd->var_name);
3619+
add_insn(parent, then_, OP_assign, vd, true_val, NULL, 0, NULL);
3620+
add_insn(parent, else_, OP_assign, vd, false_val, NULL, 0, NULL);
3621+
3622+
var_t *array_ref = NULL;
3623+
if (is_array_literal_temp(true_val))
3624+
array_ref = true_val;
3625+
else if (is_array_literal_temp(false_val))
3626+
array_ref = false_val;
3627+
3628+
if (array_ref) {
3629+
vd->array_size = array_ref->array_size;
3630+
vd->init_val = array_ref->init_val;
3631+
vd->type = array_ref->type;
3632+
}
35633633

35643634
vd->is_ternary_ret = true;
35653635
opstack_push(vd);
@@ -3708,6 +3778,11 @@ bool read_body_assignment(char *token,
37083778

37093779
read_expr(parent, bb);
37103780

3781+
var_t *rhs_val = opstack_pop();
3782+
if (!lvalue.ptr_level && !lvalue.is_reference)
3783+
rhs_val = scalarize_array_literal(parent, bb, rhs_val,
3784+
lvalue.type);
3785+
opstack_push(rhs_val);
37113786
vd = require_var(parent);
37123787
vd->init_val = increment_size;
37133788
gen_name_to(vd->var_name);
@@ -4450,27 +4525,12 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
44504525

44514526
var_t *expr_result = opstack_pop();
44524527

4453-
/* Handle array compound literal to scalar assignment.
4454-
* When assigning array compound literals to scalar
4455-
* variables, use the first element value rather than array
4456-
* address.
4457-
*/
4458-
if (expr_result && expr_result->array_size > 0 &&
4459-
!var->ptr_level && var->array_size == 0 && var->type &&
4460-
(var->type->base_type == TYPE_int ||
4461-
var->type->base_type == TYPE_short) &&
4462-
expr_result->var_name[0] == '.') {
4463-
var_t *first_elem = require_var(parent);
4464-
first_elem->type = var->type;
4465-
gen_name_to(first_elem->var_name);
4466-
4467-
/* Extract first element from compound literal array */
4468-
add_insn(parent, bb, OP_read, first_elem, expr_result,
4469-
NULL, var->type->size, NULL);
4470-
expr_result = first_elem;
4471-
}
4528+
var_t *rhs = expr_result;
4529+
if (!var->ptr_level && var->array_size == 0)
4530+
rhs =
4531+
scalarize_array_literal(parent, bb, rhs, var->type);
44724532

4473-
rs1 = resize_var(parent, &bb, expr_result, var);
4533+
rs1 = resize_var(parent, &bb, rhs, var);
44744534
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
44754535
}
44764536
}
@@ -4562,8 +4622,13 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
45624622
} else {
45634623
read_expr(parent, &bb);
45644624
read_ternary_operation(parent, &bb);
4625+
var_t *expr_result = opstack_pop();
4626+
var_t *rhs = expr_result;
4627+
if (!nv->ptr_level && nv->array_size == 0)
4628+
rhs = scalarize_array_literal(parent, bb, rhs,
4629+
nv->type);
45654630

4566-
rs1 = resize_var(parent, &bb, opstack_pop(), nv);
4631+
rs1 = resize_var(parent, &bb, rhs, nv);
45674632
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
45684633
}
45694634
}

0 commit comments

Comments
 (0)