153 lines
4.5 KiB
C
153 lines
4.5 KiB
C
#include "spl_attr.h"
|
|
|
|
static spl_attr_info_t spl_builtin_attrs[] = {
|
|
{NULL, "extern", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_DECL, SPL_ATTR_REQUIRED, 1, 1},
|
|
{NULL, "inline", SPL_ATTR_STAGE_OPT, SPL_ATTR_TARGET_DECL, SPL_ATTR_OPTIONAL, 0, 0},
|
|
{NULL, "noinline", SPL_ATTR_STAGE_OPT, SPL_ATTR_TARGET_DECL, SPL_ATTR_OPTIONAL, 0, 0},
|
|
{NULL, "align", SPL_ATTR_STAGE_LAYOUT, SPL_ATTR_TARGET_TYPE, SPL_ATTR_REQUIRED, 1, 1},
|
|
{NULL, "volatile", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_EXPR, SPL_ATTR_REQUIRED, 0, 0},
|
|
{NULL, "atomic", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_EXPR, SPL_ATTR_REQUIRED, 0, 1},
|
|
};
|
|
|
|
void spl_attr_init(spl_attr_t *ctx) {
|
|
vec_init(ctx->table);
|
|
vec_push(ctx->table, (spl_attr_node_t){0});
|
|
vec_init(ctx->registry);
|
|
spl_attr_register_builtins(ctx);
|
|
}
|
|
|
|
void spl_attr_drop(spl_attr_t *ctx) {
|
|
for (usize i = 1; i < vec_size(ctx->table); ++i)
|
|
vec_free(vec_at(ctx->table, i).args);
|
|
vec_free(ctx->table);
|
|
vec_free(ctx->registry);
|
|
}
|
|
|
|
spl_attr_id_t spl_attr_alloc(spl_attr_t *ctx, spl_attr_info_t *info, spl_attr_arg_vec_t args) {
|
|
spl_attr_node_t a = {0};
|
|
a.info = info;
|
|
a.args = args;
|
|
vec_push(ctx->table, a);
|
|
return vec_size(ctx->table) - 1;
|
|
}
|
|
|
|
spl_attr_node_t *spl_attr_node(const spl_attr_t *ctx, spl_attr_id_t id) {
|
|
if (!id || id >= vec_size(ctx->table))
|
|
return NULL;
|
|
return &vec_at(ctx->table, id);
|
|
}
|
|
|
|
void spl_attr_registry_add(spl_attr_t *ctx, spl_attr_info_t *info) {
|
|
vec_push(ctx->registry, info);
|
|
}
|
|
|
|
static int name_eq(const char *a, const char *b) {
|
|
if (a == NULL && b == NULL)
|
|
return 1;
|
|
if (a == NULL || b == NULL)
|
|
return 0;
|
|
return strcmp(a, b) == 0;
|
|
}
|
|
|
|
spl_attr_info_t *spl_attr_lookup(spl_attr_t *ctx, const char *ns, const char *name) {
|
|
for (usize i = 0; i < vec_size(ctx->registry); ++i) {
|
|
spl_attr_info_t *info = vec_at(ctx->registry, i);
|
|
if (name_eq(info->ns, ns) && strcmp(info->name, name) == 0)
|
|
return info;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void spl_attr_register_builtins(spl_attr_t *ctx) {
|
|
usize n = sizeof(spl_builtin_attrs) / sizeof(spl_builtin_attrs[0]);
|
|
for (usize i = 0; i < n; ++i)
|
|
spl_attr_registry_add(ctx, &spl_builtin_attrs[i]);
|
|
}
|
|
|
|
static const char *attr_stage_name(spl_attr_stage_t s) {
|
|
switch (s) {
|
|
case SPL_ATTR_STAGE_SEMA:
|
|
return "SEMA";
|
|
case SPL_ATTR_STAGE_LAYOUT:
|
|
return "LAYOUT";
|
|
case SPL_ATTR_STAGE_IR:
|
|
return "IR";
|
|
case SPL_ATTR_STAGE_OPT:
|
|
return "OPT";
|
|
case SPL_ATTR_STAGE_BACKEND:
|
|
return "BACKEND";
|
|
}
|
|
return "?";
|
|
}
|
|
|
|
static const char *attr_target_name(spl_attr_target_t t) {
|
|
switch (t) {
|
|
case SPL_ATTR_TARGET_DECL:
|
|
return "DECL";
|
|
case SPL_ATTR_TARGET_TYPE:
|
|
return "TYPE";
|
|
case SPL_ATTR_TARGET_EXPR:
|
|
return "EXPR";
|
|
case SPL_ATTR_TARGET_STMT:
|
|
return "STMT";
|
|
}
|
|
return "?";
|
|
}
|
|
|
|
static const char *attr_demand_name(spl_attr_demand_t d) {
|
|
return d == SPL_ATTR_REQUIRED ? "REQUIRED" : "OPTIONAL";
|
|
}
|
|
|
|
void spl_attr_dump_id(const spl_attr_t *ctx, spl_attr_id_t id) {
|
|
if (!ctx || !id) {
|
|
printf("?");
|
|
return;
|
|
}
|
|
spl_attr_node_t *a = spl_attr_node(ctx, id);
|
|
if (!a || !a->info) {
|
|
printf("?");
|
|
return;
|
|
}
|
|
printf("%s", a->info->name);
|
|
if (vec_size(a->args) > 0) {
|
|
printf("(");
|
|
for (usize i = 0; i < vec_size(a->args); ++i) {
|
|
if (i > 0)
|
|
printf(", ");
|
|
spl_attr_arg_t *arg = &vec_at(a->args, i);
|
|
switch (arg->kind) {
|
|
case SPL_ATTR_ARG_INT:
|
|
printf("%zd", arg->value.i);
|
|
break;
|
|
case SPL_ATTR_ARG_STR:
|
|
printf("\"%s\"", arg->value.s ? arg->value.s : "");
|
|
break;
|
|
case SPL_ATTR_ARG_DEF:
|
|
printf("def#%zu", arg->value.d);
|
|
break;
|
|
case SPL_ATTR_ARG_TYPE:
|
|
printf("type#%zu", arg->value.t);
|
|
break;
|
|
}
|
|
}
|
|
printf(")");
|
|
}
|
|
}
|
|
|
|
void spl_attr_dump(const spl_attr_t *ctx) {
|
|
if (!ctx)
|
|
return;
|
|
printf("AttrTable:\n");
|
|
for (usize i = 1; i < vec_size(ctx->table); ++i) {
|
|
spl_attr_node_t *a = &vec_at(ctx->table, i);
|
|
printf(" #%zu ", i);
|
|
spl_attr_dump_id(ctx, i);
|
|
if (a->info) {
|
|
printf(" [stage=%s target=%s demand=%s consumed=0x%x]", attr_stage_name(a->info->stage),
|
|
attr_target_name(a->info->target), attr_demand_name(a->info->demand),
|
|
a->consumed_mask);
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|