diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs
index a6bf286a2a8..115cd53276d 100644
--- a/src/comp/back/upcall.rs
+++ b/src/comp/back/upcall.rs
@@ -16,6 +16,7 @@ type upcalls =
      free: ValueRef,
      shared_malloc: ValueRef,
      shared_free: ValueRef,
+     memset: ValueRef,
      mark: ValueRef,
      create_shared_type_desc: ValueRef,
      free_shared_type_desc: ValueRef,
@@ -64,6 +65,7 @@ fn declare_upcalls(targ_cfg: @session::config,
                 T_ptr(T_i8())),
           shared_free:
               dv("shared_free", [T_ptr(T_i8())]),
+          memset: dv("memset", [T_ptr(T_i8()), T_i8(), T_i32(), T_i32()]),
           mark:
               d("mark", [T_ptr(T_i8())], int_t),
           create_shared_type_desc:
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index ba7882331b1..2a029c22b3d 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1942,21 +1942,21 @@ fn call_memmove(cx: @block_ctxt, dst: ValueRef, src: ValueRef,
 }
 
 fn call_bzero(cx: @block_ctxt, dst: ValueRef, n_bytes: ValueRef,
-              align_bytes: ValueRef) -> result {
+              align_bytes: ValueRef) -> @block_ctxt {
     // FIXME: switch to the 64-bit variant when on such a platform.
-    let ccx = bcx_ccx(cx);
-    let i = ccx.intrinsics;
-    assert (i.contains_key("llvm.memset.p0i8.i32"));
-    let memset = i.get("llvm.memset.p0i8.i32");
+    let ccx = bcx_ccx(cx), dst = dst;
     let dst_ptr = PointerCast(cx, dst, T_ptr(T_i8()));
     let size = IntCast(cx, n_bytes, T_i32());
-    let align =
-        if lib::llvm::llvm::LLVMIsConstant(align_bytes) == True {
-            IntCast(cx, align_bytes, T_i32())
-        } else { IntCast(cx, C_int(ccx, 0), T_i32()) };
-    let volatile = C_bool(false);
-    ret rslt(cx,
-             Call(cx, memset, [dst_ptr, C_u8(0u), size, align, volatile]));
+    let align = IntCast(cx, align_bytes, T_i32());
+    if lib::llvm::llvm::LLVMIsConstant(align_bytes) != True {
+        // Use our own upcall (see issue 843), since the LLVM intrinsic can
+        // only handle constant alignments.
+        Call(cx, ccx.upcalls.memset, [dst_ptr, C_u8(0u), size, align]);
+    } else {
+        let memset = ccx.intrinsics.get("llvm.memset.p0i8.i32");
+        Call(cx, memset, [dst_ptr, C_u8(0u), size, align, C_bool(false)]);
+    }
+    cx
 }
 
 fn memmove_ty(bcx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
@@ -3977,13 +3977,13 @@ fn zero_alloca(cx: @block_ctxt, llptr: ValueRef, t: ty::t)
         let sp = cx.sp;
         let llty = type_of(ccx, sp, t);
         Store(bcx, C_null(llty), llptr);
+        bcx
     } else {
-        let llsz = size_of(bcx, t);
+        let {bcx, val: llsz} = size_of(bcx, t);
         // FIXME passing in the align here is correct, but causes issue #843
-        // let llalign = align_of(llsz.bcx, t);
-        bcx = call_bzero(llsz.bcx, llptr, llsz.val, C_int(ccx, 0)).bcx;
+        let {bcx, val: align} = align_of(bcx, t);
+        call_bzero(bcx, llptr, llsz, align)
     }
-    ret bcx;
 }
 
 fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index 65299a7d244..096c814f7c9 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -227,6 +227,15 @@ upcall_shared_free(void* ptr) {
     UPCALL_SWITCH_STACK(&args, upcall_s_shared_free);
 }
 
+/************************************************************************
+ * Memset that, contrary to the llvm intrinsic, handles dynamic alignment
+ */
+
+extern "C" CDECL void
+upcall_memset(void* ptr, char val, unsigned size, unsigned align) {
+    memset(ptr, val, align_to(size, align));
+}
+
 /**********************************************************************
  * Called to deep copy a type descriptor onto the exchange heap.
  * Used when sending closures.  It's possible that we should have
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 745e4c6e34b..f507687df82 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -74,6 +74,7 @@ upcall_rust_personality
 upcall_s_shared_malloc
 upcall_shared_malloc
 upcall_shared_free
+upcall_memset
 upcall_vec_grow
 upcall_vec_push
 upcall_call_shim_on_c_stack