Skip to content

Commit 0376c58

Browse files
committed
Fix false scalarization on variadic call
Make scalarize_array_literal read using the literal’s element size while still allowing callers to pick a result type. Stop collapsing variadic call arguments or pointer arithmetic operands just because the other side is an integer, so array literals decay to pointers when required. Treat literal+literal arithmetic as a scalar sum of first elements to keep the historical behavior while still honoring pointer math when a real pointer participates
1 parent 62211b5 commit 0376c58

File tree

1 file changed

+43
-36
lines changed

1 file changed

+43
-36
lines changed

src/parser.c

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,12 @@ bool is_array_literal_placeholder(var_t *var)
13331333
var->var_name[0] == '.';
13341334
}
13351335

1336+
bool is_pointer_like_value(var_t *var)
1337+
{
1338+
return var && (var->ptr_level || var->array_size ||
1339+
(var->type && var->type->ptr_level > 0));
1340+
}
1341+
13361342
var_t *scalarize_array_literal(block_t *parent,
13371343
basic_block_t **bb,
13381344
var_t *array_var,
@@ -1341,20 +1347,21 @@ var_t *scalarize_array_literal(block_t *parent,
13411347
if (!is_array_literal_placeholder(array_var))
13421348
return array_var;
13431349

1344-
type_t *elem_type = hint_type ? hint_type : array_var->type;
1345-
if (!elem_type)
1346-
elem_type = TY_int;
1350+
type_t *literal_type = array_var->type ? array_var->type : TY_int;
1351+
int literal_size = literal_type->size;
1352+
if (literal_size <= 0)
1353+
literal_size = TY_int->size;
13471354

1348-
int elem_size = elem_type->size;
1349-
if (elem_size <= 0)
1350-
elem_size = TY_int->size;
1355+
type_t *result_type = hint_type ? hint_type : literal_type;
1356+
if (!result_type)
1357+
result_type = TY_int;
13511358

1352-
var_t *scalar = require_typed_var(parent, elem_type);
1359+
var_t *scalar = require_typed_var(parent, result_type);
13531360
scalar->ptr_level = 0;
13541361
gen_name_to(scalar->var_name);
13551362
scalar->init_val = array_var->init_val;
13561363

1357-
add_insn(parent, *bb, OP_read, scalar, array_var, NULL, elem_size, NULL);
1364+
add_insn(parent, *bb, OP_read, scalar, array_var, NULL, literal_size, NULL);
13581365

13591366
return scalar;
13601367
}
@@ -1656,8 +1663,6 @@ void read_func_parameters(func_t *func, block_t *parent, basic_block_t **bb)
16561663
if (!target->ptr_level && !target->array_size)
16571664
param = scalarize_array_literal(parent, bb, param,
16581665
target->type);
1659-
} else if (func->va_args) {
1660-
param = scalarize_array_literal(parent, bb, param, TY_int);
16611666
}
16621667
}
16631668
/* Handle parameter type conversion for direct calls.
@@ -2565,20 +2570,14 @@ void handle_pointer_arithmetic(block_t *parent,
25652570
}
25662571

25672572
/* Check if both have ptr_level or typedef pointer type */
2568-
bool rs1_is_ptr = (orig_rs1->ptr_level > 0) ||
2569-
(orig_rs1->type && orig_rs1->type->ptr_level > 0);
2570-
bool rs2_is_ptr = (orig_rs2->ptr_level > 0) ||
2571-
(orig_rs2->type && orig_rs2->type->ptr_level > 0);
2573+
bool rs1_is_ptr = is_pointer_like_value(orig_rs1);
2574+
bool rs2_is_ptr = is_pointer_like_value(orig_rs2);
25722575

25732576
/* If variable lookup failed, check the passed variables directly */
2574-
if (!rs1_is_ptr) {
2575-
rs1_is_ptr =
2576-
(rs1->ptr_level > 0) || (rs1->type && rs1->type->ptr_level > 0);
2577-
}
2578-
if (!rs2_is_ptr) {
2579-
rs2_is_ptr =
2580-
(rs2->ptr_level > 0) || (rs2->type && rs2->type->ptr_level > 0);
2581-
}
2577+
if (!rs1_is_ptr)
2578+
rs1_is_ptr = is_pointer_like_value(rs1);
2579+
if (!rs2_is_ptr)
2580+
rs2_is_ptr = is_pointer_like_value(rs2);
25822581

