popl ミーティング 6/7 inside adl
DESCRIPTION
POPL ミーティング 6/7 Inside ADL. 吉野 寿宏 ( 米澤研 , D1) < [email protected] >. ADL って何?. ADL: Architecture Description Language 低級言語の意味論を記述するために設計 された言語 修論研究のときに設計しました レジスタ・メモリを扱うことができる C ライクな式の構文を持つ. 修士論文の概要. 低級言語のプログラム検証器を作るための支援をするフレームワークを作成した 共通言語を固定し、その上で検証ロジックを構築 - PowerPoint PPT PresentationTRANSCRIPT
ADL って何? ADL: Architecture Description Language
低級言語の意味論を記述するために設計された言語修論研究のときに設計しましたレジスタ・メモリを扱うことができるC ライクな式の構文を持つ
修士論文の概要 低級言語のプログラム検証器を作るための
支援をするフレームワークを作成した共通言語を固定し、その上で検証ロジックを構
築共通言語に対してプログラム変換してから検証
変換器と検証ロジックとは独立 新しいアーキテクチャに対応する際に検証器は
弄らない 検証器を取り替えるときに変換器を弄らない
本研究のアイデア ( 図 )
共通言語に変換されたプログラム
低級言語のプログラム
変換器
共通言語の意味論
検証結果Success
/Fail
検証器
検証ロジック
問題はどのように解決されるか 言語の意味論の複雑さを削減
低級言語の記述は変換器の中に収める 言語の記述は一度やってしまえば OK
検証ロジックの実装者は変換器を気にする必要はない
システムの移植性の改善一度検証ロジックを実装すれば、変換器を取
り替えて他のアーキテクチャにも対応可⇒ 組み合わせの数が減らせる
今日のメニュー ADL の設計について プログラム変換器について 型理論・プログラム解析との組み合わせ まとめ
今日のメニュー ADL の設計について
デザインの着想構文、意味論の定義
プログラム変換器について 型理論・プログラム解析との組み合わせ まとめ
Design Goals
特定のアーキテクチャに依存しない 種々の低級言語を記述するための言語なので データの幅が 32bit とか 64bit であるとかいう制限は
できるだけ排除 低級言語に近いレベルの記述
λ 計算のように抽象度の高い記述は変換が手間 レジスタ・メモリに対する操作を明示的に記述できる
とよいのでは
なるべくシンプルな言語構造 基本となる命令数が多いと意味論が複雑化
抽象機械の定義 アーキテクチャの記憶域に対応
レジスタ、メモリ プログラムは抽象機械上の操作を記述
ADL抽象機械
プログラム
抽象機械の定義 レジスタ・メモリ
メモリはラベルのつけられたブロックの集合 便宜上の目的で一時変数を用意
実際のアーキテクチャには存在しない部分 計算の途中結果を格納し、プログラムを記述しやすくする
r1
r2
r3
l1 → <…>l2 → <…>l3 → <…>
…
…
x = 1y = 2
z = &l1… ADL
抽象機械
言語の扱う値 整数とポインタがあれば十分
浮動小数点数などは整数にエンコードできる
実 CPU 上のデータには「幅」の概念がある 8bit の数 (byte) 、 32bit の数 (dword) など 幅によってデータの範囲が制限される
しかし幅は計算を記述する上で障害になる例 : 32bit の値と 8bit の値を足すとどうなる?
普通は 8bit の値を 32bit に coerce するが… MSB を符号として解釈? それともゼロ拡張?
「 Value 」と「 Data 」、 2 つの世界 記憶域から取り出す・保存するときに「解釈」が
はさまると考える 整数全体の集合 との対応づけ
対応づけはアーキテクチャのパラメータとして与える
Data … 記憶領域の上での表現 「幅」の概念を持つ
Value… 計算に用いられる値 Data が「解釈」された値 任意の整数 ( とかポインタ ) を表現可能
値の定義
Value Data
a は 1 バイト幅のデータ
3 種類のコンストラクタがそれぞれ
対応
Fat Pointer
junk ─ 不定値 ADL の枠組みで値が定まらないことを表す
実際の低級言語では アドレス = 整数 だが、 ADLではメモリレイアウトについて仮定しない
メモリのラベルと整数のマッピングが不明なので アセンブリ言語のプログラムでラベル名を用いること
に相当一部のポインタ
演算等で現れる 詳細は割愛
言語構文 (1) 左辺値左辺値 … レジスタ、メモリ
[, ] にはさまれている部分はデータ幅の指定 レジスタは一部分のデータをとってくることができる メモリに関しては、オフセットは式の部分で計算する
のでデータ幅指定のみでよい
注 : 一時変数は Value を格納するのでここには含まれない
言語構文 (2) 式 ev: Value に評価される式、 eb: Bool 式 中置演算子、括弧などによる記述
四則演算、ビット演算 C, Java などと同等の記述力
レジスタ、メモリを参照するとデコードが発生する
言語構文 (3) 文 5 種類のコマンドから構成
nop, error, 代入 , goto( 無条件分岐 ), 条件実行 goto + 条件実行 = 条件分岐
レジスタ、メモリへの代入時にはエンコードされる 変数は Value を保持するのでエンコードは必要ない
ADL のプログラム ADL では、プログラムもメモリに格納
メモリブロック ::= コード列 | データ メモリ :: ラベル → メモリブロック ただしプログラムをデータとしていじることはできません
命令ポインタ = ラベル名 + 命令インデクス 「この命令は何バイト?」と考えることはナンセンス 分岐はブロックの先頭 ( つまりラベルのある箇所 ) にの
み可能 この制限により、メモリブロックが CFG の基本ブロックになる …ので、その後の解析が楽になるかと考えている
簡単な例 整数を含む連結リストの要素の総和を求める
ハコは 4 バイト幅のデータと考えてください
start:%r2 = 0;goto &loop;
loop:if %r1 = &null then goto &endelse nop;%r2 = %r2 + *[4](%r1);%r1 = *[4](%r1 + 4);goto &loop;
end:
1
2
3
null
r1
0r2 136
今日のメニュー ADL の設計について プログラム変換器について
変換アルゴリズム、テンプレート言語の設計変換の正しさに関する定義
型理論・プログラム解析との組み合わせ まとめ
プログラム変換器 実際の低級言語から ADL に変換
検証したいプログラムは、実際の CPU 上のアセンブリ言語や機械語で書かれている
検証ロジックは ADL の意味論を用いて定義する
意味論を保つ変換であることが必要そうでなければ検証が意味を為さない「意味論を保つとは何か」については後ほど定義
アセンブリ言語・機械語の変換アルゴリズム これらの言語のプログラムは命令の列
算術演算・論理演算制御構造としては分岐 (無条件・条件 ) があれ
ば十分 ループや関数呼び出しなどは全てこれらで書ける
基本的には命令単位で順次変換すればよい各命令はコンテクストを持たない
持っているとすればプロセッサの状態 ( レジスタ・メモリ ) のはず
テンプレートによる変換ルールの記述 アセンブリ言語の命令 = 種別 + オペランド
オペランドによってパラメータ化されている
たとえば mov 命令 ( データのコピー )
mov %r1, %r2 ⇔ %r1 = %r2;mov %r3, %r5
命令種別 オペランド
⇔ %r3 = %r5;mov %r2, %r4 ⇔ %r2 = %r4;
mov D , S ⇔ D = S ;
変換ルール!
テンプレートによる変換ルールの記述
すべての可能性を列挙する手間が省ける
オペランド ::= レジスタ | メモリ | 即値ADL の構文の非終端記号で言うと、 l か v
⇒ ev( 式 ) にマップすればカバーできる
mov D , S ⇔ D = S ;
テンプレート言語 ADL の式 (ev) を拡張
テンプレート引数を許容するように sizeof 演算子 (lvalue のデータ幅を返す ) の追加
引数で指定できる箇所を ev に変更 代入の左辺、左辺値のデータサイズ指定
テンプレートのインスタンス化 コンテクスト :: 変数 → ev( 式 ) 構文木をほぼそのまま写せばよい
テンプレート変数の部分は「接木」
変数を許すために便宜的に ev を使っている箇所でダウンキャストが必要 左辺値のデータ幅指定 → 整数へ 代入左辺 → 左辺値または一時変数へ ダウンキャストできない場合は、変換が失敗する
( エラー )
パターンマッチング 使用するテンプレートをどうやって指定
する?⇒ パターンマッチング
Prolog ( や O’Caml) にヒント小さな木のマッチング
パターン言語の文法を右に示した
アーキテクチャ記述と変換アルゴリズム パターン言語と ADL プログラムを関連付け
命令マッピング パターン { 命令列 } オペランドマッピング パターン = 式
変換アルゴリズムの概略1. 与えられた項 t をパターンと順にマッチング2. マッチした場合、変数から項 t への束縛が返るので、オペランドマッピングを用いて式に変換
3. 変換されたコンテクストを用いてテンプレートコードをインスタンス化
アーキテクチャ記述例 (IA-32 、抜粋 )#operand {
eax = %eax;ax = %eax[0,2];al = %eax[0,1];ah = %eax[1,1];
ebx = %ebx;...
}
mov(D, S) {D = S;
}
...
add(D, S) {// calculate resultD = D + S;
// ZFif D : int then if D == 0 then %_zf = 1 else %_zf = 0else if (D - &null) : int then if (D - &null) == 0 then %_zf = 1 else %_zf = 0else %_zf = junk;...
}
プログラム変換の正しさ プログラム = 機械の状態集合上の関数 変換の正しさ =
実機械状態と ADL 抽象機械の状態の「対応」が任意のプログラムに関して保存
変換元のプログラム
変換後のプログラム
状態
状態’
State
State’
状態の対応関係 変換器 ( ルール ) の実装者が定義
実機械の状態集合が、抽象機械の状態集合に埋め込まれるのがポイント 抽象機械の状態の集合から実機械の状態の集合へ total
な surjection が定義できればよい 実機械では値として整数値しか用いないことを考えれば直観的に明らか
変数の生存期間が局所的 ( ある一命令に対応するコード内で完結している ) ならば変数については忘れてよい
レジスタの状態 ,
メモリの中身
レジスタ、メモリ、一時変数
変換の正しさを検査する 今のところ、変換器の実装者に委ねている
いくつかの入力例について出力が等しくなることを確かめればある程度の確証を得るのでは?
(半 )自動的に保証することは future workパターンが決まっているし、プリミティブな
ループを含まないので、なんとかならないか?その前段として、 ADL の意味論を定理証明器
に載せるべく現在勉強中
今日のメニュー ADL の設計について プログラム変換器について 型理論・プログラム解析との組み合わせ
テンプレート言語の問題点テンプレート言語に対する型判定、型推論プログラム解析の手法の適用さらなる応用
まとめ
テンプレート言語の問題点これまでの定義では… テンプレート変数に予期しない値が入って
くる例 : mov(D, S) { D = S; } に対して D = 1 などを
与えると… 不正なテンプレートを書ける
例 : 引数にない変数を中で参照する可能性例 : 1 = 2; のような式を許容してしまう
⇒ いずれも「変換時に」エラーが発生「変換器をコンパイルする際に」、ではない
型理論の手法による解決 型を用いることにより、これらの問題を解決
変数に予期しない値が入ってこないように検査 これは runtime check とほぼ変わらないが逆に、型推論を行うことで引数にどういった条件が
必要かがわかる不正なテンプレートを静的にチェックできる
ここで言う「静的」とは、変換器のコンパイル時のこと
プログラムを実際に与えて変換する時、ではない 何度もコンパイルしてトライ &エラーする手間が省け
る
型の構造 右図のような subtype relation
を満たす型を導入ADL の構文定義の構造を反映
int ⇔ n ( 整数 ) const ⇔ v (Value)
ただし junk を除く lvalue ⇔ l ( 左辺値 ) assn ⇔ l | x ( 変数 )
assignable の意 * (any) ⇔ ev ( 式 )
図では上の方が subtype
* (any)
const assn
int lvalue
型付け規則 型環境 式に対する型付け規則 Γ|- ev :τ
型付け規則 Bool 式に対する型付け規則 Γ|-eb : bool
ほぼ自明なので割愛します 文に対する型付け規則 Γ|- c
コード列に対する型付け規則 Γ|- <c;…>これもほぼ自明なので割愛します
型の健全性・完全性健全性 : 型検査に通るテンプレートは (正し
い引数が与えられれば )エラーを起こさないエラーにならない ⇔ ダウンキャストが成功ダウンキャストが可能な条件を考えれば自明
完全性 : 正しいテンプレートは型検査を通るダウンキャストが成功する場合は、型付け規則
より型が整合的につけられることは明らか case analysis をすればよい
型検査の一例 型環境 Γ= D : lvalue, S : * のもとで、文
D = S + 1を型付け
*
const assn
int lvalue
型を推論する 型付け規則をそのまま使える
( テンプレート ) 変数の型を全て型変数とおいて制約を集めて解く
関連付けられているパターンに含まれている変数のみ注目
「 ( 変数 ) ( 型 ) 」という形の制約だけが出てくる不整合な型が出てきたら推論失敗
X lvalue かつ X int 、とか reg[sizeof(X), X] のような不正な式を静的に除外
さらなる応用 型を細かく定義することにより、細かい言語
の制限を記述することが可能reg lvalue などとして、レジスタのみを受け
付けるテンプレートを記述することができる
型を用いた constant folding の補助現在はデータ幅指定の部分に算術式が書けない
変換時に定数になる「式」を書けると便利? X:int で reg[sizeof(reg) – X, X] 、のような用途を想定
型付け規則を拡張してより細かい型付けを行う
ほかの問題点 ありえない instantiation がなされる可能性例 : 「レジスタのみ受け付ける」などが表現できない⇒ あり得る組み合わせが全て正しく変換されていれば
問題はないはず
変数使用の局所性を保証できない同一テンプレートの外で定義されている ( 一時 ) 変数を参照していないか
手で確かめるのは容易だが、変数の生存解析により自動で検査できる
しかし大きな障害が… 実際のところ、純粋にテンプレート言語だけ
で書けるアーキテクチャは少ない (or, ない )call は次命令のアドレスを知らなければできな
いDelayed branch をする場合、変換途中で後続命
令を変換することが必要
対応するために、式の部分を拡張して任意のコードを書けるようにする必要⇒ たとえば Java の意味論を知らないと型が求め
られない ?
今日のメニュー ADL の設計について プログラム変換器について 型理論・プログラム解析との組み合わせ まとめ
まとめ 低級言語の意味論を記述するための言語
ADL の設計について述べた プログラム変換器の実装について述べた
ルールベースの記述
変換ルールに対して型理論やプログラム解析の手法を応用できることを説明したおかしなテンプレート、 instantiation をはじく細かく型をつけることでいろいろな応用ができそ
う