あいをなくした。

あいをなくしたボカロP「あいなし」と、知識欲に飢えた大学生「アライさん」の週記です。

【LLVM】LLVMリファレンスを読む【概要の続き、識別子】

 今回は前回の続きからです。前回同様、誤った解釈を見つけた場合にはコメントなどでご連絡ください。
 ここでは、文法的にはあっていてもおかしな文法に関してのことが述べられています。

Introduction(概要)

Well-Formedness('良い'形成)

(原文)
It is important to note that this document describes ‘well formed’ LLVM assembly language. There is a difference between what the parser accepts and what is considered ‘well formed’. For example, the following instruction is syntactically okay, but not well formed:
(和訳)
この文書では、「よくできた」LLVMアセンブリ言語について説明しています。パーサが受け入れるものと「よく形成された」とみなされるものには違いがあります。例えば、以下の命令は構文的には問題ありませんが、「よくできている」とは言えません。

 次に以下のような例が示され、文章は続きます。

%x = add i32 1, %x

(原文)
because the definition of %x does not dominate all of its uses. The LLVM infrastructure provides a verification pass that may be used to verify that an LLVM module is well formed. This pass is automatically run by the parser after parsing input assembly and by the optimizer before it outputs bitcode. The violations pointed out by the verifier pass indicate bugs in transformation passes or input to the parser.
(翻訳)
%x の定義がすべての用途を支配していないためです。LLVMインフラストラクチャは、LLVMモジュールが十分に形成されていることを検証するために使用できる検証パスを提供します。このパスは、入力アセンブリを解析した後にパーサによって自動的に実行され、ビットコードを出力する前にオプティマイザによって実行されます。検証パスによって指摘された違反は、変換パスやパーサへの入力のバグを示します。

 これにおいて、何が問題なのかはぱっと見分からないのですが(なんでリファレンスシリーズ書いてるん?)、LLVMを動かすときのコンパイラではこれをバグとして識別するそうです。
 この文書において、「とりあえずのところは『よくできた』文法を教えていくけれど、それは必ずしもコンパイルしてバグが検出されない『よく形成された』文法であるとは限らないよ?」っていう認識でいればいいと思います。

 次はようやく本題となります。

Identifiers(識別子)

 滅茶苦茶長くなってまいりました。個人的にはもう気が滅入るのでここまでにしたいのですが、それをよしとする人が果たしてどれほどいるのか....
 次は識別子のお話です。

識別子のお話その1『識別子の種類』

(原文) LLVM identifiers come in two basic types: global and local. Global identifiers (functions, global variables) begin with the '@' character. Local identifiers (register names, types) begin with the '%' character. Additionally, there are three different formats for identifiers, for different purposes:
(翻訳) LLVMの識別子には、グローバルとローカルの2つの基本的なタイプがあります。グローバル識別子 (関数、グローバル変数) は '@' 文字で始まります。ローカル識別子 (レジスタ名、型) は '%' 文字で始まります。さらに、識別子には、目的に応じて3つの異なるフォーマットがあります。

