about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-11-18 15:40:23 -0800
committerNiko Matsakis <niko@alum.mit.edu>2011-11-18 16:32:19 -0800
commit9fa44a41e67151c5c392e2bd2b3989d74703efec (patch)
treeca51d17b4108c5ea64d997f04d423cbe90fc956b /src
parent6072ddad33e034a63bddd1ef577492b2842e8136 (diff)
downloadrust-9fa44a41e67151c5c392e2bd2b3989d74703efec.tar.gz
rust-9fa44a41e67151c5c392e2bd2b3989d74703efec.zip
get pure wrappers approach running
Diffstat (limited to 'src')
-rw-r--r--src/comp/back/upcall.rs11
-rw-r--r--src/comp/middle/trans.rs149
-rw-r--r--src/rt/arch/i386/ccall.S17
-rw-r--r--src/rt/arch/i386/context.h6
-rw-r--r--src/rt/arch/x86_64/ccall.S16
-rw-r--r--src/rt/arch/x86_64/context.h6
-rw-r--r--src/rt/rust_upcall.cpp10
-rw-r--r--src/rt/rustrt.def.in2
8 files changed, 111 insertions, 106 deletions
diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs
index 71137d88911..419a7fdc34c 100644
--- a/src/comp/back/upcall.rs
+++ b/src/comp/back/upcall.rs
@@ -26,7 +26,7 @@ type upcalls =
      dynastack_alloc: ValueRef,
      dynastack_free: ValueRef,
      alloc_c_stack: ValueRef,
-     call_c_stack_shim: ValueRef,
+     call_shim_on_c_stack: ValueRef,
      rust_personality: ValueRef};
 
 fn declare_upcalls(targ_cfg: @session::config,
@@ -85,11 +85,10 @@ fn declare_upcalls(targ_cfg: @session::config,
                 T_ptr(T_i8())),
           dynastack_free: dv("dynastack_free", [T_ptr(T_i8())]),
           alloc_c_stack: d("alloc_c_stack", [size_t], T_ptr(T_i8())),
-          call_c_stack_shim: d("call_c_stack_shim",
-                          // first arg is func ptr, but type of func varies,
-                          // so just call it char* for LLVM
-                          [T_ptr(T_i8()), T_ptr(T_i8())],
-                          int_t),
+          call_shim_on_c_stack: d("call_shim_on_c_stack",
+                                  // arguments: void *args, void *fn_ptr
+                                  [T_ptr(T_i8()), T_ptr(T_i8())],
+                                  int_t),
           rust_personality: d("rust_personality", [], T_i32())
          };
 }
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 58252ff9330..b821cabb6ae 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -183,12 +183,8 @@ fn type_of_inner(cx: @crate_ctxt, sp: span, t: ty::t)
         T_fn_pair(cx, type_of_fn_from_ty(cx, sp, t, 0u))
       }
       ty::ty_native_fn(abi, args, out) {
-        if native_abi_requires_pair(abi) {
-            let nft = native_fn_wrapper_type(cx, sp, 0u, t);
-            T_fn_pair(cx, nft)
-        } else {
-            raw_native_fn_type(cx, sp, args, out)
-        }
+        let nft = native_fn_wrapper_type(cx, sp, 0u, t);
+        T_fn_pair(cx, nft)
       }
       ty::ty_obj(meths) { cx.rust_object_type }
       ty::ty_res(_, sub, tps) {
@@ -3766,9 +3762,9 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
     let tcx = bcx_tcx(in_cx);
     let fn_expr_ty = ty::expr_ty(tcx, f);
 
-    if check type_is_native_fn_on_c_stack(tcx, fn_expr_ty) {
-        ret trans_c_stack_native_call(in_cx, f, args, dest);
-    }
+//NDM    if check type_is_native_fn_on_c_stack(tcx, fn_expr_ty) {
+//NDM        ret trans_c_stack_native_call(in_cx, f, args, dest);
+//NDM    }
 
     let cx = new_scope_block_ctxt(in_cx, "call");
     let f_res = trans_callee(cx, f);
@@ -3832,63 +3828,6 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
     ret next_cx;
 }
 
