about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2019-02-11 19:18:52 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2019-02-11 19:18:52 +0100
commitc68e76c33bf8b8e3fc0dabb3f7d9133328a7ea6d (patch)
treeaf7a860c4eed847a6d4116a42a78c83c3e39bb75
parent4bb8bfca94aa704b2f57f33d2f6be121ee88e3fa (diff)
downloadrust-c68e76c33bf8b8e3fc0dabb3f7d9133328a7ea6d.tar.gz
rust-c68e76c33bf8b8e3fc0dabb3f7d9133328a7ea6d.zip
Implement variadic function calling
-rw-r--r--example/mini_core.rs1
-rw-r--r--example/mini_core_hello_world.rs2
-rw-r--r--src/abi.rs24
-rw-r--r--src/base.rs2
-rw-r--r--src/main_shim.rs3
5 files changed, 26 insertions, 6 deletions
diff --git a/example/mini_core.rs b/example/mini_core.rs
index 0ddd3ade401..4da661ebb8d 100644
--- a/example/mini_core.rs
+++ b/example/mini_core.rs
@@ -338,6 +338,7 @@ pub mod libc {
     #[link(name = "c")]
     extern "C" {
         pub fn puts(s: *const u8);
+        pub fn printf(format: *const char, ...) -> i32;
         pub fn malloc(size: usize) -> *mut u8;
         pub fn free(ptr: *mut u8);
         pub fn memcpy(dst: *mut u8, src: *const u8, size: usize);
diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs
index 1254d917189..17c64ffe09f 100644
--- a/example/mini_core_hello_world.rs
+++ b/example/mini_core_hello_world.rs
@@ -121,6 +121,8 @@ fn main() {
     //return;
 
     unsafe {
+        printf("Hello %s\n\0" as *const str as *const char, "printf\0" as *const str as *const char);
+
         let hello: &[u8] = b"Hello\0" as &[u8; 6];
         let ptr: *const u8 = hello as *const [u8] as *const u8;
         puts(ptr);
diff --git a/src/abi.rs b/src/abi.rs
index 70e94db93ae..aa85349b9b8 100644
--- a/src/abi.rs
+++ b/src/abi.rs
@@ -191,12 +191,13 @@ pub fn ty_fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> ty::FnS
 pub fn get_function_name_and_sig<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     inst: Instance<'tcx>,
+    support_vararg: bool
 ) -> (String, Signature) {
     assert!(!inst.substs.needs_infer() && !inst.substs.has_param_types());
     let fn_ty = inst.ty(tcx);
     let fn_sig = ty_fn_sig(tcx, fn_ty);
-    if fn_sig.variadic {
-        unimpl!("Variadic functions are not yet supported");
+    if fn_sig.variadic && !support_vararg {
+        unimpl!("Variadic function definitions are not yet supported");
     }
     let sig = clif_sig_from_fn_sig(tcx, fn_sig);
     (tcx.symbol_name(inst).as_str().to_string(), sig)
@@ -208,7 +209,7 @@ pub fn import_function<'a, 'tcx: 'a>(
     module: &mut Module<impl Backend>,
     inst: Instance<'tcx>,
 ) -> FuncId {
-    let (name, sig) = get_function_name_and_sig(tcx, inst);
+    let (name, sig) = get_function_name_and_sig(tcx, inst, true);
     module
         .declare_function(&name, Linkage::Import, &sig)
         .unwrap()
@@ -659,6 +660,23 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
         fx.bcx.ins().call(func_ref, &call_args)
     };
 
+    // FIXME find a cleaner way to support varargs
+    if fn_sig.variadic {
+        if fn_sig.abi != Abi::C {
+            unimpl!("Variadic call for non-C abi {:?}", fn_sig.abi);
+        }
+        let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
+        let abi_params = call_args.into_iter().map(|arg| {
+            let ty = fx.bcx.func.dfg.value_type(arg);
+            if !ty.is_int() {
+                // FIXME set %al to upperbound on float args once floats are supported
+                unimpl!("Non int ty {:?} for variadic call", ty);
+            }
+            AbiParam::new(ty)
+        }).collect::<Vec<AbiParam>>();
+        fx.bcx.func.dfg.signatures[sig_ref].params = abi_params;
+    }
+
     match output_pass_mode {
         PassMode::NoPass => {}
         PassMode::ByVal(_) => {
diff --git a/src/base.rs b/src/base.rs
index 94598c65672..d2f31de71d1 100644
--- a/src/base.rs
+++ b/src/base.rs
@@ -65,7 +65,7 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
     let mir = tcx.instance_mir(instance.def);
 
     // Step 2. Declare function
-    let (name, sig) = get_function_name_and_sig(tcx, instance);
+    let (name, sig) = get_function_name_and_sig(tcx, instance, false);
     let func_id = cx.module
         .declare_function(&name, linkage, &sig)
         .unwrap();
diff --git a/src/main_shim.rs b/src/main_shim.rs
index 446089fc9a1..20d79291296 100644
--- a/src/main_shim.rs
+++ b/src/main_shim.rs
@@ -53,8 +53,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a>(
 
         let instance = Instance::mono(tcx, rust_main_def_id);
 
-        let (main_name, main_sig) = get_function_name_and_sig(tcx, instance);
-
+        let (main_name, main_sig) = get_function_name_and_sig(tcx, instance, false);
         let main_func_id = m
             .declare_function(&main_name, Linkage::Import, &main_sig)
             .unwrap();