about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-22 13:44:16 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-23 10:49:47 +0100
commit0545e4a9200a9c971f8b5f95aa9a439ea0c20116 (patch)
treebe7a9b9f697ffe007460898137d8aafd204c6e63 /src/rustc
parent894b7469d6902bba571024cc0f39c1521156d7a3 (diff)
downloadrust-0545e4a9200a9c971f8b5f95aa9a439ea0c20116.tar.gz
rust-0545e4a9200a9c971f8b5f95aa9a439ea0c20116.zip
Support [rust_stack] annotation on native functions (crudely)
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/trans/base.rs4
-rw-r--r--src/rustc/middle/trans/native.rs60
2 files changed, 47 insertions, 17 deletions
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 4d82987ce02..0252802d6a7 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -2625,7 +2625,7 @@ enum call_args {
 //  - new_fn_ctxt
 //  - trans_args
 fn trans_args(cx: block, llenv: ValueRef, args: call_args, fn_ty: ty::t,
-              dest: dest, generic_intrinsic: bool)
+              dest: dest, always_valid_retptr: bool)
     -> {bcx: block, args: [ValueRef], retslot: ValueRef} {
     let _icx = cx.insn_ctxt("trans_args");
     let mut temp_cleanups = [];
@@ -2639,7 +2639,7 @@ fn trans_args(cx: block, llenv: ValueRef, args: call_args, fn_ty: ty::t,
     // Arg 0: Output pointer.
     let llretslot = alt dest {
       ignore {
-        if ty::type_is_nil(retty) && !generic_intrinsic {
+        if ty::type_is_nil(retty) && !always_valid_retptr {
             llvm::LLVMGetUndef(T_ptr(T_nil()))
         } else {
             let {bcx: cx, val} = alloc_ty(bcx, retty);
diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs
index 049e31325d7..be10c8d0e78 100644
--- a/src/rustc/middle/trans/native.rs
+++ b/src/rustc/middle/trans/native.rs
@@ -652,24 +652,50 @@ fn trans_native_mod(ccx: @crate_ctxt,
         }
 
         let lname = link_name(native_item);
-        // Declare the "prototype" for the base function F:
-        let llbasefn = alt tys.x86_64_tys {
-            some(x86_64) {
-                decl_x86_64_fn(x86_64) {|fnty|
-                    decl_fn(ccx.llmod, lname, cc, fnty)
-                }
-            }
-            _ {
-                let llbasefnty = T_fn(tys.arg_tys, tys.ret_ty);
-                decl_fn(ccx.llmod, lname, cc, llbasefnty)
-            }
-        };
+        let llbasefn = base_fn(ccx, lname, tys, cc);
         // Name the shim function
         let shim_name = lname + "__c_stack_shim";
         ret build_shim_fn_(ccx, shim_name, llbasefn, tys, cc,
                            build_args, build_ret);
     }
 
+    fn base_fn(ccx: @crate_ctxt, lname: str, tys: @c_stack_tys,
+               cc: lib::llvm::CallConv) -> ValueRef {
+        // Declare the "prototype" for the base function F:
+        alt tys.x86_64_tys {
+          some(x86_64) {
+            decl_x86_64_fn(x86_64) {|fnty|
+                decl_fn(ccx.llmod, lname, cc, fnty)
+            }
+          }
+          _ {
+            let llbasefnty = T_fn(tys.arg_tys, tys.ret_ty);
+            decl_fn(ccx.llmod, lname, cc, llbasefnty)
+          }
+        }
+    }
+
+    // FIXME this is very shaky and probably gets ABIs wrong all over
+    // the place
+    fn build_direct_fn(ccx: @crate_ctxt, decl: ValueRef,
+                       item: @ast::native_item, tys: @c_stack_tys,
+                       cc: lib::llvm::CallConv) {
+        let fcx = new_fn_ctxt(ccx, [], decl, none);
+        let bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
+        let llbasefn = base_fn(ccx, link_name(item), tys, cc);
+        let ty = ty::lookup_item_type(ccx.tcx,
+                                      ast_util::local_def(item.id)).ty;
+        let args = vec::from_fn(ty::ty_fn_args(ty).len(), {|i|
+            get_param(decl, i + first_real_arg)
+        });
+        let retval = Call(bcx, llbasefn, args);
+        if !ty::type_is_nil(ty::ty_fn_ret(ty)) {
+            Store(bcx, retval, fcx.llretptr);
+        }
+        build_return(bcx);
+        finish_fn(fcx, lltop);
+    }
+
     fn build_wrap_fn(ccx: @crate_ctxt,
                      tys: @c_stack_tys,
                      llshimfn: ValueRef,
@@ -717,10 +743,14 @@ fn trans_native_mod(ccx: @crate_ctxt,
       alt native_item.node {
         ast::native_item_fn(fn_decl, _) {
           let id = native_item.id;
-          let tys = c_stack_tys(ccx, id);
           let llwrapfn = get_item_val(ccx, id);
-          let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
-          build_wrap_fn(ccx, tys, llshimfn, llwrapfn);
+          let tys = c_stack_tys(ccx, id);
+          if attr::attrs_contains_name(native_item.attrs, "rust_stack") {
+              build_direct_fn(ccx, llwrapfn, native_item, tys, cc);
+          } else {
+              let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
+              build_wrap_fn(ccx, tys, llshimfn, llwrapfn);
+          }
         }
       }
     }