アプリケーション・バイナリ・インターフェース
D ABI(Application Binary Interface:アプリケーション・バイナリ・インターフェース)に準拠したD実装。 インターフェイス) と相互運用できるライブラリやDLLなどを生成できるようになる。 を生成できるようになる。 Dバイナリを生成することができる。
C ABI
本仕様書でいうC ABIとは、ターゲット・システムのCアプリケーション・バイナリ・インタフェースを意味する。 バイナリ・インターフェースを意味する。 CコードとDコードは自由にリンク可能でなければならない。 コードは、C ABIランタイム・ライブラリ全体にアクセスできなければならない。
エンディアン
データのレイアウトのエンディアン (バイトオーダー)は、ターゲット・マシンのエンディアンに準拠する。 はターゲット・マシンのエンディアンに準拠する。 インテルx86CPUはリトルエンディアンである。 としてメモリに格納される: 0D 0C 0B 0A.
基本型
ブール | 8ビットバイトで、0は偽、1は真を表す。 |
バイト | 8ビット符号付き値 |
ubyte | 8ビットの符号なし値 |
short | 16ビット符号あり値 |
ushort | 16ビット符号なし値 |
int | 32ビット符号あり値 |
uint | 32ビット符号なし値 |
long | 64ビット符号あり値 |
ulong | 64ビット符号なし値 |
cent | 128ビット符号あり値 |
セント | 128ビット符号なし値 |
float | 32ビットIEEE 754浮動小数点値 |
double | 64ビットIEEE 754浮動小数点値 |
実数 | 処理系定義浮動小数点値、x86では 80ビットIEEE 754拡張実数 |
char | 8ビット符号なし値 |
wchar | 16ビット符号なし値 |
dchar | 32ビット符号なし値 |
デリゲート
デリゲートは2つの部分を持つファット・ポインターだ:
offset | property | contents |
---|---|---|
0 | .ptr | コンテキストポインタ |
ptrsize | .funcptr | 関数へのポインタ |
コンテキスト・ポインタは、クラスthis 参照、"構造体"へのポインタ、クロージャ(ネストされた関数)へのポインタのいずれかである。 クロージャへのポインタ(入れ子関数)、または関数を囲むスタック・フレームへのポインタ(入れ子関数)である。 関数のスタックフレームへのポインタである。
構造体
ターゲットのC ABI構造体レイアウトに従う。
クラス
オブジェクトは以下から構成される:
size | property | contents |
---|---|---|
ptrsize | .__vptr | vtableへのポインタ |
ptrsize | .__monitor | モニター |
ptrsize... | このクラスが実装しているインターフェースの vptrs を、左から右へ、最も派生しているものから最も派生していないものへと並べる。 | |
... | ... | super の非静的フィールドと super のインターフェイスの vptrs。 |
... | 名前付きフィールド | 非静的フィールド |
vtableは以下のような構成になっている:
size | contents |
---|---|
ptrsize | TypeInfoのインスタンスへのポインタ |
ptrsize... | 仮想メンバ関数へのポインタ |
クラス・オブジェクトをインターフェイスにキャストするには、オブジェクトのベース・アドレスにインターフェイスの対応するvptrのオフセットを追加する。 インターフェイスの対応するvptrのオフセットをオブジェクトの基底のアドレスに追加する。 インターフェイスptrを元のクラス型に戻すには、オブジェクト.インターフェイス.エントリーのvtblからそれを引くための正しいオフセットを得る必要がある。 vtbl[0]にあるobject.Interfaceのエントリから、そこから減算する正しいオフセットを取得する。 アジャスタサンクが作成され、それへのポインタがvtbl[]のメソッドエントリーに格納される。 のメソッドエントリーに格納される。 へのポインタが格納される。
アジャスターサンクは次のようになる:
ADD EAX,offset JMP method
インタフェースの継承グラフの左端は、すべてvptrsを共有している。 これが単一継承モデルである。 多重継承の場合)継承グラフが分岐するたびに、新しいvptrが作成され、クラスのインスタンスに格納される。 が作成され、クラスのインスタンスに格納される。 仮想メソッドがオーバーライドされるたびに、新しいvtbl[]が作成される。 を作成しなければならない。
クラス定義だ:
class XXXX
{
....
};
以下を生成する:
- ClassXXXXと呼ばれるクラスのインスタンス。
- すべての静的メンバを定義する StaticClassXXXX という型。
- StaticClassXXXXのインスタンスで、StaticXXXXと呼ばれる静的メンバを定義する。
インターフェイス
インターフェースは、vtbl[]へのポインターへのポインターである。 vtbl[0]エントリーは、object.Interfaceクラスの対応するインスタンスへのポインターである。 object.Interfaceクラスのインスタンスへのポインタである。 残りのvtbl[1..$] のエントリーは、そのインターフェースが実装する仮想関数へのポインターである。 へのポインタである。 へのポインタである。
COMインターフェイスが通常のインターフェイスと異なる点は、次のとおりである。 vtbl[0] には object.Interface エントリがない。 vtbl[0..$] のエントリは、宣言された順に、すべての仮想関数ポインタである。 である。 これは、Windowsで使用されるCOMオブジェクトのレイアウトと一致している。
C++とのインターフェイス "が通常のインターフェイスと異なる点は、次のとおりである。 C++インターフェイスは通常のインターフェイスと異なり、単一継承を使用するC++クラスのレイアウトと一致する。 を使用したC++クラスのレイアウトと一致する点である。
配列
ダイナミック・アレイは以下のものから構成される:
offset | property | contents |
---|---|---|
0 | .length | 配列の次元 |
size_t | .ptr | 配列データへのポインタ |
動的配列は次のように宣言される:
type[] array;一方、静的配列は次のように宣言される:
type[dimension] array;
このように、静的配列は常に型の一部として静的に次元を持つ。 静的配列と動的配列は簡単に相互変換できる。 相互に簡単に変換できる。
連想配列
連想配列は、不透明な実装定義型へのポインターで構成される。 型へのポインタである。
現在の実装は次のように定義されている。 で定義されている。
リファレンス型
Dには参照型があるが、それは暗黙的なものである。例えば、クラスは常に参照される。 つまり、クラス・インスタンスがスタック上に存在したり、関数のパラメータとして渡されたりすることはない。 つまり、クラス・インスタンスはスタック上に存在したり、関数のパラメータとして渡されたりすることはない。
名前の揶揄
Dは、D識別子をマングリングしてスコープと型情報を含むようにすることで、タイプセーフ・リンクを実現している。 にスコープと型情報を含める。
MangledName: _D QualifiedName Type _D QualifiedName Z // Internal
上記の"型 "は、変数の型または関数の戻り値の型である。 後者は関数またはデリゲートへのポインタを介してのみ値にバインドされるからである。 へのポインタを介してのみ値にバインドできるからである。
QualifiedName: SymbolFunctionName SymbolFunctionName QualifiedName SymbolFunctionName: SymbolName SymbolName TypeFunctionNoReturn SymbolName M TypeModifiersopt TypeFunctionNoReturn
M は、そのシンボルが、 ポインタを必要とする関数であることを意味する。 this ポインタを必要とする関数であることを意味する。クラスまたは構造体フィールドは、M なしでマングルされる。 修飾子scope を持つParameterから M を曖昧さをなくすには、以下の型がTypeFunctionであるかどうかをチェックする必要がある。 以下の型がTypeFunctionであるかどうかをチェックする必要がある。
SymbolName: LName TemplateInstanceName IdentifierBackRef 0 // anonymous symbols
テンプレート・インスタンス名には、パラメータの型と値がエンコードされている。 にエンコードされている:
TemplateInstanceName: TemplateID LName TemplateArgs Z TemplateID: __T __U // for symbols declared inside template constraint TemplateArgs: TemplateArg TemplateArg TemplateArgs TemplateArg: TemplateArgX H TemplateArgX
テンプレート引数が特殊化されたテンプレートパラメータにマッチする場合、引数 は接頭辞H でマングルされる。
TemplateArgX: T Type V Type Value S QualifiedName X Number ExternallyMangledName
ExternallyMangledNameには、現在のプラットフォームで許容される任意の文字列を指定できる。 例えば、C++リンケージやアノテーションを持つ関数によって生成される。 pragma(mangle,...) でアノテーションされたものなどである。
Values: Value Value Values Value: n i Number N Number e HexFloat c HexFloat c HexFloat CharWidth Number _ HexDigits A Number Values S Number Values f MangledName HexFloat: NAN INF NINF N HexDigits P Exponent HexDigits P Exponent Exponent: N Number Number HexDigits: HexDigit HexDigit HexDigits HexDigit: Digit A B C D E F CharWidth: a w d
- n
- はnull 。
- i 数値
- は正の数値リテラル(文字リテラルを含む)用である。 文字リテラルを含む)。
- N 数値
- は負の数値リテラル用である。
- e HexFloat
- は、実数および虚数の浮動小数点リテラル用である。
- c HexFloat c HexFloat
- は複素数浮動小数点リテラル用である。
- CharWidth 数値 _ HexDigits。
- CharWidthは、文字が が1バイト(a)、2バイト(w)、または4バイト(d)であるかどうかである。 Numberは文字列の文字数である。 HexDigitsは文字列の16進数データである。
- A 数値 値
- 配列または連想配列リテラル。 Numberは配列の長さである。 値は、通常の配列の場合はNumber回繰り返される、 連想配列の場合は2 *回繰り返される。
- S 数 値
- 構造体リテラル。数値は 整数回繰り返される。
Name: Namestart Namestart Namechars Namestart: _ Alpha Namechar: Namestart Digit Namechars: Namechar Namechar Namechars
LName: Number Name Number __S Number // function-local parent symbols Number: Digit Digit Number Digit: 0 1 2 3 4 5 6 7 8 9
LNameとは、名前の前に、その名前の文字数を示すNumberをつけたものである。 で始まる。
後方参照
LNameまたは非基本型(すなわち、固定された1文字または2文字のシーケンスとしてエンコードされないすべての型)。 固定された1文字か2文字のシーケンスとしてエンコードされないタイプ)である。 以前マングル・シンボルに送られたものは、再び送られることはない。 が参照される。 シンボル名における元の出現位置の相対位置を符号化した特別なシーケンスによって参照される。
バックリファレンスの数字は、26進数でエンコードされ、上位の桁には大文字のA -Z が使われるが、下位の桁には小文字の - が使われる。 でエンコードされるが、最後の桁は小文字のa -z でエンコードされる。
TypeBackRef: Q NumberBackRef IdentifierBackRef: Q NumberBackRef NumberBackRef: lower-case-letter upper-case-letter NumberBackRef
バック・リファレンスの型を区別するには、バック・リファレンスされた文字のルックアップが必 要である: 識別子の後方参照は、常に数字0 から9 を指す。 を指す。
型の揶揄
型は単純な線形スキームを使ってマングルされる:
Type: TypeModifiersopt TypeX TypeBackRef TypeX: TypeArray TypeStaticArray TypeAssocArray TypePointer TypeFunction TypeIdent TypeClass TypeStruct TypeEnum TypeTypedef TypeDelegate TypeVoid TypeByte TypeUbyte TypeShort TypeUshort TypeInt TypeUint TypeLong TypeUlong TypeCent TypeUcent TypeFloat TypeDouble TypeReal TypeIfloat TypeIdouble TypeIreal TypeCfloat TypeCdouble TypeCreal TypeBool TypeChar TypeWchar TypeDchar TypeNoreturn TypeNull TypeTuple TypeVector TypeModifiers: Const Wild Wild Const Shared Shared Const Shared Wild Shared Wild Const Immutable Shared: O Const: x Immutable: y Wild: Ng TypeArray: A Type TypeStaticArray: G Number Type TypeAssocArray: H Type Type TypePointer: P Type TypeVector: Nh Type TypeFunction: TypeFunctionNoReturn Type TypeFunctionNoReturn: CallConvention FuncAttrsopt Parametersopt ParamClose CallConvention: F // D U // C W // Windows R // C++ Y // Objective-C FuncAttrs: FuncAttr FuncAttr FuncAttrs FuncAttr: FuncAttrPure FuncAttrNothrow FuncAttrRef FuncAttrProperty FuncAttrNogc FuncAttrReturn FuncAttrScope FuncAttrTrusted FuncAttrSafe FuncAttrLive
関数属性は、return とscope を除いて、上記の順序で発せられる。 return scope は、this が return scopeパラメータである場合は の場合はthis の前に、 の場合はscope の後に来る。 scopeと return refパラメータである。
FuncAttrPure: Na FuncAttrNogc: Ni FuncAttrNothrow: Nb FuncAttrProperty: Nd FuncAttrRef: Nc FuncAttrReturn: Nj FuncAttrScope: Nl FuncAttrTrusted: Ne FuncAttrSafe: Nf FuncAttrLive: Nm Parameters: Parameter Parameter Parameters Parameter: Parameter2 M Parameter2 // scope Nk Parameter2 // return Parameter2: Type I Type // in J Type // out K Type // ref L Type // lazy ParamClose: X // variadic T t...) style Y // variadic T t,...) style Z // not variadic TypeIdent: I QualifiedName TypeClass: C QualifiedName TypeStruct: S QualifiedName TypeEnum: E QualifiedName TypeTypedef: T QualifiedName TypeDelegate: D TypeModifiersopt TypeFunction TypeVoid: v TypeByte: g TypeUbyte: h TypeShort: s TypeUshort: t TypeInt: i TypeUint: k TypeLong: l TypeUlong: m TypeCent: zi TypeUcent: zk TypeFloat: f TypeDouble: d TypeReal: e TypeIfloat: o TypeIdouble: p TypeIreal: j TypeCfloat: q TypeCdouble: r TypeCreal: c TypeBool: b TypeChar: a TypeWchar: u TypeDchar: w TypeNoreturn: Nn TypeNull: n TypeTuple: B Parameters Z
関数呼び出し規約
extern (C) およびextern (D) の呼び出し規約は、C言語の 呼び出し規約 の呼び出し規約と一致する。 ただし、Windows x86のextern (D)呼び出し規約を除く。
レジスタ規約
- EAX、ECX、EDXはスクラッチ・レジスタであり、関数によって破壊されることがある。 関数によって破壊されることがある。
- EBX, ESI, EDI, EBPは、関数呼び出しにまたがって保存されなければならない。
- EFLAGSは、方向フラグが順方向でなければならないことを除いて、関数呼び出しに よって破壊されるものとする。 方向フラグは前方でなければならない。
- FPU スタックは関数呼び出し時に空でなければならない。
- FPU 制御語は、関数呼び出しにまたがって保持されなければならない。
- 浮動小数点戻り値は FPU スタックに戻される。 これらは、たとえ使用されなくても、呼び出し側で消去しなければならない。
戻り値
- bool型、byte型、ubyte型、short型、ushort型、int型、uint型、 ポインタ、オブジェクト、インターフェース はEAXで返される。
- longとulongはEDX,EAXで返される。 はEDX,EAXで返される。 の半分が返される。
- float、double、real、ifloat、idouble、irealはST0で返される。 はST0で返される。
- cfloat、cdouble、crealはST1,ST0で返される。 は実数部、ST0 は虚数部である。
- 動的配列は、EDXにポインタ、EAXに長さを格納して返される。 で、長さは EAX で返される。
- 連想配列はEAXで返される。
- 参照はEAXにポインタとして返される。
- デリゲートは、EDXに "関数"へのポインタを、EAXにコンテキスト・ポインタを指定して返される。 へのポインタを EDX に、コンテキスト・ポインタを EAX に返す。
- 1、2、4 バイトの構造体および静的配列は、EAX に返される。
- 8バイト構造体および静的配列はEDX,EAXで返される。 EDXは最上位の半分を取得する。
- それ以外のサイズの構造体や静的配列の場合、戻り値は隠れた場所に格納される、 戻り値は、関数の引数として渡された隠しポインタに格納される。 関数の引数として渡される。
- コンストラクタはこのポインタをEAXで返す。
パラメータ
可変長でない関数のパラメータ:
foo(a1, a2, ..., an);へのパラメータは以下のように渡される:
a1 |
a2 |
... |
an |
隠された |
この |
ここで、hiddenは構造体を返すために必要であれば存在し、thisはthisポインタとして必要であれば存在する。 値を返すために必要な場合はhiddenが、メンバ関数のthisポインタとして必要な場合はthisが存在する。 メンバ関数のthisポインタとして、あるいはネストされた関数のコンテキスト・ポインタとして必要な場合に存在する。 関数のコンテキスト・ポインタとして必要な場合に存在する。
以下の条件を満たす場合、最後のパラメータはスタックにプッシュされるのではなく、EAXで渡される。 で渡される:
- EAXに収まる。
- 3バイト構造体でない。
- 浮動小数点型ではない。
パラメータは常に4バイトの倍数としてプッシュされる、 四捨五入される、 したがって、スタックは常に4バイト境界に整列される。 最上位からプッシュされる。 out また、ref はポインタとして渡される。 静的配列は最初の要素へのポインタとして渡される。 Windowsでは、realは10バイト量としてプッシュされる、 crealは20バイト量として渡される。 Linuxでは、実数は12バイト量としてプッシュされる、 crealは2つの12バイト量としてプッシュされる。 余分な2バイトのパッドは「最上位」の位置を占める。
キャリーはスタックを掃除する。
可変長引数関数へのパラメータ:
void foo(int p1, int p2, int[] p3...) foo(a1, a2, ..., an);は以下のように渡される:
p1 |
p2 |
a3 |
隠された |
この |
可変長部分は動的配列に変換される。 残りは可変長引数でない関数と同じである。
可変長引数関数のパラメータ:
void foo(int p1, int p2, ...) foo(a1, a2, a3, ..., an);は以下のように渡される:
以下の通りである。 |
... |
a3 |
a2 |
a1 |
_引数 |
非表示 |
この |
呼び出し元はスタックをクリーンにすることが期待されている。 _argptr は渡されない。 は渡されず、呼び出し元が計算する。
例外処理
Windows 32ビット
Microsoft Windowsの構造化例外処理規約に従う。 規格に準拠する。
Linux、FreeBSD、OS X
DWARF(属性付きレコード形式によるデバッグ)例外処理規約に準拠。 フォーマットによるデバッグ)例外処理規約に準拠している。
Windows 64ビット
静的アドレス範囲/ハンドラーテーブルを使用する。 MSVC x64の例外処理テーブルとは互換性がない。 スタックはEBP/RBPスタックフレームを使用すると仮定して歩く。 スタックを歩く。スタックはEBP/RBPスタック・フレーム規約を使用すると仮定して歩かれる。 EBP/RBP規約は、関連するEH(例外ハンドラ)テーブルを持つすべての関数に使用されなければならない。
例外ハンドラを持つ各関数に対して、EHテーブルのエントリーが生成される、 EHテーブルのエントリが生成される。
field | description |
---|---|
void* | 関数開始へのポインタ |
DHandlerTable* | 対応するEHデータへのポインタ |
uint | 関数のバイトサイズ |
EHテーブルのエントリは、以下の特別なセグメントに格納される。 セグメントに配置され、リンカによって連結される。
Operating System | Segment Name |
---|---|
Win32 | FI |
Win64 | ._deh$B |
Linux | .deh_eh |
フリーBSD | .deh_eh |
OS X | __deh_eh,__DATA |
残りのEHデータはどこにでも置くことができる、 それは不変である。
field | description |
---|---|
void* | 関数開始へのポインタ。 |
uint | EBP/RBPからのESP/RSPのオフセット |
uint | 関数開始からリターンコードまでのオフセット |
uint | ハンドラ情報のDHandlerInfo[] |
DHandlerInfo[] | ハンドラ情報の配列のエントリ数 |
field | description |
---|---|
uint | 関数アドレスからガード区間開始までのオフセット |
uint | ガードされたセクションの終わりのオフセット |
int | 前のテーブルインデックス |
uint | if != 0 テーブルの先頭からDCatchInfoデータへのオフセット |
void* | もしNULLでなければ、最終的に実行するコードへのポインタ |
field | description |
---|---|
uint | のエントリ数DCatchBlock[] |
DCatchBlock[] | キャッチ情報の配列 |
field | description |
---|---|
ClassInfo | キャッチ型 |
uint | EBP/RBPからキャッチ変数へのオフセット |
ガベージコレクション
このインターフェイスはDruntimeのcore/gc/gcinterface.dにある。
ModuleInfoインスタンス
のインスタンスである。 ModuleInfo のインスタンスはコンパイラによって生成され、各モジュールのオブジェクト・ファイルに挿入される。 ModuleInfo のインスタンスは、Dランタイム・ライブラリにとって有用なモジュールに関する情報を含んでいる:
- モジュールに静的コンストラクタ、静的デストラクタ、共有静的コンストラクタ、共有静的デストラクタがある場合。
- そのモジュールで定義されているユニットテストへの参照。
- インポートされたモジュールのうち、1 つ以上のモジュールへの参照の配列:
- 静的コンストラクタ
- 静的デストラクタ
- 共有静的コンストラクタ
- 共有静的デストラクタ
- ユニットテスト
- 1~5を1つ以上含むモジュールの推移的インポート
- 順序に依存しないコンストラクタ(現在は -cov)
- モジュールで定義された各クラスのClassInfo への参照の配列。
注釈:この機能は削除される可能性がある。
ModuleInfo はDruntimeのobject.dで定義されており、フラグの値もフィールドのレイアウトもコンパイラの出力と一致していなければならない。
でコンパイルされたモジュールは -betterC でコンパイルされたモジュールは、ModuleInfo インスタンスが生成されない。 とコンパイルされたモジュールには、 のインスタンスは生成されない。 同様に、ImportCモジュールはModuleInfo を生成しない。
モジュールの初期化と終了
モジュールのすべての静的コンストラクタは、1つの関数に集約される。 へのポインタが挿入される。 ModuleInfo のctorメンバに挿入される。 メンバに挿入される。
モジュールのすべての静的デストラクタは、1つの関数に集約される。 へのポインタが挿入される。 ModuleInfo のdtorメンバに挿入される。 メンバに挿入される。
単体テスト
モジュールのすべてのユニットテストは、ひとつの関数に集約される。 に集約され、その関数へのポインタが挿入される。 ModuleInfo に挿入される。 メンバに挿入される。
ランタイム・ヘルパー関数
これらはDruntimeのrt/にある。
シンボリックデバッグ
Dには、既存のCやC++のデバッガでは表現できない型がある。 動的配列、連想配列、デリゲートなどである。 これらの型を構造体として表現すると問題が発生する。 構造体に対する関数の呼び出し規約は、これらの型に対するものとは異なることが多いからである。 そのため、C/C++デバッガは誤った表現をしてしまう。 これらのデバッガでは、構造体はC型として表現される。 型の呼び出し規約と一致している。
D type | C representation |
---|---|
動的配列 | unsigned long long |
連想配列 | void* |
代議員 | long long |
dchar | unsigned long |
新しい型を受け入れるように変更できるデバッガについては、以下の拡張がその型を完全にサポートするのに役立つ。 型 "を完全にサポートするのに役立つ。
Codeviewデバッガー拡張機能
Ddchar 型は特別なプリミティブ型 0x78 で表される。 プリミティブ型0x78で表される。
Dは、 (0x0015)で示されるCodeview OEM汎用型レコードを使用する。 LF_OEM (0x0015)で示される。フォーマットは以下の通りである:
フィールドサイズ | 2 | 2 | 2 | 2 | 2 | 2 |
D Type | Leaf Index | OEM Identifier | recOEM | num indices | type index | type index |
---|---|---|---|---|---|---|
ダイナミックアレイ | LF_OEM | OEM | 1 | 2 | インデックス | 要素 |
連想配列 | LF_OEM | OEM | 2 | 2 | キー | 要素 |
デリゲート | LF_OEM | OEM | 3 | 2 | この | 関数」である。 |
OEM | 0x42 |
インデックス | 配列インデックスの型 |
キー | キーの"型"インデックス |
要素 | 配列要素の型インデックス |
この | コンテキストポインタの型インデックス |
関数". | 関数の型インデックス。 |
これらの拡張は で表示できる。 Ddbgデバッガ がサポートしている。
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.108.0
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku