https://github.com/R-Goc updated 
https://github.com/llvm/llvm-project/pull/233291

>From fc8cfd5909a0419209df33877767bf80de7a8ca1 Mon Sep 17 00:00:00 2001
From: R-Goc <[email protected]>
Date: Fri, 16 Oct 2026 21:48:27 +0200
Subject: [PATCH] [CIR] Add initial Microsoft C++ ABI support in ClangIR

* Implement foundational CIRGenMicrosoftCXXABI class and driver wiring.
* Implement string literal mangling (??_C@_).
* Implement constructor this-return (hasThisReturn).
* Add initial lit test in clang/test/CIR/CodeGen/cxx-msvc-abi.cpp.

Assisted-by: Gemini:gemini-3.8-flash-high
---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          |  14 +-
 clang/lib/CIR/CodeGen/CIRGenClass.cpp         |   1 -
 clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp       |   7 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp      |   4 +-
 .../lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp | 184 ++++++++----------
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        |  45 +++--
 clang/lib/CIR/CodeGen/CIRGenModule.h          |   7 +
 clang/lib/CIR/CodeGen/CIRGenVTables.h         |   8 +
 clang/lib/CIR/CodeGen/CIRGenerator.cpp        |  12 +-
 .../TargetLowering/LowerMicrosoftCXXABI.cpp   |  12 +-
 clang/test/CIR/CodeGen/cxx-msvc-abi.cpp       |  72 ++++++-
 11 files changed, 222 insertions(+), 144 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 2d9113c2789933..b6edbfa8ec45f9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -900,9 +900,6 @@ CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
                                ? astContext.VoidPtrTy
                                : astContext.VoidTy;
 
-  assert(!theCXXABI.hasThisReturn(gd) &&
-         "Please send PR with a test and remove this");
-
   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
 