25832582
if (rs1_is_ptr && rs2_is_ptr) {
25842583
/* Both are pointers - this is pointer difference */
@@ -2657,11 +2656,11 @@ void handle_pointer_arithmetic(block_t *parent,
26572656
}
26582657
}
26592658
/* Determine which operand is the pointer for regular pointer arithmetic */
2660-
if (rs1->ptr_level || (rs1->type && rs1->type->ptr_level > 0)) {
2659+
if (is_pointer_like_value(rs1)) {
26612660
ptr_var = rs1;
26622661
int_var = rs2;
26632662
element_size = get_pointer_element_size(rs1);
2664-
} else if (rs2->ptr_level || (rs2->type && rs2->type->ptr_level > 0)) {
2663+
} else if (is_pointer_like_value(rs2)) {
26652664
/* Only for addition (p + n == n + p) */
26662665
if (op == OP_add) {
26672666
ptr_var = rs2;
@@ -2708,8 +2707,7 @@ bool is_pointer_operation(opcode_t op, var_t *rs1, var_t *rs2)
27082707
if (op != OP_add && op != OP_sub)
27092708
return false;
27102709

2711-
return (rs1->ptr_level || (rs1->type && rs1->type->ptr_level > 0) ||
2712-
rs2->ptr_level || (rs2->type && rs2->type->ptr_level > 0));
2710+
return is_pointer_like_value(rs1) || is_pointer_like_value(rs2);
27132711
}
27142712

27152713
/* Helper function to check if a variable is a pointer based on its declaration
@@ -2902,22 +2900,31 @@ void read_expr(block_t *parent, basic_block_t **bb)
29022900
rs2 = opstack_pop();
29032901
rs1 = opstack_pop();
29042902

2903+
bool rs1_is_placeholder = is_array_literal_placeholder(rs1);
2904+
bool rs2_is_placeholder = is_array_literal_placeholder(rs2);
2905+
bool rs1_is_ptr_like = is_pointer_like_value(rs1);
2906+
bool rs2_is_ptr_like = is_pointer_like_value(rs2);
2907+
bool pointer_context = (rs1_is_ptr_like && !rs1_is_placeholder) ||
2908+
(rs2_is_ptr_like && !rs2_is_placeholder);
2909+
29052910
/* Pointer arithmetic handling */
2906-
if (is_pointer_operation(top_op, rs1, rs2)) {
2911+
if (pointer_context && is_pointer_operation(top_op, rs1, rs2)) {
29072912
handle_pointer_arithmetic(parent, bb, top_op, rs1, rs2);
29082913
continue; /* skip normal processing */
29092914
}
29102915

2911-
bool rs1_is_ptr_like = rs1 && (rs1->ptr_level || rs1->array_size);
2912-
bool rs2_is_ptr_like = rs2 && (rs2->ptr_level || rs2->array_size);
2913-
2914-
if (is_array_literal_placeholder(rs1) && !rs2_is_ptr_like)
2915-
rs1 = scalarize_array_literal(parent, bb, rs1,
2916-
rs2 && rs2->type ? rs2->type : NULL);
2916+
if (rs1_is_placeholder && rs2_is_placeholder) {
2917+
rs1 = scalarize_array_literal(parent, bb, rs1, NULL);
2918+
rs2 = scalarize_array_literal(parent, bb, rs2, NULL);
2919+
} else {
2920+
if (rs1_is_placeholder && !rs2_is_ptr_like)
2921+
rs1 = scalarize_array_literal(
2922+
parent, bb, rs1, rs2 && rs2->type ? rs2->type : NULL);
29172923

2918-
if (is_array_literal_placeholder(rs2) && !rs1_is_ptr_like)
2919-
rs2 = scalarize_array_literal(parent, bb, rs2,
2920-
rs1 && rs1->type ? rs1->type : NULL);
2924+
if (rs2_is_placeholder && !rs1_is_ptr_like)
2925+
rs2 = scalarize_array_literal(
2926+
parent, bb, rs2, rs1 && rs1->type ? rs1->type : NULL);
2927+
}
29212928
/* Constant folding for binary operations */
29222929
if (rs1 && rs2 && rs1->init_val && !rs1->ptr_level && !rs1->is_global &&
29232930
rs2->init_val && !rs2->ptr_level && !rs2->is_global) {

0 commit comments

Comments
 (0)