diff --git a/vlib/v/builder/cc.v b/vlib/v/builder/cc.v index 4fa015a8ab..0eb0ee9c69 100644 --- a/vlib/v/builder/cc.v +++ b/vlib/v/builder/cc.v @@ -290,11 +290,19 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) { ccoptions.args << '-fPIC' // -Wl,-z,defs' } } - if v.pref.is_bare { + if v.pref.is_bare && v.pref.os != .wasm32 { ccoptions.args << '-fno-stack-protector' ccoptions.args << '-ffreestanding' ccoptions.linker_flags << '-static' ccoptions.linker_flags << '-nostdlib' + } else if v.pref.os == .wasm32 { + ccoptions.args << '--no-standard-libraries' + ccoptions.args << '-target wasm32-unknown-unknown' + ccoptions.args << '-static' + ccoptions.args << '-nostdlib' + ccoptions.args << '-ffreestanding' + ccoptions.args << '-Wl,--export-all' + ccoptions.args << '-Wl,--no-entry' } if ccoptions.debug_mode && os.user_os() != 'windows' && v.pref.build_mode != .build_module { ccoptions.linker_flags << '-rdynamic' // needed for nicer symbolic backtraces @@ -525,6 +533,8 @@ pub fn (mut v Builder) cc() { '-arch armv7 -arch armv7s -arch arm64' } ccompiler = 'xcrun --sdk iphoneos clang -isysroot $isysroot $arch' + } else if v.pref.os == .wasm32 { + ccompiler = 'clang-12' } v.setup_ccompiler_options(ccompiler) v.build_thirdparty_obj_files() diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index b4170c5305..b336b4f054 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -624,19 +624,26 @@ pub fn (mut g Gen) init() { g.cheaders.writeln(g.pref.custom_prelude) } else if !g.pref.no_preludes { g.cheaders.writeln('// Generated by the V compiler') - tcc_undef_has_include := ' -#if defined(__TINYC__) && defined(__has_include) -// tcc does not support has_include properly yet, turn it off completely -#undef __has_include -#endif' - g.cheaders.writeln(tcc_undef_has_include) - g.includes.writeln(tcc_undef_has_include) - if g.pref.os == .freebsd { - g.cheaders.writeln('#include ') + if g.pref.os == .wasm32 { + g.cheaders.writeln('#define VWASM 1') + // Include instead of for WASM target + g.cheaders.writeln('#include ') g.cheaders.writeln('#include ') } else { - g.cheaders.writeln(get_guarded_include_text('', 'The C compiler can not find . Please install build-essentials')) // int64_t etc - g.cheaders.writeln(get_guarded_include_text('', 'The C compiler can not find . Please install build-essentials')) // size_t, ptrdiff_t + tcc_undef_has_include := ' + #if defined(__TINYC__) && defined(__has_include) + // tcc does not support has_include properly yet, turn it off completely + #undef __has_include + #endif' + g.cheaders.writeln(tcc_undef_has_include) + g.includes.writeln(tcc_undef_has_include) + if g.pref.os == .freebsd { + g.cheaders.writeln('#include ') + g.cheaders.writeln('#include ') + } else { + g.cheaders.writeln(get_guarded_include_text('', 'The C compiler can not find . Please install build-essentials')) // int64_t etc + g.cheaders.writeln(get_guarded_include_text('', 'The C compiler can not find . Please install build-essentials')) // size_t, ptrdiff_t + } } g.cheaders.writeln(c_builtin_types) if g.pref.is_bare { @@ -5588,7 +5595,7 @@ fn (mut g Gen) write_init_function() { // ___argv is declared as voidptr here, because that unifies the windows/unix logic g.writeln('void _vinit(int ___argc, voidptr ___argv) {') - if 'no_segfault_handler' !in g.pref.compile_defines { + if 'no_segfault_handler' !in g.pref.compile_defines || g.pref.os == .wasm32 { // 11 is SIGSEGV. It is hardcoded here, to avoid FreeBSD compilation errors for trivial examples. g.writeln('#if __STDC_HOSTED__ == 1\n\tsignal(11, v_segmentation_fault_handler);\n#endif') } diff --git a/vlib/v/gen/c/cheaders.v b/vlib/v/gen/c/cheaders.v index 25a5a9d306..e9a2d3ef46 100644 --- a/vlib/v/gen/c/cheaders.v +++ b/vlib/v/gen/c/cheaders.v @@ -753,7 +753,7 @@ static inline void _wymum(uint64_t *A, uint64_t *B){ #else *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; #endif -#elif defined(__SIZEOF_INT128__) +#elif defined(__SIZEOF_INT128__) && !defined(VWASM) __uint128_t r=*A; r*=*B; #if(WYHASH_CONDOM>1) *A^=(uint64_t)r; *B^=(uint64_t)(r>>64); diff --git a/vlib/v/pref/default.v b/vlib/v/pref/default.v index f3d33b6b96..3d538fe34c 100644 --- a/vlib/v/pref/default.v +++ b/vlib/v/pref/default.v @@ -134,9 +134,12 @@ pub fn (mut p Preferences) fill_with_defaults() { // eprintln('-usecache and -shared flags are not compatible') p.use_cache = false } - if p.bare_builtin_dir == '' { + if p.bare_builtin_dir == '' && p.os == .wasm32 { + p.bare_builtin_dir = os.join_path(p.vroot, 'vlib', 'builtin', 'wasm_bare') + } else if p.bare_builtin_dir == '' { p.bare_builtin_dir = os.join_path(p.vroot, 'vlib', 'builtin', 'linux_bare') } + $if prealloc { if !p.no_parallel { eprintln('disabling parallel cgen, since V was built with -prealloc') diff --git a/vlib/v/pref/os.v b/vlib/v/pref/os.v index 52aacf2469..97ad947b7c 100644 --- a/vlib/v/pref/os.v +++ b/vlib/v/pref/os.v @@ -21,6 +21,9 @@ pub enum OS { serenity vinix haiku + wasm32 + wasm32_emscripten + wasm32_wasi raw all } @@ -46,6 +49,9 @@ pub fn os_from_string(os_str string) ?OS { 'haiku' { return .haiku } 'raw' { return .raw } 'nix' { return .linux } + 'wasm32' { return .wasm32 } + 'wasm32-wasi' { return .wasm32_wasi } + 'wasm32-emscripten' { return .wasm32_emscripten } '' { return ._auto } else { return error('bad OS $os_str') } } @@ -70,6 +76,9 @@ pub fn (o OS) str() string { .serenity { return 'SerenityOS' } .vinix { return 'Vinix' } .haiku { return 'Haiku' } + .wasm32 { return 'WebAssembly' } + .wasm32_emscripten { return 'WebAssembly(Emscripten)' } + .wasm32_wasi { return 'WebAssembly(WASI)' } .raw { return 'Raw' } .all { return 'all' } } diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index d0354580ad..de35a05734 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -537,6 +537,9 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin eprintln('unknown operating system target `$target_os`') exit(1) } + if target_os_kind == .wasm32 { + res.is_bare = true + } res.os = target_os_kind res.build_options << '$arg $target_os' }