Skip to content

Instantly share code, notes, and snippets.

@prozacchiwawa
Created September 20, 2020 04:37
Show Gist options
  • Save prozacchiwawa/a4d40b722c4f74d51fe26142b12e0d0d to your computer and use it in GitHub Desktop.
Save prozacchiwawa/a4d40b722c4f74d51fe26142b12e0d0d to your computer and use it in GitHub Desktop.
WIP designated initialisers diff.
diff --git a/tdfc2/src/common/construct/initialise.c b/tdfc2/src/common/construct/initialise.c
index 4af7a0e0f..9a0c33ed8 100644
--- a/tdfc2/src/common/construct/initialise.c
+++ b/tdfc2/src/common/construct/initialise.c
@@ -6,9 +6,11 @@
*/
#include <stdio.h>
+#include <string.h>
#include <shared/check.h>
#include <shared/error.h>
+#include <shared/xalloc.h>
#include <tdf/bitstream.h>
@@ -55,6 +57,7 @@
#include <construct/initialise.h>
#include <construct/instance.h>
#include <construct/inttype.h>
+#include <construct/in_order_inits.h>
#include <construct/namespace.h>
#include <construct/overload.h>
#include <construct/statement.h>
@@ -1381,9 +1384,14 @@ init_direct(TYPE t, EXP a, ERROR *err)
static EXP
get_aggr_elem(LIST(EXP) p, unsigned *ptag)
{
- EXP a = DEREF_exp(HEAD_list(p));
- if (!IS_NULL_exp(a)) {
- if (IS_exp_location(a)) {
+ BUFFER buf = { 0 };
+ EXP a;
+
+ buf.posn = extend_buffer(&buf, buf.posn);
+
+ if (!IS_NULL_list(p)) {
+ a = DEREF_exp(HEAD_list(p));
+ if (!IS_NULL_exp(a) && IS_exp_location(a)) {
TYPE t;
DESTROY_exp_location(destroy, t, crt_loc, a, a);
UNUSED(t);
@@ -1399,21 +1407,26 @@ get_aggr_elem(LIST(EXP) p, unsigned *ptag)
*ptag = tag;
}
}
+
+ free_buffer(&buf);
+
return a;
}
/*
- This routine checks the aggregate initialiser expression list pointed
- to by r against the type t. The argument start is 1 to indicate the
- presence of a open brace immediately preceding r and 2 to indicate
- the top-level aggregate. The result is a structured aggregate
- initialiser expression for compound types t or a suitably converted
- initialiser expression.
+ This routine checks the aggregate initialiser expression list pointed
+ to by r against the type t. The argument start is 1 to indicate the
+ presence of a open brace immediately preceding r and 2 to indicate
+ the top-level aggregate. The result is a structured aggregate
+ initialiser expression for compound types t or a suitably converted
+ initialiser expression.
+
+ If limit is BOOL_TRUE, then do not emit padding.
*/
static EXP
-init_aggr_aux(FieldIterator_t *sf_iter, TYPE t, CV_SPEC cv, LIST(EXP) *r, int start, IDENTIFIER id,
- ERROR *err)
+init_aggr_aux(FieldIterator_t *sf_iter, TYPE t, CV_SPEC cv, LIST(EXP) *r, int start, LIST(EXP) limit, IDENTIFIER id,
+ ERROR *err)
{
EXP e;
LIST(EXP) p = *r;
@@ -1472,13 +1485,13 @@ init_aggr_aux(FieldIterator_t *sf_iter, TYPE t, CV_SPEC cv, LIST(EXP) *r, int st
LIST(EXP) q;
q = DEREF_list(exp_aggregate_args(e));
field_iterator_push(sf_iter, s, cv);
- e = init_aggr_aux(sf_iter, s, cv, &q, 1, id, &serr);
+ e = init_aggr_aux(sf_iter, s, cv, &q, 1, id, limit, &serr);
field_iterator_pop(sf_iter);
p = TAIL_list(p);
} else {
/* Otherwise read constituents from p */
field_iterator_push(sf_iter, s, cv);
- e = init_aggr_aux(sf_iter, s, cv, &p, 0, id, &serr);
+ e = init_aggr_aux(sf_iter, s, cv, &p, 0, id, limit, &serr);
field_iterator_pop(sf_iter);
}
@@ -1519,7 +1532,7 @@ init_aggr_aux(FieldIterator_t *sf_iter, TYPE t, CV_SPEC cv, LIST(EXP) *r, int st
TYPE s = DEREF_type(type_ref_sub(t));
e = init_ref_rvalue(s, NULL_exp, err);
if (IS_NULL_exp(e)) {
- e = init_aggr_aux(sf_iter, s, cv, r, start, id, err);
+ e = init_aggr_aux(sf_iter, s, cv, r, start, limit, id, err);
e = make_temporary(s, e, NULL_exp, 1, err);
e = make_ref_init(t, e);
}
@@ -1597,14 +1610,14 @@ init_aggr_aux(FieldIterator_t *sf_iter, TYPE t, CV_SPEC cv, LIST(EXP) *r, int st
LIST(EXP) q;
q = DEREF_list(exp_aggregate_args(e));
field_iterator_push(sf_iter, s, cv);
- e = init_aggr_aux(sf_iter, s, local_cv, &q, 1, id,
+ e = init_aggr_aux(sf_iter, s, local_cv, &q, 1, limit, id,
&serr);
field_iterator_pop(sf_iter);
p = TAIL_list(p);
} else {
/* Otherwise read constituents from p */
field_iterator_push(sf_iter, s, cv);
- e = init_aggr_aux(sf_iter, s, local_cv, &p, 0, id,
+ e = init_aggr_aux(sf_iter, s, local_cv, &p, 0, limit, id,
&serr);
field_iterator_pop(sf_iter);
}
@@ -1665,7 +1678,7 @@ init_aggr_aux(FieldIterator_t *sf_iter, TYPE t, CV_SPEC cv, LIST(EXP) *r, int st
if (et == exp_aggregate_tag) {
LIST(EXP)q;
q = DEREF_list(exp_aggregate_args(e));
- e = init_aggr_aux(sf_iter, t, cv, &q, 1, id, err);
+ e = init_aggr_aux(sf_iter, t, cv, &q, 1, limit, id, err);
} else {
ERROR ferr = NULL_err;
if (start == 1) {
@@ -1692,7 +1705,7 @@ token_lab: {
goto non_aggregate_lab;
}
field_iterator_push(sf_iter, s, cv);
- e = init_aggr_aux(sf_iter, s, cv, r, start, id, err);
+ e = init_aggr_aux(sf_iter, s, cv, r, start, limit, id, err);
field_iterator_pop(sf_iter);
return e;
}
@@ -1739,7 +1752,7 @@ non_aggregate_lab:
if (et == exp_aggregate_tag) {
LIST(EXP) q;
q = DEREF_list(exp_aggregate_args(e));
- e = init_aggr_aux(sf_iter, t, cv, &q, 1, id, err);
+ e = init_aggr_aux(sf_iter, t, cv, &q, 1, limit, id, err);
} else {
e = convert_reference(e, REF_ASSIGN);
if (tag == type_token_tag && is_zero_exp(e)) {
@@ -1773,6 +1786,344 @@ non_aggregate_lab:
return e;
}
+static void
+bfprint_designator_exp(BUFFER *name_target, EXP e) {
+ unsigned tag = TAG_exp(e);
+
+ while (tag == exp_designated_name_tag) {
+ IDENTIFIER id = DEREF_id(exp_designated_name_member_name(e));
+ HASHID hid = DEREF_hashid(id_name(id));
+ bfputc(name_target, '.');
+ IGNORE print_hashid(hid, 1, 0, name_target, 0);
+ fprintf(stderr, "prefix match build: %s\n", name_target->start);
+ e = DEREF_exp(exp_designated_name_member_initialiser(e));
+ tag = TAG_exp(e);
+ }
+}
+
+static unsigned long subscript_compute_idx(EXP e) {
+}
+
+static void
+handle_designated_with_aggregate(FieldIterator_t *sort_iter, InitialisersInOrder_t *designated_inits,
+ TYPE t, CV_SPEC cv, LIST(EXP) *r, ERROR *err);
+
+static EXP
+designated_aggregate_wrap(FieldIterator_t *sort_iter, InitialisersInOrder_t *designated_inits, TYPE s, CV_SPEC cv, EXP inner_exp, ERROR *err) {
+ LIST(EXP) elist = NULL_list(EXP);
+ int iio_started = designated_inits->iio_cur;
+ unsigned tag = TAG_exp(inner_exp);
+
+ CONS_list(inner_exp, elist, elist);
+
+ if (tag == exp_designated_name_tag) {
+ inner_exp = exp_designated_name_member_initialiser(inner_exp);
+ handle_designated_with_aggregate(sort_iter, designated_inits, s, cv, &elist, err);
+ elist = NULL_list(EXP);
+ iio_reduce(designated_inits, iio_started, &elist);
+ MAKE_exp_aggregate(s, elist, 0, inner_exp);
+ } else if (tag == exp_designated_subscript_tag) {
+ inner_exp = exp_designated_subscript_member_initialiser(inner_exp);
+ handle_designated_with_aggregate(sort_iter, designated_inits, s, cv, &elist, err);
+ elist = NULL_list(EXP);
+ iio_reduce(designated_inits, iio_started, &elist);
+ MAKE_exp_aggregate(s, elist, 0, inner_exp);
+ } else {
+ MAKE_exp_aggregate(s, elist, 0, inner_exp);
+ }
+
+ return inner_exp;
+}
+
+/*
+ This routine checks the aggregate initialiser expression list pointed
+ to by r against the type t. The argument start is 1 to indicate the
+ presence of a open brace immediately preceding r and 2 to indicate
+ the top-level aggregate. The result is a structured aggregate
+ initialiser expression for compound types t or a suitably converted
+ initialiser expression.
+
+ Its interface mirrors init_aggr_aux, but it processes a list containing
+ designated initialisers, which need to be collected.
+
+ The result at each level is left in a new cell in designated_inits, as
+ an exp_aggregate_init if the corresponding item is aggregate, or
+ something else matching otherwise.
+
+ Leaves behind a properly bracketed expression which can be used with
+ init_aggr_aux.
+*/
+static void
+handle_designated_with_aggregate(FieldIterator_t *sort_iter, InitialisersInOrder_t *designated_inits,
+ TYPE t, CV_SPEC cv, LIST(EXP) *r, ERROR *err)
+{
+ LIST(EXP) p = *r;
+ int i = 0;
+ int iio_started = designated_inits->iio_cur;
+ unsigned type_tag = TAG_type(t);
+ EXP new_aggregate = NULL_exp;
+ NAT zero = NULL_nat;
+ LIST(EXP) result_args = NULL_list(EXP);
+
+ MAKE_nat_small(0, zero);
+
+ fprintf(stderr, "handle_designated_with_aggregate type = %u examining %s\n", TAG_type(t), sort_iter->bf->start);
+
+ if (type_tag == type_array_tag) {
+ TYPE s = DEREF_type(type_array_sub(t));
+ int str = is_char_array(s);
+ unsigned long array_bound = get_nat_value(DEREF_nat(type_array_size(t)));
+
+ while (!IS_NULL_list(p) &&
+ (array_bound == EXTENDED_MAX ||
+ field_iterator_get_index(sort_iter) < array_bound
+ ) &&
+ field_iterator_next(sort_iter))
+ {
+ unsigned tag;
+ EXP e = get_aggr_elem(p, &tag);
+
+ fprintf(stderr, "found exp type %u looking at member %s type %u\n", tag, sort_iter->bf->start, TAG_type(s));
+
+ /* Ordered to mirror init_aggr_aux */
+ if (tag == exp_string_lit_tag && str) {
+ e = init_array(t, cv, e, 0, err);
+ iio_realloc_copy_in(designated_inits, e);
+ } else if (tag == exp_aggregate_tag) {
+ LIST(EXP) inner_args = DEREF_list(exp_aggregate_args(e));
+
+ field_iterator_push(sort_iter, s, cv);
+ handle_designated_with_aggregate(sort_iter, designated_inits, s, cv, &inner_args, err);
+ field_iterator_pop(sort_iter);
+ } else if (tag == exp_designated_subscript_tag) {
+ EXP inner_exp = exp_designated_subscript_member_initialiser(e);
+ unsigned stag = TAG_type(s);
+ unsigned long extended = 0;
+ unsigned long want_index = subscript_compute_idx(e);
+ unsigned long current_idx = field_iterator_get_index(sort_iter);
+
+ while (current_idx + extended <= want_index) {
+ EXP aggregate = NULL_exp;
+
+ if (stag == type_array_tag || stag == type_compound_tag) {
+ /* XXX Put in a proper empty 0 */
+ MAKE_exp_aggregate(s, NULL_list(EXP), 0, aggregate);
+ } else {
+ /* XXX Make a better initialiser, maybe constant 0? */
+ MAKE_exp_int_lit(s, zero, BOOL_FALSE, aggregate);
+ }
+
+ iio_realloc_copy_in(designated_inits, aggregate);
+ extended++;
+ }
+
+ inner_exp = designated_aggregate_wrap(sort_iter, designated_inits, t, cv, inner_exp, err);
+ iio_replace(designated_inits, want_index, inner_exp);
+
+ /* XXX Rewind only this level of sort_iter */
+ field_iterator_rewind(sort_iter);
+
+ /* Synchronize to the current cursor */
+ while (field_iterator_get_index(sort_iter) < want_index+1) ;
+ } else {
+ iio_realloc_copy_in(designated_inits, e);
+ }
+
+ /* Any greed above may have exhausted p */
+ if (!IS_NULL_list(p)) {
+ p = TAIL_list(p);
+ }
+ }
+
+ result_args = NULL_list(EXP);
+ iio_reduce(designated_inits, iio_started, &result_args);
+ MAKE_exp_aggregate(s, result_args, 0, new_aggregate);
+ } else if (type_tag == type_compound_tag) {
+ int len_before_init = designated_inits->iio_len;
+
+ while (!IS_NULL_list(p) && field_iterator_next(sort_iter)) {
+ unsigned tag;
+ EXP e = get_aggr_elem(p, &tag);
+ TYPE s = field_iterator_get_subtype(sort_iter);
+ unsigned stag;
+
+ stag = TAG_type(s);
+
+ fprintf(stderr, "found exp type %u looking at member %s type %u\n", tag, sort_iter->bf->start, stag);
+
+ if (tag == exp_aggregate_tag) {
+ LIST(EXP) inner_args = DEREF_list(exp_aggregate_args(e));
+
+ field_iterator_push(sort_iter, s, cv);
+ handle_designated_with_aggregate(sort_iter, designated_inits, s, cv, &inner_args, err);
+ field_iterator_pop(sort_iter);
+ } else if (tag == exp_designated_name_tag) {
+ /* We've got a designated initialiser in a struct. We'll need to identify the
+ index of the branch it refers to, so we'll iterate that type to find it.
+ */
+ int search_success;
+ BUFFER have_buf = { 0 };
+ BUFFER want_buf = { 0 };
+ FieldIterator_t search_iter = { &have_buf };
+ IDENTIFIER id = DEREF_id(exp_designated_name_member_name(e));
+ HASHID hid = DEREF_hashid(id_name(id));
+ bfputc(&want_buf, '.');
+
+ IGNORE print_hashid(hid, 1, 0, &want_buf, 0);
+ field_iterator_init(&search_iter, t, cv);
+
+ while ((search_success = field_iterator_next(&search_iter))) {
+ if (strcmp(have_buf.start, want_buf.start) == 0) {
+ break;
+ }
+ }
+
+ if (search_success) {
+ EXP inner_exp;
+ unsigned long have_idx = field_iterator_get_index(sort_iter);
+ unsigned long want_idx = field_iterator_get_index(&search_iter);
+
+ /* We'll reset the iterator here, and leave with an allocated iterator.
+ the outer scope will free it.
+ */
+ field_iterator_free(&search_iter);
+
+ /* Restart the iterator so we can construct the sub-initializers properly */
+ memset(&search_iter, 0, sizeof(search_iter));
+ search_iter.bf = &have_buf;
+ field_iterator_init(&search_iter, t, cv);
+
+ while (field_iterator_next(&search_iter) && have_idx < want_idx) {
+ EXP initialiser = NULL_exp;
+ LIST(EXP) agg_list = NULL_list(EXP);
+
+ s = field_iterator_get_subtype(sort_iter);
+ stag = TAG_type(s);
+
+ MAKE_exp_int_lit(s, zero, BOOL_FALSE, initialiser);
+ fprintf(stderr, "Creating initialiser for %s\n", search_iter.bf->start);
+ inner_exp = designated_aggregate_wrap(sort_iter, designated_inits, s, cv, initialiser, err);
+ CONS_list(initialiser, agg_list, agg_list);
+
+ if (stag == type_array_tag || stag == type_compound_tag) {
+ MAKE_exp_aggregate(s, agg_list, 0, initialiser);
+ } else {
+ /* XXX ERROR, trying to initialise a non-aggregate with designated member
+ name. */
+ initialiser = NULL_exp;
+ }
+
+ iio_realloc_copy_in(designated_inits, initialiser);
+ have_idx++;
+ }
+
+ iio_seek(designated_inits, want_idx);
+ s = field_iterator_get_subtype(sort_iter);
+ stag = TAG_type(s);
+
+ inner_exp = designated_aggregate_wrap(sort_iter, designated_inits, s, cv, inner_exp, err);
+ iio_replace(designated_inits, want_idx, inner_exp);
+
+ /* XXX Rewind only this level of sort_iter */
+ field_iterator_rewind(sort_iter);
+
+ /* Synchronize to the current cursor */
+ while (field_iterator_get_index(sort_iter) < want_idx+1 && field_iterator_next(sort_iter)) ;
+ } else {
+ /* XXX Return error */
+ iio_realloc_copy_in(designated_inits, NULL_exp);
+ }
+
+ field_iterator_free(&search_iter);
+ free_buffer(&have_buf);
+ free_buffer(&want_buf);
+ } else { /* Greedy consume flat */
+ field_iterator_push(sort_iter, s, cv);
+ handle_designated_with_aggregate(sort_iter, designated_inits, s, cv, &p, err);
+ field_iterator_pop(sort_iter);
+ }
+
+ /* Above greed may have exhausted p */
+ if (!IS_NULL_list(p)) {
+ p = TAIL_list(p);
+ }
+ }
+
+ iio_reduce(designated_inits, iio_started, &result_args);
+ MAKE_exp_aggregate(t, result_args, 0, new_aggregate);
+ } else {
+ CONS_list(DEREF_exp(HEAD_list(p)), result_args, result_args);
+ MAKE_exp_aggregate(t, result_args, 0, new_aggregate);
+ p = TAIL_list(p);
+ }
+
+ iio_realloc_copy_in(designated_inits, new_aggregate);
+ *r = p;
+}
+
+void
+init_aggr_designated(FieldIterator_t *sf_iter, TYPE t, CV_SPEC cv, LIST(EXP) *r, int start, IDENTIFIER id,
+ ERROR *err)
+{
+ BUFFER sort_iter_buf = { 0 };
+ BUFFER init_buf = { 0 };
+ FieldIterator_t sort_iter = { &sort_iter_buf };
+ InitialisersInOrder_t designated_inits = { 0 };
+ int partition_start = 0;
+ int swap_at = 0;
+ int i;
+ EXP init_expr;
+ LIST(EXP) p = *r;
+ LIST(EXP) elist = NULL_list(EXP);
+
+ fprintf(stderr, "init_aggr_designated\n");
+
+ sort_iter_buf.posn = extend_buffer(&sort_iter_buf, sort_iter_buf.posn);
+ init_buf.posn = extend_buffer(&init_buf, init_buf.posn);
+
+ field_iterator_init(&sort_iter, t, cv_none);
+
+ /* Do initial copy */
+ handle_designated_with_aggregate(&sort_iter, &designated_inits, t, cv, &p, err);
+ iio_reduce(&designated_inits, 0, &elist);
+
+ iio_free(&designated_inits);
+ field_iterator_free(&sort_iter);
+ free_buffer(&sort_iter_buf);
+ free_buffer(&init_buf);
+
+ *r = elist;
+}
+
+/*
+ Determine whether we've got designated initialisers to deal with as
+ these won't allow strictly linear handling.
+
+ This traverses the list.
+*/
+
+static int
+detect_designated_initialiser(LIST(EXP) p) {
+ fprintf(stderr, "Detecting desginated\n");
+ while (!IS_NULL_list(p)) {
+ unsigned tag;
+ EXP a = get_aggr_elem(p, &tag);
+
+ if (tag == exp_designated_name_tag) {
+ fprintf(stderr, "Found a designated initialiser\n");
+ return BOOL_TRUE;
+ } else if (tag == exp_aggregate_tag) {
+ LIST(EXP) args = DEREF_list(exp_aggregate_args(a));
+ if (detect_designated_initialiser(args)) {
+ fprintf(stderr, "Found a designated initialiser\n");
+ return BOOL_TRUE;
+ }
+ }
+ p = TAIL_list(p);
+ }
+ fprintf(stderr, "No designated initialiser\n");
+ return BOOL_FALSE;
+}
/*
This is the top-level routine for analysing the aggregate initialiser
@@ -1796,7 +2147,18 @@ init_aggregate(TYPE t, EXP e, IDENTIFIER id, ERROR *err)
bad_crt_loc++;
loc = crt_loc;
field_iterator_init(&sf_iter, t, cv_none);
- e = init_aggr_aux(&sf_iter, t, cv_none, &args, 2, id, err);
+ /* If We've got one or more designated initialisers, and the feature is reqested,
+ * then do designated initialisation. */
+ if (detect_designated_initialiser(args)) {
+ fprintf(stderr, "init_aggr_designated - begin\n");
+ init_aggr_designated(&sf_iter, t, cv_none, &args, 2, id, err);
+ fprintf(stderr, "init_aggr_designated - end\n");
+ }
+
+ fprintf(stderr, "init_aggr_aux - begin\n");
+ e = init_aggr_aux(&sf_iter, t, cv_none, &args, 2, NULL_list(EXP), id, err);
+ fprintf(stderr, "init_aggr_aux - end\n");
+
field_iterator_free(&sf_iter);
free_buffer(&field_buffer);
crt_loc = loc;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment