Understanding definition of mp_uint_t and UINT_FMT in mpconfigport.h

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
tomlogic
Posts: 13
Joined: Tue Jul 19, 2016 10:20 pm

Understanding definition of mp_uint_t and UINT_FMT in mpconfigport.h

Post by tomlogic » Thu Mar 02, 2017 10:16 pm

I've been working on a port of MicroPython as a component of existing framework for an ARM-based platform using an IAR compiler, and I'm trying to understand the relationship between mp_uint_t and UINT_FMT as defined in mpconfigport.h. The plan is to have this code work on other hardware platforms supported by this framework, so I'm trying to use existing macros/types for portability.

I'm seeing that bare-arm and qemu-arm platforms use uint32_t and "%lu" which would only make sense if uint32_t is defined as an unsigned long. I thought the Cortex-M was a 32-bit platform (and therefore uses 32-bit integers), which would mean that "%lu" is potentially the wrong format to use when printing the value of an mp_uint_t variable. Unless both "unsigned" and "unsigned long" are 32 bits, in which case "%u" would work just as well as "%lu".

I would expect to see "%lu" for a 16-bit platform where unsigned is 16 bits, pointers are 32 bits and mp_uint_t is therefore an unsigned long.

I was planning to just use macros and types from inttypes.h and stdint.h as follows (and which should work for POSIX platforms). Is this safe, or have I misunderstood the purpose of these macros/types?

Code: Select all

#define UINT_FMT  "%" PRIuPTR    // printf specifier for mp_uint_t
#define INT_FMT   "%" PRIdPTR    // printf specifier for mp_int_t
typedef intptr_t  mp_int_t;      // signed integer same size as a pointer
typedef uintptr_t mp_uint_t;     // unsigned integer same size as a pointer

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Understanding definition of mp_uint_t and UINT_FMT in mpconfigport.h

Post by dhylands » Fri Mar 03, 2017 6:30 am

The compiler will complain if you try and use printf with %u and unsigned long, or %lu and unsigned, even though unsigned and unsigned long are both 32-bits. %lu logically belongs to unsigned long and %u logically belongs to unsigned.

And yes, unsigned long and unsigned are both 32 bits on the arm.

There is a subtle difference. unsigned long is guaranteed to be able to hold a pointer, where unsigned is not, and I believe that the compiler may generate warnings when casting pointers to ints which aren't declared using long, even if they are the same size.

My recollection is that mp_int_t and mp_uint_t need to be types which are large enough to store a pointer.

tomlogic
Posts: 13
Joined: Tue Jul 19, 2016 10:20 pm

Re: Understanding definition of mp_uint_t and UINT_FMT in mpconfigport.h

Post by tomlogic » Fri Mar 03, 2017 6:45 am

dhylands wrote:My recollection is that mp_int_t and mp_uint_t need to be types which are large enough to store a pointer.
If that's the case, I believe my configuration is a good portable method of setting up those types and macros, assuming a platform has inttypes.h and stdint.h as defined in C99. Since intptr_t is a signed integer large enough to store a pointer and PRIdPTR is the matching printf specifier for that type.

Thanks for the feedback.

Post Reply