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);
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);
FD = PrimaryTemplate->getTemplatedDecl();
}
- mangleBareFunctionType(FD->getType()->getAs<FunctionType>(),
+ mangleBareFunctionType(FD->getType()->castAs<FunctionProtoType>(),
MangleReturnType, FD);
}
}
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:
//
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:
//
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:
// 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) {
}
}
+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()));
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();
// <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();
}
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) {
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)
// 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)
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 { };