Skip to content

Commit 1611d23

Browse files
authored
Merge pull request #271 from sysprog21/pointer-aliasing
Fix pointer aliasing bug in constant optimization
2 parents 3746f8d + 32cf8c7 commit 1611d23

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

src/defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ struct var {
353353
int ptr_level;
354354
bool is_func;
355355
bool is_global;
356+
bool address_taken; /* true if variable address was taken (&var) */
356357
int array_size;
357358
int array_dim1, array_dim2; /* first/second dimension size for 2D arrays */
358359
int offset; /* offset from stack or frame, index 0 is reserved */

src/globals.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,14 @@ void add_insn(block_t *block,
10891089
else
10901090
n->str[0] = '\0';
10911091

1092+
/* Mark variables as address-taken to prevent incorrect constant
1093+
* optimization
1094+
*/
1095+
if ((op == OP_address_of || op == OP_global_address_of) && rs1) {
1096+
rs1->address_taken = true;
1097+
rs1->is_const = false; /* disable constant optimization */
1098+
}
1099+
10921100
if (!bb->insn_list.head)
10931101
bb->insn_list.head = n;
10941102
else

src/reg-alloc.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,28 @@ int find_in_regs(var_t *var)
110110

111111
void load_var(basic_block_t *bb, var_t *var, int idx)
112112
{
113-
ph2_ir_t *ir = var->is_global ? bb_add_ph2_ir(bb, OP_global_load)
114-
: bb_add_ph2_ir(bb, OP_load);
115-
ir->src0 = var->offset;
113+
ph2_ir_t *ir;
114+
115+
/* Load constants directly, others from memory */
116+
if (var->is_const) {
117+
ir = bb_add_ph2_ir(bb, OP_load_constant);
118+
ir->src0 = var->init_val;
119+
} else {
120+
ir = var->is_global ? bb_add_ph2_ir(bb, OP_global_load)
121+
: bb_add_ph2_ir(bb, OP_load);
122+
ir->src0 = var->offset;
123+
}
124+
116125
ir->dest = idx;
117126
REGS[idx].var = var;
118127
REGS[idx].polluted = 0;
119128
}
120129

121130
int prepare_operand(basic_block_t *bb, var_t *var, int operand_0)
122131
{
132+
/* Force reload for address-taken variables (may be modified via pointer) */
123133
int i = find_in_regs(var);
124-
if (i > -1)
134+
if (i > -1 && !var->address_taken)
125135
return i;
126136

127137
for (i = 0; i < REG_CNT; i++) {
@@ -207,6 +217,16 @@ int prepare_dest(basic_block_t *bb, var_t *var, int operand_0, int operand_1)
207217

208218
void spill_alive(basic_block_t *bb, insn_t *insn)
209219
{
220+
/* Spill all locals on pointer writes (conservative aliasing handling) */
221+
if (insn && insn->opcode == OP_write) {
222+
for (int i = 0; i < REG_CNT; i++) {
223+
if (REGS[i].var && !REGS[i].var->is_global)
224+
spill_var(bb, REGS[i].var, i);
225+
}
226+
return;
227+
}
228+
229+
/* Standard spilling for non-pointer operations */
210230
for (int i = 0; i < REG_CNT; i++) {
211231
if (!REGS[i].var)
212232
continue;
@@ -471,9 +491,6 @@ void reg_alloc(void)
471491
break;
472492
case OP_load_constant:
473493
case OP_load_data_address:
474-
if (insn->rd->consumed == -1)
475-
break;
476-
477494
dest = prepare_dest(bb, insn->rd, -1, -1);
478495
ir = bb_add_ph2_ir(bb, insn->opcode);
479496
ir->src0 = insn->rd->init_val;
@@ -490,6 +507,12 @@ void reg_alloc(void)
490507
break;
491508
case OP_address_of:
492509
case OP_global_address_of:
510+
/* Mark variable as address-taken, disable constant
511+
* optimization
512+
*/
513+
insn->rs1->address_taken = true;
514+
insn->rs1->is_const = false;
515+
493516
/* make sure variable is on stack */
494517
if (!insn->rs1->offset) {
495518
insn->rs1->offset = bb->belong_to->stack_size;
@@ -500,6 +523,8 @@ void reg_alloc(void)
500523
ir = bb_add_ph2_ir(bb, OP_store);
501524
ir->src0 = i;
502525
ir->src1 = insn->rs1->offset;
526+
/* Clear stale register tracking */
527+
REGS[i].var = NULL;
503528
}
504529
}
505530

@@ -792,7 +817,7 @@ void dump_ph2_ir(void)
792817
printf("\t%%x%c = (%%x%c)", rd, rs1);
793818
break;
794819
case OP_write:
795-
printf("\t(%%x%c) = %%x%c", rs2, rs1);
820+
printf("\t(%%x%c) = %%x%c", rs1, rs2);
796821
break;
797822
case OP_address_of_func:
798823
printf("\t(%%x%c) = @%s", rs1, ph2_ir->func_name);

0 commit comments

Comments
 (0)