* include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h
@ 2018-11-17 0:38 Giulio Moro
2018-11-19 7:41 ` Jan Kiszka
0 siblings, 1 reply; 6+ messages in thread
From: Giulio Moro @ 2018-11-17 0:38 UTC (permalink / raw)
To: xenomai
I have clang 3.9.1 (on Debian Stretch) on armv7.
the below minimal program clz-test.c:
```
#include <stdlib.h>
#include <arm_acle.h>
int main()
{
return __clz(0);
}
```
will fail to build when compiled with
`clang -I/usr/xenomai/include/cobalt -I/usr/xenomai/include clz-test.c` , as follows:
```
In file included from test-clz.c:2:
/usr/lib/llvm-3.9/bin/../lib/clang/3.9.1/include/arm_acle.h:142:1: error: expected identifier or '('
__clz(uint32_t __t) {
^
/usr/xenomai/include/boilerplate/compiler.h:87:3: note: expanded from macro '__clz'
({ \
^
In file included from test-clz.c:2:
/usr/lib/llvm-3.9/bin/../lib/clang/3.9.1/include/arm_acle.h:142:1: error: expected ')'
/usr/xenomai/include/boilerplate/compiler.h:87:3: note: expanded from macro '__clz'
({ \
^
/usr/lib/llvm-3.9/bin/../lib/clang/3.9.1/include/arm_acle.h:142:1: note: to match this '('
/usr/xenomai/include/boilerplate/compiler.h:87:2: note: expanded from macro '__clz'
({ \
^
2 errors generated.
```
(compiler.h is included indirectly by `stdlib.h`)
This is because clang provides a definition of __clz as an inline function in /usr/lib/llvm-3.9/lib/clang/3.9.1/include/arm_acle.h :
static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__clz(uint32_t __t) {
return __builtin_clz(__t);
}
however, xenomai-3/include/boilerplate/compiler.h defines __clz() as a macro, hence the issue.
Note that compiler.h similarly defines a macro for __ctz , but that is not defined in clang's arm_acle.h, so no issue with that one.
The patch below addresses the issue, leveraging clang's `__has_builtin()` feature, while keeping things the same for gcc:
diff --git a/include/boilerplate/compiler.h b/include/boilerplate/compiler.h
index bcef7d4cc..8697a24b0 100644
--- a/include/boilerplate/compiler.h
+++ b/include/boilerplate/compiler.h
@@ -83,6 +83,15 @@ void __invalid_operand_size(void);
__ret; \
})
+#ifdef __clang__
+#if __has_builtin(__builtin_clz)
+#define DONT_DEF_CLZ
+#endif /* has_builtin */
+#endif /* __clang_ */
+
+#ifdef DONT_DEF_CLZ
+#undef DONT_DEF_CLZ
+#else /* DONT_DEF_CLZ */
#define __clz(__v) \
({ \
int __ret; \
@@ -101,6 +110,7 @@ void __invalid_operand_size(void);
} \
__ret; \
})
+#endif /* DONT_DEF_CLZ */
#ifdef __cplusplus
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h
2018-11-17 0:38 include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h Giulio Moro
@ 2018-11-19 7:41 ` Jan Kiszka
2018-11-19 11:59 ` Giulio Moro
0 siblings, 1 reply; 6+ messages in thread
From: Jan Kiszka @ 2018-11-19 7:41 UTC (permalink / raw)
To: Giulio Moro, xenomai
On 17.11.18 01:38, Giulio Moro via Xenomai wrote:
> I have clang 3.9.1 (on Debian Stretch) on armv7.
>
> the below minimal program clz-test.c:
>
> ```
> #include <stdlib.h>
> #include <arm_acle.h>
>
> int main()
> {
> return __clz(0);
> }
> ```
>
> will fail to build when compiled with
>
> `clang -I/usr/xenomai/include/cobalt -I/usr/xenomai/include clz-test.c` , as follows:
> ```
> In file included from test-clz.c:2:
> /usr/lib/llvm-3.9/bin/../lib/clang/3.9.1/include/arm_acle.h:142:1: error: expected identifier or '('
> __clz(uint32_t __t) {
> ^
> /usr/xenomai/include/boilerplate/compiler.h:87:3: note: expanded from macro '__clz'
> ({ \
> ^
> In file included from test-clz.c:2:
> /usr/lib/llvm-3.9/bin/../lib/clang/3.9.1/include/arm_acle.h:142:1: error: expected ')'
> /usr/xenomai/include/boilerplate/compiler.h:87:3: note: expanded from macro '__clz'
> ({ \
> ^
> /usr/lib/llvm-3.9/bin/../lib/clang/3.9.1/include/arm_acle.h:142:1: note: to match this '('
> /usr/xenomai/include/boilerplate/compiler.h:87:2: note: expanded from macro '__clz'
> ({ \
> ^
> 2 errors generated.
> ```
>
> (compiler.h is included indirectly by `stdlib.h`)
>
> This is because clang provides a definition of __clz as an inline function in /usr/lib/llvm-3.9/lib/clang/3.9.1/include/arm_acle.h :
>
> static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
> __clz(uint32_t __t) {
> return __builtin_clz(__t);
> }
>
> however, xenomai-3/include/boilerplate/compiler.h defines __clz() as a macro, hence the issue.
>
> Note that compiler.h similarly defines a macro for __ctz , but that is not defined in clang's arm_acle.h, so no issue with that one.
>
> The patch below addresses the issue, leveraging clang's `__has_builtin()` feature, while keeping things the same for gcc:
>
> diff --git a/include/boilerplate/compiler.h b/include/boilerplate/compiler.h
> index bcef7d4cc..8697a24b0 100644
> --- a/include/boilerplate/compiler.h
> +++ b/include/boilerplate/compiler.h
> @@ -83,6 +83,15 @@ void __invalid_operand_size(void);
> __ret; \
> })
>
> +#ifdef __clang__
> +#if __has_builtin(__builtin_clz)
> +#define DONT_DEF_CLZ
> +#endif /* has_builtin */
> +#endif /* __clang_ */
> +
> +#ifdef DONT_DEF_CLZ
> +#undef DONT_DEF_CLZ
> +#else /* DONT_DEF_CLZ */
> #define __clz(__v) \
> ({ \
> int __ret; \
> @@ -101,6 +110,7 @@ void __invalid_operand_size(void);
> } \
> __ret; \
> })
> +#endif /* DONT_DEF_CLZ */
>
> #ifdef __cplusplus
> }
>
>
We should do
#define __clz __clz
in the clang case and then
#ifndef __clz
That should save some boilerplate code. Could you send a proper patch (see
CONTRIBUTING.md)?
Thanks!
Jan
--
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h
2018-11-19 7:41 ` Jan Kiszka
@ 2018-11-19 11:59 ` Giulio Moro
2018-11-19 12:05 ` Philippe Gerum
0 siblings, 1 reply; 6+ messages in thread
From: Giulio Moro @ 2018-11-19 11:59 UTC (permalink / raw)
To: Jan Kiszka, xenomai
right, digging deeper into the issue, ARM says that if the __ARM_ACLE macro is defined by the compiler, then it's safer to include `arm_acle.h`, which will define __clz() as a function, so a better approach could be perhaps:
#ifdef __ARM_ACLE
#include <arm_acle.h>
#else
#define __clz(__v) \
// .... currently defined code
#endif
Happy to prepare a patch for the above. On the other hand, I am not sure what the current purpose of this definition of __clz() in a public header file is:
$ grep -RI __clz .
./lib/copperplate/heapobj-pshared.c: log2size = sizeof(size) * 8 - 1 - __clz(size);
./include/boilerplate/compiler.h:#define __clz(__v)
so it's used only in lib/copperplate/heapobj-pshared.c (similarly for __ctz()) . Even if they was used in multiple places, why should they be defined in a public header, risking to cause issues when user code includes stdlib.h?
It seems to me that we can safely remove
#include <boilerplate/compiler.h>
from include/cobalt/wrappers.h in order to fix the above issue for the Cobalt API. Possibly something similar can be done for the other APIs?
Giulio
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h
2018-11-19 11:59 ` Giulio Moro
@ 2018-11-19 12:05 ` Philippe Gerum
2018-11-20 18:05 ` Giulio Moro
0 siblings, 1 reply; 6+ messages in thread
From: Philippe Gerum @ 2018-11-19 12:05 UTC (permalink / raw)
To: Giulio Moro, Jan Kiszka, xenomai
On 11/19/18 12:59 PM, Giulio Moro via Xenomai wrote:
> right, digging deeper into the issue, ARM says that if the __ARM_ACLE macro is defined by the compiler, then it's safer to include `arm_acle.h`, which will define __clz() as a function, so a better approach could be perhaps:
>
> #ifdef __ARM_ACLE
> #include <arm_acle.h>
> #else
> #define __clz(__v) \
> // .... currently defined code
> #endif
>
> Happy to prepare a patch for the above. On the other hand, I am not sure what the current purpose of this definition of __clz() in a public header file is:
>
> $ grep -RI __clz .
> ./lib/copperplate/heapobj-pshared.c: log2size = sizeof(size) * 8 - 1 - __clz(size);
> ./include/boilerplate/compiler.h:#define __clz(__v)
>
> so it's used only in lib/copperplate/heapobj-pshared.c (similarly for __ctz()) . Even if they was used in multiple places, why should they be defined in a public header, risking to cause issues when user code includes stdlib.h?
>
> It seems to me that we can safely remove
> #include <boilerplate/compiler.h>
>
> from include/cobalt/wrappers.h in order to fix the above issue for the Cobalt API. Possibly something similar can be done for the other APIs?
>
> Giulio
>
>
Why not solving the namespace clash the simplest way by renaming the
offending stuff in boilerplate/compiler.h? __clz and friends are
definitely not part of the public interface, so you only have to care
about in-tree users. __clz could be renamed as count_leading_zeroes()
without affecting the API.
--
Philippe.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h
2018-11-19 12:05 ` Philippe Gerum
@ 2018-11-20 18:05 ` Giulio Moro
2018-11-20 18:27 ` Philippe Gerum
0 siblings, 1 reply; 6+ messages in thread
From: Giulio Moro @ 2018-11-20 18:05 UTC (permalink / raw)
To: Philippe Gerum, Jan Kiszka, xenomai
> Why not solving the namespace clash the simplest way by renaming the
> offending stuff in boilerplate/compiler.h? __clz and friends are
> definitely not part of the public interface, so you only have to care
> about in-tree users. __clz could be renamed as count_leading_zeroes()
> without affecting the API.
If you want to go down this path, I'd go for xenomai_count_leading_zeros(), to give some sort of protection against further namespace conflicts.
However, I don't see why this header, and its defines, should be included with `stdlib.h` (or any other system include, fwiw) at all. Granted, I don't know much about the ins and outs of libcobalt, but, at first sight, there doesn't seem to be anything in copperplate/compiler.h that should be made available to the user.
Best,
Giulio
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h
2018-11-20 18:05 ` Giulio Moro
@ 2018-11-20 18:27 ` Philippe Gerum
0 siblings, 0 replies; 6+ messages in thread
From: Philippe Gerum @ 2018-11-20 18:27 UTC (permalink / raw)
To: Giulio Moro, Jan Kiszka, xenomai
On 11/20/18 7:05 PM, Giulio Moro wrote:
>> Why not solving the namespace clash the simplest way by renaming the
>> offending stuff in boilerplate/compiler.h? __clz and friends are
>> definitely not part of the public interface, so you only have to care
>> about in-tree users. __clz could be renamed as count_leading_zeroes()
>> without affecting the API.
>
> If you want to go down this path, I'd go for xenomai_count_leading_zeros(), to give some sort of protection against further namespace conflicts.
> However, I don't see why this header, and its defines, should be included with `stdlib.h` (or any other system include, fwiw) at all. Granted, I don't know much about the ins and outs of libcobalt, but, at first sight, there doesn't seem to be anything in copperplate/compiler.h that should be made available to the user.
container_of() must be.
This said, this is about fixing the whole issue: make the Xenomai stack
(in userland) and applications all buildable with clang. Maybe this
change won't suffice wrt to the former, but at least making the proper
change would be a step forward this goal.
--
Philippe.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-11-20 18:27 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-17 0:38 include/boilerplate/compiler.h breaks clang 3.9's arm_acle.h Giulio Moro
2018-11-19 7:41 ` Jan Kiszka
2018-11-19 11:59 ` Giulio Moro
2018-11-19 12:05 ` Philippe Gerum
2018-11-20 18:05 ` Giulio Moro
2018-11-20 18:27 ` Philippe Gerum
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.