@@ -1038,13 +1035,10 @@ const CIRGenFunctionInfo 
&CIRGenTypes::arrangeCXXConstructorCall(
                               : RequiredArgs::All;
 
   GlobalDecl gd(d, ctorKind);
-  if (theCXXABI.hasThisReturn(gd))
-    cgm.errorNYI(d->getSourceRange(),
-                 "arrangeCXXConstructorCall: hasThisReturn");
-  if (theCXXABI.hasMostDerivedReturn(gd))
-    cgm.errorNYI(d->getSourceRange(),
-                 "arrangeCXXConstructorCall: hasMostDerivedReturn");
-  CanQualType resultType = astContext.VoidTy;
+  CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+                           : theCXXABI.hasMostDerivedReturn(gd)
+                               ? astContext.VoidPtrTy
+                               : astContext.VoidTy;
 
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp 
b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index bcf301a0b5ae20..3e3bb7733a9c13 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -1053,7 +1053,6 @@ void CIRGenFunction::enterDtorCleanups(const 
CXXDestructorDecl *dd,
              "only the Microsoft ABI passes an implicit deleting dtor param");
       cgm.errorNYI(dd->getSourceRange(),
                    "deleting destructor with conditional delete: MSVC ABI");
-
     } else {
       assert(!dd->getOperatorDelete()->isDestroyingOperatorDelete() &&
              "destroying operator delete is handled by emitDestructorBody");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index f30a8be15bc2bb..8d13f92b952cf6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -342,8 +342,11 @@ static void emitNullBaseClassInitialization(CIRGenFunction 
&cgf,
   stores.emplace_back(CharUnits::Zero(), nvSize);
 
   // Each store is split by the existence of a vbptr.
-  // TODO(cir): This only needs handling for the MS CXXABI.
-  assert(!cir::MissingFeatures::msabi());
+  if (cgf.cgm.getTarget().getCXXABI().isMicrosoft() && base->getNumVBases()) {
+    cgf.cgm.errorNYI(base->getSourceRange(),
+                     "emitNullBaseClassInitialization: MSVC vbptr splitting");
+    return;
+  }
 
   // If the type contains a pointer to data member we can't memset it to zero.
   // Instead, create a null constant and copy it to the destination.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index e5f20f7dec01d1..028a4e04d119a5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -1082,9 +1082,9 @@ clang::QualType 
CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd,
   const auto *md = dyn_cast<CXXMethodDecl>(fd);
   if (md && md->isImplicitObjectMemberFunction()) {
     if (cgm.getCXXABI().hasThisReturn(gd))
-      cgm.errorNYI(fd->getSourceRange(), "this return");
+      retTy = md->getThisType();
     else if (cgm.getCXXABI().hasMostDerivedReturn(gd))
-      cgm.errorNYI(fd->getSourceRange(), "most derived return");
+      retTy = getContext().VoidPtrTy;
     cgm.getCXXABI().buildThisParam(*this, args);
   }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp 
b/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp
index b866b1ee554bf9..fd4cc55c1d2dce 100644
--- a/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp
@@ -1,4 +1,4 @@
-//===--- CIRGenMicrosoftCXXABI.cpp - Emit CIR Code for MS C++ ABI --------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,10 @@
 //
 
//===----------------------------------------------------------------------===//
 //
-// This provides C++ code generation targeting the Microsoft C++ ABI.
+// This provides C++ code generation targeting the Microsoft C++ ABI.  The 
class
+// in this file generates structures that follow the Microsoft C++ ABI, which 
is
+// documented at:
+//  
https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
 //
 
//===----------------------------------------------------------------------===//
 
@@ -14,9 +17,14 @@
 #include "CIRGenFunction.h"
 #include "CIRGenModule.h"
 
+#include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Mangle.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -27,23 +35,71 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
 public:
   CIRGenMicrosoftCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {}
 
+  bool hasThisReturn(GlobalDecl gd) const override {
+    return isa<CXXConstructorDecl>(gd.getDecl());
+  }
+
+  bool hasMostDerivedReturn(GlobalDecl gd) const override { return false; }
+
+  StringRef getPureVirtualCallName() override { return "_purecall"; }
+  StringRef getDeletedVirtualCallName() override { return "_purecall"; }
+
+  bool canSpeculativelyEmitVTable(const CXXRecordDecl *rd) const override {
+    return false;
+  }
+
+  bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
+    return !vtableClass->hasAttr<MSNoVTableAttr>();
+  }
+
+  bool exportThunk() override { return false; }
+
+  bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
+                              CXXDtorType dt) const override {
+    return false;
+  }
+
+  bool isZeroInitializable(const MemberPointerType *mpt) override {
+    return true;
+  }
+
+  CharUnits getArrayCookieSizeImpl(QualType elementType) override {
+    return CharUnits::Zero();
+  }
+
+  Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
+                                mlir::Value numElements, const CXXNewExpr *e,
+                                QualType elementType) override {
+    cgf.cgm.errorNYI(e->getSourceRange(), "initializeArrayCookie: MSVC ABI");
+    return newPtr;
+  }
+
+  void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd,
+                       bool returnAdjustment) override {
+    cgm.errorNYI("setThunkLinkage: MSVC ABI");
+  }
+
   AddedStructorArgCounts
   buildStructorSignature(GlobalDecl gd,
                          SmallVectorImpl<CanQualType> &argTys) override {
-    cgm.errorNYI(gd.getDecl()->getSourceRange(),
-                 "buildStructorSignature: MSVC ABI");
     return AddedStructorArgCounts{};
   }
 
   void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy,
-                                 FunctionArgList &params) override {
-    cgf.cgm.errorNYI(cgf.curGD.getDecl()->getSourceRange(),
-                     "addImplicitStructorParams: MSVC ABI");
-  }
+                                 FunctionArgList &params) override {}
 
   void emitInstanceFunctionProlog(SourceLocation loc,
                                   CIRGenFunction &cgf) override {
-    cgf.cgm.errorNYI(loc, "emitInstanceFunctionProlog: MSVC ABI");
+    if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>())
+      return;
+
+    mlir::Value thisVal = loadIncomingCXXThis(cgf);
+    setCXXABIThisValue(cgf, thisVal);
+
+    if (hasThisReturn(cgf.curGD)) {
+      if (cgf.returnValue.isValid())
+        cgf.getBuilder().createStore(cgf.getLoc(loc), thisVal, 
cgf.returnValue);
+    }
   }
 
   AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf,
@@ -51,8 +107,6 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
                                                CXXCtorType type,
                                                bool forVirtualBase,
                                                bool delegating) override {
-    cgf.cgm.errorNYI(d->getSourceRange(),
-                     "getImplicitConstructorArgs: MSVC ABI");
     return AddedStructorArgs{};
   }
 
@@ -61,13 +115,11 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
                                             CXXDtorType type,
                                             bool forVirtualBase,
                                             bool delegating) override {
-    cgf.cgm.errorNYI(dd->getSourceRange(),
-                     "getCXXDestructorImplicitParam: MSVC ABI");
     return nullptr;
   }
 
   void emitCXXConstructors(const CXXConstructorDecl *d) override {
-    cgm.errorNYI(d->getSourceRange(), "emitCXXConstructors: MSVC ABI");
+    cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
   }
 
   void emitCXXDestructors(const CXXDestructorDecl *d) override {
@@ -75,6 +127,11 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
   }
 
   void emitCXXStructor(GlobalDecl gd) override {
+    if (auto *ctor = dyn_cast<CXXConstructorDecl>(gd.getDecl())) {
+      auto fn = cgm.codegenCXXStructor(gd.getWithCtorType(Ctor_Complete));
+      cgm.maybeSetTrivialComdat(*ctor, fn);
+      return;
+    }
     cgm.errorNYI(gd.getDecl()->getSourceRange(), "emitCXXStructor: MSVC ABI");
   }
 
@@ -102,36 +159,16 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
 
   size_t getSrcArgforCopyCtor(const CXXConstructorDecl *cd,
                               FunctionArgList &args) const override {
-    cgm.errorNYI(cd->getSourceRange(), "getSrcArgforCopyCtor: MSVC ABI");
-    assert(args.size() >= 2 &&
-           "expected the arglist to have at least two args!");
-    // The 'most_derived' parameter goes second if the ctor is variadic and
-    // has v-bases.
-    if (cd->getParent()->getNumVBases() > 0 &&
-        cd->getType()->castAs<FunctionProtoType>()->isVariadic())
-      return 2;
     return 1;
   }
 
   const CXXRecordDecl *
   getThisArgumentTypeForMethod(const CXXMethodDecl *md) override {
-    cgm.errorNYI(md->getSourceRange(),
-                 "getThisArgumentTypeForMethod: MSVC ABI");
     return md->getParent();
   }
 
-  Address adjustThisArgumentForVirtualFunctionCall(CIRGenFunction &cgf,
-                                                   GlobalDecl gd,
-                                                   Address thisAddr,
-                                                   bool virtualCall) override {
-    cgf.cgm.errorNYI(gd.getDecl()->getSourceRange(),
-                     "adjustThisArgumentForVirtualFunctionCall: MSVC ABI");
-    return thisAddr;
-  }
-
   bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
                                            CIRGenFunction::VPtr vptr) override 
{
-    cgf.cgm.errorNYI("isVirtualOffsetNeededForVTableField: MSVC ABI");
     return false;
   }
 
@@ -181,13 +218,6 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
                  "emitVirtualInheritanceTables: MSVC ABI");
   }
 
-  void
-  initializeHiddenVirtualInheritanceMembers(CIRGenFunction &cgf,
-                                            const CXXRecordDecl *rd) override {
-    cgf.cgm.errorNYI(rd->getSourceRange(),
-                     "initializeHiddenVirtualInheritanceMembers: MSVC ABI");
-  }
-
   mlir::Value
   getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
                             Address thisAddr, const CXXRecordDecl *classDecl,
@@ -199,7 +229,7 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
   cir::MethodAttr buildVirtualMethodAttr(cir::MethodType methodTy,
                                          const CXXMethodDecl *md) override {
     cgm.errorNYI(md->getSourceRange(), "buildVirtualMethodAttr: MSVC ABI");
-    return cir::MethodAttr();
+    return {};
   }
 
   mlir::Value performThisAdjustment(CIRGenFunction &cgf, Address thisAddr,
@@ -216,65 +246,12 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
     return ret.emitRawPointer();
   }
 
