Rust: Rustをemscriptenで動作させる

作成日 2012年04月18日  ·  30コメント  ·  ソース: rust-lang/rust

私はこの問題をじっくり見てきましたが、rustcはemscriptenが変換できるコードを生成しますが、コンパイルされたjavascriptはランタイム関数にヒットすると失敗します。 次のステップは、コンパイラとしてemccを使用してランタイムの構築を開始することです。 EMSCRIPTEN ifdefsの背後に構築されていないものをすべて排除します。

Emscriptenは、インラインアセンブリをjavascriptとして扱う方法を追加しているため、emscriptenでビルドされないランタイムのすべての部分は、javascriptでインラインで実装できます。

または、JavaScriptでランタイムの断片を再実装し、C ++からコンパイルする必要はまったくありません。 このアプローチはお勧めしません。

A-runtime E-hard

最も参考になるコメント

1.0の準備をするために、大規模なトリアージ作業を行っています。 この一環として、ウィッシュリストのようなものをRFCリポジトリに移動します。ここで、主要な新しいものについて話し合い、優先順位を付ける必要があります。

この問題はRFCリポジトリに移動されました:rust-lang / rfcs#604

全てのコメント30件

#3608も参照してください。

それでもいいでしょう。 成熟度のマイルストーンではありません。

それでもいいのですが、それほど重要ではありません。 ランタイムの多くが錆びて書き直されているので、これは簡単になるはずです。

ランタイムがRustで記述されたので、このバグの見通しはどのように変わりますか? ランタイムのないHelloWorldをemscriptenで実行するのはどれほど難しいでしょうか?

今、emscriptenの本当に素晴らしいサポートを追加することは特に難しいことではありません。 それはすでにrust-coreでほとんど機能します。 コンパイラーでは、適切なターゲットトリプルのサポートを追加し、さまざまなターゲット属性を正しく設定してから、現在js、スレッド化、およびコンテキスト切り替えで機能できないランタイムのいくつかの部分をフェンスで囲む必要があります。

1:1スケジューリングモードがもう少し成熟すると、Webワーカーを介してタスクのサポートを追加できるようになる可能性がありますが、現在は別のメッセージパッシングソリューションが必要になります。 js / emscriptenに追加される並列処理のサポートによっては、最終的にrustのメッセージパッシングセマンティクスを正確にサポートできるようになる可能性があります。

@brson :#

-Z no-landing-padsおかげで、これは正常に機能するようになりました。 これに対する明示的なサポートを標準ライブラリに追加することは可能ですが、ほとんどの場合(ファイル、tcp、udpなど)は機能しないため、必要ではないと思います。 標準ライブラリが独立したサポートを利用できるようになると、それが機能し始め、JavaScriptにマップできる機能に基づいてさらに多くの問題を開くことができます。

よろしければ、とりあえずこれは開いたままにしておきたいと思います。 これを行うことは、標準ライブラリが拡張可能であり、任意の数のプラットフォームで実行できるようにするための良い一歩になると思います。

ほとんどの作業がおそらく行われていることに同意します。これには、emscripten固有のI / Oを提供するためにおそらくlibemscriptenが必要になりますが、途中で十分な障害が発生する可能性があるため、これを残す価値があると思います。問題は未解決です(それはまだ興味深いプロジェクトです!)

@alexcrichton :標準ライブラリの同時実行性とemscriptenのI / Oサポートを提供することはできません。 せいぜい、stdout / stderrのコンソールに出力できます。 デフォルトのアロケータの実装を超えて、emscriptenターゲットには良いアイデアであるが、独立したターゲットにはならない標準ライブラリのことは考えられません。

状況更新:

@alexcrichton標準ライブラリを、より理解しやすい依存関係を持つ