(原文) 1. Named values are represented as a string of characters with their prefix. For example, %foo, @DivisionByZero, %a.really.long.identifier. The actual regular expression used is ‘[%@][-a-zA-Z$.][-a-zA-Z$.0-9]*’. Identifiers that require other characters in their names can be surrounded with quotes. Special characters may be escaped using \xx where xx is the ASCII code for the character in hexadecimal. In this way, any character can be used in a name value, even quotes themselves. The \01 prefix can be used on global values to suppress mangling.
2. Unnamed values are represented as an unsigned numeric value with their prefix. For example, %12, @2, %44. 3.
(翻訳)
1. 名前付き値は、接頭語を持つ文字列として表現されます(例:%foo, @DivisionByZero, %a.really.long.identifier)。実際に使用されている正規表現[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*です。 名前に他の文字を必要とする識別子は、引用符で囲むことができます。特殊文字\xx(xxは16進数の文字のASCIIコード)を使ってエスケープすることが出来ます。このようにして、名前の値には、引用符を含めて、任意の文字を使用することができます。接頭辞 "\01" は、グローバル値に使用することで、混同を防ぐことができます。
2. 名前のない値は、その接頭辞を持つ符号なしの数値として表されます。(例:%12@2%44
3. 定数は、以下の「定数」の項で説明します。

 まとめると、以下のようになります。

  • グローバル変数とローカル変数は@%で見分けます。
  • 名前付きの値は上記の@, %の後に英字から始まる英数字(ほかに$, ., _が使用可能)で構成された文字列を名前として扱います。(例:%foo, @DivisionByZero, %a.really.long.identifier
    • ほかの文字が使いたい場合、\~~(16進ASCIIコード)で記述することで表現することが出来ます。
      • これを利用する事で、グローバル変数とローカル変数を識別子で区別することが出来るようになります。
  • 名前のない値は符号なしの数値として表します。(例:%12@2%44
  • 定数は後述

 識別子の項目を終わらせないと、めっちゃ中途半端なので、今回は長引くことを覚悟してください。

識別子のお話その2『分類理由』

 続きを読みます。ここでは、先述した分類の理由について確認しています。気が向いた方は読んであげてください。

(原文)
LLVM requires that values start with a prefix for two reasons: Compilers don’t need to worry about name clashes with reserved words, and the set of reserved words may be expanded in the future without penalty. Additionally, unnamed identifiers allow a compiler to quickly come up with a temporary variable without having to avoid symbol table conflicts.
(翻訳)
LLVMでは、2つの理由から値の先頭に接頭辞を付けることを要求しています。コンパイラ予約語との名前の衝突を心配する必要がないこと、予約語のセットは将来的にペナルティなしで拡張できることです。さらに、名前のない識別子を使用することで、コンパイラはシンボルテーブルの競合を回避することなく、一時的な変数を素早く作成することができます。

識別子のお話その3『予約語

 次は予約語、この場合はLLVM内の予約語の話です。ここでは予約語%@がつかない事さえ把握しておけば読み飛ばしても構いません。

(原文)
Reserved words in LLVM are very similar to reserved words in other languages. There are keywords for different opcodes (add, bitcast, ret, etc…), for primitive type names (void, i32, etc…), and others. These reserved words cannot conflict with variable names, because none of them start with a prefix character (% or @).
(翻訳)
LLVMにおける予約語は、他の言語における予約語と非常によく似ています。異なるオペコード(add, bitcast, ret, etc...)、プリミティブ型名(void, i32, etc...)などのキーワードがあります。これらの予約語は、どれも (%@) で始まるため、変数名と競合することはありません。

識別子のお話その4『例で確認 - eight times -』

 次に、整数i32型の変数である%X8を乗算するLLVMコードがリファレンスで示されています。 はじめに簡単な方法から。

%result = mul i32 %X, 8

シンプルですね。次に、左シフトを使った計算方法です。

%result = shl i32 %X, 3

次にちょっと難解な方法で行きます。後述しますが、この方法がLLVMの重要な語彙的特徴を示しているそうです。

(原文:This last way of multiplying %X by 8 illustrates several important lexical features of LLVM

 ちなみに、仕組み的には%0%X同士を足し合わせた結果(2倍)を格納し、%1%0同士を足し合わせた結果(%Xの4倍)を格納し、%result(戻り値)に%1動詞を足し合わせた結果(%Xの8倍)を格納しています。

%0 = add i32 %X, %X           ; yields i32:%0
%1 = add i32 %0, %0           ; yields i32:%1
%result = add i32 %1, %1

 では原文を読みましょう。

(原文)
1. Comments are delimited with a ; and go until the end of line.
2. Unnamed temporaries are created when the result of a computation is not assigned to a named value.
3. Unnamed temporaries are numbered sequentially (using a per-function incrementing counter, starting with 0). Note that basic blocks and unnamed function parameters are included in this numbering. For example, if the entry basic block is not given a label name and all function parameters are named, then it will get number 0.
(翻訳)
1. コメントは;で区切られ、行末まで続きます。
2. 名前のないテンポラリ(一時変数)は、計算の結果が名前付きの値に代入されていない場合に作成されます。
3. 名前のないテンポラリ(一時変数)は、(メソッドごとのインクリメントカウンタを使用して、0から始まる)順に番号が付けられています。基本ブロックと名前のない関数パラメータはこの番号付けに含まれることに注意してください。例えば、エントリの基本ブロックにラベル名が与えられておらず、すべての関数パラメータに名前が付けられている場合、それは番号0を取得します。

 最後の説明が分かりずらいですが、要するに一時変数の命名規則について、メソッドごとに0から始まる整数値を使用すること、無名のメソッドのパラメータ(クラスなどのメンバメソッドなどに用いる隠されたパラメータなど)もこの一時変数の対象となる事が示されています。

 最後に今後の表記について示されているので、これを記して今回は終了とします。大したことは書いてないので読み飛ばして構いません。

(原文)
It also shows a convention that we follow in this document. When demonstrating instructions, we will follow an instruction with a comment that defines the type and name of value produced.
(翻訳)
また、この文書で従う規則を示しています。命令を実演する際には、生成された値の型と名前を定義するコメントを添えて命令に従うことになります。