1. ホーム
  2. rust

[解決済み] Rust の 128 ビット整数 `i128` は 64 ビットシステムでどのように動作するのでしょうか?

2022-04-26 05:09:17

質問

Rustは128ビット整数を持ち、これらはデータ型 i128 (そして u128 は符号なしint型)。

let a: i128 = 170141183460469231731687303715884105727;

Rust は、これらの i128 の値は、64ビットシステム上で動作するのでしょうか?

私の知る限り、x86-64CPUの1つのレジスタに値を収めることはできないので、コンパイラは何らかの方法で、2つのレジスタを1つの i128 の値ですか?それとも、何らかの大きな整数構造を使って表現しているのでしょうか?

どのように解決するのですか?

Rustのすべての整数型は、コンパイル時に LLVMの整数値 . LLVM 抽象マシンは 1 から 2^23 - 1 までの任意のビット幅の整数を許容します * LLVM 命令 通常、どのような大きさの整数でも動作します。

もちろん、8388607ビットのアーキテクチャはそれほど多くないので、コードがネイティブのマシンコードにコンパイルされるとき、LLVMはそれをどのように実装するかを決定しなければなりません。のような抽象的な命令のセマンティクスは add はLLVM自身によって定義されます。一般的に、ネイティブコードで単一命令に相当する抽象的な命令はそのネイティブ命令にコンパイルされますが、そうでないものは複数のネイティブ命令でエミュレートされる可能性があります。 mcartonの回答 は、LLVMがネイティブ命令とエミュレートされた命令の両方をどのようにコンパイルするかを示しています。

(これは、ネイティブマシンがサポートできるよりも大きな整数だけでなく、小さな整数にも当てはまります。例えば、最近のアーキテクチャはネイティブの8ビット演算をサポートしていない場合があるので、その場合は add 命令で、2つの i8 は、より広い命令でエミュレートされ、余分なビットは破棄されます)。

<ブロッククオート

コンパイラは、何らかの方法で1つの i128 の値ですか?それとも、何か大きな整数構造を使って表現しているのでしょうか?

LLVM IRのレベルでは、答えはどちらでもありません。 i128 は1つのレジスタに収まり、他のすべての 単一値型 . 一方、機械語に翻訳されると、構造体は整数と同じようにレジスタに分解することができるので、両者の違いはあまりありません。というのも、構造体も整数と同じようにレジスタに分解することができるからです。


* しかし、すべてのLLVMバックエンドが同じように作られているわけではありません。この回答は、x86-64に関連するものです。128以上のサイズと2のべき乗以外のサイズに対するバックエンドのサポートは不安定です(Rustが8、16、32、64、128ビット整数しか公開しない理由の一部はこれによるものです)。 Redditのest31によると rustcは128ビット整数をネイティブにサポートしていないバックエンドをターゲットにした場合、ソフトウェアで実装しています。