これに取り組むことを提案する方法は次のとおりです。

  • rustツールチェーンとLLVMツールチェーンを使っていくつかの実験を行い、asm.jsへのクロスコンパイルでcodegenがどのように機能するかを理解します。
  • emscriptenを使用してlibcoreを手動でビルドし、Web上で機能することを証明します。
  • rustcとmk / platform.mkを変更して、emscripten固有のターゲットトリプルを理解し、libcore.rlibのみを含むクロスコンパイルツールチェーンを作成します
  • システム(この場合はemscriptenが提供する)malloc、次に他のランタイムのないクレートで動作できるようにすることで、liballocに取り組みます。

それはかなり良いスタートです!

さて、私は最初のステップで試してみましたが、明らかに問題が発生しました。

libcore--emit bcでビットコードにコンパイルしました。 emcc -O0でコンパイルしようとすると、次のようになります。

/Users/arcnor/emscripten-fastcomp/build/bin/llvm-nm: /tmp/tmpfTkmfj/core_0.o: Invalid CMPXCHG record.
/Users/arcnor/emscripten-fastcomp/build/bin/opt: /tmp/tmpfTkmfj/core.bc: error: Invalid CMPXCHG record
Traceback (most recent call last):
  File "/Users/arcnor/emscripten/emcc", line 1573, in <module>
    shared.Building.llvm_opt(final, link_opts)
  File "/Users/arcnor/emscripten/tools/shared.py", line 1335, in llvm_opt
    assert os.path.exists(target), 'Failed to run llvm optimizations: ' + output
AssertionError: Failed to run llvm optimizations:

これについて何かできるかどうかわからない、またはこれにrustc --emit出力を使用できないためです。

これについてコメントする場所ではない場合は申し訳ありません...

また、より単純なlibnum試してみたところ、 bcが正しく生成されましたが、 emccプロセス中に、間違ったトリプルと結果のトリプルの使用に関する警告が表示されます。 jsにはlibnum内の関数がないので、ここではあまりにも素朴だと思います:)

@Arcnor以前にemscriptenを使用して簡単なテストをコンパイルしたことがある人にプロセスについて尋ねるかもしれません。 アイデアはほんの少ししかありません。

  • LLVMビットコードはバージョンごとに異なり、Rustが使用するバージョンは必ずしもemscriptenと同じではありません。 比較的類似したバージョンのLLVMを使用して両方を取得すると、互換性を向上させることができます。
  • エラーメッセージから、emscriptenの新しい「fastcomp」バックエンドを使用しているように見えます。 これは、古いバックエンドよりもRustyワークロードでテストされていない可能性があります。 古いバックエンドを手動でオプトインすると、少なくとも異なる結果が生じる可能性があります。
  • Emscriptenは通常、独自のターゲットトリプルを使用するため、同じものを使用するにはrustcを追跡する必要がある場合があります。

libcoreをコンパイルしようとしたときのエラーは、このemscriptenの問題に関連しているようです。 libcoreをllvmバイトコードにコンパイルするとllvmアトミック命令が生成されますが、emscriptenはアトミック命令をサポートしていません。

さびの側からこれを回避する方法があるかもしれませんが、emscriptenの問題のコメントに基づいて、emscriptenにアトミックのサポートを取得することが最も理にかなっていると思います。

emscriptenに独自のプラットフォームがある場合は、シングルスレッドのバリアントのすべてのアトミックをcfg-outすることができますが、これをアップストリームのemscriptenに含める方がよいことに同意します。

私が間違っていなければ、emscriptenの新しい「fastcomp」バックエンドはLLVMのフォークです(以前のバックエンドはLLVMの上のレイヤーでしたが)、したがって、fastcompのLLVMバージョンはおそらくアップグレードが難しく、アップグレードされません頻繁に。

これは、Rustの出力と互換性が必要な場合に問題になります。 たとえば、現在、fastcompのLLVMバージョンは3.3ですが、Rustで使用されるLLVMは3.4です。

古いemscriptenバックエンドは非推奨であり、公式ドキュメントによると使用すべきではないため、おそらくそれを使用するオプションではありません。

今のところ、emscripten用にコンパイルしようとしているのは私だけのようです。

