harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

commit ef3e7d022fcfaeeda8a7bb9a133a1e33a55e4305
parent 370029bac49b44a3f43fea025a89f44b2f20e8c7
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 27 Jul 2022 14:02:38 +0200

Implement @threadlocal globals

Diffstat:
Minclude/ast.h | 1+
Minclude/check.h | 1+
Minclude/gen.h | 1+
Minclude/lex.h | 1+
Minclude/qbe.h | 2++
Minclude/scope.h | 5+++--
Msrc/check.c | 21+++++++++++++++------
Msrc/emit.c | 9+++++++++
Msrc/gen.c | 2++
Msrc/genutil.c | 1+
Msrc/lex.c | 1+
Msrc/parse.c | 3+++
Msrc/scope.c | 4++--
Msrc/typedef.c | 3+++
14 files changed, 45 insertions(+), 10 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -360,6 +360,7 @@ struct ast_expression { struct ast_global_decl { char *symbol; + bool threadlocal; struct identifier ident; struct ast_type *type; struct ast_expression *init; diff --git a/include/check.h b/include/check.h @@ -68,6 +68,7 @@ struct function_decl { struct global_decl { const struct type *type; struct expression *value; // EXPR_CONSTANT + bool threadlocal; }; enum declaration_type { diff --git a/include/gen.h b/include/gen.h @@ -28,6 +28,7 @@ enum gen_value_kind { struct gen_value { enum gen_value_kind kind; + bool threadlocal; const struct type *type; union { char *name; diff --git a/include/lex.h b/include/lex.h @@ -15,6 +15,7 @@ enum lexical_token { T_ATTR_OFFSET, T_ATTR_SYMBOL, T_ATTR_TEST, + T_ATTR_THREADLOCAL, T_UNDERSCORE, T_ABORT, T_ALLOC, diff --git a/include/qbe.h b/include/qbe.h @@ -55,6 +55,7 @@ enum qbe_value_kind { struct qbe_value { enum qbe_value_kind kind; + bool threadlocal; const struct qbe_type *type; union { char *name; @@ -233,6 +234,7 @@ struct qbe_data_item { struct qbe_data { size_t align; char *section, *secflags; + bool threadlocal; struct qbe_data_item items; }; diff --git a/include/scope.h b/include/scope.h @@ -18,6 +18,7 @@ struct scope_object { // name is the name of the object within this scope (for lookups) // ident is the global identifier (these may be different in some cases) struct identifier name, ident; + bool threadlocal; const struct type *type; struct expression *value; // For O_CONST @@ -82,12 +83,12 @@ void scope_object_init(struct scope_object *obj, enum object_type otype, void scope_insert_from_object(struct scope *scope, struct scope_object *object); -const struct scope_object *scope_insert( +struct scope_object *scope_insert( struct scope *scope, enum object_type otype, const struct identifier *ident, const struct identifier *name, const struct type *type, struct expression *value); -const struct scope_object *scope_lookup(struct scope *scope, +struct scope_object *scope_lookup(struct scope *scope, const struct identifier *ident); #endif diff --git a/src/check.c b/src/check.c @@ -3275,6 +3275,7 @@ check_global(struct context *ctx, struct declaration *decl = xcalloc(1, sizeof(struct declaration)); decl->type = DECL_GLOBAL; decl->global.type = type; + decl->global.threadlocal = adecl->threadlocal; if (adecl->symbol) { decl->symbol = strdup(adecl->symbol); @@ -3616,7 +3617,7 @@ scan_global(struct context *ctx, const struct ast_global_decl *decl) expect(ctx, &decl->type->loc, decl->init, "Cannot infer array length without an initializer"); - // TODO: Free initialier + // TODO: Free initializer struct expression *initializer = xcalloc(1, sizeof(struct expression)); check_expression(ctx, decl->init, initializer, type); @@ -3638,7 +3639,10 @@ scan_global(struct context *ctx, const struct ast_global_decl *decl) } else { mkident(ctx, &ident, &decl->ident); } - return scope_insert(ctx->unit, O_DECL, &ident, &decl->ident, type, NULL); + struct scope_object *global = scope_insert(ctx->unit, O_DECL, + &ident, &decl->ident, type, NULL); + global->threadlocal = decl->threadlocal; + return global; } const struct scope_object * @@ -4079,8 +4083,10 @@ load_import(struct context *ctx, struct ast_imports *import, expect(ctx, &member->loc, false, "Unknown object '%s'", identifier_unparse(&ident)); } - scope_insert(scope, obj->otype, &obj->ident, - &name, obj->type, obj->value); + struct scope_object *new = scope_insert( + scope, obj->otype, &obj->ident, + &name, obj->type, obj->value); + new->threadlocal = obj->threadlocal; if (obj->otype != O_TYPE || type_dealias(obj->type)->storage != STORAGE_ENUM) { @@ -4110,10 +4116,12 @@ load_import(struct context *ctx, struct ast_imports *import, continue; } + struct scope_object *new; if (!(import->mode & AST_IMPORT_ALIAS) && import->ident.ns != NULL) { - scope_insert(scope, obj->otype, &obj->ident, + new = scope_insert(scope, obj->otype, &obj->ident, &obj->name, obj->type, obj->value); + new->threadlocal = obj->threadlocal; } struct identifier ns, name = { @@ -4128,8 +4136,9 @@ load_import(struct context *ctx, struct ast_imports *import, }; name.ns = &ns; }; - scope_insert(scope, obj->otype, &obj->ident, + new = scope_insert(scope, obj->otype, &obj->ident, &name, obj->type, obj->value); + new->threadlocal = obj->threadlocal; } } } diff --git a/src/emit.c b/src/emit.c @@ -119,6 +119,9 @@ emit_value(struct qbe_value *val, FILE *out) emit_const(val, out); break; case QV_GLOBAL: + if (val->threadlocal) { + fprintf(out, "thread "); + } fprintf(out, "$%s", val->name); break; case QV_LABEL: @@ -310,6 +313,12 @@ emit_data(struct qbe_def *def, FILE *out) def->data.section, def->data.secflags); } else if (def->data.section) { fprintf(out, "section \"%s\"", def->data.section); + } else if (def->data.threadlocal) { + if (is_zeroes(&def->data.items)) { + fprintf(out, "section \".tbss\" \"awT\""); + } else { + fprintf(out, "section \".tdata\" \"awT\""); + } } else if (is_zeroes(&def->data.items)) { fprintf(out, "section \".bss.%s\"", def->name); } else { diff --git a/src/gen.c b/src/gen.c @@ -246,6 +246,7 @@ gen_access_ident(struct gen_context *ctx, const struct expression *expr) .kind = GV_GLOBAL, .type = obj->type, .name = ident_to_sym(&obj->ident), + .threadlocal = obj->threadlocal, }; case O_CONST: case O_TYPE: @@ -3692,6 +3693,7 @@ gen_global_decl(struct gen_context *ctx, const struct declaration *decl) struct qbe_def *qdef = xcalloc(1, sizeof(struct qbe_def)); qdef->kind = Q_DATA; qdef->data.align = ALIGN_UNDEFINED; + qdef->data.threadlocal = global->threadlocal; qdef->exported = decl->exported; qdef->name = ident_to_sym(&decl->ident); gen_data_item(ctx, global->value, &qdef->data.items); diff --git a/src/genutil.c b/src/genutil.c @@ -28,6 +28,7 @@ mkqval(struct gen_context *ctx, struct gen_value *value) case GV_GLOBAL: qval.kind = QV_GLOBAL; qval.name = value->name; + qval.threadlocal = value->threadlocal; break; case GV_TEMP: qval.kind = QV_TEMPORARY; diff --git a/src/lex.c b/src/lex.c @@ -22,6 +22,7 @@ static const char *tokens[] = { [T_ATTR_OFFSET] = "@offset", [T_ATTR_SYMBOL] = "@symbol", [T_ATTR_TEST] = "@test", + [T_ATTR_THREADLOCAL] = "@threadlocal", [T_UNDERSCORE] = "_", [T_ABORT] = "abort", [T_ALLOC] = "alloc", diff --git a/src/parse.c b/src/parse.c @@ -2434,6 +2434,9 @@ parse_global_decl(struct lexer *lexer, enum lexical_token mode, case T_ATTR_SYMBOL: i->symbol = parse_attr_symbol(lexer); break; + case T_ATTR_THREADLOCAL: + i->threadlocal = true; + break; default: unlex(lexer, &tok); break; diff --git a/src/scope.c b/src/scope.c @@ -116,7 +116,7 @@ scope_insert_from_object(struct scope *scope, struct scope_object *object) *bucket = object; } -const struct scope_object * +struct scope_object * scope_insert(struct scope *scope, enum object_type otype, const struct identifier *ident, const struct identifier *name, const struct type *type, struct expression *value) @@ -127,7 +127,7 @@ scope_insert(struct scope *scope, enum object_type otype, return o; } -const struct scope_object * +struct scope_object * scope_lookup(struct scope *scope, const struct identifier *ident) { uint32_t hash = name_hash(FNV1A_INIT, ident); diff --git a/src/typedef.c b/src/typedef.c @@ -397,6 +397,9 @@ emit_decl_global(struct declaration *decl, FILE *out) if (decl->symbol) { fprintf(out, "@symbol(\"%s\") ", decl->symbol); } + if (decl->global.threadlocal) { + fprintf(out, "@threadlocal "); + } fprintf(out, "%s: ", ident); emit_exported_type(decl->global.type, out, ident); fprintf(out, ";\n");