summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h
blob: ff5602784935067b3a3ed5d18886835b8907a876 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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