diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-28 15:28:33 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-28 15:28:33 +0200 |
commit | 619d9b5e6848a72350126ea9c1e413fd133181e3 (patch) | |
tree | 1fe4ab734bd3b917ec4e9ef35d2c1e700a850605 | |
parent | 46f3f16b587ce781ab43a7b17698e1e565b2acf7 (diff) | |
download | busybox-w32-619d9b5e6848a72350126ea9c1e413fd133181e3.tar.gz busybox-w32-619d9b5e6848a72350126ea9c1e413fd133181e3.tar.bz2 busybox-w32-619d9b5e6848a72350126ea9c1e413fd133181e3.zip |
ash: less hackish implementation of evaltreenr()
Defining a function alias with __attribute__ ((alias("evaltree"),__noreturn__))
is not that usual, and clang had a bug which made it misunderstand
this construct.
Switch to:
ALWAYS_INLINE NORETURN evaltreenr() { evaltree(); unreachable(); }
Older gcc's do not know unreachable(), on them we pay the price of having
a few extra calls to abort():
function old new delta
evalsubshell 151 156 +5
evalpipe 357 362 +5
argstr 1141 1144 +3
On newer gcc, code size does not change.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/platform.h | 7 | ||||
-rw-r--r-- | shell/ash.c | 20 |
2 files changed, 21 insertions, 6 deletions
diff --git a/include/platform.h b/include/platform.h index 8210e5c49..ea49c7e92 100644 --- a/include/platform.h +++ b/include/platform.h | |||
@@ -45,6 +45,13 @@ | |||
45 | 45 | ||
46 | #define UNUSED_PARAM __attribute__ ((__unused__)) | 46 | #define UNUSED_PARAM __attribute__ ((__unused__)) |
47 | #define NORETURN __attribute__ ((__noreturn__)) | 47 | #define NORETURN __attribute__ ((__noreturn__)) |
48 | |||
49 | #if __GNUC_PREREQ(4,5) | ||
50 | # define bb_unreachable(altcode) __builtin_unreachable() | ||
51 | #else | ||
52 | # define bb_unreachable(altcode) altcode | ||
53 | #endif | ||
54 | |||
48 | /* "The malloc attribute is used to tell the compiler that a function | 55 | /* "The malloc attribute is used to tell the compiler that a function |
49 | * may be treated as if any non-NULL pointer it returns cannot alias | 56 | * may be treated as if any non-NULL pointer it returns cannot alias |
50 | * any other pointer valid when the function returns. This will often | 57 | * any other pointer valid when the function returns. This will often |
diff --git a/shell/ash.c b/shell/ash.c index f74fbd72f..1f5a8dae0 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6137,6 +6137,19 @@ struct backcmd { /* result of evalbackcmd */ | |||
6137 | #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ | 6137 | #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ |
6138 | static int evaltree(union node *, int); | 6138 | static int evaltree(union node *, int); |
6139 | 6139 | ||
6140 | /* An evaltree() which is known to never return. | ||
6141 | * Used to use an alias: | ||
6142 | * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__)); | ||
6143 | * but clang was reported to "transfer" noreturn-ness to evaltree() as well. | ||
6144 | */ | ||
6145 | static ALWAYS_INLINE NORETURN void | ||
6146 | evaltreenr(union node *n, int flags) | ||
6147 | { | ||
6148 | evaltree(n, flags); | ||
6149 | bb_unreachable(abort()); | ||
6150 | /* NOTREACHED */ | ||
6151 | } | ||
6152 | |||
6140 | static void FAST_FUNC | 6153 | static void FAST_FUNC |
6141 | evalbackcmd(union node *n, struct backcmd *result) | 6154 | evalbackcmd(union node *n, struct backcmd *result) |
6142 | { | 6155 | { |
@@ -6173,7 +6186,7 @@ evalbackcmd(union node *n, struct backcmd *result) | |||
6173 | */ | 6186 | */ |
6174 | eflag = 0; | 6187 | eflag = 0; |
6175 | ifsfree(); | 6188 | ifsfree(); |
6176 | evaltree(n, EV_EXIT); /* actually evaltreenr... */ | 6189 | evaltreenr(n, EV_EXIT); |
6177 | /* NOTREACHED */ | 6190 | /* NOTREACHED */ |
6178 | } | 6191 | } |
6179 | /* parent */ | 6192 | /* parent */ |
@@ -8796,11 +8809,6 @@ evaltree(union node *n, int flags) | |||
8796 | return exitstatus; | 8809 | return exitstatus; |
8797 | } | 8810 | } |
8798 | 8811 | ||
8799 | #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) | ||
8800 | static | ||
8801 | #endif | ||
8802 | int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__)); | ||
8803 | |||
8804 | static int | 8812 | static int |
8805 | skiploop(void) | 8813 | skiploop(void) |
8806 | { | 8814 | { |