aubinator: Add support for enum types

Signed-off-by: Kristian H. Kristensen <hoegsberg@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
Kristian H. Kristensen 2016-11-28 22:40:23 -08:00
parent 7fc659d8d5
commit d3d7cab812
2 changed files with 93 additions and 40 deletions

View File

@ -52,6 +52,8 @@ struct gen_spec {
struct gen_group *structs[256];
int nregisters;
struct gen_group *registers[256];
int nenums;
struct gen_enum *enums[256];
};
struct location {
@ -66,10 +68,14 @@ struct parser_context {
const char *platform;
struct gen_group *group;
struct gen_enum *enoom;
int nfields;
struct gen_field *fields[128];
int nvalues;
struct gen_value *values[256];
struct gen_spec *spec;
};
@ -105,6 +111,16 @@ gen_spec_find_register(struct gen_spec *spec, uint32_t offset)
return NULL;
}
struct gen_enum *
gen_spec_find_enum(struct gen_spec *spec, const char *name)
{
for (int i = 0; i < spec->nenums; i++)
if (strcmp(spec->enums[i]->name, name) == 0)
return spec->enums[i];
return NULL;
}
uint32_t
gen_spec_get_gen(struct gen_spec *spec)
{
@ -169,6 +185,20 @@ create_group(struct parser_context *ctx, const char *name, const char **atts)
return group;
}
static struct gen_enum *
create_enum(struct parser_context *ctx, const char *name, const char **atts)
{
struct gen_enum *e;
e = xzalloc(sizeof(*e));
if (name)
e->name = xstrdup(name);
e->nvalues = 0;
return e;
}
static void
get_group_offset_count(struct parser_context *ctx, const char *name,
const char **atts, uint32_t *offset, uint32_t *count)
@ -248,6 +278,7 @@ string_to_type(struct parser_context *ctx, const char *s)
{
int i, f;
struct gen_group *g;
struct gen_enum *e;
if (strcmp(s, "int") == 0)
return (struct gen_type) { .kind = GEN_TYPE_INT };
@ -267,6 +298,8 @@ string_to_type(struct parser_context *ctx, const char *s)
return (struct gen_type) { .kind = GEN_TYPE_SFIXED, .i = i, .f = f };
else if (g = gen_spec_find_struct(ctx->spec, s), g != NULL)
return (struct gen_type) { .kind = GEN_TYPE_STRUCT, .gen_struct = g };
else if (e = gen_spec_find_enum(ctx->spec, s), e != NULL)
return (struct gen_type) { .kind = GEN_TYPE_ENUM, .gen_enum = e };
else if (strcmp(s, "mbo") == 0)
return (struct gen_type) { .kind = GEN_TYPE_MBO };
else
@ -366,23 +399,9 @@ start_element(void *data, const char *element_name, const char **atts)
ctx->group->group_count--;
} while (ctx->group->group_count > 0);
} else if (strcmp(element_name, "enum") == 0) {
ctx->enoom = create_enum(ctx, name, atts);
} else if (strcmp(element_name, "value") == 0) {
if (ctx->nfields > 0) {
struct gen_field *field = ctx->fields[ctx->nfields - 1];
if (field->n_allocated_values <= field->n_values) {
if (field->n_allocated_values == 0) {
field->n_allocated_values = 2;
field->values =
xzalloc(sizeof(field->values[0]) * field->n_allocated_values);
} else {
field->n_allocated_values *= 2;
field->values =
realloc(field->values,
sizeof(field->values[0]) * field->n_allocated_values);
}
}
field->values[field->n_values++] = create_value(ctx, atts);
}
ctx->values[ctx->nvalues++] = create_value(ctx, atts);
}
}
@ -390,6 +409,7 @@ static void
end_element(void *data, const char *name)
{
struct parser_context *ctx = data;
struct gen_spec *spec = ctx->spec;
if (strcmp(name, "instruction") == 0 ||
strcmp(name, "struct") == 0 ||
@ -414,7 +434,6 @@ end_element(void *data, const char *name)
}
}
struct gen_spec *spec = ctx->spec;
if (strcmp(name, "instruction") == 0)
spec->commands[spec->ncommands++] = group;
else if (strcmp(name, "struct") == 0)
@ -424,6 +443,23 @@ end_element(void *data, const char *name)
} else if (strcmp(name, "group") == 0) {
ctx->group->group_offset = 0;
ctx->group->group_count = 0;
} else if (strcmp(name, "field") == 0) {
assert(ctx->nfields > 0);
struct gen_field *field = ctx->fields[ctx->nfields - 1];
size_t size = ctx->nvalues * sizeof(ctx->values[0]);
field->inline_enum.values = xzalloc(size);
field->inline_enum.nvalues = ctx->nvalues;
memcpy(field->inline_enum.values, ctx->values, size);
ctx->nvalues = 0;
} else if (strcmp(name, "enum") == 0) {
struct gen_enum *e = ctx->enoom;
size_t size = ctx->nvalues * sizeof(ctx->values[0]);
e->values = xzalloc(size);
e->nvalues = ctx->nvalues;
memcpy(e->values, ctx->values, size);
ctx->nvalues = 0;
ctx->enoom = NULL;
spec->enums[spec->nenums++] = e;
}
}
@ -637,13 +673,12 @@ gen_field_iterator_init(struct gen_field_iterator *iter,
}
static void
gen_field_write_value(char *str, size_t max_length,
struct gen_field *field,
uint64_t value)
gen_enum_write_value(char *str, size_t max_length,
struct gen_enum *e, uint64_t value)
{
for (int i = 0; i < field->n_values; i++) {
if (field->values[i]->value == value) {
strncpy(str, field->values[i]->name, max_length);
for (int i = 0; i < e->nvalues; i++) {
if (e->values[i]->value == value) {
strncpy(str, e->values[i]->name, max_length);
return;
}
}
@ -678,16 +713,16 @@ gen_field_iterator_next(struct gen_field_iterator *iter)
uint64_t value = field(v.qw, f->start, f->end);
snprintf(iter->value, sizeof(iter->value),
"%"PRId64, value);
gen_field_write_value(iter->description, sizeof(iter->description),
f, value);
gen_enum_write_value(iter->description, sizeof(iter->description),
&f->inline_enum, value);
break;
}
case GEN_TYPE_UINT: {
uint64_t value = field(v.qw, f->start, f->end);
snprintf(iter->value, sizeof(iter->value),
"%"PRIu64, value);
gen_field_write_value(iter->description, sizeof(iter->description),
f, value);
gen_enum_write_value(iter->description, sizeof(iter->description),
&f->inline_enum, value);
break;
}
case GEN_TYPE_BOOL: {
@ -719,6 +754,14 @@ gen_field_iterator_next(struct gen_field_iterator *iter)
break;
case GEN_TYPE_MBO:
break;
case GEN_TYPE_ENUM: {
uint64_t value = field(v.qw, f->start, f->end);
snprintf(iter->value, sizeof(iter->value),
"%"PRId64, value);
gen_enum_write_value(iter->description, sizeof(iter->description),
f->type.gen_enum, value);
break;
}
}
return true;

View File

@ -48,6 +48,7 @@ struct gen_group *gen_spec_find_register(struct gen_spec *spec, uint32_t offset)
int gen_group_get_length(struct gen_group *group, const uint32_t *p);
const char *gen_group_get_name(struct gen_group *group);
uint32_t gen_group_get_opcode(struct gen_group *group);
struct gen_enum *gen_spec_find_enum(struct gen_spec *spec, const char *name);
struct gen_field_iterator {
struct gen_group *group;
@ -72,6 +73,17 @@ struct gen_group {
uint32_t register_offset;
};
struct gen_value {
char *name;
uint64_t value;
};
struct gen_enum {
char *name;
int nvalues;
struct gen_value **values;
};
struct gen_type {
enum {
GEN_TYPE_UNKNOWN,
@ -84,14 +96,19 @@ struct gen_type {
GEN_TYPE_STRUCT,
GEN_TYPE_UFIXED,
GEN_TYPE_SFIXED,
GEN_TYPE_MBO
GEN_TYPE_MBO,
GEN_TYPE_ENUM
} kind;
/* Struct definition for GEN_TYPE_STRUCT */
struct gen_group *gen_struct;
/* Integer and fractional sizes for GEN_TYPE_UFIXED and GEN_TYPE_SFIXED */
int i, f;
union {
struct gen_group *gen_struct;
struct gen_enum *gen_enum;
struct {
/* Integer and fractional sizes for GEN_TYPE_UFIXED and GEN_TYPE_SFIXED */
int i, f;
};
};
};
struct gen_field {
@ -101,14 +118,7 @@ struct gen_field {
bool has_default;
uint32_t default_value;
struct gen_value **values;
uint32_t n_values;
uint32_t n_allocated_values;
};
struct gen_value {
char *name;
uint64_t value;
struct gen_enum inline_enum;
};
void gen_field_iterator_init(struct gen_field_iterator *iter,