diff --git lib/AST/MicrosoftMangle.cpp lib/AST/MicrosoftMangle.cpp
index baa16b0..1c23b48 100644
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -503,6 +503,10 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
       llvm_unreachable("Can't mangle Objective-C selector names here!");
       
     case DeclarationName::CXXConstructorName:
+      if (ND == Structor) {
+        assert(StructorType == Ctor_Complete &&
+               "Should never be asked to mangle a ctor other than complete");
+      }
       Out << "?0";
       break;
       
diff --git lib/CodeGen/CGCXX.cpp lib/CodeGen/CGCXX.cpp
index 43813fe..ad15ee3 100644
--- lib/CodeGen/CGCXX.cpp
+++ lib/CodeGen/CGCXX.cpp
@@ -183,14 +183,16 @@ void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
 
   // The constructor used for constructing this as a base class;
   // ignores virtual bases.
-  EmitGlobal(GlobalDecl(D, Ctor_Base));
+  if (getContext().getTargetInfo().getCXXABI().hasConstructorVariants())
+    EmitGlobal(GlobalDecl(D, Ctor_Base));
 }
 
 void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
                                        CXXCtorType ctorType) {
   // The complete constructor is equivalent to the base constructor
   // for classes with no virtual bases.  Try to emit it as an alias.
-  if (ctorType == Ctor_Complete &&
+  if (getContext().getTargetInfo().getCXXABI().hasConstructorVariants() &&
+      ctorType == Ctor_Complete &&
       !ctor->getParent()->getNumVBases() &&
       !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
                                 GlobalDecl(ctor, Ctor_Base)))
diff --git lib/CodeGen/CGClass.cpp lib/CodeGen/CGClass.cpp
index d847469..6fc2d82 100644
--- lib/CodeGen/CGClass.cpp
+++ lib/CodeGen/CGClass.cpp
@@ -753,11 +753,55 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
   const CXXRecordDecl *ClassDecl = CD->getParent();
 
   SmallVector<CXXCtorInitializer *, 8> MemberInitializers;
+  llvm::SmallPtrSet<CXXCtorInitializer*, 8> ProcessedVbaseCtors;
+
+  if (ClassDecl->getNumVBases() && getContext().getTargetInfo().getCXXABI().isMicrosoft()) {
+    // TODO: Need to abstract this into CGCXXABI?
+    // Probably, a similar code would be used by any ABI where
+    // hasConstructorVariants() == false...
+    //
+    // What about moving EmitCtorPrologue to CGCXXABI entirely?
+    // Pros: easier to do any ABI-specific stuff, e.g. initializing vbtables.
+    // Cons: some code will be duplicated.
+    llvm::Value *IsMostDerivedClass = CXXStructorImplicitParamValue;
+    assert(IsMostDerivedClass);
+    llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0);
+
+    llvm::Value *ShouldInitVbases
+      = Builder.CreateIsNotNull(IsMostDerivedClass, "should_call_vbase_ctors");
+
+    llvm::BasicBlock *CallVbaseCtorsBB = createBasicBlock("ctor.init_vbases"),
+                     *SkipVbaseCtorsBB = createBasicBlock("ctor.skip_vbases");
+
+    Builder.CreateCondBr(ShouldInitVbases, CallVbaseCtorsBB, SkipVbaseCtorsBB);
+
+    EmitBlock(CallVbaseCtorsBB);
+
+    // FIXME: emit vbtables somewhere around here.
+
+    for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
+         E = CD->init_end();
+         B != E; ++B) {
+      CXXCtorInitializer *Member = *B;
+      if (!Member->isBaseInitializer())
+        continue;
+      CXXRecordDecl *Base = Member->getBaseClass()->getAsCXXRecordDecl();
+      if (ClassDecl->isVirtuallyDerivedFrom(Base)) {
+        EmitBaseInitializer(*this, ClassDecl, Member, CtorType);
+        ProcessedVbaseCtors.insert(Member);
+      }
+    }
+    Builder.CreateBr(SkipVbaseCtorsBB);
+
+    EmitBlock(SkipVbaseCtorsBB);
+  }
   
   for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
        E = CD->init_end();
        B != E; ++B) {
     CXXCtorInitializer *Member = (*B);
+    if (ProcessedVbaseCtors.count(Member))
+      continue;
     
     if (Member->isBaseInitializer()) {
       EmitBaseInitializer(*this, ClassDecl, Member, CtorType);
@@ -1270,13 +1314,25 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
     return;
   }
 
-  llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase,
-                                     Delegating);
-  llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
+  // TODO: move EmitCXXConstructorCall to CGCXXABI?
+  llvm::Value *ImplicitParam = 0;
+  QualType ImplicitParamTy;
+  llvm::Value *Callee = 0;
+  if (getContext().getTargetInfo().getCXXABI().isMicrosoft()) {
+    if (D->getParent()->getNumVBases() != 0) {
+      ImplicitParam = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
+      ImplicitParamTy = getContext().IntTy;
+    }
+    Callee = CGM.GetAddrOfCXXConstructor(D, Ctor_Complete);
+  } else {
+    ImplicitParam = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase, Delegating);
+    ImplicitParamTy = getContext().getPointerType(getContext().VoidPtrTy);
+    Callee = CGM.GetAddrOfCXXConstructor(D, Type);
+  }
 
   // FIXME: Provide a source location here.
   EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
