Can a C compiler generate a 64-bit executable where pointers are 32-bits?

32
Most programs fit well in address space of less than 4GB, but in some cases the program may need to use the new processor features / instructions that are only available in the x64 architecture. Unfortunately the normal procedure would be to generate a 64-bit executable and gaining the cost of the pointers being twice the size.

There are specific applications in which most data structures have a large part of their pointer elements. Big pointers will produce cache miss (en) more often and if you will not use memory beyond the 4GB, 64-bit pointers are pure waste.

Are there compilers where I can use x64-specific registers and instructions, but preserving 32-bit pointers to save memory? On what platforms?

Is it possible to do this transparently in legacy code? Is there a switch / flag to link this in the compiler?

If you can not work with legacy code, what do you need to change in code to get the 64-bit features while maintaining 32-bit pointers?

I know this is only advantageous if this memory savings really matters.

    
asked by anonymous 15.01.2014 / 02:37

2 answers

29

Yes, this is possible.

However, understand that this is not a change as simple as it seems. 32-bit libraries expect you to pass arguments to records in a given format, and that pointers are 4 bytes. The 64-bits use another incompatible shape and the 8-byte pointers. If you are going to use 4-byte pointers and all the rest of the resources equal to what it would be in 64-bits, neither version of the library will be compatible with your program. This basically means that you will need to compile all of the libraries you will use in this format.

Another problem is in the kernel. When making a system call , arguments are also passed differently. Then you will also need special kernel support to run such a program.

This is implemented as a new architecture, the x32:

Wikipedia

To compile a program in x32 mode, you will need a fairly modern linux environment:

  • Linux 64-bit version 3.4 compiled with the CONFIG_X86_X32 option.
  • GLIBC 2.16
  • GCC 4.7
  • Binutils 2.22

My default ubuntu installation comes with these requirements. Compiling a program in x32 mode is simple: add the flag -mx32 to gcc. I was able to run compiled programs without any additional procedure and looking at the generated assembly makes it clear that 64-bit registers are used, even with 32-bit pointers.

Since it is a relatively new feature (integrated with the kernel at the end of 2011) and little used (ie little tested in production), it is possible that minor problems can be found.

If you do not want to change architecture and prefer something more "stable", another option would be to change all pointers to uint32_t and do a conversion whenever necessary. There is no loss of performance since this conversion does not generate instructions. However there is the problem of the pointer pointing to something beyond the 4GB. This will happen, for example, for all the pointers of the stack, since the stack starts at the end of the process virtual memory.

    
15.01.2014 / 11:36
0

I do not know if it helps, but in Visual C ++ there is the /LARGEADDRESSAWARE link flag, which allows a 32bits executable to access up to 3 gigs of RAM instead of 2 when running on a 64-bit version of Windows. p>

I use this at work because we have a program that often needs to allocate more than 2 gigs.

According to the flag documentation , you can pass /LARGEADDRESSAWARE:NO to programs 64 , which limits these programs to 2 gigabytes of RAM. It is possible that this will cause the pointers to also be in 32 bits, but I have not checked.

    
30.01.2014 / 11:09