LLVM 拡張機能

はじめに

このドキュメントでは、LLVM が互換性を目指しているツールおよびフォーマットの拡張機能について説明します。

汎用アセンブリ構文

C99 形式の16進浮動小数点定数

LLVM のアセンブラでは、必要に応じて、浮動小数点定数を10進数ではなく C99 の16進数形式で記述できます。

.section .data
.float 0x1c2.2ap3

マシン固有のアセンブリ構文

X86/COFF 依存

再配置

以下の追加の再配置タイプがサポートされています。

**@IMGREL** (AT&T 構文のみ) は、COFF 再配置タイプ IMAGE_REL_I386_DIR32NB (32 ビット) または IMAGE_REL_AMD64_ADDR32NB (64 ビット) に対応する、イメージ相対再配置を生成します。

.text
fun:
  mov foo@IMGREL(%ebx, %ecx, 4), %eax

.section .pdata
  .long fun@IMGREL
  .long (fun@imgrel + 0x3F)
  .long $unwind$fun@imgrel

**.secrel32** は、COFF 再配置タイプ IMAGE_REL_I386_SECREL (32 ビット) または IMAGE_REL_AMD64_SECREL (64 ビット) に対応する再配置を生成します。

**.secidx** 再配置は、ターゲットを含むセクションのインデックスを生成します。COFF 再配置タイプ IMAGE_REL_I386_SECTION (32 ビット) または IMAGE_REL_AMD64_SECTION (64 ビット) に対応します。

.section .debug$S,"rn"
  .long 4
  .long 242
  .long 40
  .secrel32 _function_name + 0
  .secidx   _function_name
  ...

.linkonce ディレクティブ

構文

.linkonce [ comdat タイプ ]

サポートされている COMDAT タイプ

discard

同じ COMDAT シンボルを持つ重複セクションを破棄します。タイプが指定されていない場合、これがデフォルトです。

one_only

シンボルが複数回定義されている場合、リンカはエラーを発行します。

same_size

重複は破棄されますが、サイズが異なるものがある場合、リンカはエラーを発行します。

same_contents

重複は破棄されますが、重複の内容が完全に同じでない場合、リンカはエラーを発行します。

largest

重複の中から最大のセクションをリンクします。

newest

重複の中から最新のセクションをリンクします。

.section .text$foo
.linkonce
  ...

.section ディレクティブ

MC は、.linkonce の情報を .section の最後に渡すことをサポートしています。たとえば、次の 2 つのコードは同等です。

.section secName, "dr", discard, "Symbol1"
.globl Symbol1
Symbol1:
.long 1
.section secName, "dr"
.linkonce discard
.globl Symbol1
Symbol1:
.long 1

結合された形式では、COMDAT シンボルが明示的であることに注意してください。この拡張機能は、異なる COMDAT に同じ名前の複数のセクションをサポートするために存在します。

.section secName, "dr", discard, "Symbol1"
.globl Symbol1
Symbol1:
.long 1

.section secName, "dr", discard, "Symbol2"
.globl Symbol2
Symbol2:
.long 1

.linkonce で許可されているタイプに加えて、.sectionassociative も受け入れます。これは、特定の他の COMDAT セクションがリンクされている場合に、そのセクションがリンクされることを意味します。この他のセクションは、このディレクティブの comdat シンボルによって示されます。関連付けられたセクションで定義されている任意のシンボルにすることができますが、通常は関連付けられたセクションの comdat です。

関連付けられたセクションには、次の制限が適用されます。

  1. COMDAT セクションである必要があります。

  2. 別の連想 COMDAT セクションにすることはできません。

次の例では、シンボル sym.foo の comdat シンボルであり、.bar.foo に関連付けられています。

.section        .foo,"bw",discard, "sym"
.section        .bar,"rd",associative, "sym"

MC は、COFF .section ディレクティブでこれらのフラグをサポートしています。

  • b: BSS セクション (IMAGE_SCN_CNT_INITIALIZED_DATA)

  • d: データセクション (IMAGE_SCN_CNT_UNINITIALIZED_DATA)

  • n: セクションはロードされない (IMAGE_SCN_LNK_REMOVE)

  • r: 読み取り専用

  • s: 共有セクション

  • w: 書き込み可能

  • x: 実行可能セクション

  • y: 読み取り不可

  • D: 破棄可能 (IMAGE_SCN_MEM_DISCARDABLE)