-                    VTT, getContext().getPointerType(getContext().VoidPtrTy),
+                    ImplicitParam, ImplicitParamTy,
                     ArgBeg, ArgEnd);
 }
 
diff --git lib/CodeGen/CGVTables.cpp lib/CodeGen/CGVTables.cpp
index 0c5d72f..f0bff6a 100644
--- lib/CodeGen/CGVTables.cpp
+++ lib/CodeGen/CGVTables.cpp
@@ -813,8 +813,13 @@ CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) {
   EmitVTableDefinition(VTable, Linkage, RD);
 
   if (RD->getNumVBases()) {
-    llvm::GlobalVariable *VTT = GetAddrOfVTT(RD);
-    EmitVTTDefinition(VTT, Linkage, RD);
+    // TODO: OK to leave the isMicrosoft() condition here?
+    if (!CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft()) {
+      llvm::GlobalVariable *VTT = GetAddrOfVTT(RD);
+      EmitVTTDefinition(VTT, Linkage, RD);
+    } else {
+      // FIXME: Emit vbtables here.
+    }
   }
 
   // If this is the magic class __cxxabiv1::__fundamental_type_info,
diff --git lib/CodeGen/MicrosoftCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp
index 6c9a6fd..8ce8d2a 100644
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -120,9 +120,15 @@ void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
                                  CanQualType &ResTy,
                                  SmallVectorImpl<CanQualType> &ArgTys) {
   // 'this' is already in place
-  // TODO: 'for base' flag
+
   // Ctor returns this ptr
   ResTy = ArgTys[0];
+
+  const CXXRecordDecl *Class = Ctor->getParent();
+  if (Class->getNumVBases()) {
+    // The constructors of classes with virtual bases take an implicit int parameter.
+    ArgTys.push_back(CGM.getContext().IntTy);
+  }
 }
 
 void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
@@ -153,9 +159,18 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
   if (needThisReturn(CGF.CurGD)) {
     ResTy = Params[0]->getType();
   }
