Using data model LLP64 with riscv64

Hi everyone!

We are currently working on porting legacy code for embedded systems from x86_64 windows systems to the riscv64 architecture.

However, we are faced with the problem that the data type ‘long’ is no longer 32 bit wide.
A few decades ago, we assumed that the ‘long’ data type always remains 32 bit wide and we would like to keep it that way. This choice is known as data model LLP64 [1].

Is there an easy possibility to change the used data model from LP64 to LLP64 when using the clang target triple riscv64-unknown-?

We are OS-independent, because we have our own implementation of the standard libraries.

Our considerations included:

  • asking ourselves whether there is a hidden switch to select the data model. But we didn’t find any.
  • creating a new target triple, which uses the LLP64 data model when compiling for riscv64.

What do you think is the best way to do it?

Best regards,
Alex

[1] 64-bit computing - Wikipedia

1 Like

Seems like your best bet would be to search and replace “long” with some typedef across your whole codebase. If your code is independent of windows APIs you can just use int32_t everywhere, but if you need to interoperate with windows apis in some build mode, you might want to use a different typedef that expands to “long” on windows and int32_t otherwise.

1 Like

@jyknight Thanks for the answer!

Do you know whether int32_t has to be defined as the fist 32 bit interger type from this list?:
signed char, short, int, long, long long

or can the C++ implementation choose any of them, as long as it is 32 bit wide?
I guess the common practice is to choose int, if it’s possible.

In the final draft of C++20 I found this:

The header defines all types and macros the same as the C standard library header <stdint.h>

– ISO/IEC JTC1 SC22 WG21 N4860, Section 17.4.1 “Header synopsis” [cstdint.syn], Paragraph 2

And the C Standard doesn’t seem to specify any preference.

The stdint.h typedefs may have any of them as their underlying type, so long as it’s the correct width. Although in practice I believe every common platform where sizeof(int) == 4 has made int32_t a typedef for int. For int64_t, there’s no such consistency, however. Some LP64 platforms (e.g. with sizeof(long) == sizeof(long long) == 8) have made int64_t a typedef for long long, while others have made it a typedef for long.

That’s interesting – the info about int64_t.

Some additional info, just for anyone stumbling across this thread:
The field clang::TransferrableTargetInfo::LongWidth (https://github.com/llvm/llvm-project/blob/03ed395149184776f588d5e9dbb0dd1683f468c5/clang/include/clang/Basic/TargetInfo.h#L75) seems to be the place, where the size of long is taken from. It’s overriden in many derived classes.