about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDan Gohman <sunfish@mozilla.com>2019-10-17 16:09:32 -0700
committerDan Gohman <sunfish@mozilla.com>2019-10-17 16:16:35 -0700
commitb25e3238c76a4df767b4a929011ed47c479ed115 (patch)
tree8e7491454319743d438287e02793311978e61590
parentb04338087eed5f26c72bdb0e426dc38e215e2dbb (diff)
downloadrust-b25e3238c76a4df767b4a929011ed47c479ed115.tar.gz
rust-b25e3238c76a4df767b4a929011ed47c479ed115.zip
Don't add `argc` and `argv` arguments to `main` on WASI.
Add a target setting to allow targets to specify whether the generated
`main` function should be passed `argc` and `argv` arguments. Set it
to false on wasm32-wasi, since WASI's `args::args()` calls into the
WASI APIs itself. This will allow the WASI toolchain to avoid linking
and running command-line argument initialization code when the arguments
aren't actually needed.
-rw-r--r--src/librustc_codegen_ssa/base.rs25
-rw-r--r--src/librustc_target/spec/mod.rs6
-rw-r--r--src/librustc_target/spec/wasm32_wasi.rs4
3 files changed, 28 insertions, 7 deletions
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 1c441ca7cbf..546972903e9 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 cf1a84dec97..c5277c4f90e 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 86978c05b15..d5ef230dcf7 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<Target, String> {
     // 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(),