これらのフラグはすべて gas と互換性があります。ただし、gnu as がサポートしていない D フラグは例外です。gas との互換性のために、「.debug」で始まる名前のセクションは暗黙的に破棄可能です。

ARM64/COFF 依存

再配置

以下の追加のシンボルバリアントがサポートされています。

**:secrel_lo12:** COFF 再配置タイプ IMAGE_REL_ARM64_SECREL_LOW12A または IMAGE_REL_ARM64_SECREL_LOW12L に対応する再配置を生成します。

**:secrel_hi12:** COFF 再配置タイプ IMAGE_REL_ARM64_SECREL_HIGH12A に対応する再配置を生成します。

add x0, x0, :secrel_hi12:symbol
ldr x0, [x0, :secrel_lo12:symbol]

add x1, x1, :secrel_hi12:symbol
add x1, x1, :secrel_lo12:symbol
...

ELF 依存

.section ディレクティブ

同じ名前と comdat を持つ複数のセクションを作成できるように、.section ディレクティブの最後に一意の番号を追加することができます。たとえば、次のコードは .text という名前の 2 つのセクションを作成します。

.section        .text,"ax",@progbits,unique,1
nop

.section        .text,"ax",@progbits,unique,2
nop

一意の番号は、結果のオブジェクトにはまったく存在しません。アセンブラでセクションを区別するためにのみ使用されます。

'o' フラグは SHF_LINK_ORDER にマップされます。存在する場合、.sh_link に配置されるセクションを識別するシンボルを指定する必要があります。

.section .foo,"a",@progbits
.Ltmp:
.section .bar,"ao",@progbits,.Ltmp

これは、単に次のように記述するのと同じです。

.section .foo,"a",@progbits
.section .bar,"ao",@progbits,.foo

.linker-options セクション (リンカオプション)

フロントエンドからリンカにリンカオプションを渡せるようにするために、タイプ SHT_LLVM_LINKER_OPTIONS の特別なセクション (通常は .linker-options という名前ですが、タイプによって識別されるため、名前は重要ではありません) があります。このセクションの内容は、リンカが考慮するためのディレクティブの単純なペアワイズエンコーディングです。文字列は、標準のヌル終端 UTF-8 文字列としてエンコードされます。リンカが値を取得するためにオブジェクトファイルをトラバースするのを避けるために、インラインで出力されます。リンカは、オプションを無視し、代わりに要求されたオプションが受け入れられなかったという警告/エラーをユーザーに提供することを許可されています。

セクションのタイプは SHT_LLVM_LINKER_OPTIONS で、SHF_EXCLUDE フラグが設定されているため、この機能をサポートしていないリンカではセクションが不透明として扱われ、最終的なリンク済みバイナリに出力されません。

これは、次の raw アセンブリと同等です。

.section ".linker-options","e",@llvm_linker_options
.asciz "option 1"
.asciz "value 1"
.asciz "option 2"
.asciz "value 2"

以下のディレクティブが指定されています。

  • lib

    パラメータは、リンク対象のライブラリを識別します。ライブラリは、デフォルトと指定されたライブラリ検索パス (この時点までに指定されたもの) で検索されます。

  • libpath

    パラメータは、このオプションを含めた後、ライブラリを検索する際に考慮される追加のライブラリ検索パスを識別します。

SHT_LLVM_DEPENDENT_LIBRARIES セクション (依存ライブラリ)

このセクションには、リンカによってリンクに追加されるライブラリを指定する文字列が含まれています。

このセクションはリンカによって消費され、出力には書き込まれません。

文字列は、標準のヌル終端 UTF-8 文字列としてエンコードされます。

例えば

.section ".deplibs","MS",@llvm_dependent_libraries,1
.asciz "library specifier 1"
.asciz "library specifier 2"

ライブラリ指定子の解釈は、使用するリンカによって定義されます。

SHT_LLVM_CALL_GRAPH_PROFILE セクション (コールグラフプロファイル)

