r262414 - Mangle extended qualifiers in the proper order and mangle the

John McCall via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 1 14:18:04 PST 2016


Author: rjmccall
Date: Tue Mar  1 16:18:03 2016
New Revision: 262414

URL: http://llvm.org/viewvc/llvm-project?rev=262414&view=rev
Log:
Mangle extended qualifiers in the proper order and mangle the
ARC ownership-convention function type modifications.

According to the Itanium ABI, vendor extended qualifiers are
supposed to be mangled in reverse-alphabetical order before
any CVR qualifiers.  The ARC function type conventions are
plausibly order-significant (they are associated with the
function type), which permits us to ignore the need to correctly
inter-order them with any other vendor qualifiers on the parameter
and return types.

Implementing these rules correctly is technically an ABI break.
Apple is comfortable with the risk of incompatibility here for
the ARC features, and I believe that address-space qualification
is still uncommon enough to allow us to adopt the conforming
rule without serious risk.  Still, targets which make heavy
use of address space qualification may want to revert to the
non-conforming order.

Modified:
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/test/CodeGenCXX/mangle-address-space.cpp
    cfe/trunk/test/CodeGenObjCXX/arc-attrs.mm
    cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm
    cfe/trunk/test/CodeGenObjCXX/arc-move.mm

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=262414&r1=262413&r2=262414&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Mar  1 16:18:03 2016
@@ -364,6 +364,7 @@ private:
                                       StringRef Prefix = "");
   void mangleOperatorName(DeclarationName Name, unsigned Arity);
   void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
+  void mangleVendorQualifier(StringRef qualifier);
   void mangleQualifiers(Qualifiers Quals);
   void mangleRefQualifier(RefQualifierKind RefQualifier);
 
@@ -377,7 +378,10 @@ private:
 
   void mangleType(const TagType*);
   void mangleType(TemplateName);
-  void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType,
+  static StringRef getCallingConvQualifierName(CallingConv CC);
+  void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info);
+  void mangleExtFunctionInfo(const FunctionType *T);
+  void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
                               const FunctionDecl *FD = nullptr);
   void mangleNeonVectorType(const VectorType *T);
   void mangleAArch64NeonVectorType(const VectorType *T);
@@ -523,7 +527,7 @@ void CXXNameMangler::mangleFunctionEncod
     FD = PrimaryTemplate->getTemplatedDecl();
   }
 
-  mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), 
+  mangleBareFunctionType(FD->getType()->castAs<FunctionProtoType>(),
                          MangleReturnType, FD);
 }
 
@@ -1767,14 +1771,9 @@ CXXNameMangler::mangleOperatorName(Overl
 }
 
 void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
-  // <CV-qualifiers> ::= [r] [V] [K]    # restrict (C99), volatile, const
-  if (Quals.hasRestrict())
-    Out << 'r';
-  if (Quals.hasVolatile())
-    Out << 'V';
-  if (Quals.hasConst())
-    Out << 'K';
+  // Vendor qualifiers come first.
 
+  // Address space qualifiers start with an ordinary letter.
   if (Quals.hasAddressSpace()) {
     // Address space extension:
     //
@@ -1802,10 +1801,10 @@ void CXXNameMangler::mangleQualifiers(Qu
       case LangAS::cuda_shared:     ASString = "CUshared";   break;
       }
     }
-    Out << 'U' << ASString.size() << ASString;
+    mangleVendorQualifier(ASString);
   }
-  
-  StringRef LifetimeName;
+
+  // The ARC ownership qualifiers start with underscores.
   switch (Quals.getObjCLifetime()) {
   // Objective-C ARC Extension:
   //
@@ -1816,15 +1815,15 @@ void CXXNameMangler::mangleQualifiers(Qu
     break;
     
   case Qualifiers::OCL_Weak:
-    LifetimeName = "__weak";
+    mangleVendorQualifier("__weak");
     break;
     
   case Qualifiers::OCL_Strong:
-    LifetimeName = "__strong";
+    mangleVendorQualifier("__strong");
     break;
     
   case Qualifiers::OCL_Autoreleasing:
-    LifetimeName = "__autoreleasing";
+    mangleVendorQualifier("__autoreleasing");
     break;
     
   case Qualifiers::OCL_ExplicitNone:
@@ -1837,8 +1836,18 @@ void CXXNameMangler::mangleQualifiers(Qu
     // in any type signatures that need to be mangled.
     break;
   }
-  if (!LifetimeName.empty())
-    Out << 'U' << LifetimeName.size() << LifetimeName;
+
+  // <CV-qualifiers> ::= [r] [V] [K]    # restrict (C99), volatile, const
+  if (Quals.hasRestrict())
+    Out << 'r';
+  if (Quals.hasVolatile())
+    Out << 'V';
+  if (Quals.hasConst())
+    Out << 'K';
+}
+
+void CXXNameMangler::mangleVendorQualifier(StringRef name) {
+  Out << 'U' << name.size() << name;
 }
 
 void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
@@ -2137,10 +2146,63 @@ void CXXNameMangler::mangleType(const Bu
   }
 }
 
+StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
+  switch (CC) {
+  case CC_C:
+    return "";
+
+  case CC_X86StdCall:
+  case CC_X86FastCall:
+  case CC_X86ThisCall:
+  case CC_X86VectorCall:
+  case CC_X86Pascal:
+  case CC_X86_64Win64:
+  case CC_X86_64SysV:
+  case CC_AAPCS:
+  case CC_AAPCS_VFP:
+  case CC_IntelOclBicc:
+  case CC_SpirFunction:
+  case CC_SpirKernel:
+    // FIXME: we should be mangling all of the above.
+    return "";
+  }
+  llvm_unreachable("bad calling convention");
+}
+
+void CXXNameMangler::mangleExtFunctionInfo(const FunctionType *T) {
+  // Fast path.
+  if (T->getExtInfo() == FunctionType::ExtInfo())
+    return;
+
+  // Vendor-specific qualifiers are emitted in reverse alphabetical order.
+  // This will get more complicated in the future if we mangle other
+  // things here; but for now, since we mangle ns_returns_retained as
+  // a qualifier on the result type, we can get away with this:
+  StringRef CCQualifier = getCallingConvQualifierName(T->getExtInfo().getCC());
+  if (!CCQualifier.empty())
+    mangleVendorQualifier(CCQualifier);
+
+  // FIXME: regparm
+  // FIXME: noreturn
+}
+
+void
+CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
+  // Vendor-specific qualifiers are emitted in reverse alphabetical order.
+
+  // Note that these are *not* substitution candidates.  Demanglers might
+  // have trouble with this if the parameter type is fully substituted.
+
+  if (PI.isConsumed())
+    Out << "U11ns_consumed";
+}
+
 // <type>          ::= <function-type>
 // <function-type> ::= [<CV-qualifiers>] F [Y]
 //                      <bare-function-type> [<ref-qualifier>] E
 void CXXNameMangler::mangleType(const FunctionProtoType *T) {
+  mangleExtFunctionInfo(T);
+
   // Mangle CV-qualifiers, if present.  These are 'this' qualifiers,
   // e.g. "const" in "int (A::*)() const".
   mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals()));
@@ -2173,12 +2235,9 @@ void CXXNameMangler::mangleType(const Fu
   Out << 'E';
 }
 