-  bool canSpeculativelyEmitVTable(const CXXRecordDecl *rd) const override {
-    return false;
-  }
-
-  bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
-    cgm.errorNYI(vtableClass->getSourceRange(),
-                 "doStructorsInitializeVPtrs: MSVC ABI");
-    return false;
-  }
-
-  bool exportThunk() override { return false; }
-
-  bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
-                              CXXDtorType dt) const override {
-    cgm.errorNYI(dtor->getSourceRange(), "useThunkForDtorVariant: MSVC ABI");
-    return false;
-  }
-
-  void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd,
-                       bool returnAdjustment) override {
-    cgm.errorNYI(gd.getDecl()->getSourceRange(), "setThunkLinkage: MSVC ABI");
-  }
-
-  StringRef getPureVirtualCallName() override { return "_purecall"; }
-  StringRef getDeletedVirtualCallName() override { return "_purecall"; }
-
-  bool isZeroInitializable(const MemberPointerType *mpt) override {
-    cgm.errorNYI("isZeroInitializable: MSVC ABI");
-    return true;
-  }
-
-  bool requiresArrayCookie(const CXXNewExpr *e) override {
-    cgm.errorNYI(e->getSourceRange(), "requiresArrayCookie: MSVC ABI");
-    return false;
-  }
-
-  CharUnits getArrayCookieSizeImpl(QualType elementType) override {
-    cgm.errorNYI("getArrayCookieSizeImpl: MSVC ABI");
-    return CharUnits::Zero();
-  }
-
-  Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
-                                mlir::Value numElements, const CXXNewExpr *e,
-                                QualType elementType) override {
-    cgf.cgm.errorNYI(e->getSourceRange(), "initializeArrayCookie: MSVC ABI");
-    return newPtr;
-  }
-
-  bool shouldTypeidBeNullChecked(QualType srcTy) override {
-    cgm.errorNYI("shouldTypeidBeNullChecked: MSVC ABI");
-    return false;
-  }
+  bool shouldTypeidBeNullChecked(QualType srcTy) override { return false; }
 
   mlir::Value emitTypeid(CIRGenFunction &cgf, QualType srcTy, Address thisPtr,
                          mlir::Type typeInfoPtrTy) override {
-    cgf.cgm.errorNYI(cgf.getLoc(srcTy->getAsCXXRecordDecl()->getLocation()),
-                     "emitTypeid: MSVC ABI");
-    return cgf.getBuilder().getNullPtr(
-        typeInfoPtrTy, cgf.getLoc(srcTy->getAsCXXRecordDecl()->getLocation()));
+    cgf.cgm.errorNYI("emitTypeid: MSVC ABI");
+    return nullptr;
   }
 
   void emitBadTypeidCall(CIRGenFunction &cgf, mlir::Location loc) override {
@@ -282,7 +259,7 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
   }
 
   void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override {
-    cgm.errorNYI(loc, "emitBadCastCall: MSVC ABI");
+    cgf.cgm.errorNYI(loc, "emitBadCastCall: MSVC ABI");
   }
 
   mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,
@@ -299,20 +276,15 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
     return nullptr;
   }
 
-  CatchTypeInfo getCatchAllTypeInfo() override {
-    cgm.errorNYI("getCatchAllTypeInfo: MSVC ABI");
-    return CatchTypeInfo{nullptr, 0};
-  }
-
   CatchTypeInfo
   getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
                                QualType catchHandlerType) override {
     cgm.errorNYI(loc, "getAddrOfCXXCatchHandlerType: MSVC ABI");
-    return CatchTypeInfo{nullptr, 0};
+    return {};
   }
 
   void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override {
-    cgm.errorNYI("emitRethrow: MSVC ABI");
+    cgf.cgm.errorNYI("emitRethrow: MSVC ABI");
   }
 
   void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 8801a730e8d678..3f81658f45c627 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -2185,7 +2185,7 @@ cir::GlobalLinkageKind 
