英語版
このページの英語版を見る

アプリケーション・バイナリ・インターフェース

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ビット符号付き値
ubyte8ビットの符号なし値
short16ビット符号あり値
ushort16ビット符号なし値
int32ビット符号あり値
uint32ビット符号なし値
long64ビット符号あり値
ulong64ビット符号なし値
cent128ビット符号あり値
セント128ビット符号なし値
float32ビットIEEE 754浮動小数点値
double64ビットIEEE 754浮動小数点値
実数処理系定義浮動小数点値、x86では 80ビットIEEE 754拡張実数
char8ビット符号なし値
wchar16ビット符号なし値
dchar32ビット符号なし値

デリゲート

デリゲートは2つの部分を持つファット・ポインターだ:

デリゲート・レイアウト
offsetpropertycontents
0.ptrコンテキストポインタ
ptrsize.funcptr関数へのポインタ

コンテキスト・ポインタは、クラスthis 参照、"構造体"へのポインタ、クロージャ(ネストされた関数)へのポインタのいずれかである。 クロージャへのポインタ(入れ子関数)、または関数を囲むスタック・フレームへのポインタ(入れ子関数)である。 関数のスタックフレームへのポインタである。

構造体

ターゲットのC ABI構造体レイアウトに従う。

クラス

オブジェクトは以下から構成される:

クラス オブジェクト レイアウト
sizepropertycontents
ptrsize.__vptrvtableへのポインタ
ptrsize.__monitorモニター
ptrsize...このクラスが実装しているインターフェースの vptrs を、左から右へ、最も派生しているものから最も派生していないものへと並べる。
......super の非静的フィールドと super のインターフェイスの vptrs。
...名前付きフィールド非静的フィールド

vtableは以下のような構成になっている:

仮想関数ポインタテーブルレイアウト
sizecontents
ptrsizeTypeInfoのインスタンスへのポインタ
ptrsize...仮想メンバ関数へのポインタ

クラス・オブジェクトをインターフェイスにキャストするには、オブジェクトのベース・アドレスにインターフェイスの対応するvptrのオフセットを追加する。 インターフェイスの対応するvptrのオフセットをオブジェクトの基底のアドレスに追加する。 インターフェイスptrを元のクラス型に戻すには、オブジェクト.インターフェイス.エントリーのvtblからそれを引くための正しいオフセットを得る必要がある。 vtbl[0]にあるobject.Interfaceのエントリから、そこから減算する正しいオフセットを取得する。 アジャスタサンクが作成され、それへのポインタがvtbl[]のメソッドエントリーに格納される。 のメソッドエントリーに格納される。 へのポインタが格納される。

アジャスターサンクは次のようになる:

  ADD EAX,offset
  JMP method

インタフェースの継承グラフの左端は、すべてvptrsを共有している。 これが単一継承モデルである。 多重継承の場合)継承グラフが分岐するたびに、新しいvptrが作成され、クラスのインスタンスに格納される。 が作成され、クラスのインスタンスに格納される。 仮想メソッドがオーバーライドされるたびに、新しいvtbl[]が作成される。 を作成しなければならない。

クラス定義だ:

class XXXX
{
    ....
};

以下を生成する:

インターフェイス

インターフェースは、vtbl[]へのポインターへのポインターである。 vtbl[0]エントリーは、object.Interfaceクラスの対応するインスタンスへのポインターである。 object.Interfaceクラスのインスタンスへのポインタである。 残りのvtbl[1..$] のエントリーは、そのインターフェースが実装する仮想関数へのポインターである。 へのポインタである。 へのポインタである。

COMインターフェイスが通常のインターフェイスと異なる点は、次のとおりである。 vtbl[0] には object.Interface エントリがない。 vtbl[0..$] のエントリは、宣言された順に、すべての仮想関数ポインタである。 である。 これは、Windowsで使用されるCOMオブジェクトのレイアウトと一致している。

C++とのインターフェイス "が通常のインターフェイスと異なる点は、次のとおりである。 C++インターフェイスは通常のインターフェイスと異なり、単一継承を使用するC++クラスのレイアウトと一致する。 を使用したC++クラスのレイアウトと一致する点である。

配列

ダイナミック・アレイは以下のものから構成される:

動的配列のレイアウト
offsetpropertycontents
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

ネームは標準的なD識別子である。

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

関数属性は、returnscope を除いて、上記の順序で発せられる。 return scope は、thisreturn scopeパラメータである場合は の場合はthis の前に、 の場合はscope の後に来る。 scopereturn 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)呼び出し規約を除く。

レジスタ規約

戻り値

パラメータ

可変長でない関数のパラメータ:

foo(a1, a2, ..., an);
へのパラメータは以下のように渡される:
a1
a2
...
an
隠された
この

ここで、hiddenは構造体を返すために必要であれば存在し、thisはthisポインタとして必要であれば存在する。 値を返すために必要な場合はhiddenが、メンバ関数のthisポインタとして必要な場合はthisが存在する。 メンバ関数のthisポインタとして、あるいはネストされた関数のコンテキスト・ポインタとして必要な場合に存在する。 関数のコンテキスト・ポインタとして必要な場合に存在する。

