Skip to content

Commit 9a94aa1

Browse files
author
Nicolas Pitre
committed
stdint.h: streamline type definitions
Compilers (at least gcc and clang) already provide definitions to create standard types and their range. For example, __INT16_TYPE__ is normally defined as a short to be used with the int16_t typedef, and __INT16_MAX__ is defined as 32767. So it makes sense to rely on them rather than hardcoding our own, especially for the fast types where the compiler itself knows what basic type is best. Using compiler provided definitions makes even more sense when dealing with 64-bit targets where some types such as intptr_t and size_t must have a different size and range. Those definitions are then adjusted by the compiler directly. However there are two cases for which we should override those definitions: * The __INT32_TYPE__ definition on 32-bit targets vary between an int and a long int depending on the architecture and configuration. Notably, all compilers shipped with the Zephyr SDK, except for the i586-zephyr-elfiamcu variant, define __INT32_TYPE__ to a long int. Whereas, all Linux configurations for gcc, both 32-bit and 64-bit, always define __INT32_TYPE__ as an int. Having variability here is not welcome as pointers to a long int and to an int are not deemed compatible by the compiler, and printing an int32_t defined with a long using %d makes the compiler to complain, even if they're the same size on 32-bit targets. Given that an int is always 32 bits on all targets we might care about, and given that Zephyr hardcoded int32_t to an int before, then we just redefine __INT32_TYPE__ and derrivatives to an int to keep the peace in the code. * The confusion also exists with __INTPTR_TYPE__. Looking again at the Zephyr SDK, it is defined as an int, even even when __INT32_TYPE__ is initially a long int. One notable exception is i586-zephyr-elf where __INTPTR_TYPE__ is a long int even when using -m32. On 64-bit targets this is always a long int. So let's redefine __INTPTR_TYPE__ to always be a long int on Zephyr which simplifies the code, works for both 32-bit and 64-bit targets, and mimics what the Linux kernel does. Only a few print format strings needed adjustment. In those two cases, there is a safeguard to ensure the type we're enforcing has the right size and fail the build otherwise. Signed-off-by: Nicolas Pitre <[email protected]>
1 parent 622ddcf commit 9a94aa1

File tree

6 files changed

+100
-51
lines changed

6 files changed

+100
-51
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ toolchain_cc_nostdinc()
217217
# @Intent: Set compiler specific macro inclusion of AUTOCONF_H
218218
toolchain_cc_imacros(${AUTOCONF_H})
219219

220+
# @Intent: Enforce standard integer type correspondance to match Zephyr usage.
221+
toolchain_cc_imacros(${ZEPHYR_BASE}/include/toolchain/zephyr_stdint.h)
222+
220223
# @Intent: Set compiler specific flag for bare metal freestanding option
221224
toolchain_cc_freestanding()
222225