CIRGenModule::getFunctionLinkage(GlobalDecl gd) {
 
 static cir::GlobalOp
 generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
-                      cir::GlobalLinkageKind lt, CIRGenModule &cgm,
+                      cir::GlobalLinkageKind linkageKind, CIRGenModule &cgm,
                       StringRef globalName, CharUnits alignment) {
   LangAS as = CodeGenUtils::getGlobalConstantAddressSpace(cgm.getLangOpts(),
                                                           cgm.getTarget());
@@ -2200,8 +2200,8 @@ generateStringLiteral(mlir::Location loc, mlir::TypedAttr 
c,
 
   // Set up extra information and add to the module
   gv.setAlignmentAttr(cgm.getSize(alignment));
-  gv.setLinkageAttr(
-      cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
+  gv.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
+      cgm.getBuilder().getContext(), linkageKind));
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
   CIRGenModule::setInitializer(gv, c);
@@ -2253,27 +2253,38 @@ cir::GlobalOp 
CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
         uint64_t(alignment.getQuantity()) > *gv.getAlignment())
       gv.setAlignmentAttr(getSize(alignment));
   } else {
+    std::string globalVariableName;
+    cir::GlobalLinkageKind linkageKind;
+
     // Mangle the string literal if that's how the ABI merges duplicate 
strings.
     // Don't do it if they are writable, since we don't want writes in one TU 
to
     // affect strings in another.
     if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
         !getLangOpts().WritableStrings) {
-      errorNYI(s->getSourceRange(),
-               "getGlobalForStringLiteral: mangle string literals");
+      llvm::raw_string_ostream out(globalVariableName);
+      getCXXABI().getMangleContext().mangleStringLiteral(s, out);
+      linkageKind = cir::GlobalLinkageKind::LinkOnceODRLinkage;
+    } else {
+      linkageKind = cir::GlobalLinkageKind::PrivateLinkage;
+      // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
+      // we need to do that explicitly.
+      globalVariableName = getUniqueGlobalName(name.str());
+    }
+
+    if (auto existingGV = getGlobalValue(globalVariableName)) {
+      gv = cast<cir::GlobalOp>(existingGV);
+      constantStringMap[c] = gv;
+      return gv;
     }
 
-    // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
-    // we need to do that explicitly.
-    std::string uniqueName = getUniqueGlobalName(name.str());
     // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
     // source locations. Use unknown location in those cases.
     mlir::Location loc = s->getBeginLoc().isValid()
                              ? getLoc(s->getSourceRange())
                              : builder.getUnknownLoc();
     auto typedC = llvm::cast<mlir::TypedAttr>(c);
-    gv = generateStringLiteral(loc, typedC,
-                               cir::GlobalLinkageKind::PrivateLinkage, *this,
-                               uniqueName, alignment);
+    gv = generateStringLiteral(loc, typedC, linkageKind, *this,
+                               globalVariableName, alignment);
     setDSOLocal(static_cast<mlir::Operation *>(gv));
     constantStringMap[c] = gv;
 
@@ -2914,9 +2925,10 @@ StringRef CIRGenModule::getMangledName(GlobalDecl gd) {
   // constructors get mangled the same.
   if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
     if (!getTarget().getCXXABI().hasConstructorVariants()) {
-      errorNYI(cd->getSourceRange(),
-               "getMangledName: C++ constructor without variants");
-      return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
+      CXXCtorType origCtorType = gd.getCtorType();
+      assert(origCtorType == Ctor_Base || origCtorType == Ctor_Complete);
+      if (origCtorType == Ctor_Base)
+        canonicalGd = GlobalDecl(cd, Ctor_Complete);
     }
   }
 
@@ -3752,12 +3764,13 @@ cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
   }
 
   // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
-  // each other bottoming out wiht the base dtor. Therefore we emit non-base
+  // each other bottoming out with the base dtor. Therefore we emit non-base
   // dtors on usage, even if there is no dtor definition in the TU.
   if (isa_and_nonnull<CXXDestructorDecl>(d) &&
       getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
                                          gd.getDtorType()))
