aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-09-13 23:33:14 +0200
committerEugen Wissner <belka@caraus.de>2026-09-13 23:33:14 +0200
commit8cc075c6a736fdde56ca2da03a868821695765f4 (patch)
tree2dd14d3bc47e5bf00e612a0d792f5e33f2c7a81b
parent38a24d57067b657cde572f92210c5719091c88ff (diff)
downloadelna-8cc075c6a736fdde56ca2da03a868821695765f4.tar.gz
Add threadvar section for thread-local variables
-rw-r--r--boot/lexer.ll3
-rw-r--r--boot/name_analysis.cc1
-rw-r--r--boot/parser.yy11
-rw-r--r--gcc/gcc/elna-builtins.cc8
-rw-r--r--include/elna/boot/ast.h3
-rw-r--r--include/elna/boot/symbol.h3
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.
*