|
1 |
| -Ddoc |
2 |
| -
|
3 |
| -$(SPEC_S $(TITLE), |
4 |
| -
|
5 |
| - $(P Although D is designed to make it easy to port code between |
6 |
| - 32 and 64 bit modes, being a systems programming language, |
7 |
| - dependencies can creep in. This guide points out what changes |
8 |
| - between the two. |
9 |
| - ) |
10 |
| -
|
11 |
| -$(SECTION2 Versions, |
12 |
| - $(P Not all code can be made portable between 32 and 64 bits, |
13 |
| - and must be versioned. The following works: |
14 |
| - ) |
15 |
| -
|
16 |
| ---- |
17 |
| -version (X86) |
18 |
| - ... 32 bit code ... |
19 |
| -else version (X86_64) |
20 |
| - ... 64 bit code ... |
21 |
| -else |
22 |
| - static assert("unsupported target") |
23 |
| ---- |
24 |
| -
|
25 |
| - $(P It is best to write versioning in that manner to give a compile |
26 |
| - time error on a new target, rather than guessing in advance what, for example, |
27 |
| - a 64 bit ARM target might require. |
28 |
| - Experience shows that guesses about how an unfamiliar platform might work |
29 |
| - always get it wrong. |
30 |
| - Save those decisions for when one is actually working on a 64 bit ARM. |
31 |
| - ) |
32 |
| -) |
33 |
| -
|
34 |
| -$(SECTION2 Size Changes, |
35 |
| -
|
36 |
| - $(P The size of pointers and references will increase from 4 |
37 |
| - to 8 bytes. The $(TT size_t) alias moves from $(TT uint) to |
38 |
| - $(TT ulong), and the $(TT ptrdiff_t) alias moves from $(TT int) |
39 |
| - to $(TT long). |
40 |
| - ) |
41 |
| -
|
42 |
| - $(P The sizes of compound types based on these will also increase. |
43 |
| - This includes dynamic arrays, associative arrays, delegates, |
44 |
| - and class references. |
45 |
| - ) |
46 |
| -) |
47 |
| -
|
48 |
| -$(SECTION2 Structs, |
49 |
| -
|
50 |
| - $(P The size of the struct and the alignment of its fields |
51 |
| - will change, in order to match the C ABI of the equivalent |
52 |
| - C struct. |
53 |
| - ) |
54 |
| -) |
55 |
| -
|
56 |
| -$(SECTION2 Classes, |
57 |
| -
|
58 |
| - $(P The size of the class and the alignment of its fields |
59 |
| - will change, in order to match the alignment most suitable |
60 |
| - for the 64 bit mode, and in order to accommodate the increased |
61 |
| - size of pointers and references. |
62 |
| - ) |
63 |
| -) |
64 |
| -
|
65 |
| -$(SECTION2 printf, |
66 |
| -
|
67 |
| - $(P Since $(TT printf) is a C function, it follows C typing rules. |
68 |
| - This can have consequences for using them with D types. |
69 |
| - ) |
70 |
| -
|
71 |
| - $(TABLE1 |
72 |
| - $(TR <th rowspan=2>D Type</th> <th colspan=2>printf format</th>) |
73 |
| - $(TR $(TH 32 bit) $(TH 64 bit)) |
74 |
| - $(TR $(TD $(I T)*) $(TD %p) $(TD %p)) |
75 |
| - $(TR $(TD long) $(TD %lld) $(TD %d)) |
76 |
| - $(TR $(TD ulong) $(TD %llu) $(TD %u)) |
77 |
| - $(TR $(TD ptrdiff_t) $(TD %td) $(TD %td)) |
78 |
| - $(TR $(TD size_t) $(TD %zu) $(TD %zu)) |
79 |
| - ) |
80 |
| -
|
81 |
| - $(P For 32 bit code, it was common to use the $(TT %.*s) format |
82 |
| - to print strings. This relied on the 32 bit C ABI interpreting the |
83 |
| - components of a dynamic array as separate length and pointer arguments. |
84 |
| - 64 bit parameter passing is different, and so the length and pointer |
85 |
| - should be done explicitly: |
86 |
| - ) |
87 |
| -
|
88 |
| ---- |
89 |
| -string s; |
90 |
| -... |
91 |
| -printf("s = '%.*s'\n", s); // 32 bit only |
92 |
| -printf("s = '%.*s'\n", s.length, s.ptr); // 32 and 64 bit |
93 |
| ---- |
94 |
| -) |
95 |
| -
|
96 |
| -$(SECTION2 Inline Assembly, |
97 |
| -
|
98 |
| - $(P Naturally, inline assembly for 32 bit code won't work for 64 bit code. |
99 |
| - The versioning statements to use are: |
100 |
| - ) |
101 |
| -
|
102 |
| ---- |
103 |
| -version (D_InlineAsm_X86) |
104 |
| - ... 32 bit assembler ... |
105 |
| -version (D_InlineAsm_X86_64) |
106 |
| - ... 64 bit assembler ... |
107 |
| -else |
108 |
| - static assert("unsupported target"); |
109 |
| ---- |
110 |
| -
|
111 |
| - $(P The 64 bit inline assembler uses the syntax found in the Intel |
112 |
| - and AMD instruction set references. |
113 |
| - ) |
114 |
| -) |
115 |
| -
|
116 |
| -$(SECTION2 Variadic Arguments, |
117 |
| -
|
118 |
| - $(P How variadic arguments work in 64 bits is radically different from |
119 |
| - 32 bits. They are not a simple array on the stack. You will need to use |
120 |
| - the functions and templates in $(TT std.c.stdarg) to access them. |
121 |
| - ) |
122 |
| -
|
123 |
| -) |
124 |
| -
|
125 |
| -) |
126 |
| -
|
127 |
| -Macros: |
128 |
| - TITLE=Porting 32 Bit Code to 64 Bits |
129 |
| - WIKI=32To64 |
130 |
| - CATEGORY_HOWTOS=$0 |
131 |
| -
|
| 1 | +Ddoc |
| 2 | + |
| 3 | +$(SPEC_S $(TITLE), |
| 4 | + |
| 5 | + $(P Although D is designed to make it easy to port code between |
| 6 | + 32 and 64 bit modes, being a systems programming language, |
| 7 | + dependencies can creep in. This guide points out what changes |
| 8 | + between the two. |
| 9 | + ) |
| 10 | + |
| 11 | +$(SECTION2 Versions, |
| 12 | + $(P Not all code can be made portable between 32 and 64 bits, |
| 13 | + and must be versioned. The following works: |
| 14 | + ) |
| 15 | + |
| 16 | +--- |
| 17 | +version (X86) |
| 18 | + ... 32 bit code ... |
| 19 | +else version (X86_64) |
| 20 | + ... 64 bit code ... |
| 21 | +else |
| 22 | + static assert("unsupported target") |
| 23 | +--- |
| 24 | + |
| 25 | + $(P It is best to write versioning in that manner to give a compile |
| 26 | + time error on a new target, rather than guessing in advance what, for example, |
| 27 | + a 64 bit ARM target might require. |
| 28 | + Experience shows that guesses about how an unfamiliar platform might work |
| 29 | + always get it wrong. |
| 30 | + Save those decisions for when one is actually working on a 64 bit ARM. |
| 31 | + ) |
| 32 | +) |
| 33 | + |
| 34 | +$(SECTION2 Size Changes, |
| 35 | + |
| 36 | + $(P The size of pointers and references will increase from 4 |
| 37 | + to 8 bytes. The $(TT size_t) alias moves from $(TT uint) to |
| 38 | + $(TT ulong), and the $(TT ptrdiff_t) alias moves from $(TT int) |
| 39 | + to $(TT long). |
| 40 | + ) |
| 41 | + |
| 42 | + $(P The sizes of compound types based on these will also increase. |
| 43 | + This includes dynamic arrays, associative arrays, delegates, |
| 44 | + and class references. |
| 45 | + ) |
| 46 | +) |
| 47 | + |
| 48 | +$(SECTION2 Structs, |
| 49 | + |
| 50 | + $(P The size of the struct and the alignment of its fields |
| 51 | + will change, in order to match the C ABI of the equivalent |
| 52 | + C struct. |
| 53 | + ) |
| 54 | +) |
| 55 | + |
| 56 | +$(SECTION2 Classes, |
| 57 | + |
| 58 | + $(P The size of the class and the alignment of its fields |
| 59 | + will change, in order to match the alignment most suitable |
| 60 | + for the 64 bit mode, and in order to accommodate the increased |
| 61 | + size of pointers and references. |
| 62 | + ) |
| 63 | +) |
| 64 | + |
| 65 | +$(SECTION2 printf, |
| 66 | + |
| 67 | + $(P Since $(TT printf) is a C function, it follows C typing rules. |
| 68 | + This can have consequences for using them with D types. |
| 69 | + ) |
| 70 | + |
| 71 | + $(TABLE1 |
| 72 | + $(TR <th rowspan=2>D Type</th> <th colspan=2>printf format</th>) |
| 73 | + $(TR $(TH 32 bit) $(TH 64 bit)) |
| 74 | + $(TR $(TD $(I T)*) $(TD %p) $(TD %p)) |
| 75 | + $(TR $(TD long) $(TD %lld) $(TD %d)) |
| 76 | + $(TR $(TD ulong) $(TD %llu) $(TD %u)) |
| 77 | + $(TR $(TD ptrdiff_t) $(TD %td) $(TD %td)) |
| 78 | + $(TR $(TD size_t) $(TD %zu) $(TD %zu)) |
| 79 | + ) |
| 80 | + |
| 81 | + $(P For 32 bit code, it was common to use the $(TT %.*s) format |
| 82 | + to print strings. This relied on the 32 bit C ABI interpreting the |
| 83 | + components of a dynamic array as separate length and pointer arguments. |
| 84 | + 64 bit parameter passing is different, and so the length and pointer |
| 85 | + should be done explicitly: |
| 86 | + ) |
| 87 | + |
| 88 | +--- |
| 89 | +string s; |
| 90 | +... |
| 91 | +printf("s = '%.*s'\n", s); // 32 bit only |
| 92 | +printf("s = '%.*s'\n", s.length, s.ptr); // 32 and 64 bit |
| 93 | +--- |
| 94 | +) |
| 95 | + |
| 96 | +$(SECTION2 Inline Assembly, |
| 97 | + |
| 98 | + $(P Naturally, inline assembly for 32 bit code won't work for 64 bit code. |
| 99 | + The versioning statements to use are: |
| 100 | + ) |
| 101 | + |
| 102 | +--- |
| 103 | +version (D_InlineAsm_X86) |
| 104 | + ... 32 bit assembler ... |
| 105 | +version (D_InlineAsm_X86_64) |
| 106 | + ... 64 bit assembler ... |
| 107 | +else |
| 108 | + static assert("unsupported target"); |
| 109 | +--- |
| 110 | + |
| 111 | + $(P The 64 bit inline assembler uses the syntax found in the Intel |
| 112 | + and AMD instruction set references. |
| 113 | + ) |
| 114 | +) |
| 115 | + |
| 116 | +$(SECTION2 Variadic Arguments, |
| 117 | + |
| 118 | + $(P How variadic arguments work in 64 bits is radically different from |
| 119 | + 32 bits. They are not a simple array on the stack. You will need to use |
| 120 | + the functions and templates in $(TT std.c.stdarg) to access them. |
| 121 | + ) |
| 122 | + |
| 123 | +) |
| 124 | + |
| 125 | +) |
| 126 | + |
| 127 | +Macros: |
| 128 | + TITLE=Porting 32 Bit Code to 64 Bits |
| 129 | + WIKI=32To64 |
| 130 | + CATEGORY_HOWTOS=$0 |
| 131 | + |
0 commit comments