以下の条件を満たす場合、最後のパラメータはスタックにプッシュされるのではなく、EAXで渡される。 で渡される:

パラメータは常に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テーブルのエントリが生成される。

EHテーブルエントリ
fielddescription
void*関数開始へのポインタ
DHandlerTable*対応するEHデータへのポインタ
uint関数のバイトサイズ

EHテーブルのエントリは、以下の特別なセグメントに格納される。 セグメントに配置され、リンカによって連結される。

EHテーブルセグメント
Operating SystemSegment Name
Win32FI
Win64._deh$B
Linux.deh_eh
フリーBSD.deh_eh
OS X__deh_eh,__DATA

残りのEHデータはどこにでも置くことができる、 それは不変である。

DHandlerTable
fielddescription
void*関数開始へのポインタ。
uintEBP/RBPからのESP/RSPのオフセット
uint関数開始からリターンコードまでのオフセット
uintハンドラ情報のDHandlerInfo[]
DHandlerInfo[]ハンドラ情報の配列のエントリ数

DHandlerInfo
fielddescription
uint関数アドレスからガード区間開始までのオフセット
uintガードされたセクションの終わりのオフセット
int前のテーブルインデックス
uintif != 0 テーブルの先頭からDCatchInfoデータへのオフセット
void*もしNULLでなければ、最終的に実行するコードへのポインタ

DCatchInfo
fielddescription
uintのエントリ数DCatchBlock[]
DCatchBlock[]キャッチ情報の配列

void*キャッチハンドラーコード
DCatchBlock
fielddescription
ClassInfoキャッチ型
uintEBP/RBPからキャッチ変数へのオフセット

ガベージコレクション

このインターフェイスはDruntimeのcore/gc/gcinterface.dにある。

ModuleInfoインスタンス

のインスタンスである。 ModuleInfo のインスタンスはコンパイラによって生成され、各モジュールのオブジェクト・ファイルに挿入される。 ModuleInfo のインスタンスは、Dランタイム・ライブラリにとって有用なモジュールに関する情報を含んでいる:

ModuleInfo はDruntimeのobject.dで定義されており、フラグの値もフィールドのレイアウトもコンパイラの出力と一致していなければならない。

でコンパイルされたモジュールは -betterC でコンパイルされたモジュールは、ModuleInfo インスタンスが生成されない。 とコンパイルされたモジュールには、 のインスタンスは生成されない。 同様に、ImportCモジュールはModuleInfo を生成しない。

モジュールの初期化と終了

モジュールのすべての静的コンストラクタは、1つの関数に集約される。 へのポインタが挿入される。 ModuleInfo のctorメンバに挿入される。 メンバに挿入される。

モジュールのすべての静的デストラクタは、1つの関数に集約される。 へのポインタが挿入される。 ModuleInfo のdtorメンバに挿入される。 メンバに挿入される。

単体テスト

モジュールのすべてのユニットテストは、ひとつの関数に集約される。 に集約され、その関数へのポインタが挿入される。 ModuleInfo に挿入される。 メンバに挿入される。

ランタイム・ヘルパー関数

これらはDruntimeのrt/にある。

シンボリックデバッグ

Dには、既存のCやC++のデバッガでは表現できない型がある。 動的配列、連想配列、デリゲートなどである。 これらの型を構造体として表現すると問題が発生する。 構造体に対する関数の呼び出し規約は、これらの型に対するものとは異なることが多いからである。 そのため、C/C++デバッガは誤った表現をしてしまう。 これらのデバッガでは、構造体はC型として表現される。 型の呼び出し規約と一致している。

Cデバッガ用の型
D typeC representation
動的配列unsigned long long
連想配列void*
代議員long long
dcharunsigned long

新しい型を受け入れるように変更できるデバッガについては、以下の拡張がその型を完全にサポートするのに役立つ。 型 "を完全にサポートするのに役立つ。

Codeviewデバッガー拡張機能

Ddchar 型は特別なプリミティブ型 0x78 で表される。 プリミティブ型0x78で表される。

Dは、 (0x0015)で示されるCodeview OEM汎用型レコードを使用する。 LF_OEM (0x0015)で示される。フォーマットは以下の通りである:

D の Codeview OEM 拡張。
フィールドサイズ222222
D TypeLeaf IndexOEM IdentifierrecOEMnum indices type indextype index
ダイナミックアレイLF_OEMOEM12インデックス要素
連想配列LF_OEMOEM22キー要素
デリゲートLF_OEMOEM32この関数」である。
である:
OEM0x42
インデックス配列インデックスの型
キーキーの"型"インデックス
要素配列要素の型インデックス
このコンテキストポインタの型インデックス
関数".関数の型インデックス。

これらの拡張は で表示できる Ddbgデバッガ がサポートしている。