diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 2c37709..1f86789 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -211,7 +211,23 @@ private:
 
 }
 
+static bool isStdOrFastCallFunc(const NamedDecl *ND) {
+  const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
+  if (!FD)
+    return false;
+  QualType T = FD->getType();
+  const AttributedType *AT = dyn_cast<AttributedType>(T);
+  if (!AT)
+    return false;
+  AttributedType::Kind Kind = AT->getAttrKind();
+  return Kind == AttributedType::attr_stdcall ||
+    Kind == AttributedType::attr_fastcall;
+}
+
 bool MicrosoftMangleContextImpl::shouldMangleDeclName(const NamedDecl *D) {
+  if (isStdOrFastCallFunc(D))
+    return true;
+
   // In C, functions with no attributes never need to be mangled. Fastpath them.
   if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
     return false;
@@ -288,6 +304,40 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
     Out << '\01' << ALA->getLabel();
     return;
   }
+  const ASTContext &ASTContext = getASTContext();
+
+  if (!ASTContext.getLangOpts().CPlusPlus) {
+    assert(isStdOrFastCallFunc(D));
+    const FunctionDecl *FD = cast<FunctionDecl>(D);
+    Out << '\01';
+    const AttributedType *AttrType = cast<AttributedType>(FD->getType());
+    AttributedType::Kind K = AttrType->getAttrKind();
+    const FunctionType *FT = cast<FunctionType>(AttrType->getModifiedType());
+    if (K == AttributedType::attr_stdcall)
+      Out << '_';
+    else
+      Out << '@';
+    Out << FD->getIdentifier()->getName();
+    // Variadic functions do not receive @0 suffix.
+    const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);
+    if (Proto && Proto->isVariadic())
+      return;
+    Out << '@';
+    if (!Proto) {
+      Out << '0';
+      return;
+    }
+    unsigned ArgWords = 0;
+    for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+         ArgEnd = Proto->arg_type_end();
+         Arg != ArgEnd; ++Arg) {
+      QualType AT = *Arg;
+      // Size should be aligned to DWORD boundary
+      ArgWords += (ASTContext.getTypeSize(AT) + 31)/32;
+    }
+    Out << 4 * ArgWords;
+    return;
+  }
 
   // <mangled-name> ::= ? <name> <type-encoding>
   Out << Prefix;
diff --git a/test/CodeGen/mangle-ms.c b/test/CodeGen/mangle-ms.c
new file mode 100644
index 0000000..2d1fb8f
--- /dev/null
+++ b/test/CodeGen/mangle-ms.c
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+void __stdcall f1(void) {}
+// CHECK: define x86_stdcallcc void @"\01_f1@0"
+
+void __fastcall f2(void) {}
+// CHECK: define x86_fastcallcc void @"\01@f2@0"
+
+void __stdcall f3() {}
+// CHECK: define x86_stdcallcc void @"\01_f3@0"
+
+void __stdcall f4(int a, ...) {}
+// CHECK: define x86_stdcallcc void @"\01_f4"
+
+void __stdcall f5(int a, int b, ...) {}
+// CHECK: define x86_stdcallcc void @"\01_f5"
+
+void __fastcall f6(char a) {}
+// CHECK: define x86_fastcallcc void @"\01@f6@4"
+
+void __fastcall f7(short a) {}
+// CHECK: define x86_fastcallcc void @"\01@f7@4"
+
+void __fastcall f8(int a) {}
+// CHECK: define x86_fastcallcc void @"\01@f8@4"
+
+void __fastcall f9(long a) {}
+// CHECK: define x86_fastcallcc void @"\01@f9@4"
+
+void __fastcall f10(long long a) {}
+// CHECK: define x86_fastcallcc void @"\01@f10@8"
+
+void __fastcall f11(long long a, char b, char c, short d) {}
+// CHECK: define x86_fastcallcc void @"\01@f11@20"(i64 %a, i8 signext %b, i8 signext %c, i16 signext %d)
+
+void f12(void) {}
+// CHECK: define void @f12(
