===================================================================
@@ -1,3 +1,19 @@
+2017-12-14 Sebastian Perta <sebastian.perta@renesas.com>
+
+ * config/rl78/rl78.c (rl78_get_pragma_address): New function
+ * config/rl78/rl78.c (rl78_note_pragma_address): New function
+ * config/rl78/rl78.c (rl78_output_aligned_common): use .set instead
+ of .comm for pragma address variables
+ * config/rl78/rl78.c (rl78_insert_attributes): make pragma address
+ variables volatile
+ * config/rl78/rl78-c.c (rl78_pragma_address): New function
+ * config/rl78/rl78-c.c (rl78_register_pragmas): registered the new
+ pragma address
+ * config/rl78/rl78-protos.h: New declaration
rl78_note_pragma_address
+ * doc/entend.texi: Added documenation for RL78 pragmas
+ * testsuite/gcc.target/rl78/test_pragma_address.c: New file
+
+
2017-12-14 Andreas Schwab <schwab@linux-m68k.org>
PR bootstrap/83396
===================================================================
@@ -23,7 +23,42 @@
#include "coretypes.h"
#include "tm.h"
#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
+#include "rl78-protos.h"
+/* Implements the "pragma ADDRESS" pragma. This pragma takes a
+ variable name and an address, and arranges for that variable to be
+ "at" that address. The variable is also made volatile. */
+static void
+rl78_pragma_address (cpp_reader * reader ATTRIBUTE_UNUSED)
+{
+ /* on off */
+ tree var, addr;
+ enum cpp_ttype type;
+
+ type = pragma_lex (&var);
+ if (type == CPP_NAME)
+ {
+ type = pragma_lex (&addr);
+ if (type == CPP_NUMBER)
+ {
+ if (var != error_mark_node)
+ {
+ unsigned uaddr = tree_to_uhwi (addr);
+ rl78_note_pragma_address (IDENTIFIER_POINTER (var), uaddr);
+ }
+
+ type = pragma_lex (&var);
+ if (type != CPP_EOF)
+ {
+ error ("junk at end of #pragma ADDRESS");
+ }
+ return;
+ }
+ }
+ error ("malformed #pragma ADDRESS variable address");
+}
+
/* Implements REGISTER_TARGET_PRAGMAS. */
void
rl78_register_pragmas (void)
@@ -30,4 +65,7 @@
{
c_register_addr_space ("__near", ADDR_SPACE_NEAR);
c_register_addr_space ("__far", ADDR_SPACE_FAR);
+
+ c_register_pragma (NULL, "ADDRESS", rl78_pragma_address);
+ c_register_pragma (NULL, "address", rl78_pragma_address);
}
===================================================================
@@ -52,6 +52,7 @@
int rl78_sfr_p (rtx x);
void rl78_output_aligned_common (FILE *, tree, const char *,
int, int, int);
+void rl78_note_pragma_address (const char *varname, unsigned
address);
int rl78_one_far_p (rtx *operands, int num_operands);
===================================================================
@@ -4565,6 +4565,30 @@
fputs (str2, file);
}
+struct GTY(()) pragma_entry {
+ const char *varname;
+ unsigned address;
+};
+typedef struct pragma_entry pragma_entry;
+
+/* Hash table of pragma info. */
+static GTY(()) hash_map<nofree_string_hash, unsigned> *pragma_htab;
+
+static bool
+rl78_get_pragma_address (const char *varname, unsigned *address)
+{
+ if (!pragma_htab)
+ return false;
+
+ unsigned int *slot = pragma_htab->get (varname);
+ if (slot)
+ {
+ *address = *slot;
+ return true;
+ }
+ return false;
+}
+
void
rl78_output_aligned_common (FILE *stream,
tree decl ATTRIBUTE_UNUSED,
@@ -4571,6 +4595,7 @@
const char *name,
int size, int align, int global)
{
+ unsigned int address;
/* We intentionally don't use rl78_section_tag() here. */
if (name[0] == '@' && name[2] == '.')
{
@@ -4609,14 +4634,34 @@
assemble_name (stream, name);
fprintf (stream, "\n");
}
- fprintf (stream, "\t.comm\t");
- assemble_name (stream, name);
- fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
+ if (rl78_get_pragma_address (name, &address))
+ {
+ fprintf (stream, "\t.set ");
+ assemble_name (stream, name);
+ fprintf (stream, ", 0x%08x\n", address);
+ }
+ else
+ {
+ fprintf (stream, "\t.comm\t");
+ assemble_name (stream, name);
+ fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
+ }
}
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
+void
+rl78_note_pragma_address (const char *varname, unsigned address)
+{
+ if (!pragma_htab)
+ pragma_htab = hash_map<nofree_string_hash, unsigned>::create_ggc (31);
+
+ const char *name = ggc_strdup (varname);
+ unsigned int *slot = &pragma_htab->get_or_insert (name);
+ *slot = address;
+}
+
static void
rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED)
{
@@ -4632,6 +4677,16 @@
TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q);
}
+ /* See if we need to make #pragma address variables volatile. */
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ unsigned addr;
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ if (rl78_get_pragma_address (name, &addr))
+ {
+ TREE_THIS_VOLATILE (decl) = true;
+ }
+ }
}
#undef TARGET_ASM_INTEGER
===================================================================
@@ -21843,6 +21843,7 @@
* ARM Pragmas::
* M32C Pragmas::
* MeP Pragmas::
+* RL78 Pragmas::
* RS/6000 and PowerPC Pragmas::
* S/390 Pragmas::
* Darwin Pragmas::
@@ -21994,6 +21995,29 @@
@end table
+@node RL78 Pragmas
+@subsection RL78 Pragmas
+
+@table @code
+
+@item ADDRESS @var{name} @var{address}
+@cindex pragma, address
+For any declared symbols matching @var{name}, this does three things
+to that symbol: it forces the symbol to be located at the given
+address (a number), it forces the symbol to be volatile, and it
+changes the symbol's scope to be static. Note that this pragma does
+not work in C++ only C and that the common @code{1234H} numeric syntax
+is not supported (use @code{0x1234} instead). Please also not that
+this pragma does not work to __far variables and variables which have
+initalizers. Example:
+
+@smallexample
+#pragma ADDRESS port3 0x8000
+char port3;
+@end smallexample
+
+@end table
+
@node RS/6000 and PowerPC Pragmas
@subsection RS/6000 and PowerPC Pragmas
===================================================================
@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#pragma address x 0x8000
+int x;
+
+int main()
+{
+ if((int)&x != 0x8000)
+ {
+ abort();
+ }
+ exit(0);
+}