記録のために、これが私が試したことです:

  • バイトコード(RustのLLVM 3.4によって生成された)にコンパイルし、それをfastcomp(LLVM 3.3のフォーク)に渡します; fastcompがクラッシュします
  • IRにコンパイルし、LLVM 3.3と互換性があるまで手動で編集し、fastcompに渡します。 複雑すぎて、重要なコードを変更するには多すぎる
  • Ruststage1を--llvm-rootコンパイルすると、emscriptenのfastcompがポイントされます。 ARM / MIPSなどのサポートが削除されたため、機能しませんでした。 彼らのフォークで(私はmakefilesから、そしてこれのためにリンケージ中にエラーを受け取ります)
  • RustのソースコードのLLVMgitサブモジュールを変更して、3.3時代の古いコミットを指すようにします。 LLVMのある時点でセグメンテーション違反が発生する
  • コンパイル済みのLLVM3.3(公式のubuntuリポジトリから提供)を指す--llvm-root Rustをコンパイルする; stage1のコンパイルの最後にアサーションの取得に失敗し、生成されたrustcバイナリが機能しません。

誰かが考えを持っていない限り、私の結論は、emscriptenがアップグレードするのを待つ必要があるということです。

ラム酒はそれが機能しているようです、ちょっと。 おそらくこれは役立つでしょう

マイナーアップデート:emscripten-fastcompはLLVM 3.4にアップデートされ、後でLLVM3.5にアップデートされます。

@tomaka 3.4バージョンで何かやってみましたか? ラム酒の例をコンパイルすることはできましたが、それ以上のことは理解できないエラーで失敗しました。

@ ibdknox3.4は3.5と互換性がありません
単純なHelloWorldでさえ、失敗したアサーションを生成します: LLVM ERROR: 0 && "some i64 thing we can't legalize yet"

うーん。 rustc --emit ir foo.rustから出力を取得し、emscripten-incomingを実行することができました。 LLVM 3.5に錆が発生しましたか?

Rustは長い間LLVM3.5を使用しています。 あなたは幸運であり、互換性のないものは何も生成されません。
たとえば、これは問題なくコンパイルされます。

#[start]
fn main(_: int, _: *const *const u8) -> int {}

これは、互換性のないIRが原因ではありません。

fn main() { println!("hello world"); }

@ibdknox http://www.reddit.com/r/rust_gamedev/comments/2n0x08/emscripten_experiments/
思ったよりも非互換性が少ないようです。

更新として、3.5に更新されたemscriptenを使用してhello worldをコンパイルすると、次のようになります。

Value:   %28 = call fastcc { i8, [0 x i8], [0 x i8] } @_ZN3fmt5write20h2c56fdda0b308d94DFAE({ i8*, void (i8*)** }* noalias nocapture dereferenceable(8) %arg.i, %"struct.core::fmt::Arguments[#3]"* noalias nocapture readonly dereferenceable(24) %__args31), !noalias !22
LLVM ERROR: Unrecognized struct value
Traceback (most recent call last):
  File "/Users/chris/Downloads/emsdk_portable/emscripten/incoming/emcc", line 1259, in <module>
    shared.Building.llvm_opt(final, link_opts)
  File "/Users/chris/Downloads/emsdk_portable/emscripten/incoming/tools/shared.py", line 1401, in llvm_opt
    assert os.path.exists(target), 'Failed to run llvm optimizations: ' + output
AssertionError: Failed to run llvm optimizations:

これが私がコンパイルしている方法です:

rustc --target i686-apple-darwin -C lto --emit ir foo.rust
emcc -v foo.ll -o test.html

ただし、fmtを導入していないように見えるものは、一般的には機能しているようです。

私は先週、これを調べて自由な時間を過ごしてきました。 私は夏から今までの間に錆の本を読み、言語の仕組みが本当に好きでしたが、つい最近になってそれを使って何かを実装し始めました。 私は今週学んだことと同じくらいRustコンパイラについての知識がありますが、貢献できることを願っています。

