diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 1c441ca7cbf2e..546972903e9b5 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -414,8 +414,11 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' rust_main_def_id: DefId, use_start_lang_item: bool, ) { - let llfty = - cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()); + let llfty = if cx.sess().target.target.options.main_needs_argc_argv { + cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()) + } else { + cx.type_func(&[], cx.type_int()) + }; let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).output(); // Given that `main()` has no arguments, @@ -445,11 +448,19 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' bx.insert_reference_to_gdb_debug_scripts_section_global(); - // Params from native main() used as args for rust start function - let param_argc = bx.get_param(0); - let param_argv = bx.get_param(1); - let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); - let arg_argv = param_argv; + let (arg_argc, arg_argv) = if cx.sess().target.target.options.main_needs_argc_argv { + // Params from native main() used as args for rust start function + let param_argc = bx.get_param(0); + let param_argv = bx.get_param(1); + let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); + let arg_argv = param_argv; + (arg_argc, arg_argv) + } else { + // The Rust start function doesn't need argc and argv, so just pass zeros. + let arg_argc = bx.const_int(cx.type_int(), 0); + let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); + (arg_argc, arg_argv) + }; let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index cf1a84dec97bc..c5277c4f90e7a 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -691,6 +691,9 @@ pub struct TargetOptions { /// defined in libgcc. If this option is enabled, the target must provide /// `eh_unwind_resume` lang item. pub custom_unwind_resume: bool, + /// Whether the runtime startup code requires the `main` function be passed + /// `argc` and `argv` values. + pub main_needs_argc_argv: bool, /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for /// this target. @@ -849,6 +852,7 @@ impl Default for TargetOptions { link_env_remove: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, + main_needs_argc_argv: true, allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, @@ -1159,6 +1163,7 @@ impl Target { key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); + key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(no_integrated_as, bool); @@ -1376,6 +1381,7 @@ impl ToJson for Target { target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(custom_unwind_resume); + target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(no_integrated_as); diff --git a/src/librustc_target/spec/wasm32_wasi.rs b/src/librustc_target/spec/wasm32_wasi.rs index 86978c05b15d0..d5ef230dcf7d2 100644 --- a/src/librustc_target/spec/wasm32_wasi.rs +++ b/src/librustc_target/spec/wasm32_wasi.rs @@ -101,6 +101,10 @@ pub fn target() -> Result { // without a main function. options.crt_static_allows_dylibs = true; + // WASI's `sys::args::init` function ignores its arguments; instead, + // `args::args()` makes the WASI API calls itself. + options.main_needs_argc_argv = false; + Ok(Target { llvm_target: "wasm32-wasi".to_string(), target_endian: "little".to_string(),