diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-09-13 23:33:14 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-09-13 23:33:14 +0200 |
| commit | 8cc075c6a736fdde56ca2da03a868821695765f4 (patch) | |
| tree | 2dd14d3bc47e5bf00e612a0d792f5e33f2c7a81b | |
| parent | 38a24d57067b657cde572f92210c5719091c88ff (diff) | |
| download | elna-8cc075c6a736fdde56ca2da03a868821695765f4.tar.gz | |
Add threadvar section for thread-local variables
| -rw-r--r-- | boot/lexer.ll | 3 | ||||
| -rw-r--r-- | boot/name_analysis.cc | 1 | ||||
| -rw-r--r-- | boot/parser.yy | 11 | ||||
| -rw-r--r-- | gcc/gcc/elna-builtins.cc | 8 | ||||
| -rw-r--r-- | include/elna/boot/ast.h | 3 | ||||
| -rw-r--r-- | include/elna/boot/symbol.h | 3 |
6 files changed, 29 insertions, 0 deletions
diff --git a/boot/lexer.ll b/boot/lexer.ll index 89eb4ed..1cccd35 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -134,6 +134,9 @@ const { var { return yy::parser::make_VAR(this->location); } +threadvar { + return yy::parser::make_THREADVAR(this->location); +} type { return yy::parser::make_TYPE(this->location); } diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index d5b2e91..8820684 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -1419,6 +1419,7 @@ namespace elna::boot variable_symbol->alignment = evaluate_attributes<attribute_kind::aligned>(variable_identifier.attributes).alignment; variable_symbol->value = computed; + variable_symbol->is_thread_local = declaration->is_thread_local; } } diff --git a/boot/parser.yy b/boot/parser.yy index 68af60e..ab386fe 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -100,6 +100,7 @@ along with GCC; see the file COPYING3. If not see NIL "nil" CONST "const" VAR "var" + THREADVAR "threadvar" PROCEDURE "proc" TYPE "type" RECORD "record" @@ -191,6 +192,16 @@ module_declaration: $$.insert($$.end(), variables.begin(), variables.end()); } + | "threadvar" variable_declarations + { + std::vector<boot::variable_declaration *> variables = $2; + + for (boot::variable_declaration *const variable : variables) + { + variable->is_thread_local = true; + } + $$.insert($$.end(), variables.begin(), variables.end()); + } | procedure_declaration { $$.emplace_back($1); } module_declarations: %empty {} diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index a8e54c8..365ddb9 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "elna/gcc/elna1.h" #include "stor-layout.h" #include "stringpool.h" +#include "varasm.h" #include "elna/boot/evaluator.h" #include "elna/gcc/elna-tree.h" @@ -413,6 +414,13 @@ namespace elna::gcc DECL_EXTERNAL(declaration_tree) = static_cast<unsigned>(imported || variable_info->is_extern); + + // The model depends on the linkage, so it is chosen after + // DECL_EXTERNAL is final. + if (variable_info->is_thread_local) + { + set_decl_tls_model(declaration_tree, decl_default_tls_model(declaration_tree)); + } } else if (auto procedure_info = symbol_info->is_procedure()) { diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 5d5bdce..ffc57de 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -606,6 +606,9 @@ namespace elna::boot type_expression& variable_type(); expression *initializer{ nullptr }; const bool is_extern{ false }; + + /// Whether the variable was declared in a \c threadvar section. + bool is_thread_local{ false }; }; /** diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 1ca5deb..08292bc 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -487,6 +487,9 @@ namespace elna::boot /// its type's own alignment. std::optional<std::size_t> alignment; + /// Whether the variable has thread storage duration. + bool is_thread_local{ false }; + /** * Constructs a variable symbol information. * |