ですから、私が学んだこと(しかし、それに気付くのに数夜かかりました)に最初に注意することは、Rustが7月にLLVM3.6に移行したことだと思います。 そのため、Rustとemscripten-fastcompの現在のバージョンには互換性がありません。

emscripten-fastcomp 1.29.2を指す--llvm-root rustをコンパイルしようとしましたが、次のエラーが発生しました。

rustc: x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/libcore
error: internal compiler error: unexpected panic
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html
note: run with `RUST_BACKTRACE=1` for a backtrace
thread 'rustc' panicked at 'assertion failed: self.raw.hash != self.hashes_end', /Users/zen/Code/rust/src/libstd/collections/hash/table.rs:776


make: *** [x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/stamp.core] Error 101

このエラーに到達するために、私はemscripten-fastcompを構成して構築しました

../configure --enable-optimized --disable-assertions --enable-targets=host,js,arm,aarch64,mips

emscriptenのガイドの代わりに推奨

../configure --enable-optimized --disable-assertions --enable-targets=host,js

Rustはすべてのターゲット用に構築する必要はありませんが、現在、すべてのターゲット用にコンパイルされたCPUサポートを使用してLLVMに対して常にリンクしています。 これは将来修正される可能性のある問題の回避策であるため、常にその構成でemscripten-fastcompをコンパイルする必要はないかもしれません。

RustがLLVM3.6に移行したことがわかったら、rust-lang / llvmの最後のブランチであるLLVM3.5を調べました。 https://github.com/rust-lang/llvm/tree/rust-llvm-2014-07-24 emscripten-fastcompの代わりに、それに対してコンパイルしました。どうなるか知りたいです。 emscripton-fastcompの最近のLLVM3.5への移行に対してコンパイルすると、まったく同じエラーが発生しました。 私はこれを、Rustが現在LLVM 3.5と何らかの形で互換性がないことを意味していると考えており、そうでない場合は実際には期待していません。

だから今、私たちは待つか、emscripten-fastcompをLLVM 3.6に取得する必要があります:wink:

アーカイブされた0.11コピーをダウンロードし、 emcc理解したが、リンクの問題に到達したhelloworld用のLLVMIRを作成できたことは言及する価値があります。 バイトコードの理解を超えてしまうのを見るのはかなりエキサイティングでしたが、実際にリンクを取得するには、錆びたコードベースでの作業が必要になります。

rust-lang / llvmをemscripten-fastcompにマージする方法を覗いてみました。 当時、43個のファイルに117個の競合するセクションがありました。

リンク段階に到達するためにRust0.11とemcc1.29.2を取得することについて言及しました。 これは特定の結果です:

$ emcc -v hello.ll -o hello.js
INFO     root: (Emscripten: Running sanity checks)
WARNING: Linking two modules of different data layouts: '/Users/zen/.emscripten_cache/libc.bc' is 'e-p:32:32-i64:64-v128:32:128-n32-S128' whereas '/tmp/tmpv_yB8E/hello_0.o' is 'e-p:32:32-f64:32:64-f80:128-n8:16:32'
WARNING: Linking two modules of different target triples: /Users/zen/.emscripten_cache/libc.bc' is 'asmjs-unknown-emscripten' whereas '/tmp/tmpv_yB8E/hello_0.o' is 'i686-apple-darwin'
warning: incorrect target triple 'i686-apple-darwin' (did you use emcc/em++ on all source files and not clang directly?)
warning: unresolved symbol: _ZN2io5stdio12println_args20h0caae70b0e2eb347Iol7v0_11_0E
warning: unresolved symbol: _ZN10lang_start20h70f93b7d0a75f99atre7v0_11_0E

