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