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" } } */
|