このセクションは、セクションの配置を最適化するために使用できるコールグラフプロファイルをリンカに渡すために使用されます。これは、(from シンボル, to シンボル, 重み) のタプルのシーケンスを含みます。

これは、タイプ SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) を持ち、SHF_EXCLUDE フラグが設定され、sh_link メンバーは関連付けられたシンボルテーブルのセクションヘッダーインデックスを保持し、sh_entsize は 16 である必要があります。名前は .llvm.call-graph-profile である必要があります。

セクションの内容は、Elf_CGProfile エントリのシーケンスです。

typedef struct {
  Elf_Word cgp_from;
  Elf_Word cgp_to;
  Elf_Xword cgp_weight;
} Elf_CGProfile;
cgp_from

エッジのソースのシンボルインデックス。

cgp_to

エッジのデスティネーションのシンボルインデックス。

cgp_weight

エッジの重み。

これは、アセンブリでは次のように表されます。

.cg_profile from, to, 42

.cg_profile ディレクティブはファイルの最後に処理されます。from または to が未定義の一時シンボルである場合、エラーになります。いずれかのシンボルが一時シンボルである場合、代わりにセクションシンボルが使用されます。いずれかのシンボルが未定義の場合、そのシンボルはファイルの最後に .weak symbol が記述されたかのように定義されます。これにより、シンボルがシンボルテーブルに確実に表示されます。

SHT_LLVM_ADDRSIG セクション (アドレス有意テーブル)

このセクションは、シンボルをアドレス有意としてマークするために使用されます。つまり、シンボルのアドレスが比較で使用されるか、翻訳単位の外部にリークします。これは、LLVM 属性 unnamed_addr および local_unnamed_addr が存在しないことと同じ意味です。

どのオブジェクトファイルでもアドレス有意としてマークされていないシンボルによって参照されるセクションは、C および C++ 言語標準によって提供されるアドレスの固有性保証を損なうことなく、リンカによって安全にマージできます。

セクションの内容は、アドレス有意シンボルのシンボルテーブルインデックスを参照する ULEB128 エンコード整数のシーケンスです。

2 つの関連するアセンブリディレクティブがあります

.addrsig

これは、アセンブラにアドレス有意テーブルを出力するように指示します。このディレクティブがない場合、すべてのシンボルはアドレス有意と見なされます。

.addrsig_sym sym

sym がファイル内の他の場所で参照または定義されていない場合、このディレクティブは何もしません。それ以外の場合、sym をアドレス有意としてマークします。

SHT_LLVM_SYMPART セクション (シンボルパーティション仕様)

このセクションは、シンボルに所属するパーティションをマークするために使用されます。.llvm_sympart セクションは、パーティションの名前を指定するヌル終端文字列と、パーティションに属するシンボルを参照する再配置で構成されます。次のように構築できます

.section ".llvm_sympart","",@llvm_sympart
.asciz "libpartition.so"
.word symbol_in_partition

SHT_LLVM_BB_ADDR_MAP セクション (基本ブロックアドレスマップ)

このセクションには、基本ブロックのバイナリ アドレスと、その他の関連メタデータが格納されます。この情報は、バイナリ プロファイル (perf プロファイルなど) をマシンの基本ブロックに直接マッピングするために使用できます。このセクションは -basic-block-sections=labels で出力され、すべての関数に BB アドレス マップ テーブルが含まれます。

SHT_LLVM_BB_ADDR_MAP タイプは、古いコンパイラによって生成された古いバージョンの BB アドレス マップの読み取りを可能にする後方互換性を提供します。各関数エントリは、使用するエンコーディングバージョンを指定するバージョンバイトで始まります。現在、次のバージョン管理スキームがサポートされています。

バージョン 1 (最新): 基本ブロックアドレスオフセットは、前のブロックの終わりからの相対値として計算されます。

.section  ".llvm_bb_addr_map","",@llvm_bb_addr_map
.byte     1                             # version number
.byte     0                             # feature byte (reserved for future use)
.quad     .Lfunc_begin0                 # address of the function
.byte     2                             # number of basic blocks
# BB record for BB_0
 .uleb128  .Lfunc_beign0-.Lfunc_begin0  # BB_0 offset relative to function entry (always zero)
 .uleb128  .LBB_END0_0-.Lfunc_begin0    # BB_0 size
 .byte     x                            # BB_0 metadata
