Rust: Jadikan Rust berfungsi dengan emscripten

Dibuat pada 18 Apr 2012  ·  30Komentar  ·  Sumber: rust-lang/rust

Saya telah menghabiskan beberapa waktu untuk mengatasi masalah ini dan rustc sekarang menghasilkan kode yang dapat diterjemahkan oleh emscripten, tetapi javascript yang dikompilasi gagal ketika mencapai fungsi runtime. Langkah selanjutnya adalah mulai membangun runtime menggunakan emcc sebagai compiler. Matikan semua hal yang tidak dibangun di belakang EMSCRIPTEN ifdefs.

Emscripten menambahkan cara untuk memperlakukan perakitan sebaris sebagai javascript, sehingga semua bagian runtime yang tidak dibangun dengan emscripten dapat diimplementasikan sejalan dengan javascript.

Sebagai alternatif, kita dapat mengimplementasikan kembali runtime sedikit demi sedikit dalam javascript dan tidak perlu repot mengkompilasinya dari C++ sama sekali. Pendekatan ini tidak disarankan.

A-runtime E-hard

Komentar yang paling membantu

Saya melakukan upaya triase besar-besaran untuk menyiapkan kita untuk 1.0. Sebagai bagian dari ini, saya memindahkan hal-hal yang seperti daftar keinginan ke repo RFC, karena di situlah hal-hal baru yang besar harus didiskusikan/diprioritaskan.

Masalah ini telah dipindahkan ke repo RFC: rust-lang/rfcs#604

Semua 30 komentar

Lihat juga #3608.

Akan tetap menyenangkan; tidak pada tonggak kedewasaan apa pun.

Masih akan menyenangkan, tetapi tidak terlalu penting. Ini seharusnya menjadi lebih mudah, karena banyak runtime sedang ditulis ulang dengan karat.

Sekarang runtime ditulis dalam Rust, bagaimana hal itu mengubah prospek bug ini? Seberapa sulitkah menjalankan Hello World tanpa runtime melalui emscripten?

Seharusnya tidak terlalu sulit untuk menambahkan dukungan yang sangat bagus untuk emscripten sekarang. Ini sudah cukup banyak bekerja dengan rust-core. Di kompiler kita perlu menambahkan dukungan untuk triple target yang tepat, mengatur berbagai atribut target dengan benar, lalu menutup beberapa bagian runtime yang saat ini tidak dapat bekerja di js, threading, dan pengalihan konteks.

Setelah mode penjadwalan 1:1 menjadi lebih matang, kami bahkan mungkin dapat menambahkan dukungan untuk tugas melalui pekerja web, meskipun saat ini akan memerlukan solusi pengiriman pesan yang berbeda. Bergantung pada dukungan paralelisme apa yang ditambahkan ke js/emscripten, kami akhirnya dapat mendukung semantik penyampaian pesan rust dengan tepat.

@brson : Saya pikir #10780 akan menjadi pemblokir terbesar saat ini. Rust akan menampilkan bantalan pendaratan dengan panggilan untuk memperbarui ukuran yang digunakan untuk melakukan keamanan tumpukan melalui dukungan tumpukan tersegmentasi LLVM.

Berkat -Z no-landing-pads ini sekarang berfungsi dengan baik! Menambahkan dukungan eksplisit untuk ini ke pustaka standar dimungkinkan, tetapi sebagian besar tetap tidak akan berfungsi (file, tcp, udp, dll.) jadi saya rasa itu tidak perlu. Jika dan ketika perpustakaan standar mengambil dukungan berdiri sendiri, itu akan mulai bekerja dan kami dapat membuka lebih banyak masalah berdasarkan fungsionalitas yang dapat kami petakan ke JavaScript.

Jika tidak apa-apa, saya sebenarnya ingin membiarkan ini terbuka untuk saat ini. Saya pikir melakukan ini akan menjadi langkah maju yang baik untuk memastikan perpustakaan standar dapat diperluas dan dapat berjalan di sejumlah platform.

