forked from kinaba/dlang-ref-jp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path32-64-portability.dd
More file actions
131 lines (104 loc) · 3.99 KB
/
32-64-portability.dd
File metadata and controls
131 lines (104 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Ddoc
$(SPEC_S $(TITLE),
$(P D は 32bit と 64bit の間のコード移植性を容易に保てるように設計されていますが、
システムプログラミング言語であるという性質上、
どうしても、依存性が忍び込んでしまうことがあります。
ここでは、32bit と 64bit での違いについて説明します。
)
$(SECTION2 version,
$(P 全てのコードが32bit/64bit互換で書けるとは限らず、
versionによる切り分けが必要です。以下のように記述できます:
)
---
version (X86)
... 32 bit code ...
else version (X86_64)
... 64 bit code ...
else
static assert("unsupported target")
---
$(P 未知のターゲット環境に対しては、
バージョン切り分けの結果はコンパイルエラーとするべきです。
例えば、64bit ARM 環境がどちらで動くかなどを前もって推測して設定するようなことは避けた方が良いでしょう。
経験として、未知のプラットフォームの挙動を予測のみで記述するのは、
常に誤動作の元です。
そのような決定は、実際に64bit ARMで動かす機会ができるまで取っておきましょう。
)
)
$(SECTION2 サイズの変化,
$(P ポインタと参照型のサイズは4バイトから8バイトに増えます。
$(D size_t) は $(D uint) への alias から
$(D ulong) に変わり、$(D ptrdiff_t) は $(D int)
への alias から $(D long) に変わります。
)
$(P 複合型のサイズも、ベースとなる型のサイズ増加に従って変化します。
これは、
動的配列、連想配列、delegate、クラス参照が当てはまります。
)
)
$(SECTION2 構造体,
$(P 構造体のサイズとフィールドの
alignment は、
Cの構造体のABIに合わせて変化します。
)
)
$(SECTION2 クラス,
$(P クラスのサイズとフィールドの alignment は、
64bitモードでもっとも最適になるように、
また、
ポインタサイズ等の増加を反映して変化します。
)
)
$(SECTION2 printf,
$(P $(D printf) は C の関数であるため、C の型規則に従います。
これを D から使うには、いくつか考慮すべき事があります。
)
$(TABLE1
$(TR <th rowspan=2>D の型</th> <th colspan=2>printf 書式</th>)
$(TR $(TH 32 bit) $(TH 64 bit))
$(TR $(TD $(I T)*) $(TD %p) $(TD %p))
$(TR $(TD long) $(TD %lld) $(TD %d))
$(TR $(TD ulong) $(TD %llu) $(TD %u))
$(TR $(TD ptrdiff_t) $(TD %td) $(TD %td))
$(TR $(TD size_t) $(TD %zu) $(TD %zu))
)
$(P 32bitコードでは、$(D %.*s)
という書式でDの文字列を出力するコードがよく使われていました。これは 32bit の C ABI が、
動的配列を長さとポインタ引数の列として扱うことに依存しており、
64bit の引数渡しはこれとは異なります。
したがって、長さとポインタは明示的に引き渡す必要があります:
)
---
string s;
...
printf("s = '%.*s'\n", s); // 32 bit 限定
printf("s = '%.*s'\n", s.length, s.ptr); // 32/64 bit 共通
---
)
$(SECTION2 インラインアセンブリ,
$(P 当然ながら、32bit用のインラインアセンブリは64bitでは動作しません。
バージョン切り分けは以下のように記述します:
)
---
version (D_InlineAsm_X86)
... 32 bit assembler ...
version (D_InlineAsm_X86_64)
... 64 bit assembler ...
else
static assert("unsupported target");
---
$(P 64bit のインラインアセンブラの構文は、
Intel と AMD の命令セット仕様書のものに従います。
)
)
$(SECTION2 可変長引数,
$(P 64bit環境での可変長引数の動作は、32bitのそれとは大幅に異なります。
64bitでは単純なスタック上の配列とはなりません。
アクセスには、必ず $(D std.c.stdarg) の関数とテンプレートを使う必要があります。
)
)
)
Macros:
TITLE=32bitコードの64bitへの移植
WIKI=32To64
CATEGORY_HOWTOS=$0