-  if (IsDeletingDtor(CGF.CurGD)) {
-    ASTContext &Context = getContext();
 
+  ASTContext &Context = getContext();
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+  if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
+    ImplicitParamDecl *IsMostDerived
+      = ImplicitParamDecl::Create(Context, 0,
+                                  CGF.CurGD.getDecl()->getLocation(),
+                                  &Context.Idents.get("is_most_derived"),
+                                  Context.IntTy);
+    Params.push_back(IsMostDerived);
+    getStructorImplicitParamDecl(CGF) = IsMostDerived;
+  } else if (IsDeletingDtor(CGF.CurGD)) {
     ImplicitParamDecl *ShouldDelete
       = ImplicitParamDecl::Create(Context, 0,
                                   CGF.CurGD.getDecl()->getLocation(),
@@ -171,6 +186,17 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
   if (needThisReturn(CGF.CurGD)) {
     CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
   }
+
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+  if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
+    assert(getStructorImplicitParamDecl(CGF) &&
+           "no implicit parameter for a constructor with virtual bases?");
+    getStructorImplicitParamValue(CGF)
+      = CGF.Builder.CreateLoad(
+          CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
+          "is_most_derived");
+  }
+
   if (IsDeletingDtor(CGF.CurGD)) {
     assert(getStructorImplicitParamDecl(CGF) &&
            "no implicit parameter for a deleting destructor?");
diff --git test/CodeGenCXX/microsoft-abi-structors-todo-merge.cpp test/CodeGenCXX/microsoft-abi-structors-todo-merge.cpp
new file mode 100644
index 0000000..821f0fb
--- /dev/null
+++ test/CodeGenCXX/microsoft-abi-structors-todo-merge.cpp
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti | FileCheck %s
+
+struct A {
+  A();
+  ~A();
+};
+
+// Tests that we can define constructors outside the class (PR12784).
+A::A() {
+  // CHECK: define x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %this)
+  // CHECK: ret
+}
+
+struct B : A {
+  B();
+  ~B();
+};
+
+B::B() {
+  // CHECK: define x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"(%struct.B* %this)
+  // CHECK: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %0)
+  // CHECK: ret
+}
+
+struct C : virtual A {
+  C();
+};
+
+C::C() {
+  // CHECK: define x86_thiscallcc %struct.C* @"\01??0C@@QAE@XZ"(%struct.C* %this, i32 %is_most_derived) unnamed_addr
+  // TODO: make sure this works in the Release build too;
+  // TODO: add more CHECKs to verify that the icmp operand is in fact 'is_most_derived'.
+  // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne {{.*}}, 0
+  // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+  //
+  // CHECK: [[INIT_VBASES]]
+  // CHECK-NEXT: bitcast %struct.C* %{{.*}} to %struct.A*
+  // CHECK-NEXT: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %0)
+  // CHECK-NEXT: br label %[[SKIP_VBASES]]
+  //
+  // CHECK: [[SKIP_VBASES]]
+  // CHECK: @"\01??_7C@@6B@"
+  // CHECK: ret
+}
+
+void create_C() {
+  C c;
+  // CHECK: define void @"\01?create_C@@YAXXZ"()
+  // CHECK: call x86_thiscallcc %struct.C* @"\01??0C@@QAE@XZ"(%struct.C* %c, i32 1)
+  // CHECK: ret
+}
+
+struct D : C {
+  D();
+};
+
+D::D() {
+  // CHECK: define x86_thiscallcc %struct.D* @"\01??0D@@QAE@XZ"(%struct.D* %this, i32 %is_most_derived) unnamed_addr
+  // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne {{.*}}, 0
+  // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+  //
+  // CHECK: [[INIT_VBASES]]
+  // CHECK-NEXT: bitcast %struct.D* %{{.*}} to %struct.A*
+  // CHECK-NEXT: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %0)
+  // CHECK-NEXT: br label %[[SKIP_VBASES]]
+  //
+  // CHECK: [[SKIP_VBASES]]
+  // CHECK: call x86_thiscallcc %struct.C* @"\01??0C@@QAE@XZ"(%struct.C* %{{.*}}, i32 0)
+  // CHECK: ret
+}
+
+struct E : virtual C {
+  E();
+};
+
+E::E() {
+  // CHECK: define x86_thiscallcc %struct.E* @"\01??0E@@QAE@XZ"(%struct.E* %this, i32 %is_most_derived) unnamed_addr
+  // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne {{.*}}, 0
+  // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+  //
+  // CHECK: [[INIT_VBASES]]
+  // CHECK-NEXT: bitcast %struct.E* %{{.*}} to %struct.A*
+  // CHECK-NEXT: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %0)
+  // CHECK: call x86_thiscallcc %struct.C* @"\01??0C@@QAE@XZ"(%struct.C* %{{.*}}, i32 0)
+  // CHECK-NEXT: br label %[[SKIP_VBASES]]
+  //
+  // CHECK: [[SKIP_VBASES]]
+  // CHECK: ret
+}
