Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hello WebAssembly! (MVP implementation) #10870

Merged
merged 48 commits into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
cabdb42
Add Wasm32 LibC (based on musl)
lbguilherme Jul 1, 2021
76d5e22
Add Basic Wasm32 support
lbguilherme Jul 1, 2021
98c5447
Add LibC as a symbolic link
lbguilherme Jul 1, 2021
94109db
Merge branch 'master' into feat/webassembly
lbguilherme Jul 14, 2021
fa5077a
Move wasm to a Crystal::System implementation
lbguilherme Jul 14, 2021
fe511de
Enable smoke tests for wasm32-wasi
lbguilherme Jul 14, 2021
165b974
Revert change on unix Thread
lbguilherme Jul 14, 2021
be594ed
Smoke test: build compiler for the wasm test
lbguilherme Jul 14, 2021
ffe4b5b
Merge remote-tracking branch 'upstream/master' into feat/webassembly
lbguilherme Jul 20, 2021
598c99f
Mark stub methods with NotImplementedError or TODO
lbguilherme Jul 21, 2021
2d78c9b
Update src/crystal/system/wasm/process.cr
lbguilherme Jul 21, 2021
ffd9c12
Update wasi libc: it's now limited to what wasi actually provides. Mo…
lbguilherme Jul 22, 2021
9faf715
Use arc4random instead of getentropy
lbguilherme Jul 22, 2021
b0797c1
Remove Signal, Process and Sockets unimplemented method from Wasm32
lbguilherme Aug 2, 2021
aec74ad
Work around compiler bug in previous commit: BUG: `typeof(_io)` at ex…
lbguilherme Aug 2, 2021
463d4cd
fix: cleanup from previous commit
lbguilherme Aug 2, 2021
5faf601
Merge remote-tracking branch 'upstream/master' into feat/webassembly
lbguilherme Aug 2, 2021
3d91387
Merge remote-tracking branch 'upstream/master' into feat/webassembly
lbguilherme Aug 3, 2021
b1dd5f7
crystal tool format
lbguilherme Aug 3, 2021
00b10d6
fix: use correct .wasm extension
lbguilherme Dec 18, 2021
eab4739
Merge remote-tracking branch 'upstream/master' into feat/webassembly
lbguilherme Dec 18, 2021
4e33d92
Merge remote-tracking branch 'upstream/master' into feat/webassembly
lbguilherme Dec 23, 2021
e86b675
feat: implement Crystal::System::Fiber with malloc/free
lbguilherme Dec 23, 2021
ba5a531
fix: mark system_linger as not implemented
lbguilherme Dec 24, 2021
2582817
feat: add direct wasi integration for Dir.entries
lbguilherme Dec 24, 2021
4d5b061
feat: enable libpcre
lbguilherme Dec 24, 2021
5b4627f
chore: refactor Crystal::Program.object_extension
lbguilherme Dec 28, 2021
2519a6a
fix: mock Thread.current
lbguilherme Dec 28, 2021
fdef3ac
chore: change PREOPENS to @@preopens
lbguilherme Dec 28, 2021
10c6eb7
fix: print fatal errors
lbguilherme Dec 28, 2021
a0407ca
fix: use Sync logger until channels work
lbguilherme Dec 28, 2021
c3f035f
chore: rename wasierror.cr -> wasi_error.cr
lbguilherme Dec 28, 2021
3ba1b96
chore: preopen cleanup
lbguilherme Dec 28, 2021
e58cf26
fix: there is no need to initialize PREOPENS as early as possible if …
lbguilherme Dec 29, 2021
7bcd75a
fix: missing wasi require
lbguilherme Dec 29, 2021
cb2ea23
feat: generate better linker command
lbguilherme Dec 29, 2021
ad2e402
chore: stub Exception::CallStack#decode_backtrace until callback support
lbguilherme Dec 29, 2021
2e4b517
chore: remove some unused pieces from wasm libc
lbguilherme Dec 31, 2021
5faa13a
fix: use "out fd"
lbguilherme Jan 27, 2022
9de1150
feat: add wasi random_get to avoid relying on arc4random polyfill
lbguilherme Feb 8, 2022
2d3158e
Mark WASI as a UNIX target and use it as the system environment, inst…
lbguilherme Feb 8, 2022
ac74bad
Update spec/compiler/loader/unix_spec.cr
lbguilherme Feb 8, 2022
9f72ef9
Update spec/compiler/ffi/ffi_spec.cr
lbguilherme Feb 8, 2022
fea289a
Revert "Update spec/compiler/loader/unix_spec.cr"
lbguilherme Feb 8, 2022
53f6c25
Revert "Update spec/compiler/ffi/ffi_spec.cr"
lbguilherme Feb 8, 2022
5995375
fix: correct usage of some wasm32<->wasi flags
lbguilherme Feb 8, 2022
570eb32
Merge remote-tracking branch 'upstream/master' into feat/webassembly
lbguilherme Feb 11, 2022
b011761
fix: home_path for wasi
lbguilherme Feb 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ jobs:
target:
- aarch64-darwin
- arm-linux-gnueabihf
- i386-linux-musl
- i386-linux-gnu
- i386-linux-musl
- wasm32-unknown-wasi
- x86_64-dragonfly
- x86_64-freebsd
- x86_64-netbsd
Expand All @@ -56,5 +57,9 @@ jobs:
- name: Download Crystal source
uses: actions/checkout@v2

