r232538 - MS ABI: Emit HandlerMap entries for C++ catch

David Majnemer david.majnemer at gmail.com
Tue Mar 17 13:35:05 PDT 2015


Author: majnemer
Date: Tue Mar 17 15:35:05 2015
New Revision: 232538

URL: http://llvm.org/viewvc/llvm-project?rev=232538&view=rev
Log:
MS ABI: Emit HandlerMap entries for C++ catch

The HandlerMap describes, to the runtime, what sort of catches surround
the try.  In principle, this structure has to be emitted by the backend
because only it knows the layout of the stack (the runtime needs to know
where on the stack the destination of a copy lives, etc.) but there is
some C++ specific information that the backend can't reason about.

Stick this information in special LLVM globals with the relevant
"const", "volatile", "reference" info mangled into the name.

Modified:
    cfe/trunk/include/clang/AST/Mangle.h
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGException.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp

Modified: cfe/trunk/include/clang/AST/Mangle.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Mangle.h (original)
+++ cfe/trunk/include/clang/AST/Mangle.h Tue Mar 17 15:35:05 2015
@@ -208,6 +208,10 @@ public:
                                       uint32_t NVOffset, int32_t VBPtrOffset,
                                       uint32_t VBIndex, raw_ostream &Out) = 0;
 
+  virtual void mangleCXXHandlerMapEntry(QualType T, bool IsConst,
+                                        bool IsVolatile, bool IsReference,
+                                        raw_ostream &Out) = 0;
+
   virtual void mangleCXXRTTIBaseClassDescriptor(
       const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
       uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Tue Mar 17 15:35:05 2015
@@ -122,6 +122,8 @@ public:
                               CXXCtorType CT, uint32_t Size, uint32_t NVOffset,
                               int32_t VBPtrOffset, uint32_t VBIndex,
                               raw_ostream &Out) override;
+  void mangleCXXHandlerMapEntry(QualType T, bool IsConst, bool IsVolatile,
+                                bool IsReference, raw_ostream &Out);
   void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
   void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
   void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
@@ -2339,6 +2341,22 @@ void MicrosoftMangleContextImpl::mangleC
   Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
 }
 
+void MicrosoftMangleContextImpl::mangleCXXHandlerMapEntry(QualType T,
+                                                          bool IsConst,
+                                                          bool IsVolatile,
+                                                          bool IsReference,
+                                                          raw_ostream &Out) {
+  MicrosoftCXXNameMangler Mangler(*this, Out);
+  Mangler.getStream() << "llvm.eh.handlermapentry.";
+  if (IsConst)
+    Mangler.getStream() << "const.";
+  if (IsVolatile)
+    Mangler.getStream() << "volatile.";
+  if (IsReference)
+    Mangler.getStream() << "reference.";
+  Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+}
+
 void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T,
                                                     bool IsConst,
                                                     bool IsVolatile,

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue Mar 17 15:35:05 2015
@@ -225,7 +225,8 @@ public:
                                       llvm::Value *Exn);
 
   virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0;
-  virtual llvm::Constant *getAddrOfCXXCatchDescriptor(QualType Ty) = 0;
+  virtual llvm::Constant *
+  getAddrOfCXXHandlerMapEntry(QualType Ty, QualType CatchHandlerType) = 0;
 
   virtual bool shouldTypeidBeNullChecked(bool IsDeref,
                                          QualType SrcRecordTy) = 0;

Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Tue Mar 17 15:35:05 2015
@@ -567,7 +567,8 @@ void CodeGenFunction::EnterCXXTryStmt(co
       if (CaughtType->isObjCObjectPointerType())
         TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
       else
-        TypeInfo = CGM.getAddrOfCXXCatchDescriptor(CaughtType);
+        TypeInfo =
+            CGM.getAddrOfCXXHandlerMapEntry(CaughtType, C->getCaughtType());
       CatchScope->setHandler(I, TypeInfo, Handler);
     } else {
       // No exception decl indicates '...', a catch-all.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Mar 17 15:35:05 2015
@@ -3644,8 +3644,10 @@ llvm::Constant *CodeGenModule::EmitUuido
   return llvm::ConstantStruct::getAnon(Fields);
 }
 
