summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h')
-rw-r--r--gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h142
1 files changed, 142 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h b/gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h
new file mode 100644
index 000000000..ff5602784
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h
@@ -0,0 +1,142 @@
+#include "check.h"
+
+
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
+#ifdef __cplusplus
+extern "C" void abort (void);
+#else
+extern void abort (void);
+#endif
+
+extern void foo(void);
+
+#define INIT_EDI 1
+#define INIT_ESI 2
+#define INIT_EBX 3
+
+/* Set DI/SI/BX to wrong value
+ Use following template so that RA will save/restore callee
+ save registers in prologue/epilogue */
+#define ALTER_REGS() \
+ { \
+ int dummy; \
+ __asm__ __volatile__ (\
+ "movl %1, %0" : "=D" (dummy) : "i" (-INIT_EDI)\
+ );\
+ __asm__ __volatile__ (\
+ "movl %1, %0" : "=S" (dummy) : "i" (-INIT_ESI)\
+ );\
+ __asm__ __volatile__ (\
+ "movl %1, %0" : "=b" (dummy) : "i" (-INIT_EBX)\
+ );\
+ }
+
+#if defined __PIC__ || defined __USING_SJLJ_EXCEPTIONS__
+int
+main ()
+{
+ return 0;
+}
+#else
+void __attribute__ ((noinline))
+copy (char *p, int size)
+{
+ __builtin_strncpy (p, "good", size);
+}
+
+int g_edi __attribute__((externally_visible)) =INIT_EDI;
+int g_esi __attribute__((externally_visible)) =INIT_ESI;
+int g_ebx __attribute__((externally_visible)) = INIT_EBX;
+int g_ebp __attribute__((externally_visible));
+int g_esp __attribute__((externally_visible));
+int g_ebp_save __attribute__((externally_visible));
+int g_esp_save __attribute__((externally_visible));
+int n_error;
+
+int
+main()
+{
+ int dummy;
+ // Init registers to correct value.
+ // Use following template so that RA will save/restore callee
+ // save registers in prologue/epilogue
+ __asm__ __volatile__ (
+ "movl %1, %0"
+ : "=D" (dummy)
+ : "i" (INIT_EDI)
+ );
+ __asm__ __volatile__ (
+ "movl %1, %0"
+ : "=S" (dummy)
+ : "i" (INIT_ESI)
+ );
+ __asm__ __volatile__ (
+ "movl %1, %0"
+ : "=b" (dummy)
+ : "i" (INIT_EBX)
+ );
+ __asm__ __volatile__ (
+ "movl %ebp," ASMNAME("g_ebp_save")"\n\t"
+ "movl %esp," ASMNAME("g_esp_save")"\n\t"
+ );
+ try {
+ foo();
+ }
+ catch (...)
+ {
+ }
+
+ // Get DI/SI/BX register value after exception caught
+ __asm__ __volatile__ (
+ "movl %edi," ASMNAME("g_edi")"\n\t"
+ "movl %esi," ASMNAME("g_esi")"\n\t"
+ "movl %ebx," ASMNAME("g_ebx")"\n\t"
+ "movl %ebp," ASMNAME("g_ebp")"\n\t"
+ "movl %esp," ASMNAME("g_esp")"\n\t"
+ );
+
+ // Check if DI/SI/BX register value are the same as before calling
+ // foo.
+ if (g_edi != INIT_EDI)
+ {
+ n_error++;
+#ifdef DEBUG
+ printf("edi=%d, correct value:%d\n", g_edi, INIT_EDI);
+#endif
+ }
+ if (g_esi != INIT_ESI)
+ {
+ n_error++;
+#ifdef DEBUG
+ printf("esi=%d, correct value:%d\n", g_esi, INIT_ESI);
+#endif
+ }
+ if (g_ebx != INIT_EBX)
+ {
+ n_error++;
+#ifdef DEBUG
+ printf("ebx=%d, correct value:%d\n", g_ebx, INIT_EBX);
+#endif
+ }
+ if (g_ebp != g_ebp_save)
+ {
+ n_error++;
+#ifdef DEBUG
+ printf("ebp=0x%x, correct value:0x%x\n", g_ebp, g_ebp_save);
+#endif
+ }
+ if (g_esp != g_esp_save)
+ {
+ n_error++;
+#ifdef DEBUG
+ printf("esp=0x%x, correct value:0x%x\n", g_esp, g_esp_save);
+#endif
+ }
+ if (n_error !=0)
+ abort();
+ return 0;
+}
+#endif