aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/decl.cc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-06-23 18:24:07 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-06-24 20:49:58 +0200
commit91418c42089cd1cbe71edcd6b2f5b26559819372 (patch)
tree6419c5301b4fb08e5b0cac64baddc66f7e3acadf /gcc/d/decl.cc
parent8288cd635fa0bd75a8c5f25c7a90d4a7a4acec81 (diff)
downloadgcc-91418c42089cd1cbe71edcd6b2f5b26559819372.zip
gcc-91418c42089cd1cbe71edcd6b2f5b26559819372.tar.gz
gcc-91418c42089cd1cbe71edcd6b2f5b26559819372.tar.bz2
d: Add `@register' attribute to compiler and library.
The `@register` attribute specifies that a local or `__gshared` variable is to be given a register storage-class in the C sense of the term, and will be placed into a register named `registerName`. The variable needs to boiled down to a data type that fits the target register. It also cannot have either thread-local or `extern` storage. It is an error to take the address of a register variable. PR d/105413 gcc/d/ChangeLog: * d-attribs.cc (d_handle_register_attribute): New function. (d_langhook_attribute_table): Add register attribute. * d-codegen.cc (d_mark_addressable): Error if taken address of register variable. (build_frame_type): Error if register variable has non-local references. * d-tree.h (d_mark_addressable): Add complain parameter. * decl.cc (get_symbol_decl): Mark register varibles DECL_REGISTER. Error when register variable declared thread-local or extern. * expr.cc (ExprVisitor::visit (IndexExp *)): Don't complain about marking register vectors as addressable in an ARRAY_REF. libphobos/ChangeLog: * libdruntime/gcc/attributes.d (register): Define. gcc/testsuite/ChangeLog: * gdc.dg/attr_register1.d: New test. * gdc.dg/attr_register2.d: New test. * gdc.dg/attr_register3.d: New test.
Diffstat (limited to 'gcc/d/decl.cc')
-rw-r--r--gcc/d/decl.cc24
1 files changed, 22 insertions, 2 deletions
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index b82e2d5..5032ae0 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -670,10 +670,14 @@ public:
rest_of_decl_compilation (decl, 1, 0);
}
}
- else if (d->isDataseg () && !(d->storage_class & STCextern))
+ else if (d->isDataseg ())
{
tree decl = get_symbol_decl (d);
+ /* Only need to build the VAR_DECL for extern declarations. */
+ if (d->storage_class & STCextern)
+ return;
+
/* Duplicated VarDeclarations map to the same symbol. Check if this
is the one declaration which will be emitted. */
tree ident = DECL_ASSEMBLER_NAME (decl);
@@ -1343,7 +1347,11 @@ get_symbol_decl (Declaration *decl)
if (decl->storage_class & STCvolatile)
TREE_THIS_VOLATILE (decl->csym) = 1;
- /* Likewise, so could the deprecated attribute. */
+ /* Symbol was marked register. */
+ if (decl->storage_class & STCregister)
+ DECL_REGISTER (decl->csym) = 1;
+
+ /* Symbol was declared with deprecated attribute. */
if (decl->storage_class & STCdeprecated)
TREE_DEPRECATED (decl->csym) = 1;
@@ -1376,6 +1384,18 @@ get_symbol_decl (Declaration *decl)
/* Apply any user attributes that may affect semantic meaning. */
apply_user_attributes (decl, decl->csym);
+ /* Handle any conflicts between D language attributes and compiler-recognized
+ * user attributes. */
+ if (VAR_P (decl->csym) && DECL_HARD_REGISTER (decl->csym))
+ {
+ if (decl->storage_class & STCextern)
+ error_at (make_location_t (decl->loc), "explicit register variable "
+ "%qs declared %<extern%>", decl->toChars ());
+ else if (decl->isThreadlocal ())
+ error_at (make_location_t (decl->loc), "explicit register variable "
+ "%qs declared thread local", decl->toChars ());
+ }
+
/* %% Probably should be a little more intelligent about setting this. */
TREE_USED (decl->csym) = 1;
d_keep (decl->csym);