about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-19 04:32:04 -0700
committerbors <bors@rust-lang.org>2013-08-19 04:32:04 -0700
commit81a78161b5354c9cfecd8c659cc1dc3711d347d6 (patch)
treebe212089ce62d2909018cf36d7c3aa563b886d94 /src/libsyntax/ext
parent3e4f40ec5aee04c0e5386153644255b6beeba095 (diff)
parent0479d946c83cf9ed90bba5b33820ea4118dd8f9e (diff)
downloadrust-81a78161b5354c9cfecd8c659cc1dc3711d347d6.tar.gz
rust-81a78161b5354c9cfecd8c659cc1dc3711d347d6.zip
auto merge of #8535 : nikomatsakis/rust/issue-3678-wrappers-be-gone-2, r=graydon
Long-standing branch to remove foreign function wrappers altogether. Calls to C functions are done "in place" with no stack manipulation; the scheme relies entirely on the correct use of `#[fixed_stack_segment]` to guarantee adequate stack space. A linter is added to detect when `#[fixed_stack_segment]` annotations are missing. An `externfn!` macro is added to make it easier to declare foreign fns and wrappers in one go: this macro may need some refinement, though, for example it might be good to be able to declare a group of foreign fns. I leave that for future work (hopefully somebody else's work :) ).

Fixes #3678.

Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/expand.rs79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index a4132e6c879..4bea1dc23e7 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -968,6 +968,85 @@ pub fn std_macros() -> @str {
             pub static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key;
         )
     )
+
+    // externfn! declares a wrapper for an external function.
+    // It is intended to be used like:
+    //
+    // externfn!(#[nolink]
+    //           #[abi = \"cdecl\"]
+    //           fn memcmp(cx: *u8, ct: *u8, n: u32) -> u32)
+    //
+    // Due to limitations in the macro parser, this pattern must be
+    // implemented with 4 distinct patterns (with attrs / without
+    // attrs CROSS with args / without ARGS).
+    //
+    // Also, this macro grammar allows for any number of return types
+    // because I couldn't figure out the syntax to specify at most one.
+    macro_rules! externfn(
+        (fn $name:ident () $(-> $ret_ty:ty),*) => (
+            pub unsafe fn $name() $(-> $ret_ty),* {
+                // Note: to avoid obscure bug in macros, keep these
+                // attributes *internal* to the fn
+                #[fixed_stack_segment];
+                #[inline(never)];
+                #[allow(missing_doc)];
+
+                return $name();
+
+                extern {
+                    fn $name() $(-> $ret_ty),*;
+                }
+            }
+        );
+        (fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
+            pub unsafe fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),* {
+                // Note: to avoid obscure bug in macros, keep these
+                // attributes *internal* to the fn
+                #[fixed_stack_segment];
+                #[inline(never)];
+                #[allow(missing_doc)];
+
+                return $name($($arg_name),*);
+
+                extern {
+                    fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
+                }
+            }
+        );
+        ($($attrs:attr)* fn $name:ident () $(-> $ret_ty:ty),*) => (
+            pub unsafe fn $name() $(-> $ret_ty),* {
+                // Note: to avoid obscure bug in macros, keep these
+                // attributes *internal* to the fn
+                #[fixed_stack_segment];
+                #[inline(never)];
+                #[allow(missing_doc)];
+
+                return $name();
+
+                $($attrs)*
+                extern {
+                    fn $name() $(-> $ret_ty),*;
+                }
+            }
+        );
+        ($($attrs:attr)* fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
+            pub unsafe fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),* {
+                // Note: to avoid obscure bug in macros, keep these
+                // attributes *internal* to the fn
+                #[fixed_stack_segment];
+                #[inline(never)];
+                #[allow(missing_doc)];
+
+                return $name($($arg_name),*);
+
+                $($attrs)*
+                extern {
+                    fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
+                }
+            }
+        )
+    )
+
 }";
 }