- name: Make compiler (special case only for wasm32, until next release).
if: ${{ matrix.target == 'wasm32-unknown-wasi' }}
run: bin/ci with_build_env make

- name: Run smoke test
run: bin/ci with_build_env make smoke_test target=${{ matrix.target }}
2 changes: 1 addition & 1 deletion spec/compiler/ffi/ffi_spec.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% skip_file if !flag?(:unix) || flag?(:without_ffi) %}
{% skip_file if !flag?(:unix) || flag?(:without_ffi) || flag?(:wasm32) %}
lbguilherme marked this conversation as resolved.
Show resolved Hide resolved

require "../spec_helper"
require "compiler/crystal/ffi"
Expand Down
2 changes: 1 addition & 1 deletion spec/compiler/loader/unix_spec.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% skip_file unless flag?(:unix) %}
{% skip_file if !flag?(:unix) || flag?(:wasm32) %}
lbguilherme marked this conversation as resolved.
Show resolved Hide resolved

require "./spec_helper"
require "../spec_helper"
Expand Down
2 changes: 2 additions & 0 deletions spec/std/process_spec.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% skip_file if flag?(:wasm32) %}

require "spec"
require "process"
require "./spec_helper"
Expand Down
2 changes: 2 additions & 0 deletions spec/std/signal_spec.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% skip_file if flag?(:wasm32) %}

require "spec"
require "signal"

Expand Down
4 changes: 2 additions & 2 deletions spec/std/socket/addrinfo_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ describe Socket::Addrinfo, tags: "network" do
end

describe "Error" do
{% unless flag?(:win32) %}
# This method is not available on windows because windows support was introduced after deprecation.
{% unless flag?(:win32) || flag?(:wasm32) %}
# This method is not available on windows/wasm because windows/wasm support was introduced after deprecation.
it ".new (deprecated)" do
error = Socket::Addrinfo::Error.new(LibC::EAI_NONAME, "No address found", "foobar.com")
error.os_error.should eq Errno.new(LibC::EAI_NONAME)
Expand Down
2 changes: 2 additions & 0 deletions spec/std/socket/tcp_server_spec.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% skip_file if flag?(:wasm32) %}

require "./spec_helper"
require "../../support/win32"

Expand Down
2 changes: 2 additions & 0 deletions spec/std/socket/tcp_socket_spec.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% skip_file if flag?(:wasm32) %}

require "./spec_helper"
require "../../support/win32"

Expand Down
12 changes: 7 additions & 5 deletions spec/std/string_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2719,12 +2719,14 @@ describe "String" do
string.should be(clone)
end

it "allocates buffer of correct size when UInt8 is given to new (#3332)" do
String.new(255_u8) do |buffer|
LibGC.size(buffer).should be >= 255
{255, 0}
{% unless flag?(:wasm32) %}
it "allocates buffer of correct size when UInt8 is given to new (#3332)" do
String.new(255_u8) do |buffer|
LibGC.size(buffer).should be >= 255
{255, 0}
end
end
end
{% end %}

it "raises on String.new if returned bytesize is greater than capacity" do
expect_raises ArgumentError, "Bytesize out of capacity bounds" do
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/crystal/codegen/link.cr
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ module Crystal

class Program
def object_extension
has_flag?("windows") ? ".obj" : ".o"
case
when has_flag?("windows") then ".obj"
when has_flag?("wasm32") then ".wasm"
else ".o"
end
end

def lib_flags
Expand Down
8 changes: 7 additions & 1 deletion src/compiler/crystal/codegen/target.cr
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,16 @@ class Crystal::Codegen::Target
@environment.starts_with?("linux")
end

def wasi?
@environment.starts_with?("wasi")
end

def bsd?
freebsd? || netbsd? || openbsd? || dragonfly?
end

def unix?
macos? || bsd? || linux?
macos? || bsd? || linux? || wasi?
end