-    errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
+    errorNYI(d->getSourceRange(),
+             "getOrCreateCIRFunction: MSVC non-base destructor thunk");
 
   // This is the first use or definition of a mangled name. If there is a
   // deferred decl with this name, remember that we need to emit it at the end
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 074ca5818ae2ee..baa0342a4ab82b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -595,6 +595,13 @@ class CIRGenModule : public CIRGenTypeCache {
     return vtables.getItaniumVTableContext();
   }
 
+  MicrosoftVTableContext &getMicrosoftVTableContext() {
+    return vtables.getMicrosoftVTableContext();
+  }
+  const MicrosoftVTableContext &getMicrosoftVTableContext() const {
+    return vtables.getMicrosoftVTableContext();
+  }
+
   /// This contains all the decls which have definitions but which are deferred
   /// for emission and therefore should only be output if they are actually
   /// used. If a decl is in this, then it is known to have not been referenced
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.h 
b/clang/lib/CIR/CodeGen/CIRGenVTables.h
index 1e4da7d8f945f0..29fde7445c9465 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.h
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.h
@@ -76,6 +76,14 @@ class CIRGenVTables {
     return *llvm::cast<clang::ItaniumVTableContext>(vtContext);
   }
 
+  clang::MicrosoftVTableContext &getMicrosoftVTableContext() {
+    return *cast<clang::MicrosoftVTableContext>(vtContext);
+  }
+
+  const clang::MicrosoftVTableContext &getMicrosoftVTableContext() const {
+    return *cast<clang::MicrosoftVTableContext>(vtContext);
+  }
+
   /// Generate a construction vtable for the given base subobject.
   cir::GlobalOp
   generateConstructionVTable(const CXXRecordDecl *rd, const BaseSubobject 
&base,
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp 
b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index d2f1b54e43325c..a9e19b123baf63 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -163,8 +163,16 @@ void CIRGenerator::HandleTagDeclDefinition(TagDecl *d) {
 
   // For MSVC compatibility, treat declarations of static data members with
   // inline initializers as definitions.
-  if (astContext->getTargetInfo().getCXXABI().isMicrosoft())
-    cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: MSABI");
+  if (astContext->getTargetInfo().getCXXABI().isMicrosoft()) {
+    for (Decl *member : d->decls()) {
+      if (auto *vd = dyn_cast<VarDecl>(member)) {
+        if (astContext->isMSStaticDataMemberInlineDefinition(vd) &&
+            astContext->DeclMustBeEmitted(vd)) {
+          cgm->emitGlobal(vd);
+        }
+      }
+    }
+  }
 
   // For OpenMP emit declare reduction functions or declare mapper, if
   // required.
diff --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
index 1cd7306d74dba9..ffb913e0459191 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
@@ -1,4 +1,5 @@
-//===---- LowerMicrosoftCXXABI.cpp - Emit CIR for Microsoft-specific code 
-===//
+//===---- LowerMicrosoftCXXABI.cpp - Emit CIR code Microsoft-specific code
+//-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -136,7 +137,9 @@ class LowerMicrosoftCXXABI : public CIRCXXABI {
 
   clang::CharUnits
   getArrayCookieSizeImpl(clang::CharUnits elementAlign) const override {
-    llvm_unreachable("Microsoft ABI array cookie lowering NYI");
+    clang::CharUnits cookieSize =
+        clang::CharUnits::fromQuantity(getPtrSizeInBits() / 8);
+    return std::max(cookieSize, elementAlign);
   }
 
   mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
@@ -144,7 +147,10 @@ class LowerMicrosoftCXXABI : public CIRCXXABI {
                                   clang::CharUnits cookieAlignment,
                                   const mlir::DataLayout &dataLayout,
                                   CIRBaseBuilderTy &builder) const override {
-    llvm_unreachable("Microsoft ABI array cookie lowering NYI");
+    mlir::Type sizeTy = builder.getUIntNTy(getPtrSizeInBits());
+    mlir::Value cookiePtr =
+        builder.createBitcast(allocPtr, builder.getPointerTo(sizeTy));
+    return builder.createLoad(loc, cookiePtr);
   }
 };
 
diff --git a/clang/test/CIR/CodeGen/cxx-msvc-abi.cpp 
b/clang/test/CIR/CodeGen/cxx-msvc-abi.cpp
index e1a4d7519f5d46..8fea5651a186af 100644
--- a/clang/test/CIR/CodeGen/cxx-msvc-abi.cpp
+++ b/clang/test/CIR/CodeGen/cxx-msvc-abi.cpp
@@ -1,6 +1,74 @@
 // RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++17 -fclangir 
-emit-cir %s -o %t.cir
 // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
 
-void empty() {}
+// Adapted from Clang CodeGenCXX/microsoft-abi-methods.cpp,
+// microsoft-abi-structors.cpp, and microsoft-abi-vftables.cpp.
 
-// CIR: cir.func {{.*}} @"?empty@@YAXXZ"()
+//===----------------------------------------------------------------------===//
+// Section 1: Member Functions & Calling Conventions
+//===----------------------------------------------------------------------===//
+
+class MethodsTest {
+public:
+  void simple_method() {}
+  void vararg_method(const char *fmt, ...) {}
+  static void static_method() {}
+};
+
+void call_methods() {
+  MethodsTest obj;
+  obj.simple_method();
+  obj.vararg_method("test");
+  MethodsTest::static_method();
+}
+
+// CIR-DAG: cir.global {{.*}} linkonce_odr {{.*}} @"??_C@_
+// CIR-DAG: cir.func {{.*}} @"?simple_method@MethodsTest@@QEAAXXZ"(%{{.*}}: 
!cir.ptr<!rec_MethodsTest>
+// CIR-DAG: cir.func {{.*}} 
@"?vararg_method@MethodsTest@@QEAAXPEBDZZ"(%{{.*}}: 
!cir.ptr<!rec_MethodsTest>{{.*}}, %{{.*}}: !cir.ptr<!s8i>{{.*}}, ...)
+// CIR-DAG: cir.func {{.*}} @"?static_method@MethodsTest@@SAXXZ"()
+
+//===----------------------------------------------------------------------===//
+// Section 2: Structors and 'this' Return Calling Convention
+//===----------------------------------------------------------------------===//
+
+class BasicA {
+  int x;
+public:
+  BasicA() { x = 42; }
+};
+
+void test_basic() {
+  BasicA a;
+}
+
+// In the MSVC ABI, constructors return 'this' (hasThisReturn is true).
+// CIR-LABEL: cir.func {{.*}} @"??0BasicA@@QEAA@XZ"
+// CIR-SAME: (%[[THIS_ARG:.*]]: !cir.ptr<!rec_BasicA>{{.*}}) -> 
(!cir.ptr<!rec_BasicA>
+// CIR:   %[[RETVAL:.*]] = cir.alloca "__retval"
+// CIR:   %[[THIS_ALLOCA:.*]] = cir.alloca "this"
+// CIR:   cir.store %[[THIS_ARG]], %[[THIS_ALLOCA]]
+// CIR:   %[[LOADED_THIS:.*]] = cir.load %[[THIS_ALLOCA]]
+// CIR:   cir.store {{.*}}%[[LOADED_THIS]], %[[RETVAL]]
+// CIR:   cir.const #cir.int<42>
+// CIR:   %[[LOADED_RET:.*]] = cir.load %[[RETVAL]]
+// CIR:   cir.return %[[LOADED_RET]] : !cir.ptr<!rec_BasicA>
+// CIR: }
+
+// Constructor & Destructor Inheritance chain:
+class Base {
+public:
+  Base();
+};
+
+class Derived : public Base {
+public:
+  Derived();
+};
+
+Derived::Derived() {}
+
+// Derived ctor calls Base ctor and returns this:
+// CIR-LABEL: cir.func {{.*}} @"??0Derived@@QEAA@XZ"
+// CIR-SAME: (%[[THIS:.*]]: !cir.ptr<!rec_Derived>{{.*}}) -> 
(!cir.ptr<!rec_Derived>
+// CIR:   cir.call @"??0Base@@QEAA@XZ"
+// CIR:   cir.return %{{.*}} : !cir.ptr<!rec_Derived>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to