emcc / fastcompは、記号のドットをアンダースコアに置き換えているようですが、Rustは別のアンダースコアをプレフィックスとして付けることを期待していますが、これについてはよくわかりません。 最初の未解決のシンボルは、i686-apple-darwinビルドのlibstdに__ZN2io5stdio12println_args20h0caae70b0e2eb347Iol7v0.11.0Eとして表示されます。 構築されたライブラリでこのシンボルを見つける方法をemccに知ってもらうことができたとしても、ライブラリにはマシンコードが含まれているのに対し、emccにはLLVMバイトコードが必要だと思います。 emscriptenの標準ライブラリをコンパイルする必要があると言った人を思い出すと思います。 これはその必要性の一部です。

ですから、誰かが自分でショットを撮りたいと思ったら、これが私が試し、取り組むことを探している次のステップです。 (または、私がどれほど正しいか間違っているかを教えてください。)

  • rust-lang / llvmをemscripten-fastcompにマージします
  • JSバックエンドサポートなしでマージされたfastcompで錆を構築する
    これがマージの健全性テストになることを願っています。
  • emscriptenのトリプルをRustに追加してビルドします
    私が知る限り、変更または追加する必要のあるファイルがいくつかあります。

    • mk / cfg / asmjs-unknown-emscripten.mk

    • rt / arch / asmjs / {morestack.S、r​​ecord_sp.S}(空にできる可能性がありますか?)

      これらのファイルは、RustがLLVMのセグメント化されたスタックをサポートするためにmorestack.aをビルドするために必要です。 正しく思い出せば、Emscriptenのスタックも頭です。 ヒープの反対側の端をスタックとして使用します。asmjsの場合、配列のサイズを変更できないため、新しいスタックセグメントを作成することはできません。 librustc_backターゲットファイルのTargetOptionに、これを無効にできるフィールドがあります。

    • librustc_trans / trans / cabi_asmjs.rs

    • librustc_trans / trans / cabi.rs

      これらが必要かどうかはわかりませんが、現時点では推測にすぎません。

    • librustc_back / target / asmjs_unknown_emscripten.rs

    • librustc_back / asmjs.rs

    • librustc_syntax / abi.rs

    • librustc_back / back / write.js configure_llvm()

    • librustc_llvm / lib.rs static_link_hack_this_sucks()

  • 不足しているシステムインターフェイスを実装する
    私は11月にlibgreenが削除されたのを見ました。 emscriptenはブラウザのワーカーと共有する方法を待つ必要があるため、万が一発生した場合は、libgreenのようなものを復元するか、pthreadやWindowsスレッドAPIのrustがどのように構築されるかなどのemscripten専用の方法でpthreadをシムする必要があります。

IOも。 おそらく私が知らない他の部分。

「rust-lang / llvmをemscripten-fastcompにマージします」

あなたはこれをしたくないかもしれません-Emscriptenはpnacl-llvm / pnacl-clangに基づいているので、パッチにパッチを適用したフォークを作成していますが、これはおそらく苦痛です。 興味がある場合は、 https: //github.com/kripken/emscripten-fastcomp/issues/51#issuecomment -62323164で、r33-> r34からのEmscriptenマージについて行った調査で分岐の詳細を確認できます。 。

pnaclは以前よりも少し近くでアップストリームを追跡することを計画していると聞きましたが、pnacl Issue Trackerで3.6に更新する関連する問題が見当たらないため、しばらく時間がかかる場合があります(特に、3.6は5日前に分岐しただけです!)。 ..問題が発生する可能性があると思いますか? 自分のEmscriptenフォークに反対する場合は、2つのオプションがあります。pnaclを待つか、Emscriptenがpnaclを降りてアップストリームに入るのを支援するかです。

編集:「今」を「ではない」に修正。 決定的な違い。

1.0の準備をするために、大規模なトリアージ作業を行っています。 この一環として、ウィッシュリストのようなものをRFCリポジトリに移動します。ここで、主要な新しいものについて話し合い、優先順位を付ける必要があります。

この問題はRFCリポジトリに移動されました:rust-lang / rfcs#604

このページは役に立ちましたか?
0 / 5 - 0 評価