def gnu?
Expand Down Expand Up @@ -144,6 +148,8 @@ class Crystal::Codegen::Target
if cpu.empty? && !features.includes?("fp") && armhf?
features += "+vfp2"
end
when "wasm32"
LLVM.init_webassembly
else
raise Target::Error.new("Unsupported architecture for target triple: #{self}")
end
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/command.cr
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ class Crystal::Command
begin
elapsed = Time.measure do
Process.run(output_filename, args: run_args, input: Process::Redirect::Inherit, output: Process::Redirect::Inherit, error: Process::Redirect::Inherit) do |process|
{% unless flag?(:win32) %}
{% unless flag?(:win32) || flag?(:wasm32) %}
# Ignore the signal so we don't exit the running process
# (the running process can still handle this signal)
::Signal::INT.ignore # do
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/crystal/compiler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ module Crystal
end

{cmd, nil}
elsif program.has_flag? "wasm32"
link_flags = @link_flags || ""
{ %(wasm-ld "${@}" -o #{Process.quote_posix(output_filename)} #{link_flags} -lc #{program.lib_flags}), object_names }
else
link_flags = @link_flags || ""
link_flags += " -rdynamic"
Expand Down
5 changes: 4 additions & 1 deletion src/crystal/system.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ module Crystal::System
# def self.cpu_count
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./system/wasi/hostname"
require "./system/wasi/cpucount"
{% elsif flag?(:unix) %}
require "./system/unix/hostname"

{% if flag?(:bsd) %}
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/dir.cr
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ module Crystal::System::Dir
# def self.delete(path : String) : Nil
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/dir"
{% elsif flag?(:unix) %}
require "./unix/dir"
{% elsif flag?(:win32) %}
require "./win32/dir"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/event_loop.cr
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ struct Crystal::Event
# def add(time_span : Time::Span?) : Nil
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/event_loop"
{% elsif flag?(:unix) %}
require "./unix/event_loop_libevent"
{% elsif flag?(:win32) %}
require "./win32/event_loop_iocp"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/fiber.cr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ module Crystal::System::Fiber
# def self.main_fiber_stack(stack_bottom : Void*) : Void*
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/fiber"
{% elsif flag?(:unix) %}
require "./unix/fiber"
{% elsif flag?(:win32) %}
require "./win32/fiber"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/file.cr
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ module Crystal::System::File
# def file_descriptor_close
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/file"
{% elsif flag?(:unix) %}
require "./unix/file"
{% elsif flag?(:win32) %}
require "./win32/file"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/file_descriptor.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/file_descriptor"
{% elsif flag?(:unix) %}
require "./unix/file_descriptor"
{% elsif flag?(:win32) %}
require "./win32/file_descriptor"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/group.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/group"
{% elsif flag?(:unix) %}
require "./unix/group"
{% else %}
{% raise "No Crystal::System::Group implementation available" %}
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/path.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ module Crystal::System::Path
# def self.home : String
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/path"
{% elsif flag?(:unix) %}
require "./unix/path"
{% elsif flag?(:win32) %}
require "./win32/path"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ module Crystal::System
ORIGINAL_STDERR = IO::FileDescriptor.new(2, blocking: true)
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/process"
{% elsif flag?(:unix) %}
require "./unix/process"
{% elsif flag?(:win32) %}
require "./win32/process"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/random.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ module Crystal::System::Random
# def self.next_u
end

{% if flag?(:linux) %}
{% if flag?(:wasi) %}
require "./wasi/random"
{% elsif flag?(:linux) %}
require "./unix/getrandom"
{% elsif flag?(:openbsd) || flag?(:netbsd) %}
require "./unix/arc4random"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/socket.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ module Crystal::System::Socket
# private def system_tcp_keepalive_count=(val : Int)
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/socket"
{% elsif flag?(:unix) %}
require "./unix/socket"
{% elsif flag?(:win32) %}
require "./win32/socket"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/thread.cr
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ end

require "./thread_linked_list"

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/thread"
{% elsif flag?(:unix) %}
require "./unix/pthread"
require "./unix/pthread_condition_variable"
{% elsif flag?(:win32) %}
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/thread_mutex.cr
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class Thread
end
end

{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/thread_mutex"
{% elsif flag?(:unix) %}
require "./unix/pthread_mutex"
{% elsif flag?(:win32) %}
require "./win32/thread_mutex"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/user.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% if flag?(:unix) %}
{% if flag?(:wasi) %}
require "./wasi/user"
{% elsif flag?(:unix) %}
require "./unix/user"
{% else %}
{% raise "No Crystal::System::User implementation available" %}
Expand Down
6 changes: 6 additions & 0 deletions src/crystal/system/wasi/cpucount.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Crystal::System
def self.cpu_count
# TODO: There isn't a good way to get the number of CPUs on WebAssembly
1
end
end
Loading