# BB record for BB_1
 .uleb128  .LBB0_1-.LBB_END0_0          # BB_1 offset relative to the end of last block (BB_0).
 .uleb128  .LBB_END0_1-.LBB0_1          # BB_1 size
 .byte     y                            # BB_1 metadata

バージョン 0: 基本ブロックアドレスオフセットは、関数アドレスからの相対値として計算されます。これは、バージョン管理されていない SHT_LLVM_BB_ADDR_MAP_V0 セクションタイプを使用し、バージョンフィールドがゼロの SHT_LLVM_BB_ADDR_MAP を使用することと意味的に同等です。

.section  ".llvm_bb_addr_map","",@llvm_bb_addr_map_v0
.quad     .Lfunc_begin0                 # address of the function
.byte     2                             # number of basic blocks
# BB record for BB_0
 .uleb128  .Lfunc_beign0-.Lfunc_begin0  # BB_0 offset relative to the function entry (always zero)
 .uleb128  .LBB_END0_0-.Lfunc_begin0    # BB_0 size
 .byte     x                            # BB_0 metadata
# BB record for BB_1
 .uleb128  .LBB0_1-.Lfunc_begin0        # BB_1 offset relative to the function entry
 .uleb128  .LBB_END0_1-.LBB0_1          # BB_1 size
 .byte     y                            # BB_1 metadata
PGO 分析マップ

PGO 関連の分析データは、オプションの pgo-analysis-map フラグを介して、SHT_LLVM_BB_ADDR_MAP 内の各関数の後に出力できます。現在サポートされている分析は、関数エントリカウント、基本ブロック頻度、および分岐確率です。

各分析は、feature バイトのビットによって有効または無効になります。現在、これらのビットは次のとおりです。

  1. 関数エントリカウント - PGO プロファイルから取得した関数が呼び出された回数。PGO が使用されなかった場合、またはプロファイルで関数が検出されなかった場合、これは常にゼロになります。

  2. 基本ブロック頻度 - MBFI 分析から取得した生のブロック頻度値としてエンコードされます。この値は、エントリブロックと比較した相対頻度をエンコードする整数です。詳細については、「llvm/Support/BlockFrequency.h」を参照してください。

  3. 分岐確率 - MBPI 分析から取得した分岐確率の生の分子としてエンコードされます。この値は、「llvm/Support/BranchProbability.h」で定義されている固定小数点数の分子です。これは、実行中にブロックが特定の後続ブロックに続く確率を示します。

この追加データには、バージョン 2 以降が必要です。これは、基本ブロックの後続はインデックスを知らないが、BB ID は知っているため必要です。

PGO データを含む BBAddrMap の例

.section  ".llvm_bb_addr_map","",@llvm_bb_addr_map
.byte     2                             # version number
.byte     7                             # feature byte - PGO analyses enabled mask
.quad     .Lfunc_begin0                 # address of the function
.uleb128  4                             # number of basic blocks
# BB record for BB_0
 .uleb128  0                            # BB_0 BB ID
 .uleb128  .Lfunc_begin0-.Lfunc_begin0  # BB_0 offset relative to function entry (always zero)
 .uleb128  .LBB_END0_0-.Lfunc_begin0    # BB_0 size
 .byte     0x18                         # BB_0 metadata (multiple successors)
# BB record for BB_1
 .uleb128  1                            # BB_1 BB ID
 .uleb128  .LBB0_1-.LBB_END0_0          # BB_1 offset relative to the end of last block (BB_0).
 .uleb128  .LBB_END0_1-.LBB0_1          # BB_1 size
 .byte     0x0                          # BB_1 metadata (two successors)
# BB record for BB_2
 .uleb128  2                            # BB_2 BB ID
 .uleb128  .LBB0_2-.LBB_END1_0          # BB_2 offset relative to the end of last block (BB_1).
 .uleb128  .LBB_END0_2-.LBB0_2          # BB_2 size
 .byte     0x0                          # BB_2 metadata (one successor)
