Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -2355,6 +2355,12 @@ /// If \p T is null pointer, assume the target in ASTContext. MangleContext *createMangleContext(const TargetInfo *T = nullptr); + /// Creates a device mangle context to correctly mangle lambdas in a mixed + /// architecture compile by setting the lambda mangling number source to the + /// DeviceLambdaManglingNumber. Currently this asserts that the TargetInfo + /// (from the AuxTargetInfo) is a an itanium target. + MangleContext *createDeviceMangleContext(const TargetInfo &T); + void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, SmallVectorImpl &Ivars) const; Index: clang/include/clang/AST/Mangle.h =================================================================== --- clang/include/clang/AST/Mangle.h +++ clang/include/clang/AST/Mangle.h @@ -107,9 +107,6 @@ virtual bool shouldMangleCXXName(const NamedDecl *D) = 0; virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0; - virtual bool isDeviceMangleContext() const { return false; } - virtual void setDeviceMangleContext(bool) {} - virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) { return false; } @@ -173,10 +170,8 @@ class ItaniumMangleContext : public MangleContext { public: - using ShouldCallKernelCallbackTy = bool (*)(ASTContext &, - const CXXRecordDecl *); - using KernelMangleCallbackTy = void (*)(ASTContext &, const CXXRecordDecl *, - raw_ostream &); + using KernelMangleCallbackTy = + llvm::Optional (*)(ASTContext &, const CXXRecordDecl *); explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D) : MangleContext(C, D, MK_Itanium) {} @@ -199,21 +194,19 @@ virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0; - // These have to live here, otherwise the CXXNameMangler won't have access to - // them. - virtual ShouldCallKernelCallbackTy getShouldCallKernelCallback() const = 0; - virtual KernelMangleCallbackTy getKernelMangleCallback() const = 0; + // This has to live here, otherwise the CXXNameMangler won't have access to + // it. + virtual KernelMangleCallbackTy getKernelMangleCallback() const = 0; static bool classof(const MangleContext *C) { return C->getKind() == MK_Itanium; } static ItaniumMangleContext *create(ASTContext &Context, DiagnosticsEngine &Diags); - static ItaniumMangleContext * - create(ASTContext &Context, DiagnosticsEngine &Diags, - ShouldCallKernelCallbackTy ShouldKernelMangleCB, - KernelMangleCallbackTy KernelMangleCB); + static ItaniumMangleContext *create(ASTContext &Context, + DiagnosticsEngine &Diags, + KernelMangleCallbackTy KernelMangleCB); }; class MicrosoftMangleContext : public MangleContext { Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -2458,7 +2458,7 @@ // The preferred alignment of member pointers is that of a pointer. if (T->isMemberPointerType()) return getPreferredTypeAlign(getPointerDiffType().getTypePtr()); - + if (!Target->allowsLargerPreferedTypeAlignment()) return ABIAlign; @@ -11075,6 +11075,31 @@ llvm_unreachable("Unsupported ABI"); } +MangleContext *ASTContext::createDeviceMangleContext(const TargetInfo &T) { + assert(T.getCXXABI().getKind() != TargetCXXABI::Microsoft && + "Device mangle context does not support Microsoft mangling."); + switch (T.getCXXABI().getKind()) { + case TargetCXXABI::AppleARM64: + case TargetCXXABI::Fuchsia: + case TargetCXXABI::GenericAArch64: + case TargetCXXABI::GenericItanium: + case TargetCXXABI::GenericARM: + case TargetCXXABI::GenericMIPS: + case TargetCXXABI::iOS: + case TargetCXXABI::WebAssembly: + case TargetCXXABI::WatchOS: + case TargetCXXABI::XL: + return ItaniumMangleContext::create( + *this, getDiagnostics(), + [](ASTContext &, const CXXRecordDecl *RD) -> llvm::Optional { + return RD->getDeviceLambdaManglingNumber(); + }); + case TargetCXXABI::Microsoft: + return MicrosoftMangleContext::create(*this, getDiagnostics()); + } + llvm_unreachable("Unsupported ABI"); +} + CXXABI::~CXXABI() = default; size_t ASTContext::getSideTableAllocatedMemory() const { Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -546,12 +546,8 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context, QualType Ty) { - auto ShouldMangleCallback = [](ASTContext &Ctx, const CXXRecordDecl *RD) { - return Ctx.IsSYCLKernelNamingDecl(RD); - }; - auto MangleCallback = [](ASTContext &Ctx, const CXXRecordDecl *RD, - raw_ostream &OS) { - assert(Ctx.IsSYCLKernelNamingDecl(RD) && "Not a sycl kernel?"); + auto MangleCallback = + [](ASTContext &Ctx, const CXXRecordDecl *RD) -> llvm::Optional { // This replaces the 'lambda number' in the mangling with a unique number // based on its order in the declaration. To provide some level of visual // notability (actual uniqueness from normal lambdas isn't necessary, as @@ -559,10 +555,15 @@ // For example: // _ZTSZ3foovEUlvE10005_ // Demangles to: typeinfo name for foo()::'lambda10005'() - OS << (10'000 + Ctx.GetSYCLKernelNamingIndex(RD)); + // Note that the mangler subtracts 2, since with normal lambdas the lambda + // mangling number '0' is an anonymous struct mangle, and '1' is omitted. + // So 10,002 results in the first number being 10,000. + if (Ctx.IsSYCLKernelNamingDecl(RD)) + return 10'002 + Ctx.GetSYCLKernelNamingIndex(RD); + return llvm::None; }; std::unique_ptr Ctx{ItaniumMangleContext::create( - Context, Context.getDiagnostics(), ShouldMangleCallback, MangleCallback)}; + Context, Context.getDiagnostics(), MangleCallback)}; std::string Buffer; Buffer.reserve(128); Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -125,20 +125,15 @@ typedef std::pair DiscriminatorKeyTy; llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; - const ShouldCallKernelCallbackTy ShouldCallKernelCallback = nullptr; const KernelMangleCallbackTy KernelMangleCallback = nullptr; - bool IsDevCtx = false; bool NeedsUniqueInternalLinkageNames = false; public: - explicit ItaniumMangleContextImpl( - ASTContext &Context, DiagnosticsEngine &Diags, - ShouldCallKernelCallbackTy ShouldCallKernelCB, - KernelMangleCallbackTy KernelCB) - : ItaniumMangleContext(Context, Diags), - ShouldCallKernelCallback(ShouldCallKernelCB), - KernelMangleCallback(KernelCB) {} + explicit ItaniumMangleContextImpl(ASTContext &Context, + DiagnosticsEngine &Diags, + KernelMangleCallbackTy KernelCB) + : ItaniumMangleContext(Context, Diags), KernelMangleCallback(KernelCB) {} /// @name Mangler Entry Points /// @{ @@ -153,9 +148,6 @@ NeedsUniqueInternalLinkageNames = true; } - bool isDeviceMangleContext() const override { return IsDevCtx; } - void setDeviceMangleContext(bool IsDev) override { IsDevCtx = IsDev; } - void mangleCXXName(GlobalDecl GD, raw_ostream &) override; void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &) override; @@ -252,9 +244,6 @@ return Name; } - ShouldCallKernelCallbackTy getShouldCallKernelCallback() const override { - return ShouldCallKernelCallback; - } KernelMangleCallbackTy getKernelMangleCallback() const override { return KernelMangleCallback; } @@ -1529,7 +1518,7 @@ // # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast(TD)) { if (Record->isLambda() && (Record->getLambdaManglingNumber() || - Context.getShouldCallKernelCallback()( + Context.getKernelMangleCallback()( Context.getASTContext(), Record))) { assert(!AdditionalAbiTags && "Lambda type cannot have additional abi tags"); @@ -1968,16 +1957,10 @@ // if the host-side CXX ABI has different numbering for lambda. In such case, // if the mangle context is that device-side one, use the device-side lambda // mangling number for this lambda. - - unsigned Number = Context.isDeviceMangleContext() - ? Lambda->getDeviceLambdaManglingNumber() - : Lambda->getLambdaManglingNumber(); - - if (Context.getShouldCallKernelCallback()(Context.getASTContext(), Lambda)) { - Context.getKernelMangleCallback()(Context.getASTContext(), Lambda, Out); - Out << '_'; - return; - } + llvm::Optional DeviceNumber = + Context.getKernelMangleCallback()(Context.getASTContext(), Lambda); + unsigned Number = DeviceNumber.hasValue() ? *DeviceNumber + : Lambda->getLambdaManglingNumber(); assert(Number > 0 && "Lambda should be mangled as an unnamed class"); if (Number > 1) @@ -6414,14 +6397,14 @@ ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { return new ItaniumMangleContextImpl( - Context, Diags, [](ASTContext &, const CXXRecordDecl *) { return false; }, - [](ASTContext &, const CXXRecordDecl *, raw_ostream &) {}); + Context, Diags, + [](ASTContext &, const CXXRecordDecl *) -> llvm::Optional { + return llvm::None; + }); } ItaniumMangleContext *ItaniumMangleContext::create( ASTContext &Context, DiagnosticsEngine &Diags, - ShouldCallKernelCallbackTy ShouldCallKernelCallback, KernelMangleCallbackTy MangleCallback) { - return new ItaniumMangleContextImpl(Context, Diags, ShouldCallKernelCallback, - MangleCallback); + return new ItaniumMangleContextImpl(Context, Diags, MangleCallback); } Index: clang/lib/CodeGen/CGCUDANV.cpp =================================================================== --- clang/lib/CodeGen/CGCUDANV.cpp +++ clang/lib/CodeGen/CGCUDANV.cpp @@ -191,12 +191,27 @@ return ((Twine("__cuda") + Twine(FuncName)).str()); } +static std::unique_ptr InitDeviceMC(CodeGenModule &CGM) { + // If the host and device have different C++ ABIs, mark it as the device + // mangle context so that the mangling needs to retrieve the additonal + // device lambda mangling number instead of the regular host one. + if (CGM.getContext().getAuxTargetInfo() && + CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft() && + CGM.getContext().getAuxTargetInfo()->getCXXABI().isItaniumFamily()) { + return std::unique_ptr( + CGM.getContext().createDeviceMangleContext( + *CGM.getContext().getAuxTargetInfo())); + } + + return std::unique_ptr(CGM.getContext().createMangleContext( + CGM.getContext().getAuxTargetInfo())); +} + CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM) : CGCUDARuntime(CGM), Context(CGM.getLLVMContext()), TheModule(CGM.getModule()), RelocatableDeviceCode(CGM.getLangOpts().GPURelocatableDeviceCode), - DeviceMC(CGM.getContext().createMangleContext( - CGM.getContext().getAuxTargetInfo())) { + DeviceMC(InitDeviceMC(CGM)) { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); @@ -207,14 +222,6 @@ CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy)); VoidPtrTy = cast(Types.ConvertType(Ctx.VoidPtrTy)); VoidPtrPtrTy = VoidPtrTy->getPointerTo(); - if (CGM.getContext().getAuxTargetInfo()) { - // If the host and device have different C++ ABIs, mark it as the device - // mangle context so that the mangling needs to retrieve the additonal - // device lambda mangling number instead of the regular host one. - DeviceMC->setDeviceMangleContext( - CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft() && - CGM.getContext().getAuxTargetInfo()->getCXXABI().isItaniumFamily()); - } } llvm::FunctionCallee CGNVCUDARuntime::getSetupArgumentFn() const { Index: clang/lib/Sema/SemaSYCL.cpp =================================================================== --- clang/lib/Sema/SemaSYCL.cpp +++ clang/lib/Sema/SemaSYCL.cpp @@ -65,16 +65,17 @@ } void Sema::AddSYCLKernelLambda(const FunctionDecl *FD) { - auto ShouldMangleCallback = [](ASTContext &Ctx, const CXXRecordDecl *RD) { - // We ALWAYS want to descend into the lambda mangling for these. - return true; + auto MangleCallback = + [](ASTContext &Ctx, const CXXRecordDecl *RD) -> llvm::Optional { + Ctx.AddSYCLKernelNamingDecl(RD); + // We always want to go into the lambda mangling (skipping the unnamed + // struct version), so make sure we return a value here. + return 1; }; - auto MangleCallback = [](ASTContext &Ctx, const CXXRecordDecl *RD, - raw_ostream &) { Ctx.AddSYCLKernelNamingDecl(RD); }; QualType Ty = GetSYCLKernelObjectType(FD); std::unique_ptr Ctx{ItaniumMangleContext::create( - Context, Context.getDiagnostics(), ShouldMangleCallback, MangleCallback)}; + Context, Context.getDiagnostics(), MangleCallback)}; llvm::raw_null_ostream Out; Ctx->mangleTypeName(Ty, Out); }