Saya setuju bahwa sebagian besar pekerjaan mungkin sudah selesai, dan ini mungkin perlu libemscripten untuk menyediakan I/O khusus emscripten, tetapi saya pikir mungkin ada cukup banyak hambatan yang terjadi sehingga ini layak untuk ditinggalkan masalah terbuka untuk (ini masih merupakan proyek yang menarik!)

@alexcrichton : Tidak mungkin menyediakan konkurensi perpustakaan standar dan dukungan I/O untuk emscripten. Paling-paling, itu bisa ditampilkan ke konsol untuk stdout/stderr. Saya tidak dapat memikirkan hal apa pun di perpustakaan standar yang akan menjadi ide bagus untuk target emscripten tetapi bukan yang berdiri sendiri, di luar implementasi pengalokasi default.

Pembaruan status:

@alexcrichton Telah

Inilah cara saya menyarankan untuk mengatasi ini:

  • Lakukan beberapa eksperimen dengan rantai alat karat dan LLVM untuk memahami cara kerja codegen untuk kompilasi silang ke asm.js.
  • Bangun libcore dengan emscripten secara manual dan buktikan bahwa itu berfungsi di web.
  • Ubah rustc dan mk/platform.mk untuk memahami triple target khusus emscripten, buat rantai alat kompilasi silang yang tidak berisi apa pun selain libcore.rlib
  • Atasi liballoc dengan mengizinkannya bekerja dengan sistem (dalam hal ini disediakan oleh emscripten) malloc, lalu peti bebas runtime lainnya.

Itu awal yang cukup bagus!

Oke, jadi saya mencoba dengan langkah pertama, dan jelas langsung mendapat masalah.

Saya mengkompilasi libcore ke bitcode dengan --emit bc , dan ketika mencoba mengompilasinya dengan emcc -O0 , saya mendapatkan:

/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:

Tidak yakin apakah saya dapat melakukan sesuatu tentang ini, atau karena kami tidak dapat menggunakan output rustc --emit untuk ini.

Maaf jika ini bukan tempat untuk berkomentar tentang ini...

Saya juga mencoba dengan libnum , yang lebih sederhana, dan bc menghasilkan dengan benar, tetapi saya mendapat peringatan selama proses emcc tentang menggunakan triple yang salah dan hasil . js tidak memiliki fungsi apa pun di dalam libnum , jadi saya pikir saya terlalu naif di sini :)

@Arcnor Anda mungkin bertanya kepada beberapa dari mereka yang sebelumnya telah mengkompilasi tes sederhana dengan emscripten tentang prosesnya. Saya hanya punya beberapa ide.

  • Bitcode LLVM berubah dari versi ke versi dan versi yang digunakan Rust tidak selalu sama dengan emscripten. Membuat keduanya menggunakan versi LLVM yang relatif mirip dapat meningkatkan kompatibilitas.
  • Dari pesan kesalahan Anda, Anda tampaknya menggunakan backend 'fastcomp' baru dari emscripten. Ini mungkin kurang diuji pada beban kerja Rusty daripada backend lama mereka. Memilih secara manual ke backend lama setidaknya dapat menghasilkan hasil yang berbeda.
  • Emscripten umumnya menggunakan triple targetnya sendiri, jadi rustc mungkin perlu dibujuk untuk menggunakan yang sama.

Kesalahan saat mencoba mengkompilasi libcore tampaknya terkait dengan masalah emscripten ini . Mengkompilasi libcore ke llvm bytecode menghasilkan instruksi atom llvm, tetapi emscripten tidak mendukung instruksi atom.

Mungkin ada cara untuk mengatasi ini dari sisi karat, tetapi berdasarkan komentar di masalah emscripten, saya pikir mendapatkan dukungan untuk atom ke dalam emscripten paling masuk akal.