-// Translates a native call on the C stack. Calls into the runtime to perform
-// the stack switching operation. Must be kept in sync with
-// trans_native_mod().
-fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr,
-                             args: [@ast::expr], dest: dest) -> @block_ctxt {
-    let ccx = bcx_ccx(bcx);
-    let f_res = trans_callee(bcx, f);
-    let llfn = f_res.val, bcx = f_res.bcx;
-    let llfn = BitCast(bcx, llfn, T_ptr(T_fn([], bcx_ccx(bcx).int_type)));
-
-    // Translate the callee.
-    let { params: _, ty: fn_ty } = ty::expr_ty_params_and_ty(bcx_tcx(bcx), f);
-    let fn_arg_tys = ty::ty_fn_args(bcx_tcx(bcx), fn_ty);
-    let llargtys = type_of_explicit_args(ccx, f.span, fn_arg_tys);
-
-    // Determine return type.
-    let ret_ty = ty::ty_fn_ret(bcx_tcx(bcx), fn_ty);
-    check type_has_static_size(ccx, ret_ty);
-    let llretty = type_of(ccx, f.span, ret_ty);
-
-    // Translate arguments.
-    // n.b.: We must do this before allocating the argument
-    // bundle in order to avoid problems with nested function calls.
-    let (to_zero, to_revoke) = ([], []);
-    let i = 0u, n = vec::len(args);
-    let llargs = [];
-    while i < n {
-        let ty_arg = fn_arg_tys[i];
-        let arg = args[i];
-        let llargty = llargtys[i];
-        let r = trans_arg_expr(bcx, ty_arg, llargty, to_zero, to_revoke, arg);
-        bcx = r.bcx;
-        llargs += [r.val];
-        i += 1u;
-    }
-
-    // Allocate the argument bundle and store arguments.
-    let llargbundlety = T_struct(llargtys + [llretty]);
-    let llargbundlesz = llsize_of(ccx, llargbundlety);
-    let llrawargbundle = Call(bcx, ccx.upcalls.alloc_c_stack,
-                              [llargbundlesz]);
-    let llargbundle = PointerCast(bcx, llrawargbundle, T_ptr(llargbundlety));
-    i = 0u;
-    while i < n {
-        store_inbounds(bcx, llargs[i], llargbundle, [0, i as int]);
-        i += 1u;
-    }
-
-    // Call the upcall function then extract return value from the bundle.
-    let upcall_fn = ccx.upcalls.call_c_stack_shim;
-    let llfnptr = PointerCast(bcx, llfn, T_ptr(T_i8()));
-    Call(bcx, upcall_fn, [llfnptr, llrawargbundle]);
-    let llres = load_inbounds(bcx, llargbundle, [0, n as int]);
-    bcx = zero_and_revoke(bcx, to_zero, to_revoke);
-    ret store_in_dest(bcx, llres, dest);
-}
-
 fn zero_and_revoke(bcx: @block_ctxt,
                    to_zero: [{v: ValueRef, t: ty::t}],
                    to_revoke: [{v: ValueRef, t: ty::t}]) -> @block_ctxt {
@@ -5354,6 +5293,7 @@ fn trans_const(cx: @crate_ctxt, e: @ast::expr, id: ast::node_id) {
 type c_stack_tys = {
     arg_tys: [TypeRef],
     ret_ty: TypeRef,
+    ret_def: bool,
     base_fn_ty: TypeRef,
     bundle_ty: TypeRef,
     shim_fn_ty: TypeRef
@@ -5364,13 +5304,16 @@ fn c_stack_tys(ccx: @crate_ctxt,
                id: ast::node_id) -> @c_stack_tys {
     alt ty::struct(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)) {
       ty::ty_native_fn(_, arg_tys, ret_ty) {
+        let tcx = ccx.tcx;
         let llargtys = type_of_explicit_args(ccx, sp, arg_tys);
         check non_ty_var(ccx, ret_ty); // NDM does this truly hold?
-        let llretty = T_ptr(type_of_inner(ccx, sp, ret_ty));
-        let bundle_ty = T_struct(llargtys + [llretty]);
+        let llretty = type_of_inner(ccx, sp, ret_ty);
+        let bundle_ty = T_struct(llargtys + [T_ptr(llretty)]);
         ret @{
             arg_tys: llargtys,
             ret_ty: llretty,
+            ret_def: !ty::type_is_bot(tcx, ret_ty) &&
+                !ty::type_is_nil(tcx, ret_ty),
             base_fn_ty: T_fn(llargtys, llretty),
             bundle_ty: bundle_ty,
             shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void())
@@ -5451,8 +5394,15 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod) {
         }
 
         // Create the call itself and store the return value:
-        let llretval = CallWithConv(bcx, llbasefn, llargvals, cc);
-        store_inbounds(bcx, llretval, llargbundle, [0, n as int, 0]);
+        let llretval = CallWithConv(bcx, llbasefn, llargvals, cc); // r
+        if tys.ret_def {
+            // R** llretptr = &args->r;
+            let llretptr = GEPi(bcx, llargbundle, [0, n as int]);
+            // R* llretloc = *llretptr; /* (args->r) */
+            let llretloc = Load(bcx, llretptr);
+            // *args->r = r;
+            Store(bcx, llretval, llretloc);
+        }
 
         // Finish up:
         build_return(bcx);
@@ -5464,25 +5414,32 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod) {
     fn build_wrap_fn(lcx: @local_ctxt,
                      native_item: @ast::native_item,
                      tys: @c_stack_tys,
+                     num_tps: uint,
                      llshimfn: ValueRef,
                      llwrapfn: ValueRef) {
-        let fcx = new_fn_ctxt(lcx, span, llshimfn);
+        let span = native_item.span;
+        let ccx = lcx_ccx(lcx);
+        let fcx = new_fn_ctxt(lcx, span, llwrapfn);
         let bcx = new_top_block_ctxt(fcx);
         let lltop = bcx.llbb;
 
         // Allocate the struct and write the arguments into it.
         let llargbundle = alloca(bcx, tys.bundle_ty);
-        let imp = 2u, i = 0u, n = vec::len(tys.arg_tys);
+        let i = 0u, n = vec::len(tys.arg_tys);
+        let implicit_args = 2u + num_tps; // ret + env
         while i < n {
-            let llargval = llvm::LLVMGetParam(llwrapfn, i + imp);
+            let llargval = llvm::LLVMGetParam(llwrapfn, i + implicit_args);
             store_inbounds(bcx, llargval, llargbundle, [0, i as int]);
             i += 1u;
         }
-        let llretptr = llvm::LLVMGetParam(llwrapfn, 0);
+        let llretptr = llvm::LLVMGetParam(llwrapfn, 0u);
         store_inbounds(bcx, llretptr, llargbundle, [0, n as int]);
 
-        // Create call itself:
-
+        // Create call itself.
+        let call_shim_on_c_stack = ccx.upcalls.call_shim_on_c_stack;
+        let llshimfnptr = PointerCast(bcx, llshimfn, T_ptr(T_i8()));
+        let llrawargbundle = PointerCast(bcx, llargbundle, T_ptr(T_i8()));
+        Call(bcx, call_shim_on_c_stack, [llrawargbundle, llshimfnptr]);
         build_return(bcx);
         finish_fn(fcx, lltop);
     }
@@ -5498,13 +5455,15 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod) {
     for native_item in native_mod.items {
       alt native_item.node {
         ast::native_item_ty. {}
-        ast::native_item_fn(fn_decl, _) {
+        ast::native_item_fn(fn_decl, tps) {
+          let span = native_item.span;
           let id = native_item.id;
           let tys = c_stack_tys(ccx, span, id);
           alt ccx.item_ids.find(id) {
             some(llwrapfn) {
-              let llshimfn = build_shim_fn(lcx, native_item, cc, tys);
-              build_wrap_fn(lcx, native_item, tys, llshimfn, llwrapfn);
+              let llshimfn = build_shim_fn(lcx, native_item, tys, cc);
+              build_wrap_fn(lcx, native_item, tys,
+                            vec::len(tps), llshimfn, llwrapfn);
             }
 
             none. {
@@ -5733,21 +5692,6 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
     ret count;
 }
 
-pure fn native_abi_requires_pair(abi: ast::native_abi) -> bool {
-    alt abi {
-        ast::native_abi_rust_intrinsic. { ret true; }
-        ast::native_abi_cdecl. |
-        ast::native_abi_stdcall. { ret false; }
-    }
-}
-
-pure fn type_is_native_fn_on_c_stack(tcx: ty::ctxt, t: ty::t) -> bool {
-    alt ty::struct(tcx, t) {
-        ty::ty_native_fn(abi, _, _) { ret !native_abi_requires_pair(abi); }
-        _ { ret false; }
-    }
-}
-
 fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span, ty_param_count: uint,
                           x: ty::t) -> TypeRef {
     alt ty::struct(cx.tcx, x) {
@@ -5778,19 +5722,24 @@ fn collect_native_item(ccx: @crate_ctxt, i: @ast::native_item, &&pt: [str],
     alt i.node {
       ast::native_item_fn(_, tps) {
         if !ccx.obj_methods.contains_key(i.id) {
+            let sp = i.span;
+            let id = i.id;
+            let node_type = node_id_type(ccx, id);
             // FIXME NDM abi should come from attr
-            let abi = ty::ty_fn_abi(ccx.tcx, fn_type);
+            let abi = ty::ty_fn_abi(ccx.tcx, node_type);
 
             alt abi {
               ast::native_abi_rust_intrinsic. {
                 // For intrinsics: link the function directly to the intrinsic
                 // function itself.
                 let num_ty_param = vec::len(tps);
-                let node_type = node_id_type(ccx, id);
-                let fn_type = type_of_fn_from_ty(ccx, sp, node_type, num_ty_param);
-                let ri_name = "rust_intrinsic_" + name;
-                let llnativefn = get_extern_fn(ccx.externs, ccx.llmod, ri_name,
-                                               lib::llvm::LLVMCCallConv, fn_type);
+                check returns_non_ty_var(ccx, node_type);
+                let fn_type = type_of_fn_from_ty(ccx, sp, node_type,
+                                                 num_ty_param);
+                let ri_name = "rust_intrinsic_" + link_name(i);
+                let llnativefn = get_extern_fn(
+                    ccx.externs, ccx.llmod, ri_name,
+                    lib::llvm::LLVMCCallConv, fn_type);
                 ccx.item_ids.insert(id, llnativefn);
                 ccx.item_symbols.insert(id, ri_name);
               }
diff --git a/src/rt/arch/i386/ccall.S b/src/rt/arch/i386/ccall.S
index 297f4c79569..370c0e7c990 100644
--- a/src/rt/arch/i386/ccall.S
+++ b/src/rt/arch/i386/ccall.S
@@ -45,3 +45,20 @@ upcall_call_c_stack_shim:
     movl %ebp,%esp          // would like to use "leave" but it's slower
     popl %ebp
     ret
+
+#if defined(__APPLE__) || defined(_WIN32)
+.globl _asm_call_on_stack
+_asm_call_on_stack:
+#else
+.globl asm_call_on_stack
+asm_call_on_stack:
+#endif
+    pushl %ebp
+    movl %esp,%ebp          // save esp
+    movl 16(%ebp),%esp      // load new esp
+    subl $12,%esp           // maintain 16-byte alignment
+    pushl 8(%ebp)           // push ptr to argument block
+    calll *12(%ebp)
+    movl %ebp,%esp          // would like to use "leave" but it's slower
+    popl %ebp
+    ret
diff --git a/src/rt/arch/i386/context.h b/src/rt/arch/i386/context.h
index e36db0d0121..fc5eb900a5c 100644
--- a/src/rt/arch/i386/context.h
+++ b/src/rt/arch/i386/context.h
@@ -29,6 +29,8 @@ struct registers_t {
   uint32_t eip;
 };
 
+extern "C" void asm_call_on_stack(void *args, void *fn_ptr, uintptr_t stack_ptr);
+
 class context {
 public:
   registers_t regs;
@@ -55,6 +57,10 @@ public:
 
     return reinterpret_cast<void *>(top);
   }
+
+  void call_shim_on_c_stack(void *args, void *fn_ptr) {
+      asm_call_on_stack(args, fn_ptr, regs.esp);
+  }
 };
 
 #endif
diff --git a/src/rt/arch/x86_64/ccall.S b/src/rt/arch/x86_64/ccall.S
index 7ea29f2cea1..943a2027907 100644
--- a/src/rt/arch/x86_64/ccall.S
+++ b/src/rt/arch/x86_64/ccall.S
@@ -2,6 +2,7 @@
 
 #define ARG0 RUSTRT_ARG0_S
 #define ARG1 RUSTRT_ARG1_S
+#define ARG2 RUSTRT_ARG2_S
         
         .text
 
@@ -72,3 +73,18 @@ upcall_call_c_stack_shim:
     mov %rbp,%rsp
     pop %rbp
     ret
+
+#if defined(__APPLE__) || defined(_WIN32)
+.globl _asm_call_on_stack
+_asm_call_on_stack:
+#else
+.globl asm_call_on_stack
+asm_call_on_stack:
+#endif
+    push %rbp
+    mov %rsp,%rbp          // save rsp
+    mov ARG2,%rsp          // switch stack
+    call *ARG1             // invoke target address
+    mov %rbp,%rsp
+    pop %rbp
+    ret
diff --git a/src/rt/arch/x86_64/context.h b/src/rt/arch/x86_64/context.h
index 75427d473f9..11c85092747 100644
--- a/src/rt/arch/x86_64/context.h
+++ b/src/rt/arch/x86_64/context.h
@@ -29,6 +29,8 @@ struct registers_t {
     uint64_t data[RUSTRT_MAX];
 };
 
+extern "C" void asm_call_on_stack(void *args, void *fn_ptr, uintptr_t stack_ptr);
+
 class context {
 public:
     registers_t regs;
@@ -55,6 +57,10 @@ public:
 
         return reinterpret_cast<void *>(top);
     }
+
+    void call_shim_on_c_stack(void *args, void *fn_ptr) {
+        asm_call_on_stack(args, fn_ptr, regs.data[RUSTRT_RSP]);
+    }
 };
 
 #endif
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index c0544383d23..aac4212cac7 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -219,6 +219,16 @@ upcall_alloc_c_stack(size_t nbytes) {
     return sched->c_context.alloc_stack(nbytes);
 }
 
+/**
+ * Allocates |nbytes| bytes in the C stack and returns a pointer to the start
+ * of the allocated space.
+ */
+extern "C" CDECL void
+upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
+    rust_scheduler *sched = rust_scheduler::get_task()->sched;
+    sched->c_context.call_shim_on_c_stack(args, fn_ptr);
+}
+
 extern "C" _Unwind_Reason_Code
 __gxx_personality_v0(int version,
                      _Unwind_Action actions,
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 3147eeeca40..c0a9a92ba1b 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -74,3 +74,5 @@ upcall_shared_malloc
 upcall_shared_free
 upcall_vec_grow
 upcall_vec_push
+upcall_call_shim_on_c_stack
+asm_call_on_stack
\ No newline at end of file