summaryrefslogtreecommitdiff
path: root/libgcc/crtstuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/crtstuff.c')
-rw-r--r--libgcc/crtstuff.c104
1 files changed, 99 insertions, 5 deletions
diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c
index 66b2cdf2446..77b8d4201cd 100644
--- a/libgcc/crtstuff.c
+++ b/libgcc/crtstuff.c
@@ -127,6 +127,10 @@ call_ ## FUNC (void) \
# define HIDDEN_DTOR_LIST_END
#endif
+#if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF)
+# define USE_TM_CLONE_REGISTRY 1
+#endif
+
/* We do not want to add the weak attribute to the declarations of these
routines in unwind-dw2-fde.h because that will cause the definition of
these symbols to be weak as well.
@@ -163,6 +167,10 @@ extern void __do_global_ctors_1 (void);
/* Likewise for _Jv_RegisterClasses. */
extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK;
+/* Likewise for transactional memory clone tables. */
+extern void _ITM_registerTMCloneTable (void *, size_t) TARGET_ATTRIBUTE_WEAK;
+extern void _ITM_deregisterTMCloneTable (void *) TARGET_ATTRIBUTE_WEAK;
+
#ifdef OBJECT_FORMAT_ELF
/* Declare a pointer to void function type. */
@@ -242,6 +250,55 @@ STATIC void *__JCR_LIST__[]
= { };
#endif /* JCR_SECTION_NAME */
+#if USE_TM_CLONE_REGISTRY
+STATIC func_ptr __TMC_LIST__[]
+ __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void*))))
+ = { };
+# ifdef HAVE_GAS_HIDDEN
+extern func_ptr __TMC_END__[] __attribute__((__visibility__ ("hidden")));
+# endif
+
+static inline void
+deregister_tm_clones (void)
+{
+ void (*fn) (void *);
+
+#ifdef HAVE_GAS_HIDDEN
+ if (__TMC_END__ - __TMC_LIST__ == 0)
+ return;
+#else
+ if (__TMC_LIST__[0] == NULL)
+ return;
+#endif
+
+ fn = _ITM_deregisterTMCloneTable;
+ __asm ("" : "+r" (fn));
+ if (fn)
+ fn (__TMC_LIST__);
+}
+
+static inline void
+register_tm_clones (void)
+{
+ void (*fn) (void *, size_t);
+ size_t size;
+
+#ifdef HAVE_GAS_HIDDEN
+ size = (__TMC_END__ - __TMC_LIST__) / 2;
+#else
+ for (size = 0; __TMC_LIST__[size * 2] != NULL; size++)
+ continue;
+#endif
+ if (size == 0)
+ return;
+
+ fn = _ITM_registerTMCloneTable;
+ __asm ("" : "+r" (fn));
+ if (fn)
+ fn (__TMC_LIST__, size);
+}
+#endif /* USE_TM_CLONE_REGISTRY */
+
#if defined(INIT_SECTION_ASM_OP) || defined(INIT_ARRAY_SECTION_ASM_OP)
#ifdef OBJECT_FORMAT_ELF
@@ -331,6 +388,10 @@ __do_global_dtors_aux (void)
}
#endif /* !defined(FINI_ARRAY_SECTION_ASM_OP) */
+#if USE_TM_CLONE_REGISTRY
+ deregister_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
+
#ifdef USE_EH_FRAME_REGISTRY
#ifdef CRT_GET_RFIB_DATA
/* If we used the new __register_frame_info_bases interface,
@@ -362,7 +423,9 @@ __do_global_dtors_aux_1 (void)
CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_dtors_aux_1)
#endif
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+#if defined(USE_EH_FRAME_REGISTRY) \
+ || defined(JCR_SECTION_NAME) \
+ || defined(USE_TM_CLONE_REGISTRY)
/* Stick a call to __register_frame_info into the .init section. For some
reason calls with no arguments work more reliably in .init, so stick the
call in another function. */
@@ -383,6 +446,7 @@ frame_dummy (void)
__register_frame_info (__EH_FRAME_BEGIN__, &object);
#endif /* CRT_GET_RFIB_DATA */
#endif /* USE_EH_FRAME_REGISTRY */
+
#ifdef JCR_SECTION_NAME
if (__JCR_LIST__[0])
{
@@ -392,6 +456,10 @@ frame_dummy (void)
register_classes (__JCR_LIST__);
}
#endif /* JCR_SECTION_NAME */
+
+#if USE_TM_CLONE_REGISTRY
+ register_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
}
#ifdef INIT_SECTION_ASM_OP
@@ -401,7 +469,7 @@ static func_ptr __frame_dummy_init_array_entry[]
__attribute__ ((__used__, section(".init_array")))
= { frame_dummy };
#endif /* !defined(INIT_SECTION_ASM_OP) */
-#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
+#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME || USE_TM_CLONE_REGISTRY */
#else /* OBJECT_FORMAT_ELF */
@@ -458,13 +526,19 @@ __do_global_dtors (void)
for (p = __DTOR_LIST__ + 1; (f = *p); p++)
f ();
+#if USE_TM_CLONE_REGISTRY
+ deregister_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
+
#ifdef USE_EH_FRAME_REGISTRY
if (__deregister_frame_info)
__deregister_frame_info (__EH_FRAME_BEGIN__);
#endif
}
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+#if defined(USE_EH_FRAME_REGISTRY) \
+ || defined(JCR_SECTION_NAME) \
+ || defined(USE_TM_CLONE_REGISTRY)
/* A helper function for __do_global_ctors, which is in crtend.o. Here
in crtbegin.o, we can reference a couple of symbols not visible there.
Plus, since we're before libgcc.a, we have no problems referencing
@@ -477,6 +551,7 @@ __do_global_ctors_1(void)
if (__register_frame_info)
__register_frame_info (__EH_FRAME_BEGIN__, &object);
#endif
+
#ifdef JCR_SECTION_NAME
if (__JCR_LIST__[0])
{
@@ -486,8 +561,12 @@ __do_global_ctors_1(void)
register_classes (__JCR_LIST__);
}
#endif
+
+#if USE_TM_CLONE_REGISTRY
+ register_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
}
-#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
+#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME || USE_TM_CLONE_REGISTRY */
#else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
#error "What are you doing with crtstuff.c, then?"
@@ -571,6 +650,19 @@ STATIC void *__JCR_END__[1]
= { 0 };
#endif /* JCR_SECTION_NAME */
+#if USE_TM_CLONE_REGISTRY
+# ifndef HAVE_GAS_HIDDEN
+static
+# endif
+func_ptr __TMC_END__[]
+ __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void *))))
+# ifdef HAVE_GAS_HIDDEN
+ __attribute__((__visibility__ ("hidden"))) = { };
+# else
+ = { 0, 0 };
+# endif
+#endif /* USE_TM_CLONE_REGISTRY */
+
#ifdef INIT_ARRAY_SECTION_ASM_OP
/* If we are using .init_array, there is nothing to do. */
@@ -635,7 +727,9 @@ void
__do_global_ctors (void)
{
func_ptr *p;
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+#if defined(USE_EH_FRAME_REGISTRY) \
+ || defined(JCR_SECTION_NAME) \
+ || defined(USE_TM_CLONE_REGISTRY)
__do_global_ctors_1();
#endif
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)