# BB record for BB_3
 .uleb128  3                            # BB_3 BB ID
 .uleb128  .LBB0_3-.LBB_END0_2          # BB_3 offset relative to the end of last block (BB_2).
 .uleb128  .LBB_END0_3-.LBB0_3          # BB_3 size
 .byte     0x0                          # BB_3 metadata (zero successors)
# PGO Analysis Map
.uleb128  1000                          # function entry count (only when enabled)
# PGO data record for BB_0
 .uleb128  1000                         # BB_0 basic block frequency (only when enabled)
 .uleb128  3                            # BB_0 successors count (only enabled with branch probabilities)
 .uleb128  1                            # BB_0 successor 1 BB ID (only enabled with branch probabilities)
 .uleb128  0x22222222                   # BB_0 successor 1 branch probability (only enabled with branch probabilities)
 .uleb128  2                            # BB_0 successor 2 BB ID (only enabled with branch probabilities)
 .uleb128  0x33333333                   # BB_0 successor 2 branch probability (only enabled with branch probabilities)
 .uleb128  3                            # BB_0 successor 3 BB ID (only enabled with branch probabilities)
 .uleb128  0xaaaaaaaa                   # BB_0 successor 3 branch probability (only enabled with branch probabilities)
# PGO data record for BB_1
 .uleb128  133                          # BB_1 basic block frequency (only when enabled)
 .uleb128  2                            # BB_1 successors count (only enabled with branch probabilities)
 .uleb128  2                            # BB_1 successor 1 BB ID (only enabled with branch probabilities)
 .uleb128  0x11111111                   # BB_1 successor 1 branch probability (only enabled with branch probabilities)
 .uleb128  3                            # BB_1 successor 2 BB ID (only enabled with branch probabilities)
 .uleb128  0x11111111                   # BB_1 successor 2 branch probability (only enabled with branch probabilities)
# PGO data record for BB_2
 .uleb128  18                           # BB_2 basic block frequency (only when enabled)
 .uleb128  1                            # BB_2 successors count (only enabled with branch probabilities)
 .uleb128  3                            # BB_2 successor 1 BB ID (only enabled with branch probabilities)
 .uleb128  0xffffffff                   # BB_2 successor 1 branch probability (only enabled with branch probabilities)
# PGO data record for BB_3
 .uleb128  1000                         # BB_3 basic block frequency (only when enabled)
 .uleb128  0                            # BB_3 successors count (only enabled with branch probabilities)

SHT_LLVM_OFFLOADING セクション (オフロードデータ)

このセクションには、オフロードデバイスのリンクと実行を実行するために使用されるバイナリデータが格納され、ファットバイナリが作成されます。このセクションは、OpenMP や CUDA などのオフロード言語のコンパイル中に生成されます。データがデバイスリンカのみによって使用されることを目的としている場合は、SHF_EXCLUDE フラグを使用して、最終的な実行可能ファイルまたは共有ライブラリから自動的に削除されるようにする必要があります。

このセクションに格納されているバイナリデータは、オフロードメタデータを格納するために使用されるカスタムバイナリ形式に準拠しています。この形式は、事実上、デバイスイメージを伴うメタデータを含む文字列テーブルです。

SHT_LLVM_LTO セクション (ファット LTO 用の LLVM ビットコード)

このセクションには、リンク時に通常の LTO または ThinLTO を実行するために使用される LLVM ビットコードが格納されます。このセクションは、コンパイラがファット LTO を有効にしたときに生成されます。このセクションには SHF_EXCLUDE フラグがあるため、最終的な実行可能ファイルまたは共有ライブラリから削除されます。

CodeView 依存

.cv_file ディレクティブ

構文

.cv_file ファイル番号 ファイル名 [ チェックサム ] [ チェックサムの種類 ]

.cv_func_id ディレクティブ

.cv_loc で使用できる関数 ID を導入します。

構文

.cv_func_id 関数 ID

.cv_inline_site_id ディレクティブ

.cv_loc で使用できる関数 ID を導入します。呼び出し元の行テーブルで使用するための inlined at ソースロケーション情報を含みます。呼び出し元が実際の関数であるか、別のインライン化された呼び出しサイトであるかは関係ありません。