-llvm::Constant *CodeGenModule::getAddrOfCXXCatchDescriptor(QualType Ty) {
-  return getCXXABI().getAddrOfCXXCatchDescriptor(Ty);
+llvm::Constant *
+CodeGenModule::getAddrOfCXXHandlerMapEntry(QualType Ty,
+                                           QualType CatchHandlerType) {
+  return getCXXABI().getAddrOfCXXHandlerMapEntry(Ty, CatchHandlerType);
 }
 
 llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Mar 17 15:35:05 2015
@@ -719,7 +719,8 @@ public:
   /// Get the address of the RTTI descriptor for the given type.
   llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
 
-  llvm::Constant *getAddrOfCXXCatchDescriptor(QualType Ty);
+  llvm::Constant *getAddrOfCXXHandlerMapEntry(QualType Ty,
+                                              QualType CatchHandlerType);
 
   /// Get the address of a uuid descriptor .
   llvm::Constant *GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Mar 17 15:35:05 2015
@@ -126,7 +126,8 @@ public:
   void EmitFundamentalRTTIDescriptor(QualType Type);
   void EmitFundamentalRTTIDescriptors();
   llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
-  llvm::Constant *getAddrOfCXXCatchDescriptor(QualType Ty) {
+  llvm::Constant *getAddrOfCXXHandlerMapEntry(QualType Ty,
+                                              QualType CatchHandlerType) {
     return getAddrOfRTTIDescriptor(Ty);
   }
 

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Mar 17 15:35:05 2015
@@ -45,7 +45,7 @@ public:
       : CGCXXABI(CGM), BaseClassDescriptorType(nullptr),
         ClassHierarchyDescriptorType(nullptr),
         CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr),
-        ThrowInfoType(nullptr) {}
+        ThrowInfoType(nullptr), HandlerMapEntryType(nullptr) {}
 
   bool HasThisReturn(GlobalDecl GD) const override;
   bool hasMostDerivedReturn(GlobalDecl GD) const override;
@@ -84,7 +84,8 @@ public:
                                                    const VPtrInfo *Info);
 
   llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
-  llvm::Constant *getAddrOfCXXCatchDescriptor(QualType Ty) override;
+  llvm::Constant *
+  getAddrOfCXXHandlerMapEntry(QualType Ty, QualType CatchHandlerType) override;
 
   bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
   void EmitBadTypeidCall(CodeGenFunction &CGF) override;
@@ -572,6 +573,18 @@ public:
 
   void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
 
+  llvm::StructType *getHandlerMapEntryType() {
+    if (!HandlerMapEntryType) {
+      llvm::Type *FieldTypes[] = {
+        CGM.IntTy,                           // Flags
+        getImageRelativeType(CGM.Int8PtrTy), // TypeDescriptor
+      };
+      HandlerMapEntryType = llvm::StructType::create(
+          CGM.getLLVMContext(), FieldTypes, "eh.HandlerMapEntry");
+    }
+    return HandlerMapEntryType;
+  }
+
   llvm::StructType *getCatchableTypeType() {
     if (CatchableTypeType)
       return CatchableTypeType;
@@ -685,6 +698,7 @@ private:
   llvm::StructType *CatchableTypeType;
   llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
   llvm::StructType *ThrowInfoType;
+  llvm::StructType *HandlerMapEntryType;
 };
 
 }
@@ -3186,14 +3200,48 @@ static QualType decomposeTypeForEH(ASTCo
   return T;
 }
 
