1/* { dg-do run { target *-*-linux* } } */
2/* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2" } */
3/* Test complex CFA value expressions.  */
4
5#include <unwind.h>
6#include <stdlib.h>
7#include <string.h>
8#include <stdio.h>
9#include <unistd.h>
10
11static _Unwind_Reason_Code
12force_unwind_stop (int version, _Unwind_Action actions,
13		   _Unwind_Exception_Class exc_class,
14		   struct _Unwind_Exception *exc_obj,
15		   struct _Unwind_Context *context,
16		   void *stop_parameter)
17{
18  if (actions & _UA_END_OF_STACK)
19    abort ();
20  return _URC_NO_REASON;
21}
22
23static void
24force_unwind ()
25{
26  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
27  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
28  exc->exception_cleanup = 0;
29
30  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
31  abort ();
32}
33
34int count;
35
36static void
37counter (void *p __attribute__((unused)))
38{
39  ++count;
40}
41
42static void
43handler (void *p __attribute__((unused)))
44{
45  if (count != 2)
46    abort ();
47  _exit (0);
48}
49
50static int __attribute__((noinline))
51fn5 (void)
52{
53  char dummy __attribute__((cleanup (counter)));
54  force_unwind ();
55  return 0;
56}
57
58void
59bar (void)
60{
61  char dummy __attribute__((cleanup (counter)));
62  fn5 ();
63}
64
65void __attribute__((noinline))
66foo (int x)
67{
68  char buf[256];
69#ifdef __i386__
70  __asm (
71	"testl	%0, %0\n\t"
72	"jnz	1f\n\t"
73	".subsection 1\n\t"
74	".type	_L_mutex_lock_%=, @function\n"
75"_L_mutex_lock_%=:\n"
76"1:\t"	"leal	%1, %%ecx\n"
77"2:\t"	"call	bar\n"
78"3:\t"	"jmp	18f\n"
79"4:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
80	".previous\n\t"
81	".section	.eh_frame,\"a\",@progbits\n"
82"5:\t"	".long	7f-6f	# Length of Common Information Entry\n"
83"6:\t"	".long	0x0	# CIE Identifier Tag\n\t"
84	".byte	0x1	# CIE Version\n\t"
85	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
86	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
87	".sleb128 -4	# CIE Data Alignment Factor\n\t"
88	".byte	0x8	# CIE RA Column\n\t"
89	".uleb128 0x1	# Augmentation size\n\t"
90	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
91	".byte	0xc	# DW_CFA_def_cfa\n\t"
92	".uleb128 0x4\n\t"
93	".uleb128 0x0\n\t"
94	".align 4\n"
95"7:\t"	".long	17f-8f	# FDE Length\n"
96"8:\t"	".long	8b-5b	# FDE CIE offset\n\t"
97	".long	1b-.	# FDE initial location\n\t"
98	".long	4b-1b	# FDE address range\n\t"
99	".uleb128 0x0	# Augmentation size\n\t"
100	".byte	0x16	# DW_CFA_val_expression\n\t"
101	".uleb128 0x8\n\t"
102	".uleb128 10f-9f\n"
103"9:\t"	".byte	0x78	# DW_OP_breg8\n\t"
104	".sleb128 3b-1b\n"
105"10:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
106	".byte	0x16	# DW_CFA_val_expression\n\t"
107	".uleb128 0x8\n\t"
108	".uleb128 12f-11f\n"
109"11:\t"	".byte	0x78	# DW_OP_breg8\n\t"
110	".sleb128 3b-2b\n"
111"12:\t"	".byte	0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t"
112	".byte	0x16	# DW_CFA_val_expression\n\t"
113	".uleb128 0x8\n\t"
114	".uleb128 16f-13f\n"
115"13:\t"	".byte	0x78	# DW_OP_breg8\n\t"
116	".sleb128 15f-14f\n\t"
117	".byte	0x0d	# DW_OP_const4s\n"
118"14:\t"	".4byte	3b-.\n\t"
119	".byte	0x1c	# DW_OP_minus\n\t"
120	".byte	0x0d	# DW_OP_const4s\n"
121"15:\t"	".4byte	18f-.\n\t"
122	".byte	0x22	# DW_OP_plus\n"
123"16:\t"	".align 4\n"
124"17:\t"	".previous\n"
125"18:"
126	: : "r" (x), "m" (x), "r" (buf)
127	: "memory", "eax", "edx", "ecx");
128#elif defined __x86_64__
129  __asm (
130	"testl	%0, %0\n\t"
131	"jnz	1f\n\t"
132	".subsection 1\n\t"
133	".type	_L_mutex_lock_%=, @function\n"
134"_L_mutex_lock_%=:\n"
135"1:\t"	"leaq	%1, %%rdi\n"
136"2:\t"	"subq	$128, %%rsp\n"
137"3:\t"	"call	bar\n"
138"4:\t"	"addq	$128, %%rsp\n"
139"5:\t"	"jmp	24f\n"
140"6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
141	".previous\n\t"
142	".section	.eh_frame,\"a\",@progbits\n"
143"7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
144"8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
145	".byte	0x1	# CIE Version\n\t"
146	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
147	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
148	".sleb128 -8	# CIE Data Alignment Factor\n\t"
149	".byte	0x10	# CIE RA Column\n\t"
150	".uleb128 0x1	# Augmentation size\n\t"
151	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
152	".byte	0x12	# DW_CFA_def_cfa_sf\n\t"
153	".uleb128 0x7\n\t"
154	".sleb128 16\n\t"
155	".align 8\n"
156"9:\t"	".long	23f-10f	# FDE Length\n"
157"10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
158	".long	1b-.	# FDE initial location\n\t"
159	".long	6b-1b	# FDE address range\n\t"
160	".uleb128 0x0	# Augmentation size\n\t"
161	".byte	0x16	# DW_CFA_val_expression\n\t"
162	".uleb128 0x10\n\t"
163	".uleb128 12f-11f\n"
164"11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
165	".sleb128 4b-1b\n"
166"12:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
167	".byte	0x16	# DW_CFA_val_expression\n\t"
168	".uleb128 0x10\n\t"
169	".uleb128 14f-13f\n"
170"13:\t"	".byte	0x80	# DW_OP_breg16\n\t"
171	".sleb128 4b-2b\n"
172"14:\t"	".byte	0x40 + (3b-2b) # DW_CFA_advance_loc\n\t"
173	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
174	".uleb128 0\n\t"
175	".byte	0x16	# DW_CFA_val_expression\n\t"
176	".uleb128 0x10\n\t"
177	".uleb128 16f-15f\n"
178"15:\t"	".byte	0x80	# DW_OP_breg16\n\t"
179	".sleb128 4b-3b\n"
180"16:\t"	".byte	0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t"
181	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
182	".uleb128 128\n\t"
183	".byte	0x16	# DW_CFA_val_expression\n\t"
184	".uleb128 0x10\n\t"
185	".uleb128 20f-17f\n"
186"17:\t"	".byte	0x80	# DW_OP_breg16\n\t"
187	".sleb128 19f-18f\n\t"
188	".byte	0x0d	# DW_OP_const4s\n"
189"18:\t"	".4byte	4b-.\n\t"
190	".byte	0x1c	# DW_OP_minus\n\t"
191	".byte	0x0d	# DW_OP_const4s\n"
192"19:\t"	".4byte	24f-.\n\t"
193	".byte	0x22	# DW_OP_plus\n"
194"20:\t"	".byte	0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t"
195	".byte	0x13	# DW_CFA_def_cfa_offset_sf\n\t"
196	".sleb128 16\n\t"
197	".byte	0x16	# DW_CFA_val_expression\n\t"
198	".uleb128 0x10\n\t"
199	".uleb128 22f-21f\n"
200"21:\t"	".byte	0x80	# DW_OP_breg16\n\t"
201	".sleb128 4b-5b\n"
202"22:\t"	".align 8\n"
203"23:\t"	".previous\n"
204"24:"
205	: : "r" (x), "m" (x), "r" (buf)
206	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
207	  "r8", "r9", "r10", "r11");
208#else
209# error Unsupported test architecture
210#endif
211}
212
213static int __attribute__((noinline))
214fn2 (void)
215{
216  foo (3);
217  return 0;
218}
219
220static int __attribute__((noinline))
221fn1 (void)
222{
223  fn2 ();
224  return 0;
225}
226
227static void *
228fn0 (void)
229{
230  char dummy __attribute__((cleanup (handler)));
231  fn1 ();
232  return 0;
233}
234
235int
236main (void)
237{
238  fn0 ();
239  return 0;
240}
241