Skip to content

Commit a35da48

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 34c8aac commit a35da48

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
{
@@ -1287,9 +1287,9 @@ void parse_array_init(var_t *var,
12871287
}
12881288

12891289
void parse_array_compound_literal(var_t *var,
1290-
block_t *parent,
1291-
basic_block_t **bb,
1292-
bool emit_code)
1290+
block_t *parent,
1291+
basic_block_t **bb,
1292+
bool emit_code)
12931293
{
12941294
int elem_size = var->type->size;
12951295
int count = 0;
@@ -1307,8 +1307,8 @@ void parse_array_compound_literal(var_t *var,
13071307
target.type = var->type;
13081308
target.ptr_level = 0;
13091309
var_t *store_val = resize_var(parent, bb, value, &target);
1310-
var_t *elem_addr = compute_element_address(
1311-
parent, bb, var, count, elem_size);
1310+
var_t *elem_addr =
1311+
compute_element_address(parent, bb, var, count, elem_size);
13121312
add_insn(parent, *bb, OP_write, NULL, elem_addr, store_val,
13131313
elem_size, NULL);
13141314
}
@@ -1322,6 +1322,35 @@ void parse_array_compound_literal(var_t *var,
13221322
lex_expect(T_close_curly);
13231323
var->array_size = count;
13241324
}
1325+
static bool is_array_literal_temp(var_t *var)
1326+
{
1327+
return var && var->array_size > 0 && var->var_name[0] == '.';
1328+
}
1329+
1330+
static var_t *scalarize_array_literal(block_t *parent,
1331+
basic_block_t **bb,
1332+
var_t *array_var,
1333+
type_t *hint_type)
1334+
{
1335+
if (!is_array_literal_temp(array_var))
1336+
return array_var;
1337+
1338+
type_t *elem_type = hint_type ? hint_type : array_var->type;
1339+
if (!elem_type)
1340+
elem_type = TY_int;
1341+
1342+
int elem_size = elem_type->size;
1343+
if (elem_size <= 0)
1344+
elem_size = TY_int->size;
1345+
1346+
var_t *scalar = require_typed_var(parent, elem_type);
1347+
scalar->ptr_level = 0;
1348+
gen_name_to(scalar->var_name);
1349+
scalar->init_val = array_var->init_val;
1350+
1351+
add_insn(parent, *bb, OP_read, scalar, array_var, NULL, elem_size, NULL);
1352+
return scalar;
1353+
}
13251354
void read_inner_var_decl(var_t *vd, bool anon, bool is_param)
13261355
{
13271356
/* Preserve typedef pointer level - don't reset if already inherited */
@@ -1614,7 +1643,16 @@ void read_func_parameters(func_t *func, block_t *parent, basic_block_t **bb)
16141643
read_ternary_operation(parent, bb);
16151644

16161645
param = opstack_pop();
1617-
1646+
if (func) {
1647+
if (param_num < func->num_params) {
1648+
var_t *target = &func->param_defs[param_num];
1649+
if (!target->ptr_level && !target->array_size)
1650+
param = scalarize_array_literal(parent, bb, param,
1651+
target->type);
1652+
} else if (func->va_args) {
1653+
param = scalarize_array_literal(parent, bb, param, TY_int);
1654+
}
1655+
}
16181656
/* Handle parameter type conversion for direct calls.
16191657
* Indirect calls currently don't provide function instance.
16201658
*/
@@ -2857,6 +2895,16 @@ void read_expr(block_t *parent, basic_block_t **bb)
28572895
continue; /* skip normal processing */
28582896
}
28592897

2898+
bool rs1_is_ptr_like = rs1 && (rs1->ptr_level || rs1->array_size);
2899+
bool rs2_is_ptr_like = rs2 && (rs2->ptr_level || rs2->array_size);
2900+
2901+
if (is_array_literal_temp(rs1) && !rs2_is_ptr_like)
2902+
rs1 = scalarize_array_literal(parent, bb, rs1,
2903+
rs2 && rs2->type ? rs2->type : NULL);
2904+
2905+
if (is_array_literal_temp(rs2) && !rs1_is_ptr_like)
2906+
rs2 = scalarize_array_literal(parent, bb, rs2,
2907+
rs1 && rs1->type ? rs1->type : NULL);
28602908
/* Constant folding for binary operations */
28612909
if (rs1 && rs2 && rs1->init_val && !rs1->ptr_level && !rs1->is_global &&
28622910
rs2->init_val && !rs2->ptr_level && !rs2->is_global) {
@@ -3477,7 +3525,7 @@ void finalize_logical(opcode_t op,
34773525

34783526
void read_ternary_operation(block_t *parent, basic_block_t **bb)
34793527
{
3480-
var_t *vd, *rs1;
3528+
var_t *vd;
34813529

34823530
if (!lex_accept(T_question))
34833531
return;
@@ -3502,17 +3550,39 @@ void read_ternary_operation(block_t *parent, basic_block_t **bb)
35023550
abort();
35033551
}
35043552

3505-
rs1 = opstack_pop();
3506-
vd = require_var(parent);
3507-
gen_name_to(vd->var_name);
3508-
add_insn(parent, then_, OP_assign, vd, rs1, NULL, 0, NULL);
3553+
var_t *true_val = opstack_pop();
35093554

35103555
/* false branch */
35113556
read_expr(parent, &else_);
35123557
bb_connect(*bb, else_, ELSE);
3558+
var_t *false_val = opstack_pop();
3559+
bool true_array = is_array_literal_temp(true_val);
3560+
bool false_array = is_array_literal_temp(false_val);
35133561

3514-
rs1 = opstack_pop();
3515-
add_insn(parent, else_, OP_assign, vd, rs1, NULL, 0, NULL);
3562+
if (true_array && !false_array)
3563+
true_val = scalarize_array_literal(parent, &then_, true_val,
3564+
false_val ? false_val->type : NULL);
3565+
3566+
if (false_array && !true_array)
3567+
false_val = scalarize_array_literal(parent, &else_, false_val,
3568+
true_val ? true_val->type : NULL);
3569+
3570+
vd = require_var(parent);
3571+
gen_name_to(vd->var_name);
3572+
add_insn(parent, then_, OP_assign, vd, true_val, NULL, 0, NULL);
3573+
add_insn(parent, else_, OP_assign, vd, false_val, NULL, 0, NULL);
3574+
3575+
var_t *array_ref = NULL;
3576+
if (is_array_literal_temp(true_val))
3577+
array_ref = true_val;
3578+
else if (is_array_literal_temp(false_val))
3579+
array_ref = false_val;
3580+
3581+
if (array_ref) {
3582+
vd->array_size = array_ref->array_size;
3583+
vd->init_val = array_ref->init_val;
3584+
vd->type = array_ref->type;
3585+
}
35163586

35173587
vd->is_ternary_ret = true;
35183588
opstack_push(vd);
@@ -3661,6 +3731,11 @@ bool read_body_assignment(char *token,
36613731

36623732
read_expr(parent, bb);
36633733

3734+
var_t *rhs_val = opstack_pop();
3735+
if (!lvalue.ptr_level && !lvalue.is_reference)
3736+
rhs_val = scalarize_array_literal(parent, bb, rhs_val,
3737+
lvalue.type);
3738+
opstack_push(rhs_val);
36643739
vd = require_var(parent);
36653740
vd->init_val = increment_size;
36663741
gen_name_to(vd->var_name);
@@ -4403,27 +4478,12 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
44034478

44044479
var_t *expr_result = opstack_pop();
44054480

4406-
/* Handle array compound literal to scalar assignment.
4407-
* When assigning array compound literals to scalar
4408-
* variables, use the first element value rather than array
4409-
* address.
4410-
*/
4411-
if (expr_result && expr_result->array_size > 0 &&
4412-
!var->ptr_level && var->array_size == 0 && var->type &&
4413-
(var->type->base_type == TYPE_int ||
4414-
var->type->base_type == TYPE_short) &&
4415-
expr_result->var_name[0] == '.') {
4416-
var_t *first_elem = require_var(parent);
4417-
first_elem->type = var->type;
4418-
gen_name_to(first_elem->var_name);
4419-
4420-
/* Extract first element from compound literal array */
4421-
add_insn(parent, bb, OP_read, first_elem, expr_result,
4422-
NULL, var->type->size, NULL);
4423-
expr_result = first_elem;
4424-
}
4481+
var_t *rhs = expr_result;
4482+
if (!var->ptr_level && var->array_size == 0)
4483+
rhs =
4484+
scalarize_array_literal(parent, bb, rhs, var->type);
44254485

4426-
rs1 = resize_var(parent, &bb, expr_result, var);
4486+
rs1 = resize_var(parent, &bb, rhs, var);
44274487
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
44284488
}
44294489
}
@@ -4515,8 +4575,13 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
45154575
} else {
45164576
read_expr(parent, &bb);
45174577
read_ternary_operation(parent, &bb);
4578+
var_t *expr_result = opstack_pop();
4579+
var_t *rhs = expr_result;
4580+
if (!nv->ptr_level && nv->array_size == 0)
4581+
rhs = scalarize_array_literal(parent, bb, rhs,
4582+
nv->type);
45184583

4519-
rs1 = resize_var(parent, &bb, opstack_pop(), nv);
4584+
rs1 = resize_var(parent, &bb, rhs, nv);
45204585
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
45214586
}
45224587
}

0 commit comments

Comments
 (0)