3番地コード

3アドレスコードとは



3アドレスコードは、コンパイラなどのプログラミング言語処理系で用いられる中間表現の一種です。この形式は、最適化処理を施すのに適しており、効率的なコード生成を可能にします。名前の通り、各命令は2つのソース(入力)アドレスと1つのデスティネーション(出力)アドレスを持ちます。これは、命令セットアーキテクチャにおける3オペランド形式と類似しています。

形式



3アドレスコードにおける各命令は、一般的に`(オペコード, ソース1, ソース2, デスティネーション)`の4つ組で表現されます。数式のように記述すると以下のようになります。


x ← a ⊕ b


ここで `⊕` は任意の二項演算子を表します。`a` と `b` は、具体的な実装においては即値、レジスタ、またはメモリアドレスであり、抽象的なレベルでは定数、変数、または一時的な中間変数です。`x` は代入の対象となる左辺値であり、即値や定数ではありません。

複数演算を含む式



ソースコード中に複数の演算を含む式がある場合、例えば `x := i + m n;` のような代入文は、3アドレスコードでは複数の命令に分解されます。


t ← m × n
x ← i + t


このように分解することで、各命令が単一の演算に対応し、ソースやデスティネーションは単純な変数に限定されます。これは、2アドレスコードのようにデスティネーションがソースと共通である必要がないため、より柔軟なコード生成が可能です。

他のコード形式との比較



2アドレスコードでは、デスティネーションがソースの片方と同一である必要があり、オペランドにメモリを使用できないなどの制限がありますが、3アドレスコードではこれらの制限がなく、任意の組み合わせが可能です。また、3オペランド形式はRISCプロセッサで多く採用されており、命令フォーマットの効率化と最適化の促進に貢献しています。

ゼロレジスタの活用例



RISCプロセッサでは、ゼロレジスタ(例えばDEC AlphaのR31)を利用することで、例えば `y := -x;` という演算を以下のように3オペランド形式で表現できます。


y ← R31 - x


このように、3アドレスコードは、命令形式を統一し、より効率的なコード生成を可能にする点も、RISCの特徴的な部分を担っています。

具体例



以下は、C言語のプログラム例を3アドレスコードに変換したものです。

c
i := 0
L1: if i < 10 goto L2
goto L3
L2: t0 := i i
t1 := &b
t2 := i << 2
t3 := t1 + t2
*t3 := t0
i := i + 1
goto L1
L3:


この例では、配列へのアクセスや条件分岐など、より複雑な処理も3アドレスコードで表現できることがわかります。


まとめ



3アドレスコードは、コンパイラにおける中間表現として、効率的な最適化とコード生成に不可欠な役割を果たします。2アドレスコードと比較して、より柔軟で汎用的な命令形式を提供し、様々な最適化技術を適用しやすいという利点があります。

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。