about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-11-14 10:04:55 -0800
committerAlex Crichton <alex@alexcrichton.com>2013-11-18 21:45:58 -0800
commit508b7b996e5d557ec1c49e1d11563ecf4fc9d287 (patch)
tree56afc4b9b834d4496c175a3ab701823dbba72e15
parente8bf0788027932a0b547819cc9edd13c40426e36 (diff)
downloadrust-508b7b996e5d557ec1c49e1d11563ecf4fc9d287.tar.gz
rust-508b7b996e5d557ec1c49e1d11563ecf4fc9d287.zip
Move runtime files to C instead of C++
Explicitly have the only C++ portion of the runtime be one file with exception
handling. All other runtime files must now live in C and be fully defined in C.
-rw-r--r--mk/clean.mk48
-rw-r--r--mk/platform.mk4
-rw-r--r--mk/rt.mk27
-rw-r--r--src/libstd/rt/args.rs1
-rw-r--r--src/rt/miniz.c (renamed from src/rt/miniz.cpp)0
-rw-r--r--src/rt/rust_android_dummy.c (renamed from src/rt/rust_android_dummy.cpp)38
-rw-r--r--src/rt/rust_builtin.c (renamed from src/rt/rust_builtin.cpp)135
-rw-r--r--src/rt/rust_cxx_glue.cpp31
-rw-r--r--src/rt/rust_globals.h8
-rw-r--r--src/rt/rust_test_helpers.c (renamed from src/rt/rust_test_helpers.cpp)68
-rw-r--r--src/rt/rust_upcall.c (renamed from src/rt/rust_upcall.cpp)28
-rw-r--r--src/rt/rust_uv.c (renamed from src/rt/rust_uv.cpp)68
12 files changed, 248 insertions, 208 deletions
diff --git a/mk/clean.mk b/mk/clean.mk
index d2f17fd52c8..dc2aefeb865 100644
--- a/mk/clean.mk
+++ b/mk/clean.mk
@@ -12,13 +12,19 @@
 # Cleanup
 ######################################################################
 
