個人的な学習メモです。
functions1
関数定義は、"define"キーワードと関数名、オプションのリンクタイプ、ランタイムプリエンプション指定子、呼び出し規約、パラメータアトリビュート、関数アトリビュート、アラインメント、メタデータ情報などからなる。
define [linkage] [PreemptionSpecifier] [visibility] [DLLStorageClass]
[cconv] [ret attrs]
<ResultType> @<FunctionName> ([argument list])
[(unnamed_addr|local_unnamed_addr)] [AddrSpace] [fn Attrs]
[section "name"] [partition "name"] [comdat [($name)]] [align N]
[gc] [prefix Constant] [prologue Constant] [personality Constant]
(!name !N)* { ... }
example
define void @f(ptr noundef %0, ptr noundef %1, ptr noundef %2, i32 noundef %3) #0 {
関数宣言は、"declare"キーワードと関数名、オプションのリンクタイプ、アドレス空間、戻り値型、呼び出し規約、アラインメントなどからなる。
declare [linkage] [visibility] [DLLStorageClass]
[cconv] [ret attrs]
<ResultType> @<FunctionName> ([argument list])
[(unnamed_addr|local_unnamed_addr)] [align N] [gc]
[prefix Constant] [prologue Constant]
関数定義には基本ブロックのリストが含まれ、関数のCFG(コントロール・フロー・グラフ)を形成する。各基本ブロックは、オプションでラベルをつけることができる。また、命令とデバッグレコードのリストを含み、分岐や関数リターンなどの終端命令で終わる。明示的なラベル名が提供されないときは、ブロックには暗黙的に番号付きラベルが割り当てられる。
example
define void @f(ptr noundef %0, ptr noundef %1, ptr noundef %2, i32 noundef %3) #0 {
%5 = alloca ptr, align 8
%6 = alloca ptr, align 8
%7 = alloca ptr, align 8
%8 = alloca i32, align 4
%9 = alloca i32, align 4
store ptr %0, ptr %5, align 8
store ptr %1, ptr %6, align 8
store ptr %2, ptr %7, align 8
store i32 %3, ptr %8, align 4
store i32 0, ptr %9, align 4
br label %10
10: ; preds = %30, %4
%11 = load i32, ptr %9, align 4
%12 = load i32, ptr %8, align 4
%13 = icmp slt i32 %11, %12
br i1 %13, label %14, label %33
関数の最初の基本ブロックは、関数の入口で即座に実行され、先行する基本ブロックを持つことができない。(PHIノードも持つことができない)
アラインメントは2の冪乗で明示的に指定することもできる。