-void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
+void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,
                                             bool MangleReturnType,
                                             const FunctionDecl *FD) {
-  // We should never be mangling something without a prototype.
-  const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
-
   // Record that we're in a function type.  See mangleFunctionParam
   // for details on what we're trying to achieve here.
   FunctionTypeDepthState saved = FunctionTypeDepth.push();
@@ -2186,7 +2245,20 @@ void CXXNameMangler::mangleBareFunctionT
   // <bare-function-type> ::= <signature type>+
   if (MangleReturnType) {
     FunctionTypeDepth.enterResultType();
-    mangleType(Proto->getReturnType());
+
+    // Mangle ns_returns_retained as an order-sensitive qualifier here.
+    if (Proto->getExtInfo().getProducesResult())
+      mangleVendorQualifier("ns_returns_retained");
+
+    // Mangle the return type without any direct ARC ownership qualifiers.
+    QualType ReturnTy = Proto->getReturnType();
+    if (ReturnTy.getObjCLifetime()) {
+      auto SplitReturnTy = ReturnTy.split();
+      SplitReturnTy.Quals.removeObjCLifetime();
+      ReturnTy = getASTContext().getQualifiedType(SplitReturnTy);
+    }
+    mangleType(ReturnTy);
+
     FunctionTypeDepth.leaveResultType();
   }
 
@@ -2200,7 +2272,13 @@ void CXXNameMangler::mangleBareFunctionT
 
   assert(!FD || FD->getNumParams() == Proto->getNumParams());
   for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) {
-    const auto &ParamTy = Proto->getParamType(I);
+    // Mangle extended parameter info as order-sensitive qualifiers here.
+    if (Proto->hasExtParameterInfos()) {
+      mangleExtParameterInfo(Proto->getExtParameterInfo(I));
+    }
+
+    // Mangle the type.
+    QualType ParamTy = Proto->getParamType(I);
     mangleType(Context.getASTContext().getSignatureParameterType(ParamTy));
 
     if (FD) {

Modified: cfe/trunk/test/CodeGenCXX/mangle-address-space.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-address-space.cpp?rev=262414&r1=262413&r2=262414&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-address-space.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-address-space.cpp Tue Mar  1 16:18:03 2016
@@ -10,3 +10,6 @@ typedef OpaqueType __attribute__((addres
 
 // CHECK-LABEL: define {{.*}}void @_Z2f0PU5AS10010OpaqueType
 void f0(OpaqueTypePtr) { }
+
+// CHECK-LABEL: define {{.*}}void @_Z2f1PU3AS1Kc
+void f1(char __attribute__((address_space(1))) const *p) {}
\ No newline at end of file

Modified: cfe/trunk/test/CodeGenObjCXX/arc-attrs.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-attrs.mm?rev=262414&r1=262413&r2=262414&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/arc-attrs.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/arc-attrs.mm Tue Mar  1 16:18:03 2016
@@ -12,7 +12,7 @@ void sanityTest() {
   id x = makeObject1();
 
   // CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z11makeObject2v()
-  // CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]])
+  // CHECK-NEXT: call void @_Z13releaseObjectU11ns_consumedP11objc_object(i8* [[OBJ2]])
   releaseObject(makeObject2());
 
   // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
@@ -31,16 +31,16 @@ void releaseObjectT(__attribute__((ns_co
 // CHECK-LABEL: define void @_Z12templateTestv
 void templateTest() {
   // CHECK: [[X:%.*]] = alloca i8*, align 8
-  // CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z12makeObjectT1IU8__strongP11objc_objectET_v()
+  // CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z12makeObjectT1IU8__strongP11objc_objectEU19ns_returns_retainedT_v()
   // CHECK-NEXT: store i8* [[OBJ1]], i8** [[X]], align 8
   id x = makeObjectT1<id>();
 
-  // CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z12makeObjectT2IU8__strongP11objc_objectET_v()
-  // CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]])
+  // CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z12makeObjectT2IU8__strongP11objc_objectEU19ns_returns_retainedT_v()
+  // CHECK-NEXT: call void @_Z13releaseObjectU11ns_consumedP11objc_object(i8* [[OBJ2]])
   releaseObject(makeObjectT2<id>());
 
   // CHECK-NEXT: [[OBJ3:%.*]] = call i8* @_Z11makeObject1v()
-  // CHECK-NEXT: call void @_Z14releaseObjectTIU8__strongP11objc_objectEvT_(i8* [[OBJ3]])
+  // CHECK-NEXT: call void @_Z14releaseObjectTIU8__strongP11objc_objectEvU11ns_consumedT_(i8* [[OBJ3]])
   releaseObjectT(makeObject1());
 
   // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)

Modified: cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm?rev=262414&r1=262413&r2=262414&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm Tue Mar  1 16:18:03 2016
@@ -8,15 +8,20 @@ void f(__weak id *) {}
 void f(__autoreleasing id *) {}
 // CHECK-LABEL: define {{.*}}void @_Z1fPP11objc_object(i8**)
 void f(__unsafe_unretained id *) {}
-// CHECK-LABEL: define {{.*}}void @_Z1fPKU8__strongP11objc_object(i8**)
+// CHECK-LABEL: define {{.*}}void @_Z1fPU8__strongKP11objc_object(i8**)
 void f(const __strong id *) {}
-// CHECK-LABEL: define {{.*}}void @_Z1fPKU6__weakP11objc_object(i8**)
+// CHECK-LABEL: define {{.*}}void @_Z1fPU6__weakKP11objc_object(i8**)
 void f(const __weak id *) {}
-// CHECK-LABEL: define {{.*}}void @_Z1fPKU15__autoreleasingP11objc_object(i8**)
+// CHECK-LABEL: define {{.*}}void @_Z1fPU15__autoreleasingKP11objc_object(i8**)
 void f(const __autoreleasing id *) {}
 // CHECK-LABEL: define {{.*}}void @_Z1fPKP11objc_object(i8**)
 void f(const __unsafe_unretained id *) {}
-
+// CHECK-LABEL: define {{.*}}void @_Z1fPFU19ns_returns_retainedP11objc_objectvE
+void f(__attribute__((ns_returns_retained)) id (*fn)()) {}
+// CHECK-LABEL: define {{.*}}void @_Z1fPFP11objc_objectU11ns_consumedS0_S0_E
+void f(id (*fn)(__attribute__((ns_consumed)) id, id)) {}
+// CHECK-LABEL: define {{.*}}void @_Z1fPFP11objc_objectS0_U11ns_consumedS0_E
+void f(__strong id (*fn)(id, __attribute__((ns_consumed)) id)) {}
 
 template<unsigned N> struct unsigned_c { };
 

Modified: cfe/trunk/test/CodeGenObjCXX/arc-move.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-move.mm?rev=262414&r1=262413&r2=262414&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/arc-move.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/arc-move.mm Tue Mar  1 16:18:03 2016
@@ -72,10 +72,10 @@ void library_move(__strong id &y) {
   // CHECK-NEXT: ret void
 }
 
-// CHECK-LABEL: define void @_Z10const_moveRKU8__strongP11objc_object(
+// CHECK-LABEL: define void @_Z10const_moveRU8__strongKP11objc_object(
 void const_move(const __strong id &x) {
   // CHECK:      [[Y:%.*]] = alloca i8*,
-  // CHECK:      [[X:%.*]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRKU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_(
+  // CHECK:      [[X:%.*]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongKP11objc_objectEON16remove_referenceIT_E4typeEOS5_(
   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
   // CHECK-NEXT: store i8* [[T1]], i8** [[Y]]




More information about the cfe-commits mailing list