-CLEAN_STAGE_RULES =								\
- $(foreach stage, $(STAGES),					\
-  $(foreach host, $(CFG_HOST),		\
+CLEAN_STAGE_RULES :=							\
+ $(foreach stage, $(STAGES),						\
+  $(foreach host, $(CFG_HOST),						\
    clean$(stage)_H_$(host)						\
-   $(foreach target, $(CFG_TARGET),		\
+   $(foreach target, $(CFG_TARGET),					\
     clean$(stage)_T_$(target)_H_$(host))))
 
+CLEAN_STAGE_RULES := $(CLEAN_STAGE_RULES)				\
+    $(foreach host, $(CFG_HOST), clean-generic-H-$(host))
+
+CLEAN_STAGE_RULES := $(CLEAN_STAGE_RULES)				\
+    $(foreach host, $(CFG_TARGET), clean-generic-T-$(host))
+
 CLEAN_LLVM_RULES = 								\
  $(foreach target, $(CFG_HOST),		\
   clean-llvm$(target))
@@ -33,19 +39,6 @@ clean: clean-misc $(CLEAN_STAGE_RULES)
 
 clean-misc:
 	@$(call E, cleaning)
-	$(Q)find $(CFG_BUILD)/rustllvm \
-	         $(CFG_BUILD)/rt \
-		 $(CFG_BUILD)/test \
-         -name '*.[odasS]' -o \
-         -name '*.so' -o      \
-         -name '*.dylib' -o   \
-         -name '*.dll' -o     \
-         -name '*.def' -o     \
-         -name '*.bc'         \
-         | xargs rm -f
-	$(Q)find $(CFG_BUILD)\
-         -name '*.dSYM'       \
-         | xargs rm -Rf
 	$(Q)rm -f $(RUNTIME_OBJS) $(RUNTIME_DEF)
 	$(Q)rm -f $(RUSTLLVM_LIB_OBJS) $(RUSTLLVM_OBJS_OBJS) $(RUSTLLVM_DEF)
 	$(Q)rm -Rf $(DOCS)
@@ -60,6 +53,27 @@ clean-misc:
 	$(Q)rm -Rf $(foreach sub, index styles files search javascript, \
                  $(wildcard doc/*/$(sub)))
 
+define CLEAN_GENERIC
+
+clean-generic-$(2)-$(1):
+	$(Q)find $(1)/rustllvm \
+	         $(1)/rt \
+		 $(1)/test \
+         -name '*.[odasS]' -o \
+         -name '*.so' -o      \
+         -name '*.dylib' -o   \
+         -name '*.dll' -o     \
+         -name '*.def' -o     \
+         -name '*.bc'         \
+         | xargs rm -f
+	$(Q)find $(1)\
+         -name '*.dSYM'       \
+         | xargs rm -Rf
+endef
+
+$(foreach host, $(CFG_HOST), $(eval $(call CLEAN_GENERIC,$(host),H)))
+$(foreach targ, $(CFG_TARGET), $(eval $(call CLEAN_GENERIC,$(targ),T)))
+
 define CLEAN_HOST_STAGE_N
 
 clean$(1)_H_$(2):
diff --git a/mk/platform.mk b/mk/platform.mk
index d9df4d42f57..622f85302d3 100644
--- a/mk/platform.mk
+++ b/mk/platform.mk
@@ -206,7 +206,7 @@ CFG_LIB_GLOB_arm-apple-darwin = lib$(1)-*.dylib
 CFG_LIB_DSYM_GLOB_arm-apple-darwin = lib$(1)-*.dylib.dSYM
 CFG_GCCISH_CFLAGS_arm-apple-darwin := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS)
 CFG_GCCISH_CXXFLAGS_arm-apple-darwin := -fno-rtti $(CFG_IOS_FLAGS)
-CFG_GCCISH_LINK_FLAGS_arm-apple-darwin := -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind 
+CFG_GCCISH_LINK_FLAGS_arm-apple-darwin := -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind
 CFG_GCCISH_DEF_FLAG_arm-apple-darwin := -Wl,-exported_symbols_list,
 CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-darwin :=
 CFG_GCCISH_POST_LIB_FLAGS_arm-apple-darwin :=
@@ -506,7 +506,7 @@ define CFG_MAKE_TOOLCHAIN
         -c -o $$(1) $$(2)
   CFG_LINK_C_$(1) = $$(CC_$(1)) \
         $$(CFG_GCCISH_LINK_FLAGS) -o $$(1)          \
-        $$(CFG_GCCISH_LINK_FLAGS_$(1)))             \
+        $$(CFG_GCCISH_LINK_FLAGS_$(1))              \
         $$(CFG_GCCISH_DEF_FLAG_$(1))$$(3) $$(2)     \
         $$(call CFG_INSTALL_NAME_$(1),$$(4))
   CFG_COMPILE_CXX_$(1) = $$(CXX_$(1)) \
diff --git a/mk/rt.mk b/mk/rt.mk
index 26e4222e4eb..94de05d0eaf 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -90,13 +90,18 @@ endif
 endif
 
 RUNTIME_CXXS_$(1)_$(2) := \
-              rt/rust_builtin.cpp \
-              rt/rust_upcall.cpp \
-              rt/miniz.cpp \
-              rt/rust_android_dummy.cpp \
-              rt/rust_test_helpers.cpp
+	      rt/rust_cxx_glue.cpp
 
-RUNTIME_CS_$(1)_$(2) :=
+RUNTIME_CS_$(1)_$(2) := \
+              rt/rust_builtin.c \
+              rt/rust_upcall.c \
+              rt/miniz.c \
+              rt/rust_android_dummy.c \
+              rt/rust_test_helpers.c
+
+# stage0 remove this after the next snapshot
+%.cpp:
+	@touch tmp/foo.o
 
 RUNTIME_S_$(1)_$(2) := rt/arch/$$(HOST_$(1))/_context.S \
 			rt/arch/$$(HOST_$(1))/record_sp.S
@@ -114,7 +119,7 @@ ALL_OBJ_FILES += $$(RUNTIME_OBJS_$(1)_$(2))
 MORESTACK_OBJS_$(1)_$(2) := $$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/morestack.o
 ALL_OBJ_FILES += $$(MORESTACK_OBJS_$(1)_$(2))
 
-$$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.cpp $$(MKFILE_DEPS)
+$$(RT_BUILD_DIR_$(1)_$(2))/rust_cxx_glue.o: rt/rust_cxx_glue.cpp $$(MKFILE_DEPS)
 	@$$(call E, compile: $$@)
 	$$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, $$(RUNTIME_INCS_$(1)_$(2)) \
                  $$(SNAP_DEFINES) $$(RUNTIME_CXXFLAGS_$(1)_$(2))) $$<
@@ -241,13 +246,13 @@ endif
 UV_SUPPORT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),uv_support)
 UV_SUPPORT_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/uv_support
 UV_SUPPORT_LIB_$(1) := $$(UV_SUPPORT_DIR_$(1))/$$(UV_SUPPORT_NAME_$(1))
-UV_SUPPORT_CS_$(1) := rt/rust_uv.cpp
-UV_SUPPORT_OBJS_$(1) := $$(UV_SUPPORT_CS_$(1):rt/%.cpp=$$(UV_SUPPORT_DIR_$(1))/%.o)
+UV_SUPPORT_CS_$(1) := rt/rust_uv.c
+UV_SUPPORT_OBJS_$(1) := $$(UV_SUPPORT_CS_$(1):rt/%.c=$$(UV_SUPPORT_DIR_$(1))/%.o)
 
-$$(UV_SUPPORT_DIR_$(1))/%.o: rt/%.cpp
+$$(UV_SUPPORT_DIR_$(1))/%.o: rt/%.c
 	@$$(call E, compile: $$@)
 	@mkdir -p $$(@D)
-	$$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, \
+	$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
 		-I $$(S)src/libuv/include \
                  $$(RUNTIME_CFLAGS_$(1))) $$<
 
diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs
index b9238224d6e..0d32d2d7dba 100644
--- a/src/libstd/rt/args.rs
+++ b/src/libstd/rt/args.rs
@@ -63,6 +63,7 @@ pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) }
 #[cfg(target_os = "android")]
 #[cfg(target_os = "freebsd")]
 mod imp {
+    use cast;
     use libc;
     use option::{Option, Some, None};
     use iter::Iterator;
diff --git a/src/rt/miniz.cpp b/src/rt/miniz.c
index 2b803b06d09..2b803b06d09 100644
--- a/src/rt/miniz.cpp
+++ b/src/rt/miniz.c
diff --git a/src/rt/rust_android_dummy.cpp b/src/rt/rust_android_dummy.c
index 05869c010af..9d91b995073 100644
--- a/src/rt/rust_android_dummy.cpp
+++ b/src/rt/rust_android_dummy.c
@@ -14,53 +14,53 @@ char **backtrace_symbols(void *const *array, int size) { return 0; }
 
 void backtrace_symbols_fd (void *const *array, int size, int fd) {}
 
-extern "C" volatile int* __errno_location() {
+volatile int* __errno_location() {
     return &errno;
 }
 
-extern "C" float log2f(float f)
+float log2f(float f)
 {
     return logf( f ) / logf( 2 );
 }
 
-extern "C" double log2( double n )
+double log2( double n )
 {
     return log( n ) / log( 2 );
 }
 
-extern "C" void telldir()
+void telldir()
 {
 }
 
-extern "C" void seekdir()
+void seekdir()
 {
 }
 
-extern "C" void mkfifo()
+void mkfifo()
 {
 }
 
-extern "C" void abs()
+void abs()
 {
 }
 
-extern "C" void labs()
+void labs()
 {
 }
 
-extern "C" void rand()
+void rand()
 {
 }
 
-extern "C" void srand()
+void srand()
 {
 }
 
-extern "C" void atof()
+void atof()
 {
 }
 
-extern "C" int glob(const char *pattern,
+int glob(const char *pattern,
                     int flags,
                     int (*errfunc) (const char *epath, int eerrno),
                     glob_t *pglob)
@@ -68,38 +68,38 @@ extern "C" int glob(const char *pattern,
     return 0;
 }
 
-extern "C" void globfree(glob_t *pglob)
+void globfree(glob_t *pglob)
 {
 }
 
-extern "C" int pthread_atfork(void (*prefork)(void),
+int pthread_atfork(void (*prefork)(void),
                               void (*postfork_parent)(void),
                               void (*postfork_child)(void))
 {
     return 0;
 }
 
-extern "C" int mlockall(int flags)
+int mlockall(int flags)
 {
     return 0;
 }
 
-extern "C" int munlockall(void)
+int munlockall(void)
 {
     return 0;
 }
 
-extern "C" int shm_open(const char *name, int oflag, mode_t mode)
+int shm_open(const char *name, int oflag, mode_t mode)
 {
     return 0;
 }
 
-extern "C" int shm_unlink(const char *name)
+int shm_unlink(const char *name)
 {
     return 0;
 }
 
-extern "C" int posix_madvise(void *addr, size_t len, int advice)
+int posix_madvise(void *addr, size_t len, int advice)
 {
     return 0;
 }
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.c
index 31ab96f91b9..c8ed61bfc41 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.c
@@ -58,12 +58,12 @@ timegm(struct tm *tm)
 #endif
 
 #if defined(__WIN32__)
-extern "C" CDECL char**
+char**
 rust_env_pairs() {
     return 0;
 }
 #else
-extern "C" CDECL char**
+char**
 rust_env_pairs() {
 #if defined(__APPLE__) && !(TARGET_OS_IPHONE)
     char **environ = *_NSGetEnviron();
@@ -72,18 +72,18 @@ rust_env_pairs() {
 }
 #endif
 
-extern "C" CDECL char*
+char*
 #if defined(__WIN32__)
 rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
     return entry_ptr->cFileName;
 }
 #else
-rust_list_dir_val(dirent* entry_ptr) {
+rust_list_dir_val(struct dirent* entry_ptr) {
     return entry_ptr->d_name;
 }
 #endif
 
-extern "C" CDECL size_t
+size_t
 #if defined(__WIN32__)
 rust_list_dir_wfd_size() {
     return sizeof(WIN32_FIND_DATAW);
@@ -94,7 +94,7 @@ rust_list_dir_wfd_size() {
 }
 #endif
 
-extern "C" CDECL void*
+void*
 #if defined(__WIN32__)
 rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) {
     if(wfd == NULL) {
@@ -110,7 +110,7 @@ rust_list_dir_wfd_fp_buf(void* wfd) {
 }
 #endif
 
-extern "C" CDECL int
+int
 rust_path_is_dir(const char *path) {
     struct stat buf;
     if (stat(path, &buf)) {
@@ -119,7 +119,7 @@ rust_path_is_dir(const char *path) {
     return S_ISDIR(buf.st_mode);
 }
 
-extern "C" CDECL int
+int
 #if defined(__WIN32__)
 rust_path_is_dir_u16(const wchar_t *path) {
     struct _stat buf;
@@ -137,7 +137,7 @@ rust_path_is_dir_u16(const void *path) {
 }
 #endif
 
-extern "C" CDECL int
+int
 rust_path_exists(const char *path) {
     struct stat buf;
     if (stat(path, &buf)) {
@@ -146,7 +146,7 @@ rust_path_exists(const char *path) {
     return 1;
 }
 
-extern "C" CDECL int
+int
 #if defined(__WIN32__)
 rust_path_exists_u16(const wchar_t *path) {
     struct _stat buf;
@@ -162,12 +162,12 @@ rust_path_exists_u16(const void *path) {
 }
 #endif
 
-extern "C" CDECL FILE* rust_get_stdin() {return stdin;}
-extern "C" CDECL FILE* rust_get_stdout() {return stdout;}
-extern "C" CDECL FILE* rust_get_stderr() {return stderr;}
+FILE* rust_get_stdin() {return stdin;}
+FILE* rust_get_stdout() {return stdout;}
+FILE* rust_get_stderr() {return stderr;}
 
 #if defined(__WIN32__)
-extern "C" CDECL void
+void
 rust_get_time(int64_t *sec, int32_t *nsec) {
     FILETIME fileTime;
     GetSystemTimeAsFileTime(&fileTime);
@@ -186,7 +186,7 @@ rust_get_time(int64_t *sec, int32_t *nsec) {
     *nsec = (ns_since_1970 % 1000000) * 1000;
 }
 #else
-extern "C" CDECL void
+void
 rust_get_time(int64_t *sec, int32_t *nsec) {
 #ifdef __APPLE__
     struct timeval tv;
@@ -194,7 +194,7 @@ rust_get_time(int64_t *sec, int32_t *nsec) {
     *sec = tv.tv_sec;
     *nsec = tv.tv_usec * 1000;
 #else
-    timespec ts;
+    struct timespec ts;
     clock_gettime(CLOCK_REALTIME, &ts);
     *sec = ts.tv_sec;
     *nsec = ts.tv_nsec;
@@ -204,7 +204,7 @@ rust_get_time(int64_t *sec, int32_t *nsec) {
 
 const int64_t ns_per_s = 1000000000LL;
 
-extern "C" CDECL void
+void
 rust_precise_time_ns(uint64_t *ns) {
 
 #ifdef __APPLE__
@@ -227,23 +227,22 @@ rust_precise_time_ns(uint64_t *ns) {
     assert(query_result);
     *ns = (uint64_t)((ticks.QuadPart * ns_per_s) / ticks_per_s.QuadPart);
 #else
-    timespec ts;
+    struct timespec ts;
     clock_gettime(CLOCK_MONOTONIC, &ts);
     *ns = (uint64_t)(ts.tv_sec * ns_per_s + ts.tv_nsec);
 #endif
 }
 
-struct
-rust_vec
+typedef struct
 {
     size_t fill;    // in bytes; if zero, heapified
     size_t alloc;   // in bytes
     uint8_t data[0];
-};
+} rust_vec;
 
 typedef rust_vec rust_str;
 
-struct rust_tm {
+typedef struct {
     int32_t tm_sec;
     int32_t tm_min;
     int32_t tm_hour;
@@ -256,10 +255,10 @@ struct rust_tm {
     int32_t tm_gmtoff;
     rust_str *tm_zone;
     int32_t tm_nsec;
-};
+} rust_tm;
 
-void rust_tm_to_tm(rust_tm* in_tm, tm* out_tm) {
-    memset(out_tm, 0, sizeof(tm));
+void rust_tm_to_tm(rust_tm* in_tm, struct tm* out_tm) {
+    memset(out_tm, 0, sizeof(struct tm));
     out_tm->tm_sec = in_tm->tm_sec;
     out_tm->tm_min = in_tm->tm_min;
     out_tm->tm_hour = in_tm->tm_hour;
@@ -271,7 +270,7 @@ void rust_tm_to_tm(rust_tm* in_tm, tm* out_tm) {
     out_tm->tm_isdst = in_tm->tm_isdst;
 }
 
-void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
+void tm_to_rust_tm(struct tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
                    const char *zone, int32_t nsec) {
     out_tm->tm_sec = in_tm->tm_sec;
     out_tm->tm_min = in_tm->tm_min;
@@ -300,13 +299,13 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
 #define LOCALTIME(clock, result) localtime_s((result), (clock))
 #define TIMEGM(result) _mkgmtime64(result)
 #else
-struct tm* GMTIME(const time_t *clock, tm *result) {
+struct tm* GMTIME(const time_t *clock, struct tm *result) {
     struct tm* t = gmtime(clock);
     if (t == NULL || result == NULL) { return NULL; }
     *result = *t;
     return result;
 }
-struct tm* LOCALTIME(const time_t *clock, tm *result) {
+struct tm* LOCALTIME(const time_t *clock, struct tm *result) {
     struct tm* t = localtime(clock);
     if (t == NULL || result == NULL) { return NULL; }
     *result = *t;
@@ -321,23 +320,23 @@ struct tm* LOCALTIME(const time_t *clock, tm *result) {
 #define TIMEGM(result) timegm(result)
 #endif
 
-extern "C" CDECL void
+void
 rust_tzset() {
     TZSET();
 }
 
-extern "C" CDECL void
+void
 rust_gmtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
-    tm tm;
+    struct tm tm;
     time_t s = sec;
     GMTIME(&s, &tm);
 
     tm_to_rust_tm(&tm, timeptr, 0, "UTC", nsec);
 }
 
-extern "C" CDECL void
+void
 rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
-    tm tm;
+    struct tm tm;
     time_t s = sec;
     LOCALTIME(&s, &tm);
 
@@ -365,16 +364,16 @@ rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
     tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec);
 }
 
-extern "C" CDECL int64_t
+int64_t
 rust_timegm(rust_tm* timeptr) {
-    tm t;
+    struct tm t;
     rust_tm_to_tm(timeptr, &t);
     return TIMEGM(&t);
 }
 
-extern "C" CDECL int64_t
+int64_t
 rust_mktime(rust_tm* timeptr) {
-    tm t;
+    struct tm t;
     rust_tm_to_tm(timeptr, &t);
     return mktime(&t);
 }
@@ -383,47 +382,29 @@ rust_mktime(rust_tm* timeptr) {
 #include <sys/types.h>
 #include <dirent.h>
 
-extern "C" DIR*
+DIR*
 rust_opendir(char *dirname) {
     return opendir(dirname);
 }
 
-extern "C" dirent*
+struct dirent*
 rust_readdir(DIR *dirp) {
     return readdir(dirp);
 }
 
 #else
 
-extern "C" void
+void
 rust_opendir() {
 }
 
-extern "C" void
+void
 rust_readdir() {
 }
 
 #endif
 
-typedef void *(rust_try_fn)(void*, void*);
-
-extern "C" CDECL uintptr_t
-rust_try(rust_try_fn f, void *fptr, void *env) {
-    try {
-        f(fptr, env);
-    } catch (uintptr_t token) {
-        assert(token != 0);
-        return token;
-    }
-    return 0;
-}
-
-extern "C" CDECL void
-rust_begin_unwind(uintptr_t token) {
-    throw token;
-}
-
-extern "C" CDECL uintptr_t
+uintptr_t
 rust_running_on_valgrind() {
     return RUNNING_ON_VALGRIND;
 }
@@ -470,24 +451,24 @@ get_num_cpus() {
 }
 #endif
 
-extern "C" CDECL uintptr_t
+uintptr_t
 rust_get_num_cpus() {
     return get_num_cpus();
 }
 
-extern "C" CDECL unsigned int
+unsigned int
 rust_valgrind_stack_register(void *start, void *end) {
   return VALGRIND_STACK_REGISTER(start, end);
 }
 
-extern "C" CDECL void
+void
 rust_valgrind_stack_deregister(unsigned int id) {
   VALGRIND_STACK_DEREGISTER(id);
 }
 
 #if defined(__WIN32__)
 
-extern "C" CDECL void
+void
 rust_unset_sigprocmask() {
     // empty stub for windows to keep linker happy
 }
@@ -497,7 +478,7 @@ rust_unset_sigprocmask() {
 #include <signal.h>
 #include <unistd.h>
 
-extern "C" CDECL void
+void
 rust_unset_sigprocmask() {
     // this can't be safely converted to rust code because the
     // representation of sigset_t is platform-dependent
@@ -526,7 +507,7 @@ win32_require(LPCTSTR fn, BOOL ok) {
     }
 }
 
-extern "C" CDECL void
+void
 rust_win32_rand_acquire(HCRYPTPROV* phProv) {
     win32_require
         (_T("CryptAcquireContext"),
@@ -536,12 +517,12 @@ rust_win32_rand_acquire(HCRYPTPROV* phProv) {
                              CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
 
 }
-extern "C" CDECL void
+void
 rust_win32_rand_gen(HCRYPTPROV hProv, DWORD dwLen, BYTE* pbBuffer) {
     win32_require
         (_T("CryptGenRandom"), CryptGenRandom(hProv, dwLen, pbBuffer));
 }
-extern "C" CDECL void
+void
 rust_win32_rand_release(HCRYPTPROV hProv) {
     win32_require
         (_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0));
@@ -552,15 +533,15 @@ rust_win32_rand_release(HCRYPTPROV hProv) {
 // these symbols are listed in rustrt.def.in, so they need to exist; but they
 // should never be called.
 
-extern "C" CDECL void
+void
 rust_win32_rand_acquire() {
     abort();
 }
-extern "C" CDECL void
+void
 rust_win32_rand_gen() {
     abort();
 }
-extern "C" CDECL void
+void
 rust_win32_rand_release() {
     abort();
 }
@@ -569,20 +550,20 @@ rust_win32_rand_release() {
 
 #if defined(__WIN32__)
 
-extern "C" CDECL int
+int
 rust_crit_section_size() { return sizeof(CRITICAL_SECTION); }
-extern "C" CDECL int
+int
 rust_pthread_mutex_t_size() { return 0; }
-extern "C" CDECL int
+int
 rust_pthread_cond_t_size() { return 0; }
 
 #else
 
-extern "C" CDECL int
+int
 rust_crit_section_size() { return 0; }
-extern "C" CDECL int
+int
 rust_pthread_mutex_t_size() { return sizeof(pthread_mutex_t); }
-extern "C" CDECL int
+int
 rust_pthread_cond_t_size() { return sizeof(pthread_cond_t); }
 
 #endif
diff --git a/src/rt/rust_cxx_glue.cpp b/src/rt/rust_cxx_glue.cpp
new file mode 100644
index 00000000000..b44d29642c4
--- /dev/null
+++ b/src/rt/rust_cxx_glue.cpp
@@ -0,0 +1,31 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/* Foreign builtins which require C++ */
+
+#include "rust_globals.h"
+
+typedef void *(rust_try_fn)(void*, void*);
+
+extern "C" CDECL uintptr_t
+rust_try(rust_try_fn f, void *fptr, void *env) {
+    try {
+        f(fptr, env);
+    } catch (uintptr_t token) {
+        assert(token != 0);
+        return token;
+    }
+    return 0;
+}
+
+extern "C" CDECL void
+rust_begin_unwind(uintptr_t token) {
+    throw token;
+}
diff --git a/src/rt/rust_globals.h b/src/rt/rust_globals.h
index b6191fb4bd1..317f8af237f 100644
--- a/src/rt/rust_globals.h
+++ b/src/rt/rust_globals.h
@@ -39,6 +39,10 @@
 #define __STDC_FORMAT_MACROS 1
 #endif
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
 #define ERROR 0
 
 #include <stdlib.h>
@@ -62,11 +66,15 @@
 #ifndef NOMINMAX
 #define NOMINMAX
 #endif
+#if defined(__cplusplus)
 extern "C" {
+#endif
 #include <windows.h>
 #include <tchar.h>
 #include <wincrypt.h>
+#if defined(__cplusplus)
 }
+#endif
 #elif defined(__GNUC__)
 #include <unistd.h>
 #include <dlfcn.h>
diff --git a/src/rt/rust_test_helpers.cpp b/src/rt/rust_test_helpers.c
index bf5fb059e76..d2b69337e72 100644
--- a/src/rt/rust_test_helpers.cpp
+++ b/src/rt/rust_test_helpers.c
@@ -14,41 +14,41 @@
 
 // These functions are used in the unit tests for C ABI calls.
 
-extern "C" CDECL uint32_t
+uint32_t
 rust_dbg_extern_identity_u32(uint32_t u) {
     return u;
 }
 
-extern "C" CDECL uint64_t
+uint64_t
 rust_dbg_extern_identity_u64(uint64_t u) {
     return u;
 }
 
-extern "C" CDECL double
+double
 rust_dbg_extern_identity_double(double u) {
     return u;
 }
 
-extern "C" CDECL char
+char
 rust_dbg_extern_identity_u8(char u) {
     return u;
 }
 
 typedef void *(*dbg_callback)(void*);
 
-extern "C" CDECL void *
+void *
 rust_dbg_call(dbg_callback cb, void *data) {
     return cb(data);
 }
 
-extern "C" CDECL void rust_dbg_do_nothing() { }
+void rust_dbg_do_nothing() { }
 
 struct TwoU8s {
     uint8_t one;
     uint8_t two;
 };
 
-extern "C" CDECL TwoU8s
+struct TwoU8s
 rust_dbg_extern_return_TwoU8s() {
     struct TwoU8s s;
     s.one = 10;
@@ -56,8 +56,8 @@ rust_dbg_extern_return_TwoU8s() {
     return s;
 }
 
-extern "C" CDECL TwoU8s
-rust_dbg_extern_identity_TwoU8s(TwoU8s u) {
+struct TwoU8s
+rust_dbg_extern_identity_TwoU8s(struct TwoU8s u) {
     return u;
 }
 
@@ -66,7 +66,7 @@ struct TwoU16s {
     uint16_t two;
 };
 
-extern "C" CDECL TwoU16s
+struct TwoU16s
 rust_dbg_extern_return_TwoU16s() {
     struct TwoU16s s;
     s.one = 10;
@@ -74,8 +74,8 @@ rust_dbg_extern_return_TwoU16s() {
     return s;
 }
 
-extern "C" CDECL TwoU16s
-rust_dbg_extern_identity_TwoU16s(TwoU16s u) {
+struct TwoU16s
+rust_dbg_extern_identity_TwoU16s(struct TwoU16s u) {
     return u;
 }
 
@@ -84,7 +84,7 @@ struct TwoU32s {
     uint32_t two;
 };
 
-extern "C" CDECL TwoU32s
+struct TwoU32s
 rust_dbg_extern_return_TwoU32s() {
     struct TwoU32s s;
     s.one = 10;
@@ -92,8 +92,8 @@ rust_dbg_extern_return_TwoU32s() {
     return s;
 }
 
-extern "C" CDECL TwoU32s
-rust_dbg_extern_identity_TwoU32s(TwoU32s u) {
+struct TwoU32s
+rust_dbg_extern_identity_TwoU32s(struct TwoU32s u) {
     return u;
 }
 
@@ -102,7 +102,7 @@ struct TwoU64s {
     uint64_t two;
 };
 
-extern "C" CDECL TwoU64s
+struct TwoU64s
 rust_dbg_extern_return_TwoU64s() {
     struct TwoU64s s;
     s.one = 10;
@@ -110,8 +110,8 @@ rust_dbg_extern_return_TwoU64s() {
     return s;
 }
 
-extern "C" CDECL TwoU64s
-rust_dbg_extern_identity_TwoU64s(TwoU64s u) {
+struct TwoU64s
+rust_dbg_extern_identity_TwoU64s(struct TwoU64s u) {
     return u;
 }
 
@@ -120,12 +120,12 @@ struct TwoDoubles {
     double two;
 };
 
-extern "C" CDECL TwoDoubles
-rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) {
+struct TwoDoubles
+rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) {
     return u;
 }
 
-extern "C" CDECL intptr_t
+intptr_t
 rust_get_test_int() {
   return 1;
 }
@@ -149,29 +149,29 @@ struct floats {
     double c;
 };
 
-extern "C" quad
-rust_dbg_abi_1(quad q) {
-    quad qq = { q.c + 1,
-                q.d - 1,
-                q.a + 1,
-                q.b - 1 };
+struct quad
+rust_dbg_abi_1(struct quad q) {
+    struct quad qq = { q.c + 1,
+                       q.d - 1,
+                       q.a + 1,
+                       q.b - 1 };
     return qq;
 }
 
-extern "C" floats
-rust_dbg_abi_2(floats f) {
-    floats ff = { f.c + 1.0,
-                  0xff,
-                  f.a - 1.0 };
+struct floats
+rust_dbg_abi_2(struct floats f) {
+    struct floats ff = { f.c + 1.0,
+                         0xff,
+                         f.a - 1.0 };
     return ff;
 }
 
-extern "C" int
+int
 rust_dbg_static_mut;
 
 int rust_dbg_static_mut = 3;
 
-extern "C" void
+void
 rust_dbg_static_mut_check_four() {
     assert(rust_dbg_static_mut == 4);
 }
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.c
index 95f4bec02e9..16621d29d4a 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.c
@@ -35,24 +35,24 @@ struct _Unwind_Exception;
 #  endif
 #endif
 
-extern "C" _Unwind_Reason_Code
+_Unwind_Reason_Code
 PERSONALITY_FUNC(int version,
                      _Unwind_Action actions,
                      uint64_t exception_class,
-                     _Unwind_Exception *ue_header,
-                     _Unwind_Context *context);
+                     struct _Unwind_Exception *ue_header,
+                     struct _Unwind_Context *context);
 
 struct s_rust_personality_args {
     _Unwind_Reason_Code retval;
     int version;
     _Unwind_Action actions;
     uint64_t exception_class;
-    _Unwind_Exception *ue_header;
-    _Unwind_Context *context;
+    struct _Unwind_Exception *ue_header;
+    struct _Unwind_Context *context;
 };
 
-extern "C" void
-upcall_s_rust_personality(s_rust_personality_args *args) {
+void
+upcall_s_rust_personality(struct s_rust_personality_args *args) {
     args->retval = PERSONALITY_FUNC(args->version,
                                     args->actions,
                                     args->exception_class,
@@ -65,15 +65,15 @@ upcall_s_rust_personality(s_rust_personality_args *args) {
    out what to do with each landing pad. Just a stack-switching
    wrapper around the C++ personality function.
 */
-extern "C" _Unwind_Reason_Code
+_Unwind_Reason_Code
 upcall_rust_personality(int version,
                         _Unwind_Action actions,
                         uint64_t exception_class,
-                        _Unwind_Exception *ue_header,
-                        _Unwind_Context *context) {
-    s_rust_personality_args args = {(_Unwind_Reason_Code)0,
-                                    version, actions, exception_class,
-                                    ue_header, context};
+                        struct _Unwind_Exception *ue_header,
+                        struct _Unwind_Context *context) {
+    struct s_rust_personality_args args = {(_Unwind_Reason_Code)0,
+                                           version, actions, exception_class,
+                                           ue_header, context};
     upcall_s_rust_personality(&args);
     return args.retval;
 }
@@ -82,7 +82,7 @@ upcall_rust_personality(int version,
 // correct limit into TLS.
 // NB: This must run on the Rust stack because it
 // needs to acquire the value of the stack pointer
-extern "C" CDECL void
+void
 upcall_reset_stack_limit() {
 }
 
diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.c
index f3be486a25a..9c9f7d14e5a 100644
--- a/src/rt/rust_uv.cpp
+++ b/src/rt/rust_uv.c
@@ -22,7 +22,7 @@
 
 #include "rust_globals.h"
 
-extern "C" void*
+void*
 rust_uv_loop_new() {
 // XXX libuv doesn't always ignore SIGPIPE even though we don't need it.
 #ifndef __WIN32__
@@ -31,67 +31,67 @@ rust_uv_loop_new() {
     return (void*)uv_loop_new();
 }
 
-extern "C" void
+void
 rust_uv_loop_set_data(uv_loop_t* loop, void* data) {
     loop->data = data;
 }
 
-extern "C" uv_udp_t*
+uv_udp_t*
 rust_uv_get_udp_handle_from_send_req(uv_udp_send_t* send_req) {
     return send_req->handle;
 }
 
-extern "C" uv_stream_t*
+uv_stream_t*
 rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) {
     return connect->handle;
 }
-extern "C" uv_stream_t*
+uv_stream_t*
 rust_uv_get_stream_handle_from_write_req(uv_write_t* write_req) {
     return write_req->handle;
 }
 
-extern "C" uv_loop_t*
+uv_loop_t*
 rust_uv_get_loop_for_uv_handle(uv_handle_t* handle) {
     return handle->loop;
 }
 
-extern "C" void*
+void*
 rust_uv_get_data_for_uv_loop(uv_loop_t* loop) {
     return loop->data;
 }
 
-extern "C" void
+void
 rust_uv_set_data_for_uv_loop(uv_loop_t* loop,
         void* data) {
     loop->data = data;
 }
 
-extern "C" void*
+void*
 rust_uv_get_data_for_uv_handle(uv_handle_t* handle) {
     return handle->data;
 }
 
-extern "C" void
+void
 rust_uv_set_data_for_uv_handle(uv_handle_t* handle, void* data) {
     handle->data = data;
 }
 
-extern "C" void*
+void*
 rust_uv_get_data_for_req(uv_req_t* req) {
     return req->data;
 }
 
-extern "C" void
+void
 rust_uv_set_data_for_req(uv_req_t* req, void* data) {
     req->data = data;
 }
 
-extern "C" int
+int
 rust_sockaddr_size() {
     return sizeof(struct sockaddr_storage);
 }
 
-extern "C" struct sockaddr*
+struct sockaddr*
 rust_malloc_ip4_addr(char *name, int port) {
     struct sockaddr_in *addr = (struct sockaddr_in*) calloc(1, rust_sockaddr_size());
     assert(addr != NULL);
@@ -101,7 +101,7 @@ rust_malloc_ip4_addr(char *name, int port) {
     return (struct sockaddr*) addr;
 }
 
-extern "C" struct sockaddr*
+struct sockaddr*
 rust_malloc_ip6_addr(char *name, int port) {
     struct sockaddr_in6 *addr = (struct sockaddr_in6*) calloc(1, rust_sockaddr_size());
     assert(addr != NULL);
@@ -111,58 +111,58 @@ rust_malloc_ip6_addr(char *name, int port) {
     return (struct sockaddr*) addr;
 }
 
-extern "C" unsigned int
+unsigned int
 rust_ip4_port(struct sockaddr_in* src) {
     return ntohs(src->sin_port);
 }
-extern "C" unsigned int
+unsigned int
 rust_ip6_port(struct sockaddr_in6* src) {
     return ntohs(src->sin6_port);
 }
 
-extern "C" int
-rust_is_ipv4_sockaddr(sockaddr* addr) {
+int
+rust_is_ipv4_sockaddr(struct sockaddr* addr) {
     return addr->sa_family == AF_INET;
 }
 
-extern "C" int
-rust_is_ipv6_sockaddr(sockaddr* addr) {
+int
+rust_is_ipv6_sockaddr(struct sockaddr* addr) {
     return addr->sa_family == AF_INET6;
 }
 
-extern "C" uintptr_t
+uintptr_t
 rust_uv_handle_type_max() {
   return UV_HANDLE_TYPE_MAX;
 }
 
-extern "C" uintptr_t
+uintptr_t
 rust_uv_req_type_max() {
   return UV_REQ_TYPE_MAX;
 }
 
-extern "C" int
+int
 rust_uv_get_result_from_fs_req(uv_fs_t* req) {
   return req->result;
 }
-extern "C" const char*
+const char*
 rust_uv_get_path_from_fs_req(uv_fs_t* req) {
   return req->path;
 }
-extern "C" void*
+void*
 rust_uv_get_ptr_from_fs_req(uv_fs_t* req) {
   return req->ptr;
 }
-extern "C" uv_loop_t*
+uv_loop_t*
 rust_uv_get_loop_from_fs_req(uv_fs_t* req) {
   return req->loop;
 }
 
-extern "C" uv_loop_t*
+uv_loop_t*
 rust_uv_get_loop_from_getaddrinfo_req(uv_getaddrinfo_t* req) {
   return req->loop;
 }
 
-extern "C" void
+void
 rust_uv_populate_uv_stat(uv_fs_t* req_in, uv_stat_t* stat_out) {
   stat_out->st_dev = req_in->statbuf.st_dev;
   stat_out->st_mode = req_in->statbuf.st_mode;
@@ -186,27 +186,27 @@ rust_uv_populate_uv_stat(uv_fs_t* req_in, uv_stat_t* stat_out) {
   stat_out->st_birthtim.tv_nsec = req_in->statbuf.st_birthtim.tv_nsec;
 }
 
-extern "C" void
+void
 rust_set_stdio_container_flags(uv_stdio_container_t *c, int flags) {
   c->flags = (uv_stdio_flags) flags;
 }
 
-extern "C" void
+void
 rust_set_stdio_container_fd(uv_stdio_container_t *c, int fd) {
   c->data.fd = fd;
 }
 
-extern "C" void
+void
 rust_set_stdio_container_stream(uv_stdio_container_t *c, uv_stream_t *stream) {
   c->data.stream = stream;
 }
 
-extern "C" int
+int
 rust_uv_process_pid(uv_process_t* p) {
   return p->pid;
 }
 
-extern "C" int
+int
 rust_uv_guess_handle(int fd) {
   return uv_guess_handle(fd);
 }