arch/arm/core/cortex_m/mpu/arm_core_mpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ void z_arch_configure_dynamic_mpu_regions(struct k_thread *thread)
175175
*/
176176
continue;
177177
}
178-
LOG_DBG("set region 0x%x 0x%x",
178+
LOG_DBG("set region 0x%lx 0x%x",
179179
partition.start, partition.size);
180180
__ASSERT(region_num < _MAX_DYNAMIC_MPU_REGIONS_NUM,
181181
"Out-of-bounds error for dynamic region map.");

include/toolchain/zephyr_stdint.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2019 BayLibre SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_STDINT_H_
8+
#define ZEPHYR_INCLUDE_TOOLCHAIN_STDINT_H_
9+
10+
/*
11+
* Some gcc versions and/or configurations as found in the Zephyr SDK
12+
* (questionably) define __INT32_TYPE__ and derrivatives as a long int
13+
* which makes the printf format checker to complain about long vs int
14+
* mismatch when %u is given a u32_t argument, and u32_t pointers not
15+
* being compatible with int pointers. Let's redefine them to follow
16+
* common expectations and usage.
17+
*/
18+
19+
#if __SIZEOF_INT__ != 4
20+
#error "unexpected int width"
21+
#endif
22+
23+
#undef __INT32_TYPE__
24+
#undef __UINT32_TYPE__
25+
#undef __INT_LEAST32_TYPE__
26+
#undef __UINT_LEAST32_TYPE__
27+
#define __INT32_TYPE__ int
28+
#define __UINT32_TYPE__ unsigned int
29+
#define __INT_LEAST32_TYPE__ __INT32_TYPE__
30+
#define __UINT_LEAST32_TYPE__ __UINT32_TYPE__
31+
32+
/*
33+
* The confusion also exists with __INTPTR_TYPE__ which is either an int
34+
* (even when __INT32_TYPE__ is a long int) or a long int. Let's redefine
35+
* it to a long int to get some uniformity. Doing so also makes it compatible
36+
* with LP64 (64-bit) targets where a long is always 64-bit wide.
37+
*/
38+
39+
#if __SIZEOF_POINTER__ != __SIZEOF_LONG__
40+
#error "unexpected size difference between pointers and long ints"
41+
#endif
42+
43+
#undef __INTPTR_TYPE__
44+
#undef __UINTPTR_TYPE__
45+
#define __INTPTR_TYPE__ long int
46+
#define __UINTPTR_TYPE__ long unsigned int
47+
48+
#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_STDINT_H_ */

kernel/mem_domain.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static bool sane_partition(const struct k_mem_partition *part,
3131

3232
if (exec && write) {
3333
__ASSERT(false,
34-
"partition is writable and executable <start %x>",
34+
"partition is writable and executable <start %lx>",
3535
part->start);
3636
return false;
3737
}
@@ -59,7 +59,7 @@ static bool sane_partition(const struct k_mem_partition *part,
5959
if ((cur_write && exec) || (cur_exec && write)) {
6060
__ASSERT(false, "overlapping partitions are "
6161
"writable and executable "
62-
"<%x...%x>, <%x...%x>",
62+
"<%lx...%x>, <%lx...%x>",
6363
part->start, last,
6464
parts[i].start, cur_last);
6565
return false;

lib/libc/minimal/include/inttypes.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,36 @@
1414
#define PRId16 "d" /* int16_t */
1515
#define PRId32 "d" /* int32_t */
1616
#define PRId64 "lld" /* int64_t */
17-
#define PRIdPTR "d" /* intptr_t */
17+
#define PRIdPTR "ld" /* intptr_t */
1818

1919
#define PRIi8 "i" /* int8_t */
2020
#define PRIi16 "i" /* int16_t */
2121
#define PRIi32 "i" /* int32_t */
2222
#define PRIi64 "lli" /* int64_t */
23-
#define PRIiPTR "i" /* intptr_t */
23+
#define PRIiPTR "li" /* intptr_t */
2424

2525
#define PRIo8 "o" /* int8_t */
2626
#define PRIo16 "o" /* int16_t */
2727
#define PRIo32 "o" /* int32_t */
2828
#define PRIo64 "llo" /* int64_t */
29-
#define PRIoPTR "o" /* intptr_t */
29+
#define PRIoPTR "lo" /* intptr_t */
3030

3131
#define PRIu8 "u" /* uint8_t */
3232
#define PRIu16 "u" /* uint16_t */
3333
#define PRIu32 "u" /* uint32_t */
3434
#define PRIu64 "llu" /* uint64_t */
35-
#define PRIuPTR "u" /* uintptr_t */
35+
#define PRIuPTR "lu" /* uintptr_t */
3636

3737
#define PRIx8 "x" /* uint8_t */
3838
#define PRIx16 "x" /* uint16_t */
3939
#define PRIx32 "x" /* uint32_t */
4040
#define PRIx64 "llx" /* uint64_t */
41-
#define PRIxPTR "x" /* uintptr_t */
41+
#define PRIxPTR "lx" /* uintptr_t */
4242

4343
#define PRIX8 "X" /* uint8_t */
4444
#define PRIX16 "X" /* uint16_t */
4545
#define PRIX32 "X" /* uint32_t */
4646
#define PRIX64 "llX" /* uint64_t */
47-
#define PRIXPTR "X" /* uintptr_t */
47+
#define PRIXPTR "lX" /* uintptr_t */
4848

4949
#endif

lib/libc/minimal/include/stdint.h

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,64 +13,62 @@
1313
extern "C" {
1414
#endif
1515

16-
#define INT8_MAX 0x7F
17-
#define INT16_MAX 0x7FFF
18-
#define INT32_MAX 0x7FFFFFFF
19-
#define INT64_MAX 0x7FFFFFFFFFFFFFFFLL
16+
#define INT8_MAX __INT8_MAX__
17+
#define INT16_MAX __INT16_MAX__
18+
#define INT32_MAX __INT32_MAX__
19+
#define INT64_MAX __INT64_MAX__
2020

2121
#define INT8_MIN (-INT8_MAX - 1)
2222
#define INT16_MIN (-INT16_MAX - 1)
2323
#define INT32_MIN (-INT32_MAX - 1)
2424
#define INT64_MIN (-INT64_MAX - 1LL)
2525

26-
#define UINT8_MAX 0xFF
27-
#define UINT16_MAX 0xFFFF
28-
#define UINT32_MAX 0xFFFFFFFFU
29-
#define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL
26+
#define UINT8_MAX __UINT8_MAX__
27+
#define UINT16_MAX __UINT16_MAX__
28+
#define UINT32_MAX __UINT32_MAX__
29+
#define UINT64_MAX __UINT64_MAX__
3030

31-
#define INTPTR_MIN INT32_MIN
32-
#define INTPTR_MAX INT32_MAX
33-
#define UINTPTR_MAX UINT32_MAX
31+
#define INTPTR_MAX __INTPTR_MAX__
32+
#define INTPTR_MIN (-INTPTR_MAX - 1)
33+
#define UINTPTR_MAX __UINTPTR_MAX__
3434

35-
#define PTRDIFF_MIN INT32_MIN
36-
#define PTRDIFF_MAX INT32_MAX
35+
#define PTRDIFF_MAX __PTRDIFF_MAX__
36+
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
3737

38-
#define SIZE_MAX UINT32_MAX
38+
#define SIZE_MAX __SIZE_MAX__
3939

40-
typedef signed char int8_t;
41-
typedef signed short int16_t;
42-
typedef signed int int32_t;
43-
typedef signed long long int64_t;
40+
typedef __INT8_TYPE__ int8_t;
41+
typedef __INT16_TYPE__ int16_t;
42+
typedef __INT32_TYPE__ int32_t;
43+
typedef __INT64_TYPE__ int64_t;
4444

45-
/* Assume int to be the fastest type for all types except 64bit ones */
45+
typedef __INT_FAST8_TYPE__ int_fast8_t;
46+
typedef __INT_FAST16_TYPE__ int_fast16_t;
47+
typedef __INT_FAST32_TYPE__ int_fast32_t;
48+
typedef __INT_FAST64_TYPE__ int_fast64_t;
4649

47-
typedef signed int int_fast8_t;
48-
typedef signed int int_fast16_t;
49-
typedef signed int int_fast32_t;
50-
typedef signed long long int_fast64_t;
50+
typedef __INT_LEAST8_TYPE__ int_least8_t;
51+
typedef __INT_LEAST16_TYPE__ int_least16_t;
52+
typedef __INT_LEAST32_TYPE__ int_least32_t;
53+
typedef __INT_LEAST64_TYPE__ int_least64_t;
5154

52-
typedef signed char int_least8_t;
53-
typedef signed short int_least16_t;
54-
typedef signed int int_least32_t;
55-
typedef signed long long int_least64_t;
55+
typedef __UINT8_TYPE__ uint8_t;
56+
typedef __UINT16_TYPE__ uint16_t;
57+
typedef __UINT32_TYPE__ uint32_t;
58+
typedef __UINT64_TYPE__ uint64_t;
5659

57-
typedef unsigned char uint8_t;
58-
typedef unsigned short uint16_t;
59-
typedef unsigned int uint32_t;
60-
typedef unsigned long long uint64_t;
60+
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
61+
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
62+
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
63+
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
6164

62-
typedef unsigned int uint_fast8_t;
63-
typedef unsigned int uint_fast16_t;
64-
typedef unsigned int uint_fast32_t;
65-
typedef unsigned long long uint_fast64_t;
65+
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
66+
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
67+
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
68+
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
6669

67-
typedef unsigned char uint_least8_t;
68-
typedef unsigned short uint_least16_t;
69-
typedef unsigned int uint_least32_t;
70-
typedef unsigned long long uint_least64_t;
71-
72-
typedef int intptr_t;
73-
typedef unsigned int uintptr_t;
70+
typedef __INTPTR_TYPE__ intptr_t;
71+
typedef __UINTPTR_TYPE__ uintptr_t;
7472

7573
#ifdef __cplusplus
7674
}

0 commit comments

Comments
 (0)