Difference between revisions of "Porting 32 Bit Code to 64 Bits"

From D Wiki
Jump to: navigation, search
(Versions)
 
Line 83: Line 83:
 
== Variadic Arguments ==
 
== Variadic Arguments ==
 
How variadic arguments work in 64 bits is radically different from 32 bits. They are not a simple array on the stack. You will need to use the functions and templates in std.c.stdarg to access them.
 
How variadic arguments work in 64 bits is radically different from 32 bits. They are not a simple array on the stack. You will need to use the functions and templates in std.c.stdarg to access them.
 +
 +
[[Category:HowTo]]

Latest revision as of 10:14, 14 November 2014

Although D is designed to make it easy to port code between 32 and 64 bit modes, being a systems programming language, dependencies can creep in. This guide points out what changes between the two.

Versions

Not all code can be made portable between 32 and 64 bits, and must be versioned. The following works:

version (X86)
    // ... 32 bit code ...
else version (X86_64)
    // ... 64 bit code ...
else
    static assert("unsupported target")

It is best to write versioning in that manner to give a compile time error on a new target, rather than guessing in advance what, for example, a 64 bit ARM target might require. Experience shows that guesses about how an unfamiliar platform might work always get it wrong. Save those decisions for when one is actually working on a 64 bit ARM.

Size Changes

The size of pointers and references will increase from 4 to 8 bytes. The size_t alias moves from uint to ulong, and the ptrdiff_t alias moves from int to long.

The sizes of compound types based on these will also increase. This includes dynamic arrays, associative arrays, delegates, and class references.

Structs

The size of the struct and the alignment of its fields will change, in order to match the C ABI of the equivalent C struct.

Classes

The size of the class and the alignment of its fields will change, in order to match the alignment most suitable for the 64 bit mode, and in order to accommodate the increased size of pointers and references.

printf

Since printf is a C function, it follows C typing rules. This can have consequences for using them with D types.

D Type printf format
32 bit 64 bit
T* %p %p
long %lld %d
ulong %llu %u
ptrdiff_t %td %td
size_t %zu %zu

For 32 bit code, it was common to use the %.*s format to print strings. This relied on the 32 bit C ABI interpreting the components of a dynamic array as separate length and pointer arguments. 64 bit parameter passing is different, and so the length and pointer should be done explicitly:

string s;
...
printf("s = '%.*s'\n", s);               // 32 bit only
printf("s = '%.*s'\n", s.length, s.ptr); // 32 and 64 bit

Inline Assembly

Naturally, inline assembly for 32 bit code won't work for 64 bit code. The versioning statements to use are:

version (D_InlineAsm_X86)
    // ... 32 bit assembler ...
version (D_InlineAsm_X86_64)
    // ... 64 bit assembler ...
else
    static assert("unsupported target");

The 64 bit inline assembler uses the syntax found in the Intel and AMD instruction set references.

Variadic Arguments

How variadic arguments work in 64 bits is radically different from 32 bits. They are not a simple array on the stack. You will need to use the functions and templates in std.c.stdarg to access them.