-llvm::Constant *MicrosoftCXXABI::getAddrOfCXXCatchDescriptor(QualType Type) {
-  // TypeDescriptors for exceptions never has qualified pointer types,
+llvm::Constant *
+MicrosoftCXXABI::getAddrOfCXXHandlerMapEntry(QualType Type,
+                                             QualType CatchHandlerType) {
+  // TypeDescriptors for exceptions never have qualified pointer types,
   // qualifiers are stored seperately in order to support qualification
   // conversions.
   bool IsConst, IsVolatile;
   Type = decomposeTypeForEH(getContext(), Type, IsConst, IsVolatile);
 
-  return getAddrOfRTTIDescriptor(Type);
+  bool IsReference = CatchHandlerType->isReferenceType();
+
+  SmallString<256> MangledName;
+  {
+    llvm::raw_svector_ostream Out(MangledName);
+    getMangleContext().mangleCXXHandlerMapEntry(Type, IsConst, IsVolatile,
+                                                IsReference, Out);
+  }
+
+  if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
+    return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+
+  uint32_t Flags = 0;
+  if (IsConst)
+    Flags |= 1;
+  if (IsVolatile)
+    Flags |= 2;
+  if (IsReference)
+    Flags |= 8;
+
+  llvm::Constant *Fields[] = {
+      llvm::ConstantInt::get(CGM.IntTy, Flags),                // Flags
+      getImageRelativeConstant(getAddrOfRTTIDescriptor(Type)), // TypeDescriptor
+  };
+  llvm::StructType *HandlerMapEntryType = getHandlerMapEntryType();
+  auto *Var = new llvm::GlobalVariable(
+      CGM.getModule(), HandlerMapEntryType, /*Constant=*/true,
+      llvm::GlobalValue::PrivateLinkage,
+      llvm::ConstantStruct::get(HandlerMapEntryType, Fields),
+      StringRef(MangledName));
+  Var->setUnnamedAddr(true);
+  Var->setSection("llvm.metadata");
+  return Var;
 }
 
 /// \brief Gets a TypeDescriptor.  Returns a llvm::Constant * rather than a
@@ -3201,7 +3249,7 @@ llvm::Constant *MicrosoftCXXABI::getAddr
 /// types, and need to be abstracted.  They are abstracting by casting the
 /// address to an Int8PtrTy.
 llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
-  SmallString<256> MangledName, TypeInfoString;
+  SmallString<256> MangledName;
   {
     llvm::raw_svector_ostream Out(MangledName);
     getMangleContext().mangleCXXRTTI(Type, Out);
@@ -3212,6 +3260,7 @@ llvm::Constant *MicrosoftCXXABI::getAddr
     return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
 
   // Compute the fields for the TypeDescriptor.
+  SmallString<256> TypeInfoString;
   {
     llvm::raw_svector_ostream Out(TypeInfoString);
     getMangleContext().mangleCXXRTTIName(Type, Out);

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp?rev=232538&r1=232537&r2=232538&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp Tue Mar 17 15:35:05 2015
@@ -6,6 +6,8 @@
 // THROW-DAG: @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0H at 84"] }, section ".xdata", comdat
 // THROW-DAG: @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1H to i8*) }, section ".xdata", comdat
 
+// TRY-DAG: @llvm.eh.handlermapentry.const.PAH = private unnamed_addr constant %eh.HandlerMapEntry { i32 1, i8* bitcast (%rtti.TypeDescriptor4* @"\01??_R0PAH at 8" to i8*) }, section "llvm.metadata"
+
 void external();
 
 inline void not_emitted() {
@@ -39,7 +41,7 @@ void qual_catch() {
     external();
   } catch (const int *) {
   }
-  // TRY: catch i8* bitcast (%rtti.TypeDescriptor4* @"\01??_R0PAH at 8" to i8*)
-  // TRY: call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor4* @"\01??_R0PAH at 8" to i8*))
+  // TRY: catch %eh.HandlerMapEntry* @llvm.eh.handlermapentry.const.PAH
+  // TRY: call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry.const.PAH to i8*))
 }
 #endif





More information about the cfe-commits mailing list