From 5b59db46b2358a2084528bd64a988b95e06a1cfe Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Tue, 13 Aug 2013 15:47:01 +0200 Subject: [PATCH] introduce pet_type When we add support for arrays of structs, we will need to keep track of the definition of the struct so that outside users can generate proper code. Such defintions will be stored in a pet_type. Signed-off-by: Sven Verdoolaege --- emit.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-- include/pet.h | 14 +++++++++++ parse.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- scop.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ scop.h | 4 ++++ 5 files changed, 225 insertions(+), 5 deletions(-) diff --git a/emit.c b/emit.c index 93644e9..30bdaba 100644 --- a/emit.c +++ b/emit.c @@ -201,6 +201,67 @@ static int emit_named_multi_pw_aff(yaml_emitter_t *emitter, const char *name, return 0; } +/* Print "type" to "emitter". + */ +static int emit_type(yaml_emitter_t *emitter, struct pet_type *type) +{ + yaml_event_t event; + + if (!yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, + YAML_BLOCK_MAPPING_STYLE)) + return -1; + if (!yaml_emitter_emit(emitter, &event)) + return -1; + + if (emit_string(emitter, "name") < 0) + return -1; + if (emit_string(emitter, type->name) < 0) + return -1; + + if (emit_string(emitter, "definition") < 0) + return -1; + if (emit_string(emitter, type->definition) < 0) + return -1; + + if (!yaml_mapping_end_event_initialize(&event)) + return -1; + if (!yaml_emitter_emit(emitter, &event)) + return -1; + + return 0; +} + +/* Print the list of "n_type" "types", if any, to "emitter". + */ +static int emit_types(yaml_emitter_t *emitter, int n_type, + struct pet_type **types) +{ + int i; + yaml_event_t event; + + if (n_type == 0) + return 0; + + if (emit_string(emitter, "types") < 0) + return -1; + if (!yaml_sequence_start_event_initialize(&event, NULL, NULL, 1, + YAML_BLOCK_SEQUENCE_STYLE)) + return -1; + if (!yaml_emitter_emit(emitter, &event)) + return -1; + + for (i = 0; i < n_type; ++i) + if (emit_type(emitter, types[i]) < 0) + return -1; + + if (!yaml_sequence_end_event_initialize(&event)) + return -1; + if (!yaml_emitter_emit(emitter, &event)) + return -1; + + return 0; +} + static int emit_array(yaml_emitter_t *emitter, struct pet_array *array) { yaml_event_t event; @@ -288,7 +349,7 @@ static int emit_arrays(yaml_emitter_t *emitter, int n_array, return 0; } -static int emit_type(yaml_emitter_t *emitter, enum pet_expr_type type) +static int emit_expr_type(yaml_emitter_t *emitter, enum pet_expr_type type) { if (emit_string(emitter, pet_type_str(type)) < 0) return -1; @@ -307,7 +368,7 @@ static int emit_expr(yaml_emitter_t *emitter, struct pet_expr *expr) if (emit_string(emitter, "type") < 0) return -1; - if (emit_type(emitter, expr->type) < 0) + if (emit_expr_type(emitter, expr->type) < 0) return -1; switch (expr->type) { @@ -558,6 +619,8 @@ static int emit_scop(yaml_emitter_t *emitter, struct pet_scop *scop) emit_named_set(emitter, "context_value", scop->context_value) < 0) return -1; + if (emit_types(emitter, scop->n_type, scop->types) < 0) + return -1; if (emit_arrays(emitter, scop->n_array, scop->arrays) < 0) return -1; diff --git a/include/pet.h b/include/pet.h index a44f58a..1642763 100644 --- a/include/pet.h +++ b/include/pet.h @@ -184,6 +184,15 @@ __isl_give isl_id_to_ast_expr *pet_stmt_build_ast_exprs(struct pet_stmt *stmt, __isl_give isl_printer *pet_stmt_print_body(struct pet_stmt *stmt, __isl_take isl_printer *p, __isl_keep isl_id_to_ast_expr *ref2expr); +/* This structure represents a defined type. + * "name" is the name of the type, while "definition" is a string + * representation of its definition. + */ +struct pet_type { + char *name; + char *definition; +}; + /* context holds constraints on the parameter that ensure that * this array has a valid (i.e., non-negative) size * @@ -237,6 +246,8 @@ struct pet_implication { * context_value describes assignments to the parameters (if any) * outside of the scop. * + * The n_type types define types that may be referenced from by the arrays. + * * The n_implication implications describe implications on boolean filters. */ struct pet_scop { @@ -246,6 +257,9 @@ struct pet_scop { isl_set *context; isl_set *context_value; + int n_type; + struct pet_type **types; + int n_array; struct pet_array **arrays; diff --git a/parse.c b/parse.c index 17928db..6b8cd50 100644 --- a/parse.c +++ b/parse.c @@ -67,8 +67,8 @@ static double extract_double(isl_ctx *ctx, yaml_document_t *document, return strtod((char *) node->data.scalar.value, NULL); } -static enum pet_expr_type extract_type(isl_ctx *ctx, yaml_document_t *document, - yaml_node_t *node) +static enum pet_expr_type extract_expr_type(isl_ctx *ctx, + yaml_document_t *document, yaml_node_t *node) { if (node->type != YAML_SCALAR_NODE) isl_die(ctx, isl_error_invalid, "expecting scalar node", @@ -130,6 +130,73 @@ static __isl_give isl_multi_pw_aff *extract_multi_pw_aff(isl_ctx *ctx, (char *) node->data.scalar.value); } +/* Extract a pet_type from "node". + */ +static struct pet_type *extract_type(isl_ctx *ctx, + yaml_document_t *document, yaml_node_t *node) +{ + struct pet_type *type; + yaml_node_pair_t * pair; + + if (node->type != YAML_MAPPING_NODE) + isl_die(ctx, isl_error_invalid, "expecting mapping", + return NULL); + + type = isl_calloc_type(ctx, struct pet_type); + if (!type) + return NULL; + + for (pair = node->data.mapping.pairs.start; + pair < node->data.mapping.pairs.top; ++pair) { + yaml_node_t *key, *value; + + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) + isl_die(ctx, isl_error_invalid, "expecting scalar key", + return pet_type_free(type)); + + if (!strcmp((char *) key->data.scalar.value, "name")) + type->name = extract_string(ctx, document, value); + if (!strcmp((char *) key->data.scalar.value, "definition")) + type->definition = extract_string(ctx, document, value); + } + + return type; +} + +/* Extract a sequence of types from "node" and store them in scop->types. + */ +static struct pet_scop *extract_types(isl_ctx *ctx, + yaml_document_t *document, yaml_node_t *node, struct pet_scop *scop) +{ + int i; + yaml_node_item_t *item; + + if (node->type != YAML_SEQUENCE_NODE) + isl_die(ctx, isl_error_invalid, "expecting sequence", + return NULL); + + scop->n_type = node->data.sequence.items.top + - node->data.sequence.items.start; + scop->types = isl_calloc_array(ctx, struct pet_type *, scop->n_type); + if (!scop->types) + return pet_scop_free(scop); + + for (item = node->data.sequence.items.start, i = 0; + item < node->data.sequence.items.top; ++item, ++i) { + yaml_node_t *n; + + n = yaml_document_get_node(document, *item); + scop->types[i] = extract_type(ctx, document, n); + if (!scop->types[i]) + return pet_scop_free(scop); + } + + return scop; +} + static struct pet_array *extract_array(isl_ctx *ctx, yaml_document_t *document, yaml_node_t *node) { @@ -414,7 +481,7 @@ static struct pet_expr *extract_expr(isl_ctx *ctx, yaml_document_t *document, return pet_expr_free(expr)); if (!strcmp((char *) key->data.scalar.value, "type")) - expr->type = extract_type(ctx, document, value); + expr->type = extract_expr_type(ctx, document, value); if (!strcmp((char *) key->data.scalar.value, "arguments")) expr = extract_arguments(ctx, document, value, expr); @@ -649,6 +716,8 @@ static struct pet_scop *extract_scop(isl_ctx *ctx, yaml_document_t *document, scop->context = extract_set(ctx, document, value); if (!strcmp((char *) key->data.scalar.value, "context_value")) scop->context_value = extract_set(ctx, document, value); + if (!strcmp((char *) key->data.scalar.value, "types")) + scop = extract_types(ctx, document, value, scop); if (!strcmp((char *) key->data.scalar.value, "arrays")) scop = extract_arrays(ctx, document, value, scop); if (!strcmp((char *) key->data.scalar.value, "statements")) diff --git a/scop.c b/scop.c index f2ab134..88a2fa5 100644 --- a/scop.c +++ b/scop.c @@ -843,6 +843,40 @@ void pet_stmt_dump(struct pet_stmt *stmt) stmt_dump(stmt, 0); } +/* Allocate a new pet_type with the given "name" and "definition". + */ +struct pet_type *pet_type_alloc(isl_ctx *ctx, const char *name, + const char *definition) +{ + struct pet_type *type; + + type = isl_alloc_type(ctx, struct pet_type); + if (!type) + return NULL; + + type->name = strdup(name); + type->definition = strdup(definition); + + if (!type->name || !type->definition) + return pet_type_free(type); + + return type; +} + +/* Free "type" and return NULL. + */ +struct pet_type *pet_type_free(struct pet_type *type) +{ + if (!type) + return NULL; + + free(type->name); + free(type->definition); + + free(type); + return NULL; +} + struct pet_array *pet_array_free(struct pet_array *array) { if (!array) @@ -1395,6 +1429,10 @@ struct pet_scop *pet_scop_free(struct pet_scop *scop) return NULL; isl_set_free(scop->context); isl_set_free(scop->context_value); + if (scop->types) + for (i = 0; i < scop->n_type; ++i) + pet_type_free(scop->types[i]); + free(scop->types); if (scop->arrays) for (i = 0; i < scop->n_array; ++i) pet_array_free(scop->arrays[i]); @@ -1413,6 +1451,14 @@ struct pet_scop *pet_scop_free(struct pet_scop *scop) return NULL; } +void pet_type_dump(struct pet_type *type) +{ + if (!type) + return; + + fprintf(stderr, "%s -> %s\n", type->name, type->definition); +} + void pet_implication_dump(struct pet_implication *implication) { if (!implication) @@ -1432,6 +1478,8 @@ void pet_scop_dump(struct pet_scop *scop) isl_set_dump(scop->context); isl_set_dump(scop->context_value); + for (i = 0; i < scop->n_type; ++i) + pet_type_dump(scop->types[i]); for (i = 0; i < scop->n_array; ++i) pet_array_dump(scop->arrays[i]); for (i = 0; i < scop->n_stmt; ++i) @@ -1505,6 +1553,22 @@ int pet_stmt_is_equal(struct pet_stmt *stmt1, struct pet_stmt *stmt2) return 1; } +/* Return 1 if the two pet_types are equivalent. + * + * We only compare the names of the types since the exact representation + * of the definition may depend on the version of clang being used. + */ +int pet_type_is_equal(struct pet_type *type1, struct pet_type *type2) +{ + if (!type1 || !type2) + return 0; + + if (strcmp(type1->name, type2->name)) + return 0; + + return 1; +} + /* Return 1 if the two pet_implications are equivalent. */ int pet_implication_is_equal(struct pet_implication *implication1, @@ -1535,6 +1599,12 @@ int pet_scop_is_equal(struct pet_scop *scop1, struct pet_scop *scop2) if (!isl_set_is_equal(scop1->context_value, scop2->context_value)) return 0; + if (scop1->n_type != scop2->n_type) + return 0; + for (i = 0; i < scop1->n_type; ++i) + if (!pet_type_is_equal(scop1->types[i], scop2->types[i])) + return 0; + if (scop1->n_array != scop2->n_array) return 0; for (i = 0; i < scop1->n_array; ++i) diff --git a/scop.h b/scop.h index 6cf2970..a23a1f1 100644 --- a/scop.h +++ b/scop.h @@ -54,6 +54,10 @@ struct pet_stmt *pet_stmt_from_pet_expr(isl_ctx *ctx, int line, void pet_stmt_dump(struct pet_stmt *stmt); void *pet_stmt_free(struct pet_stmt *stmt); +struct pet_type *pet_type_alloc(isl_ctx *ctx, const char *name, + const char *definition); +struct pet_type *pet_type_free(struct pet_type *type); + void pet_array_dump(struct pet_array *array); struct pet_array *pet_array_free(struct pet_array *array); -- 2.11.4.GIT