summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.target/arm/long-calls-1.c
blob: f10f10606a6cfceedde69ade83c9174f5e9fdcd7 (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
/* Check that long calls to different sections are not optimized to "bl".  */
/* { dg-do compile { target { arm32 && nonpic } } } */
/* { dg-options "-O2" } */
/* This test expects that short calls are the default.  */
/* { dg-skip-if "-mlong-calls in use" { "*-*-*" } { "-mlong-calls" } { "" } } */

#define section(S) __attribute__((section(S)))
#define weak __attribute__((weak))
#define noinline __attribute__((noinline))
#define long_call __attribute__((long_call))
#define short_call __attribute__((short_call))

#define REMOTE_CALL(ID, TARGET_ATTRS, CALL_ATTRS)			\
  const char *TARGET_ATTRS ID (void);					\
  const char *CALL_ATTRS call_##ID (void) { return ID () + 1; }

#define EXTERN_CALL(ID, TARGET_ATTRS, CALL_ATTRS)			\
  const char *TARGET_ATTRS noinline ID (void) { return #ID; }		\
  const char *CALL_ATTRS call_##ID (void) { return ID () + 1; }		\
  const char *CALL_ATTRS sibcall_##ID (void) { return ID (); }

#define STATIC_CALL(ID, TARGET_ATTRS, CALL_ATTRS)			\
  static const char *TARGET_ATTRS noinline ID (void) { return #ID; }	\
  const char *CALL_ATTRS call_##ID (void) { return ID () + 1; }		\
  const char *CALL_ATTRS sibcall_##ID (void) { return ID (); }

#define DO_TESTS_SECTION(ID, TEST, TARGET_ATTRS)			\
  TEST (ID##1, TARGET_ATTRS, )						\
  TEST (ID##2, TARGET_ATTRS section (".test.a"), section (".test.b"))	\
  TEST (ID##3, TARGET_ATTRS section (".test.c"), section (".test.c"))

#define DO_TESTS_CALL_ATTR(ID, TEST, TARGET_ATTRS)			\
  DO_TESTS_SECTION (ID##n, TEST, TARGET_ATTRS)				\
  DO_TESTS_SECTION (ID##l, TEST, TARGET_ATTRS long_call)		\
  DO_TESTS_SECTION (ID##s, TEST, TARGET_ATTRS short_call)

DO_TESTS_CALL_ATTR (remote_, REMOTE_CALL,)
DO_TESTS_CALL_ATTR (strong_, EXTERN_CALL,)
DO_TESTS_CALL_ATTR (weak_, EXTERN_CALL, weak)
DO_TESTS_CALL_ATTR (static_, STATIC_CALL,)


/* Calls to remote_* should honor the call type attribute,
   with "short" being the default.

   In the regular expressions below:
   
   * We allow both "b" and "bl" in some cases to allow for the
     possibility of sibling calls.  As of this writing, GCC does not
     use sibling calls in Thumb-2 mode.  */

/* { dg-final { scan-assembler "\tbl\tremote_n1\n" } } */
/* { dg-final { scan-assembler "\tbl\tremote_n2\n" } } */
/* { dg-final { scan-assembler "\tbl\tremote_n3\n" } } */

/* { dg-final { scan-assembler-not "\tbl\tremote_l1\n" } } */
/* { dg-final { scan-assembler-not "\tbl\tremote_l2\n" } } */
/* { dg-final { scan-assembler-not "\tbl\tremote_l3\n" } } */

/* { dg-final { scan-assembler "\tbl\tremote_s1\n" } } */
/* { dg-final { scan-assembler "\tbl\tremote_s2\n" } } */
/* { dg-final { scan-assembler "\tbl\tremote_s3\n" } } */


/* Calls to strong_*2 calls should honor the call type attribute,
   with "short" being the default.  Calls to other strong_* functions
   should be short.  */

/* { dg-final { scan-assembler "\tbl\tstrong_n1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_n1\n" } } */
/* { dg-final { scan-assembler "\tbl\tstrong_n2\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_n2\n" } } */
/* { dg-final { scan-assembler "\tbl\tstrong_n3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_n3\n" } } */

/* { dg-final { scan-assembler "\tbl\tstrong_l1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_l1\n" } } */
/* { dg-final { scan-assembler-not "\tbl?\tstrong_l2\n" } } */
/* { dg-final { scan-assembler "\tbl\tstrong_l3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_l3\n" } } */

/* { dg-final { scan-assembler "\tbl\tstrong_s1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_s1\n" } } */
/* { dg-final { scan-assembler "\tbl\tstrong_s2\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_s2\n" } } */
/* { dg-final { scan-assembler "\tbl\tstrong_s3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstrong_s3\n" } } */


/* Calls to weak_* should honor the call type attribute,
   with "short" being the default.  */

/* { dg-final { scan-assembler "\tbl\tweak_n1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tweak_n1\n" } } */
/* { dg-final { scan-assembler "\tbl\tweak_n2\n" } } */
/* { dg-final { scan-assembler "\tbl?\tweak_n2\n" } } */
/* { dg-final { scan-assembler "\tbl\tweak_n3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tweak_n3\n" } } */

/* { dg-final { scan-assembler-not "\tbl?\tweak_l1\n" } } */
/* { dg-final { scan-assembler-not "\tbl?\tweak_l2\n" } } */
/* { dg-final { scan-assembler-not "\tbl?\tweak_l3\n" } } */

/* { dg-final { scan-assembler "\tbl\tweak_s1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tweak_s1\n" } } */
/* { dg-final { scan-assembler "\tbl\tweak_s2\n" } } */
/* { dg-final { scan-assembler "\tbl?\tweak_s2\n" } } */
/* { dg-final { scan-assembler "\tbl\tweak_s3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tweak_s3\n" } } */


/* Calls to static_*2 calls should honor the call type attribute,
   with "short" being the default.  Calls to other static_* functions
   should be short.  */

/* { dg-final { scan-assembler "\tbl\tstatic_n1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_n1\n" } } */
/* { dg-final { scan-assembler "\tbl\tstatic_n2\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_n2\n" } } */
/* { dg-final { scan-assembler "\tbl\tstatic_n3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_n3\n" } } */

/* { dg-final { scan-assembler "\tbl\tstatic_l1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_l1\n" } } */
/* { dg-final { scan-assembler-not "\tbl?\tstatic_l2\n" } } */
/* { dg-final { scan-assembler "\tbl\tstatic_l3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_l3\n" } } */

/* { dg-final { scan-assembler "\tbl\tstatic_s1\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_s1\n" } } */
/* { dg-final { scan-assembler "\tbl\tstatic_s2\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_s2\n" } } */
/* { dg-final { scan-assembler "\tbl\tstatic_s3\n" } } */
/* { dg-final { scan-assembler "\tbl?\tstatic_s3\n" } } */