diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-11-01 01:34:46 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-11-01 01:34:46 +0000 |
commit | ea6bc23d769d33e366a94601496b86d86edb2857 (patch) | |
tree | e29eb82e9ef8900f2521ff36b326527221c6fe5b /lib/CodeGen/ItaniumCXXABI.cpp | |
parent | b3524deb09dbcaaa5cfec24b4fb447ae906a6d50 (diff) |
Implement ABI proposal for throwing noexcept function pointers, per discussion
on cxx-abi-dev (thread starting 2016-10-11). This is currently hidden behind a
cc1-only -m flag, pending discussion of how best to deal with language changes
that require use of new symbols from the ABI library.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285664 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 113 |
1 files changed, 109 insertions, 4 deletions
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 29261fd4b3..b54dd365b0 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -46,6 +46,7 @@ protected: bool UseARMMethodPtrABI; bool UseARMGuardVarABI; bool Use32BitVTableOffsetABI; + bool UseQualifiedFunctionTypeInfoABI; ItaniumMangleContext &getMangleContext() { return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext()); @@ -57,7 +58,8 @@ public: bool UseARMGuardVarABI = false) : CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI), UseARMGuardVarABI(UseARMGuardVarABI), - Use32BitVTableOffsetABI(false) { } + Use32BitVTableOffsetABI(false), + UseQualifiedFunctionTypeInfoABI(CGM.getCodeGenOpts().QualifiedFunctionTypeInfo) { } bool classifyReturnType(CGFunctionInfo &FI) const override; @@ -2427,6 +2429,9 @@ class ItaniumRTTIBuilder { /// descriptor of the given type. llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); + /// Determine whether FnTy should be emitted as a qualified function type. + bool EmitAsQualifiedFunctionType(const FunctionType *FnTy); + /// BuildVTablePointer - Build the vtable pointer for the given type. void BuildVTablePointer(const Type *Ty); @@ -2439,6 +2444,10 @@ class ItaniumRTTIBuilder { /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c. void BuildVMIClassTypeInfo(const CXXRecordDecl *RD); + /// Build an abi::__qualified_function_type_info struct, used for function + /// types with various kinds of qualifiers. + void BuildQualifiedFunctionTypeInfo(const FunctionType *FnTy); + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used /// for pointer types. void BuildPointerTypeInfo(QualType PointeeTy); @@ -2455,6 +2464,27 @@ public: ItaniumRTTIBuilder(const ItaniumCXXABI &ABI) : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {} + // Function type info flags. + enum { + /// Qualifiers for 'this' pointer of member function type. + //@{ + QFTI_Const = 0x1, + QFTI_Volatile = 0x2, + QFTI_Restrict = 0x4, + QFTI_LValRef = 0x8, + QFTI_RValRef = 0x10, + //@} + + /// Noexcept function qualifier (C++17 onwards). + QFTI_Noexcept = 0x20, + + // Transaction-safe function qualifier (Transactional Memory TS). + //QFTI_TxSafe = 0x40, + + /// Noreturn function type qualifier (GNU/Clang extension). + QFTI_Noreturn = 0x80 + }; + // Pointer type info flags. enum { /// PTI_Const - Type has const qualifier. @@ -2806,8 +2836,12 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { case Type::FunctionNoProto: case Type::FunctionProto: - // abi::__function_type_info. - VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; + if (EmitAsQualifiedFunctionType(cast<FunctionType>(Ty))) + // abi::__qualified_function_type_info. + VTableName = "_ZTVN10__cxxabiv130__qualified_function_type_infoE"; + else + // abi::__function_type_info. + VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; break; case Type::Enum: @@ -3021,10 +3055,15 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force, break; case Type::FunctionNoProto: - case Type::FunctionProto: + case Type::FunctionProto: { + auto *FnTy = cast<FunctionType>(Ty); // Itanium C++ ABI 2.9.5p5: // abi::__function_type_info adds no data members to std::type_info. + if (EmitAsQualifiedFunctionType(FnTy)) + // abi::__qualified_type_info adds a base function type and qualifiers. + BuildQualifiedFunctionTypeInfo(FnTy); break; + } case Type::Enum: // Itanium C++ ABI 2.9.5p5: @@ -3319,6 +3358,72 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { } } +bool ItaniumRTTIBuilder::EmitAsQualifiedFunctionType(const FunctionType *FnTy) { + if (!CXXABI.UseQualifiedFunctionTypeInfoABI) + return false; + + auto *FPT = dyn_cast<FunctionProtoType>(FnTy); + if (!FPT) + return false; + return FPT->getTypeQuals() || FPT->getRefQualifier() != RQ_None || + FPT->isNothrow(CXXABI.getContext()) || FPT->getNoReturnAttr(); +} + +void ItaniumRTTIBuilder::BuildQualifiedFunctionTypeInfo( + const FunctionType *FnTy) { + unsigned int Qualifiers = 0; + + auto ExtInfo = FnTy->getExtInfo(); + if (ExtInfo.getNoReturn()) { + Qualifiers |= QFTI_Noreturn; + ExtInfo = ExtInfo.withNoReturn(false); + } + + QualType BaseType; + if (auto *FPT = dyn_cast<FunctionProtoType>(FnTy)) { + auto EPI = FPT->getExtProtoInfo(); + EPI.ExtInfo = ExtInfo; + + if (EPI.TypeQuals & Qualifiers::Const) + Qualifiers |= QFTI_Const; + if (EPI.TypeQuals & Qualifiers::Volatile) + Qualifiers |= QFTI_Volatile; + if (EPI.TypeQuals & Qualifiers::Restrict) + Qualifiers |= QFTI_Restrict; + EPI.TypeQuals = 0; + + if (EPI.RefQualifier == RQ_LValue) + Qualifiers |= QFTI_LValRef; + else if (EPI.RefQualifier == RQ_RValue) + Qualifiers |= QFTI_RValRef; + EPI.RefQualifier = RQ_None; + + if (EPI.ExceptionSpec.Type == EST_BasicNoexcept) + Qualifiers |= QFTI_Noexcept; + else + assert(EPI.ExceptionSpec.Type == EST_None && + "unexpected canonical non-dependent exception spec"); + EPI.ExceptionSpec.Type = EST_None; + + BaseType = CXXABI.getContext().getFunctionType(FPT->getReturnType(), + FPT->getParamTypes(), EPI); + } else { + BaseType = + QualType(CXXABI.getContext().adjustFunctionType(FnTy, ExtInfo), 0); + } + + assert(Qualifiers && "should not have created qualified type info"); + + // __base_type is a pointer to the std::type_info derivation for the + // unqualified version of the function type. + Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(BaseType)); + + // __qualifiers is a flag word describing the qualifiers of the function type. + llvm::Type *UnsignedIntLTy = + CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Qualifiers)); +} + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, /// used for pointer types. void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { |