Skip to content

Commit 9a853a3

Browse files
committed
Add a simple pointer provenance tracking scheme
1 parent ecb2c1e commit 9a853a3

File tree

9 files changed

+215
-50
lines changed

9 files changed

+215
-50
lines changed

src/jit/jit-irgen.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,11 +1370,17 @@ static void irgen_op_return(jit_irgen_t *g, mir_value_t n)
13701370
case MIR_UNIT_THUNK:
13711371
if (mir_count_args(g->mu, n) > 0)
13721372
irgen_send_args(g, n, 0);
1373-
else {
1373+
else
13741374
j_send(g, 0, jit_null_ptr()); // Procedure compiled as function
13751375

1376-
if (g->used_tlab)
1376+
if (g->used_tlab) {
1377+
const mir_mem_t mem = mir_get_mem(g->mu, mir_get_arg(g->mu, n, 0));
1378+
if (mem <= MIR_MEM_CONST)
13771379
macro_trim(g);
1380+
else if (mem == MIR_MEM_STACK) {
1381+
mir_dump(g->mu);
1382+
fatal_trace("returning pointer to stack allocation");
1383+
}
13781384
}
13791385
break;
13801386

src/mir/mir-dump.c

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -370,29 +370,46 @@ static void mir_dump_stamp(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp)
370370

371371
printf(" => ");
372372

373-
const stamp_data_t *sd = mir_stamp_data(mu, stamp);
374-
switch (sd->kind) {
375-
case _MIR_INVALID_STAMP:
376-
break;
373+
for (;;) {
374+
const stamp_data_t *sd = mir_stamp_data(mu, stamp);
375+
switch (sd->kind) {
376+
case _MIR_INVALID_STAMP:
377+
return;
378+
379+
case MIR_STAMP_INT:
380+
if (sd->u.intg.low != sd->u.intg.high) {
381+
mir_pretty_print_int(sd->u.intg.low);
382+
printf("..");
383+
mir_pretty_print_int(sd->u.intg.high);
384+
}
385+
else
386+
mir_pretty_print_int(sd->u.intg.low);
387+
return;
388+
389+
case MIR_STAMP_REAL:
390+
if (sd->u.real.low == -DBL_MAX && sd->u.real.high == DBL_MAX)
391+
printf("%%");
392+
else if (sd->u.real.low == sd->u.real.high)
393+
printf("%f", sd->u.real.low);
394+
else
395+
printf("%f..%f", sd->u.real.low, sd->u.real.high);
396+
return;
377397

378-
case MIR_STAMP_INT:
379-
if (sd->u.intg.low != sd->u.intg.high) {
380-
mir_pretty_print_int(sd->u.intg.low);
381-
printf("..");
382-
mir_pretty_print_int(sd->u.intg.high);
383-
}
384-
else
385-
mir_pretty_print_int(sd->u.intg.low);
386-
break;
398+
case MIR_STAMP_POINTER:
399+
{
400+
static const char *map[] = {
401+
"", "const", "stack", "local", "global", ""
402+
};
403+
printf("%s", map[sd->u.pointer.memory]);
387404

388-
case MIR_STAMP_REAL:
389-
if (sd->u.real.low == -DBL_MAX && sd->u.real.high == DBL_MAX)
390-
printf("%%");
391-
else if (sd->u.real.low == sd->u.real.high)
392-
printf("%f", sd->u.real.low);
393-
else
394-
printf("%f..%f", sd->u.real.low, sd->u.real.high);
395-
break;
405+
if (mir_is_null(sd->u.pointer.elem))
406+
return;
407+
408+
printf(", ");
409+
stamp = sd->u.pointer.elem;
410+
}
411+
break;
412+
}
396413
}
397414
}
398415

@@ -407,8 +424,9 @@ static int mir_dump_const_array(mir_unit_t *mu, mir_value_t value,
407424
if (td->class != MIR_TYPE_INT || td->u.intg.low < 0 || td->u.intg.high > 255)
408425
is_string = false;
409426

410-
if (!mir_is_null(n->stamp)) {
411-
const stamp_data_t *sd = mir_stamp_data(mu, n->stamp);
427+
mir_stamp_t elem = mir_stamp_elem(mu, n->stamp);
428+
if (!mir_is_null(elem)) {
429+
const stamp_data_t *sd = mir_stamp_data(mu, elem);
412430
if (sd->kind != MIR_STAMP_INT || !isprint(sd->u.intg.low)
413431
|| !isprint(sd->u.intg.high))
414432
is_string = false;
@@ -934,7 +952,7 @@ void mir_annotate(mir_unit_t *mu, const mir_annotate_t *cb, void *ctx)
934952
col += printf(" [");
935953
for (int i = 1; i < n->nargs; i += 3) {
936954
if (i > 1) col += printf(", ");
937-
mir_dump_dim(mu, result, i, cb, ctx);
955+
col += mir_dump_dim(mu, result, i, cb, ctx);
938956
}
939957
col += printf("]");
940958
mir_dump_type(mu, col, n->type);

src/mir/mir-node.c

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ mir_value_t mir_add_param(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
204204
param_data_t pd = {
205205
.name = name,
206206
.type = type,
207-
.stamp = mir_is_null(stamp) ? mir_top_stamp(mu, type) : stamp
207+
.stamp = stamp,
208208
};
209209
APUSH(mu->params, pd);
210210

@@ -216,11 +216,15 @@ mir_value_t mir_add_var(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
216216
{
217217
mir_value_t v = { .tag = MIR_TAG_VAR, .id = mu->vars.count };
218218

219+
mir_mem_t mem = MIR_MEM_STACK;
220+
if (flags & MIR_VAR_HEAP)
221+
mem = MIR_MEM_LOCAL;
222+
219223
var_data_t vd = {
220224
.name = name,
221225
.type = type,
222226
.pointer = mir_get_var_pointer(mu, type),
223-
.stamp = mir_is_null(stamp) ? mir_top_stamp(mu, type) : stamp,
227+
.stamp = mir_pointer_stamp(mu, mem, stamp),
224228
.flags = flags,
225229
};
226230
APUSH(mu->vars, vd);
@@ -536,6 +540,8 @@ mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
536540
return mir_node_data(mu, value)->stamp;
537541
case MIR_TAG_PARAM:
538542
return mir_param_data(mu, value)->stamp;
543+
case MIR_TAG_VAR:
544+
return mir_var_data(mu, value)->stamp;
539545
case MIR_TAG_CONST:
540546
{
541547
const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
@@ -546,6 +552,33 @@ mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
546552
}
547553
}
548554

555+
mir_mem_t mir_get_mem(mir_unit_t *mu, mir_value_t value)
556+
{
557+
mir_type_t type = mir_get_type(mu, value);
558+
if (mir_is_null(type))
559+
return MIR_MEM_NONE;
560+
561+
switch (mir_type_data(mu, type)->class) {
562+
case MIR_TYPE_UARRAY:
563+
case MIR_TYPE_CARRAY:
564+
case MIR_TYPE_RECORD:
565+
case MIR_TYPE_POINTER:
566+
case MIR_TYPE_ACCESS:
567+
break;
568+
default:
569+
return MIR_MEM_NONE;
570+
}
571+
572+
mir_stamp_t stamp = mir_get_stamp(mu, value);
573+
if (mir_is_null(stamp))
574+
return MIR_MEM_TOP;
575+
576+
const stamp_data_t *sd = mir_stamp_data(mu, stamp);
577+
assert(sd->kind == MIR_STAMP_POINTER);
578+
579+
return sd->u.pointer.memory;
580+
}
581+
549582
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
550583
{
551584
switch (value.tag) {
@@ -722,6 +755,27 @@ bool mir_is_const(mir_unit_t *mu, mir_value_t value)
722755
}
723756
}
724757

758+
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b)
759+
{
760+
const mir_mem_t a_mem = mir_get_mem(mu, a);
761+
if (a_mem == MIR_MEM_NONE)
762+
return false;
763+
764+
if (mir_equals(a, b))
765+
return true;
766+
767+
const mir_mem_t b_mem = mir_get_mem(mu, b);
768+
if (b_mem == MIR_MEM_NONE)
769+
return false;
770+
771+
if (a_mem == MIR_MEM_CONST || b_mem == MIR_MEM_CONST) {
772+
// Aliasing is only relevant in the presence of mutability
773+
return false;
774+
}
775+
776+
return a_mem == b_mem || a_mem == MIR_MEM_TOP || b_mem == MIR_MEM_TOP;
777+
}
778+
725779
#ifdef DEBUG
726780
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
727781
{
@@ -793,8 +847,11 @@ mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
793847
}
794848
}
795849

850+
mir_stamp_t stamp = MIR_NULL_STAMP;
796851
if (integral && low <= high)
797-
n->stamp = mir_int_stamp(mu, low, high);
852+
stamp = mir_int_stamp(mu, low, high);
853+
854+
n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
798855

799856
return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
800857
}
@@ -1319,7 +1376,7 @@ void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
13191376
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
13201377
{
13211378
mir_type_t type = mir_get_type(mu, value);
1322-
mir_stamp_t stamp = mir_get_stamp(mu, value);
1379+
mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
13231380
mir_type_t pointed = mir_get_pointer(mu, type);
13241381

13251382
mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);

src/mir/mir-node.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,15 @@ typedef enum {
294294
MIR_REPR_U64,
295295
} mir_repr_t;
296296

297+
typedef enum {
298+
MIR_MEM_NONE,
299+
MIR_MEM_CONST,
300+
MIR_MEM_STACK,
301+
MIR_MEM_LOCAL,
302+
MIR_MEM_GLOBAL,
303+
MIR_MEM_TOP,
304+
} mir_mem_t;
305+
297306
#define MIR_APPEND UINT_MAX
298307

299308
mir_type_t mir_int_type(mir_unit_t *mu, int64_t low, int64_t high);
@@ -332,7 +341,7 @@ const mir_type_t *mir_get_fields(mir_unit_t *mu, mir_type_t type,
332341

333342
mir_stamp_t mir_int_stamp(mir_unit_t *mu, int64_t low, int64_t high);
334343
mir_stamp_t mir_real_stamp(mir_unit_t *mu, double low, double high);
335-
mir_stamp_t mir_top_stamp(mir_unit_t *mu, mir_type_t type);
344+
mir_stamp_t mir_pointer_stamp(mir_unit_t *mu, mir_mem_t mem, mir_stamp_t elem);
336345

337346
mir_block_t mir_add_block(mir_unit_t *mu);
338347
void mir_set_cursor(mir_unit_t *mu, mir_block_t block, unsigned pos);
@@ -362,6 +371,7 @@ bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result);
362371
bool mir_get_const_real(mir_unit_t *mu, mir_value_t value, double *result);
363372
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value);
364373
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value);
374+
mir_mem_t mir_get_mem(mir_unit_t *mu, mir_value_t value);
365375
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value);
366376
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value);
367377
mir_var_flags_t mir_get_var_flags(mir_unit_t *mu, mir_value_t value);
@@ -380,6 +390,7 @@ bool mir_is_signal(mir_unit_t *mu, mir_value_t value);
380390
bool mir_is_offset(mir_unit_t *mu, mir_value_t value);
381391
bool mir_is(mir_unit_t *mu, mir_value_t value, mir_class_t class);
382392
bool mir_points_to(mir_unit_t *mu, mir_value_t value, mir_class_t class);
393+
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b);
383394

384395
const char *mir_op_string(mir_op_t op);
385396

src/mir/mir-priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ bool mir_is_top(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp);
5454

5555
mir_type_t mir_get_var_pointer(mir_unit_t *mu, mir_type_t type);
5656

57+
mir_stamp_t mir_stamp_elem(mir_unit_t *mu, mir_stamp_t stamp);
5758
mir_stamp_t mir_stamp_add(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right);
5859
mir_stamp_t mir_stamp_sub(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right);
5960
mir_stamp_t mir_stamp_mul(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right);

src/mir/mir-structs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,21 @@ typedef enum {
132132
_MIR_INVALID_STAMP,
133133
MIR_STAMP_INT,
134134
MIR_STAMP_REAL,
135+
MIR_STAMP_POINTER,
135136
} mir_stamp_kind_t;
136137

138+
typedef struct {
139+
mir_stamp_t elem;
140+
mir_mem_t memory;
141+
} mir_ptr_stamp_t;
142+
137143
typedef struct {
138144
mir_stamp_kind_t kind;
139145
uint32_t hash;
140146
union {
141147
mir_intg_type_t intg;
142148
mir_real_type_t real;
149+
mir_ptr_stamp_t pointer;
143150
} u;
144151
} stamp_data_t;
145152

src/mir/mir-type.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -841,9 +841,15 @@ static uint32_t mir_hash_stamp(mir_unit_t *mu, const stamp_data_t *sd)
841841
h ^= mix_bits_64(FLOAT_BITS(sd->u.real.low)) >> 32;
842842
h ^= mix_bits_64(FLOAT_BITS(sd->u.real.high));
843843
break;
844+
845+
case MIR_STAMP_POINTER:
846+
h += knuth_hash(sd->u.pointer.memory);
847+
if (!mir_is_null(sd->u.pointer.elem))
848+
h ^= mir_stamp_data(mu, sd->u.pointer.elem)->hash;
849+
break;
844850
}
845851

846-
return mix_bits_32(h);
852+
return h;
847853
}
848854

849855
static bool mir_compare_stamps(const stamp_data_t *a, const stamp_data_t *b)
@@ -862,6 +868,10 @@ static bool mir_compare_stamps(const stamp_data_t *a, const stamp_data_t *b)
862868
case MIR_STAMP_REAL:
863869
return a->u.real.low == b->u.real.low
864870
&& a->u.real.high == b->u.real.high;
871+
872+
case MIR_STAMP_POINTER:
873+
return a->u.pointer.memory == b->u.pointer.memory
874+
&& a->u.pointer.elem.bits == b->u.pointer.elem.bits;
865875
}
866876

867877
should_not_reach_here();
@@ -919,21 +929,14 @@ mir_stamp_t mir_real_stamp(mir_unit_t *mu, double low, double high)
919929
return mir_build_stamp(mu, &sd);
920930
}
921931

922-
mir_stamp_t mir_top_stamp(mir_unit_t *mu, mir_type_t type)
932+
mir_stamp_t mir_pointer_stamp(mir_unit_t *mu, mir_mem_t mem, mir_stamp_t elem)
923933
{
924-
const type_data_t *td = mir_type_data(mu, type);
925-
926-
switch (td->class) {
927-
case MIR_TYPE_INT:
928-
case MIR_TYPE_OFFSET:
929-
return mir_int_stamp(mu, td->u.intg.low, td->u.intg.high);
930-
931-
case MIR_TYPE_SIGNAL:
932-
return mir_top_stamp(mu, td->u.signal.base);
934+
const stamp_data_t sd = {
935+
.kind = MIR_STAMP_POINTER,
936+
.u = { .pointer = { .memory = mem, .elem = elem } },
937+
};
933938

934-
default:
935-
return MIR_NULL_STAMP;
936-
}
939+
return mir_build_stamp(mu, &sd);
937940
}
938941

939942
bool mir_is_top(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp)
@@ -952,6 +955,20 @@ bool mir_is_top(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp)
952955
}
953956
}
954957

958+
mir_stamp_t mir_stamp_elem(mir_unit_t *mu, mir_stamp_t stamp)
959+
{
960+
if (mir_is_null(stamp))
961+
return MIR_NULL_STAMP;
962+
963+
const stamp_data_t *sd = mir_stamp_data(mu, stamp);
964+
switch (sd->kind) {
965+
case MIR_STAMP_POINTER:
966+
return sd->u.pointer.elem;
967+
default:
968+
return MIR_NULL_STAMP;
969+
}
970+
}
971+
955972
mir_stamp_t mir_stamp_add(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
956973
{
957974
if (mir_is_null(left) || mir_is_null(right))

test/test_jit.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,13 +2033,13 @@ START_TEST(test_trim1)
20332033
int32_t delta;
20342034
} cases[] = {
20352035
{ "FUNC1()Q", +8 },
2036-
{ "FUNC2()J", +8 }, // XXX: should be 0
2037-
{ "FUNC3(I)C", +96 }, // XXX: should be 0
2036+
{ "FUNC2()J", 0 },
2037+
{ "FUNC3(I)C", 0 },
20382038
{ "FUNC4()Q", +16 }, // Context pointer plus array
20392039
{ "PROC1", 0 },
2040-
{ "FUNC5(I)I", +336 }, // XXX: should be 0
2041-
{ "FUNC6()J", +16 }, // XXX: should be 0
2042-
{ "FUNC7(I)I", +168 }, // XXX: should be 0
2040+
{ "FUNC5(I)I", 0 },
2041+
{ "FUNC6()J", 0 },
2042+
{ "FUNC7(I)I", 0 },
20432043
};
20442044

20452045
jit_handle_t pack = jit_compile(j, ident_new("WORK.TRIM1"));

0 commit comments

Comments
 (0)