構文

.cv_inline_site_id 関数 ID within 関数 inlined_at ファイル番号 行番号 [ 列番号 ]

.cv_loc ディレクティブ

最初の数字はファイル番号で、.file ディレクティブで事前に割り当てられている必要があります。2 番目の数字は行番号で、オプションで 3 番目の数字は列位置です (指定されていない場合はゼロ)。残りのオプション項目は、.loc サブディレクティブです。

構文

.cv_loc 関数ID ファイル番号 [ ] [ ] [ prologue_end ] [ is_stmt ]

.cv_linetable ディレクティブ

構文

.cv_linetable 関数ID , 関数開始 , 関数終了

.cv_inline_linetable ディレクティブ

構文

.cv_inline_linetable プライマリ関数ID , ファイル番号 行 関数開始 関数終了

.cv_def_range ディレクティブ

GapStartGapEnd オプションは必要に応じて繰り返すことができます。

構文

.cv_def_range 範囲開始 範囲終了 [ Gap開始 Gap終了 ] , バイト数

.cv_stringtable ディレクティブ

.cv_filechecksums ディレクティブ

.cv_filechecksumoffset ディレクティブ

構文

.cv_filechecksumoffset ファイル番号

.cv_fpo_data ディレクティブ

構文

.cv_fpo_data procsym

ターゲット固有の動作

X86

再配置

@ABS8 は、8ビット即値形式を持つオペランドを持つ命令の即値オペランドとして現れるシンボルに適用できます。これにより、アセンブラは8ビット形式とシンボルに8ビット再配置(例:R_386_8 または R_X86_64_8)を使用します。

例えば

cmpq $foo@ABS8, %rdi

これにより、アセンブラは、32ビット即値オペランドを取る cmpq $foo, %rdi とは対照的に、64ビットに符号拡張される8ビット即値オペランドを取る64ビット cmpq 命令の形式を選択します。これは、8ビット比較である cmpb $foo, %dil とも同じではありません。

@GOTPCREL_NORELAX は、@GOTPCREL の代わりに使用して、アセンブラが緩和可能な R_X86_64[_REX]_GOTPCRELX 再配置ではなく、R_X86_64_GOTPCREL 再配置を確実に発行するようにすることができます。

ARM 上の Windows

スタックプローブの発行

リファレンス実装(Microsoft Visual Studio 2012)は、以下の方法でスタックプローブを発行します

movw r4, #constant
bl __chkstk
sub.w sp, sp, r4

ただし、これは32 MiB(±16MiB)の制限があります。より大きなバイナリに対応するために、LLVMは-mcmodel=largeを使用して、わずかな偏差を介して4GiBの範囲を許可することをサポートしています。以下のように間接ジャンプが生成されます

movw r4, #constant
movw r12, :lower16:__chkstk
movt r12, :upper16:__chkstk
blx r12
sub.w sp, sp, r4

可変長配列

リファレンス実装(Microsoft Visual Studio 2012)では、可変長配列(VLA)の発行は許可されていません。

Windows ARM Itanium ABI は、動的スタック割り当ての発行のサポートを追加することで、基本 ABI を拡張します。可変スタック割り当てを発行する場合、ガードページが正しく設定されていることを確認するために、__chkstk の呼び出しが無条件に発行されます。このスタックプローブ発行の発行は、標準のスタックプローブ発行と同様に処理されます。

MSVC 環境は、現在 VLA のコードを発行しません。

ARM64 上の Windows

スタックプローブの発行

リファレンス実装(Microsoft Visual Studio 2017)は、以下の方法でスタックプローブを発行します

mov x15, #constant
bl __chkstk
sub sp, sp, x15, lsl #4

ただし、これは 256 MiB(±128MiB)の制限があります。より大きなバイナリに対応するために、LLVM は -mcmodel=large を使用して、わずかな偏差を介して 8GiB(±4GiB)の範囲を許可することをサポートしています。以下のように間接ジャンプが生成されます

mov x15, #constant
adrp x16, __chkstk
add x16, x16, :lo12:__chkstk
blr x16
sub sp, sp, x15, lsl #4