Jika emscripten memiliki platformnya sendiri, kami mungkin dapat melakukan cfg-out semua atom untuk varian utas tunggal mereka, tetapi saya setuju bahwa akan lebih baik untuk memiliki ini di emscripten hulu!

Jika saya tidak salah, backend "fastcomp" baru dari emscripten adalah cabang dari LLVM (sementara backend sebelumnya hanya satu lapisan di atas LLVM), jadi versi LLVM dari fastcomp mungkin sulit untuk ditingkatkan dan tidak akan ditingkatkan sering.

Ini akan bermasalah jika perlu kompatibel dengan output Rust. Misalnya saat ini versi LLVM dari fastcomp adalah 3.3, sedangkan LLVM yang digunakan oleh Rust adalah 3.4.

Backend emscripten lama sudah usang dan tidak boleh digunakan sesuai dengan dokumen resmi, jadi mungkin bukan pilihan untuk menggunakannya.

Sepertinya saya satu-satunya yang mencoba mengkompilasi untuk emscripten untuk saat ini.

Sebagai catatan, berikut adalah hal-hal yang saya coba:

  • Kompilasi ke bytecode (dihasilkan oleh Rust's LLVM 3.4) dan meneruskannya ke fastcomp (garpu LLVM 3.3); menyebabkan fastcomp crash
  • Mengkompilasi ke IR, mengeditnya secara manual hingga kompatibel dengan LLVM 3.3 dan meneruskannya ke fastcomp ; terlalu rumit, terlalu banyak hal untuk dimodifikasi untuk kode non-sepele
  • Kompilasi Rust stage1 dengan --llvm-root menunjuk ke fastcomp emscripten; itu tidak berhasil karena mereka menghapus dukungan untuk ARM/MIPS/dll. di garpu mereka (saya mendapatkan kesalahan dari makefile dan selama tautan karena ini)
  • Ubah submodule git LLVM dalam kode sumber Rust untuk menunjuk ke komit lama dari era 3.3 ; mendapatkan segfault di beberapa titik di LLVM
  • Mengkompilasi Rust dengan --llvm-root menunjuk ke LLVM 3.3 yang telah dikompilasi sebelumnya (berasal dari repo ubuntu resmi); mendapatkan pernyataan gagal di akhir kompilasi stage1 dan biner rustc yang dihasilkan tidak berfungsi.

Kecuali seseorang memiliki ide, kesimpulan saya adalah bahwa kita perlu menunggu emscripten untuk meningkatkan.

rum tampaknya berhasil, agak; mungkin ini akan membantu

Pembaruan kecil: emscripten-fastcomp telah diperbarui ke LLVM 3.4, dan akan diperbarui ke LLVM 3.5 nanti.

@tomaka sudahkah Anda mencoba melakukan sesuatu dengan versi 3.4? Saya bisa mendapatkan contoh rum yang dikompilasi dengannya, tetapi ada lagi yang gagal dengan kesalahan yang tidak dapat dipahami.

@ibdknox 3.4 tidak kompatibel dengan 3.5
Bahkan hello world yang sederhana menghasilkan pernyataan yang gagal: LLVM ERROR: 0 && "some i64 thing we can't legalize yet"

Hm. Saya dapat mengambil output dari rustc --emit ir foo.rust dan menjalankannya melalui emscripten-incoming. Apakah karat sekarang di LLVM 3.5?

Rust telah menggunakan LLVM 3.5 sejak lama. Anda bisa beruntung dan tidak ada yang tidak kompatibel yang dihasilkan.
Misalnya ini mengkompilasi dengan baik:

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

Ini bukan karena IR yang tidak kompatibel:

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

@ibdknox http://www.reddit.com/r/rust_gamedev/comments/2n0x08/emscripten_experiments/
Sepertinya ada lebih sedikit ketidakcocokan daripada yang saya kira.

Sebagai pembaruan, ketika saya mengkompilasi hello world dengan emscripten yang sekarang telah diperbarui ke 3.5, saya mendapatkan yang berikut:

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:

Inilah cara saya mengkompilasi:

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

Namun, hal-hal yang tampaknya tidak berhasil pada umumnya tampaknya berhasil.

Saya telah menghabiskan waktu luang saya minggu lalu untuk melihat ini. Saya membaca buku rust antara musim panas dan sekarang dan sangat menyukai mekanika bahasanya tetapi baru-baru ini mulai menerapkan sesuatu dengannya. Saya hanya memiliki pengetahuan tentang kompiler karat tentang apa yang saya pelajari minggu ini tetapi berharap saya dapat berkontribusi.

Jadi saya kira hal pertama yang perlu diperhatikan dari apa yang saya pelajari (tetapi saya perlu beberapa malam untuk memperhatikannya) adalah bahwa Rust pindah ke LLVM 3.6 pada bulan Juli. Jadi versi Rust dan emscripten-fastcomp saat ini tidak kompatibel.

Saya mencoba mengkompilasi rust dengan --llvm-root menunjuk ke emscripten-fastcomp 1.29.2 dan mendapatkan kesalahan ini:

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

Untuk mendapatkan kesalahan ini, saya mengonfigurasi dan membuat emscripten-fastcomp dengan

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

Alih-alih panduan emscripten direkomendasikan

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

Meskipun Rust tidak perlu dibuat untuk semua target, saat ini Rust selalu terhubung dengan LLVM dengan dukungan CPU yang dikompilasi untuk semua target. Ini adalah solusi untuk masalah yang dapat diperbaiki di masa mendatang sehingga kami mungkin tidak perlu selalu mengkompilasi emscripten-fastcomp dengan konfigurasi tersebut.

Setelah saya menemukan bahwa Rust telah pindah ke LLVM 3.6, saya mencari cabang terakhir di rust-lang/llvm yaitu LLVM 3.5. https://github.com/rust-lang/llvm/tree/rust-llvm-2014-07-24 Saya mengkompilasinya alih-alih emscripten-fastcomp, penasaran ingin melihat apa yang akan terjadi. Saya mendapatkan kesalahan yang sama persis ketika mengkompilasi terhadap emscripton-fastcomp baru-baru ini pindah ke LLVM 3.5. Saya menganggap ini berarti bahwa Rust dalam beberapa hal tidak kompatibel dengan LLVM 3.5 sekarang dan saya tidak akan mengharapkan sebaliknya.

Jadi sekarang kita menunggu atau harus mendapatkan emscripten-fastcomp ke LLVM 3.6 :wink:

Patut disebutkan bahwa saya mengunduh salinan 0,11 yang diarsipkan dan mampu menghasilkan LLVM IR untuk hello world yang dipahami emcc tetapi kemudian mencapai masalah penautan. Sangat menarik untuk melihatnya melewati pemahaman kode byte tetapi sebenarnya untuk menghubungkannya akan membutuhkan pekerjaan di basis kode karat.

Saya mengintip penggabungan rust-lang/llvm ke dalam emscripten-fastcomp. Pada saat itu ada 117 bagian yang saling bertentangan lebih dari 43 file.

Saya menyebutkan mendapatkan Rust 0.11 dan emcc 1.29.2 untuk sampai ke tahap penautan. Ini adalah hasil spesifiknya:

$ 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

Tampaknya emcc/fastcomp mengganti titik-titik dalam simbol dengan garis bawah sementara Rust mengharapkan awalan dengan garis bawah lain, tetapi saya tidak terlalu yakin tentang ini. Simbol unresolved pertama muncul sebagai __ZN2io5stdio12println_args20h0caae70b0e2eb347Iol7v0.11.0E di libstd di i686-apple-darwin build. Bahkan jika saya bisa mendapatkan emcc untuk mengetahui bagaimana menemukan simbol ini di perpustakaan yang dibangun, saya menduga bahwa lib berisi kode mesin sementara emcc akan membutuhkan kode byte LLVM. Saya pikir saya ingat seseorang yang menyebutkan perlu mengkompilasi perpustakaan standar untuk emscripten. Ini akan menjadi bagian dari kebutuhan untuk itu.

Jadi, inilah langkah selanjutnya yang ingin saya coba dan kerjakan jika ada yang ingin mencobanya sendiri. (Atau dapat memberi tahu saya seberapa benar atau salah saya.)

  • Gabungkan rust-lang/llvm ke dalam emscripten-fastcomp
  • Bangun karat dengan fastcomp yang digabungkan tanpa dukungan backend JS
    Berharap ini akan menjadi tes kewarasan yang bagus untuk penggabungan.
  • Tambahkan triple emscripten ke Rust dan buat itu
    Dari apa yang saya tahu ada sejumlah file yang perlu saya ubah atau tambahkan.

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

    • rt/arch/asmjs/{morestack.S,record_sp.S} (mungkin bisa kosong?)

      File-file ini diperlukan untuk membangun morestack.a agar Rust mendukung tumpukan tersegmentasi LLVM. Jika saya mengingatnya dengan benar, tumpukan Emscripten juga merupakan kepala. Ini menggunakan ujung tumpukan yang berlawanan sebagai tumpukan dan karena untuk asmjs Anda tidak dapat mengubah ukuran array, membuat segmen tumpukan baru tidak dimungkinkan. Saya melihat bidang di TargetOption di file target librustc_back yang semoga dapat menonaktifkan ini.

    • librustc_trans/trans/cabi_asmjs.rs

    • librustc_trans/trans/cabi.rs

      Saya tidak yakin apakah ini akan dibutuhkan, saat ini hanya tebakan.

    • 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()

  • Menerapkan antarmuka sistem yang hilang
    Saya melihat pada bulan November libgreen telah dihapus. Karena emscripten perlu menunggu beberapa cara untuk dibagikan dengan pekerja di browser, jika itu pernah terjadi, sesuatu seperti libgreen perlu dipulihkan atau pthread shimmed dengan cara tertentu khusus untuk emscripten seperti bagaimana rust dibangun untuk pthreads atau windows threads api.

IO juga. Mungkin bagian lain yang tidak saya ketahui.

"Gabungkan rust-lang/llvm ke dalam emscripten-fastcomp"

Anda mungkin tidak ingin melakukan ini - Emscripten didasarkan pada pnacl-llvm/pnacl-clang sehingga Anda membuat garpu dengan tambalan di tambalan, yang mungkin akan menyakitkan. Jika Anda tertarik, Anda dapat melihat beberapa detail percabangan dalam penyelidikan yang saya lakukan untuk penggabungan Emscripten dari r33 -> r34 di https://github.com/kripken/emscripten-fastcomp/issues/51#issuecomment -62323164 .

Saya mendengar bahwa pnacl berencana melacak upstream sedikit lebih dekat daripada sebelumnya, tetapi saya tidak dapat melihat masalah yang relevan di pelacak masalah pnacl untuk memperbarui ke 3.6 jadi mungkin perlu waktu (terutama mengingat 3.6 hanya bercabang 5 hari yang lalu!). ..Saya kira Anda bisa membuat masalah? Jika Anda memutuskan untuk tidak menggunakan garpu Emscripten Anda sendiri, saya melihat dua opsi - menunggu pnacl atau membantu Emscripten turun dari pnacl dan ke hulu.

Sunting: dikoreksi 'sekarang' menjadi 'tidak'. Perbedaan yang krusial.

Saya melakukan upaya triase besar-besaran untuk menyiapkan kita untuk 1.0. Sebagai bagian dari ini, saya memindahkan hal-hal yang seperti daftar keinginan ke repo RFC, karena di situlah hal-hal baru yang besar harus didiskusikan/diprioritaskan.

Masalah ini telah dipindahkan ke repo RFC: rust-lang/rfcs#604

Apakah halaman ini membantu?
0 / 5 - 0 peringkat