diff options
| author | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
|---|---|---|
| committer | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
| commit | 38500d63e14ce340236840f60d356cdefb56a52c (patch) | |
| tree | 17edbec446ce9b50d2f215a483b83afb293a635d /clang/lib/CodeGen | |
| parent | 1a3d5daaef7a6a63448a497da3eff7fc9e23df26 (diff) | |
| parent | 27f30029741ecf023baece7b3dde1ff9011ffefc (diff) | |
Merge branch 'main' into users/meinersbur/flang_runtime_split-headersusers/meinersbur/flang_runtime_split-headers
Diffstat (limited to 'clang/lib/CodeGen')
23 files changed, 398 insertions, 500 deletions
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index bf9b04f02e9f..04358cd6d7c2 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -77,6 +77,7 @@ #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h" #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" +#include "llvm/Transforms/Instrumentation/TypeSanitizer.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/Transforms/Scalar/GVN.h" @@ -735,9 +736,17 @@ static void addSanitizers(const Triple &TargetTriple, MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } + if (LangOpts.Sanitize.has(SanitizerKind::Type)) { + MPM.addPass(ModuleTypeSanitizerPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(TypeSanitizerPass())); + } + if (LangOpts.Sanitize.has(SanitizerKind::NumericalStability)) MPM.addPass(NumericalStabilitySanitizerPass()); + if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) + MPM.addPass(RealtimeSanitizerPass()); + auto ASanPass = [&](SanitizerMask Mask, bool CompileKernel) { if (LangOpts.Sanitize.has(Mask)) { bool UseGlobalGC = asanUseGlobalsGC(TargetTriple, CodeGenOpts); @@ -789,13 +798,12 @@ static void addSanitizers(const Triple &TargetTriple, } if (LowerAllowCheckPass::IsRequested()) { - // We can optimize after inliner, and PGO profile matching. The hook below - // is called at the end `buildFunctionSimplificationPipeline`, which called - // from `buildInlinerPipeline`, which called after profile matching. - PB.registerScalarOptimizerLateEPCallback( - [](FunctionPassManager &FPM, OptimizationLevel Level) { - FPM.addPass(LowerAllowCheckPass()); - }); + // We want to call it after inline, which is about OptimizerEarlyEPCallback. + PB.registerOptimizerEarlyEPCallback([](ModulePassManager &MPM, + OptimizationLevel Level, + ThinOrFullLTOPhase Phase) { + MPM.addPass(createModuleToFunctionPassAdaptor(LowerAllowCheckPass())); + }); } } @@ -1020,15 +1028,24 @@ void EmitAssemblyHelper::RunOptimizationPipeline( // of the pipeline. if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) PB.registerScalarOptimizerLateEPCallback( - [](FunctionPassManager &FPM, OptimizationLevel Level) { - FPM.addPass(BoundsCheckingPass()); - }); - - if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) - PB.registerScalarOptimizerLateEPCallback( - [](FunctionPassManager &FPM, OptimizationLevel Level) { - RealtimeSanitizerOptions Opts; - FPM.addPass(RealtimeSanitizerPass(Opts)); + [this](FunctionPassManager &FPM, OptimizationLevel Level) { + BoundsCheckingPass::ReportingMode Mode; + bool Merge = CodeGenOpts.SanitizeMergeHandlers.has( + SanitizerKind::LocalBounds); + + if (CodeGenOpts.SanitizeTrap.has(SanitizerKind::LocalBounds)) { + Mode = BoundsCheckingPass::ReportingMode::Trap; + } else if (CodeGenOpts.SanitizeMinimalRuntime) { + Mode = CodeGenOpts.SanitizeRecover.has(SanitizerKind::LocalBounds) + ? BoundsCheckingPass::ReportingMode::MinRuntime + : BoundsCheckingPass::ReportingMode::MinRuntimeAbort; + } else { + Mode = CodeGenOpts.SanitizeRecover.has(SanitizerKind::LocalBounds) + ? BoundsCheckingPass::ReportingMode::FullRuntime + : BoundsCheckingPass::ReportingMode::FullRuntimeAbort; + } + BoundsCheckingPass::BoundsCheckingOptions Options(Mode, Merge); + FPM.addPass(BoundsCheckingPass(Options)); }); // Don't add sanitizers if we are here from ThinLTO PostLink. That already diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 497a0b3952af..4d4b7428abd5 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4860,6 +4860,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Buffer is a void**. Address Buf = EmitPointerWithAlignment(E->getArg(0)); + if (getTarget().getTriple().getArch() == llvm::Triple::systemz) { + // On this target, the back end fills in the context buffer completely. + // It doesn't really matter if the frontend stores to the buffer before + // calling setjmp, the back-end is going to overwrite them anyway. + Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); + return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); + } + // Store the frame pointer to the setjmp buffer. Value *FrameAddr = Builder.CreateCall( CGM.getIntrinsic(Intrinsic::frameaddress, AllocaInt8PtrTy), @@ -10201,6 +10209,8 @@ CodeGenFunction::getSVEType(const SVETypeFlags &TypeFlags) { case SVETypeFlags::EltTyInt64: return llvm::ScalableVectorType::get(Builder.getInt64Ty(), 2); + case SVETypeFlags::EltTyMFloat8: + return llvm::ScalableVectorType::get(Builder.getInt8Ty(), 16); case SVETypeFlags::EltTyFloat16: return llvm::ScalableVectorType::get(Builder.getHalfTy(), 8); case SVETypeFlags::EltTyBFloat16: @@ -10646,7 +10656,7 @@ Value *CodeGenFunction::EmitSMELd1St1(const SVETypeFlags &TypeFlags, NewOps.push_back(Ops[2]); llvm::Value *BasePtr = Ops[3]; - + llvm::Value *RealSlice = Ops[1]; // If the intrinsic contains the vnum parameter, multiply it with the vector // size in bytes. if (Ops.size() == 5) { @@ -10658,10 +10668,13 @@ Value *CodeGenFunction::EmitSMELd1St1(const SVETypeFlags &TypeFlags, Builder.CreateMul(StreamingVectorLengthCall, Ops[4], "mulvl"); // The type of the ptr parameter is void *, so use Int8Ty here. BasePtr = Builder.CreateGEP(Int8Ty, Ops[3], Mulvl); + RealSlice = Builder.CreateZExt(RealSlice, Int64Ty); + RealSlice = Builder.CreateAdd(RealSlice, Ops[4]); + RealSlice = Builder.CreateTrunc(RealSlice, Int32Ty); } NewOps.push_back(BasePtr); NewOps.push_back(Ops[0]); - NewOps.push_back(Ops[1]); + NewOps.push_back(RealSlice); Function *F = CGM.getIntrinsic(IntID); return Builder.CreateCall(F, NewOps); } @@ -10706,7 +10719,16 @@ Value *CodeGenFunction::EmitSVEDupX(Value *Scalar, llvm::Type *Ty) { cast<llvm::VectorType>(Ty)->getElementCount(), Scalar); } -Value *CodeGenFunction::EmitSVEDupX(Value* Scalar) { +Value *CodeGenFunction::EmitSVEDupX(Value *Scalar) { + if (auto *Ty = Scalar->getType(); Ty->isVectorTy()) { +#ifndef NDEBUG + auto *VecTy = cast<llvm::VectorType>(Ty); + ElementCount EC = VecTy->getElementCount(); + assert(EC.isScalar() && VecTy->getElementType() == Int8Ty && + "Only <1 x i8> expected"); +#endif + Scalar = Builder.CreateExtractElement(Scalar, uint64_t(0)); + } return EmitSVEDupX(Scalar, getSVEVectorForElementType(Scalar->getType())); } @@ -11252,6 +11274,10 @@ Value *CodeGenFunction::EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, BuiltinID == SME::BI__builtin_sme_svstr_za) return EmitSMELdrStr(TypeFlags, Ops, Builtin->LLVMIntrinsic); + // Emit set FPMR for intrinsics that require it + if (TypeFlags.setsFPMR()) + Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_set_fpmr), + Ops.pop_back_val()); // Handle builtins which require their multi-vector operands to be swapped swapCommutativeSMEOperands(BuiltinID, Ops); @@ -19410,6 +19436,15 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(), ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step"); } + case Builtin::BI__builtin_hlsl_wave_active_all_true: { + Value *Op = EmitScalarExpr(E->getArg(0)); + assert(Op->getType()->isIntegerTy(1) && + "Intrinsic WaveActiveAllTrue operand must be a bool"); + + Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic(); + return EmitRuntimeCall( + Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op}); + } case Builtin::BI__builtin_hlsl_wave_active_any_true: { Value *Op = EmitScalarExpr(E->getArg(0)); assert(Op->getType()->isIntegerTy(1) && diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7c8d962fa5a9..f139c30f3dfd 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3235,22 +3235,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType()); - if (ArgI.isDirect() && !ArgI.getCanBeFlattened() && STy && - STy->getNumElements() > 1) { - [[maybe_unused]] llvm::TypeSize StructSize = - CGM.getDataLayout().getTypeAllocSize(STy); - [[maybe_unused]] llvm::TypeSize PtrElementSize = - CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(Ty)); - if (STy->containsHomogeneousScalableVectorTypes()) { - assert(StructSize == PtrElementSize && - "Only allow non-fractional movement of structure with" - "homogeneous scalable vector type"); - - ArgVals.push_back(ParamValue::forDirect(AI)); - break; - } - } - Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg), Arg->getName()); @@ -4379,7 +4363,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, llvm::PHINode *phiToUse = CGF.Builder.CreatePHI(valueToUse->getType(), 2, "icr.to-use"); phiToUse->addIncoming(valueToUse, copyBB); - phiToUse->addIncoming(llvm::UndefValue::get(valueToUse->getType()), + phiToUse->addIncoming(llvm::PoisonValue::get(valueToUse->getType()), originBB); valueToUse = phiToUse; } @@ -4529,7 +4513,7 @@ void CodeGenFunction::EmitCallArgs( ArgTypes.assign(MD->param_type_begin() + ParamsToSkip, MD->param_type_end()); } else { - const auto *FPT = Prototype.P.get<const FunctionProtoType *>(); + const auto *FPT = cast<const FunctionProtoType *>(Prototype.P); IsVariadic = FPT->isVariadic(); ExplicitCC = FPT->getExtInfo().getCC(); ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip, @@ -5414,21 +5398,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType()); - if (STy && ArgInfo.isDirect() && !ArgInfo.getCanBeFlattened()) { - llvm::Type *SrcTy = ConvertTypeForMem(I->Ty); - [[maybe_unused]] llvm::TypeSize SrcTypeSize = - CGM.getDataLayout().getTypeAllocSize(SrcTy); - [[maybe_unused]] llvm::TypeSize DstTypeSize = - CGM.getDataLayout().getTypeAllocSize(STy); - if (STy->containsHomogeneousScalableVectorTypes()) { - assert(SrcTypeSize == DstTypeSize && - "Only allow non-fractional movement of structure with " - "homogeneous scalable vector type"); - - IRCallArgs[FirstIRArg] = I->getKnownRValue().getScalarVal(); - break; - } - } // FIXME: Avoid the conversion through memory if possible. Address Src = Address::invalid(); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 60f32f76109e..f29ddece5dbc 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2021,28 +2021,10 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType( // ThisPtr may be null if the member function has an explicit 'this' // parameter. if (!ThisPtr.isNull()) { - const CXXRecordDecl *RD = ThisPtr->getPointeeCXXRecordDecl(); - if (isa<ClassTemplateSpecializationDecl>(RD)) { - // Create pointer type directly in this case. - const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr); - uint64_t Size = CGM.getContext().getTypeSize(ThisPtrTy); - auto Align = getTypeAlignIfRequired(ThisPtrTy, CGM.getContext()); - llvm::DIType *PointeeType = - getOrCreateType(ThisPtrTy->getPointeeType(), Unit); - llvm::DIType *ThisPtrType = - DBuilder.createPointerType(PointeeType, Size, Align); - TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType); - // TODO: This and the artificial type below are misleading, the - // types aren't artificial the argument is, but the current - // metadata doesn't represent that. - ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); - Elts.push_back(ThisPtrType); - } else { - llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit); - TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType); - ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); - Elts.push_back(ThisPtrType); - } + llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit); + TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType); + ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); + Elts.push_back(ThisPtrType); } // Copy rest of the arguments. @@ -2995,20 +2977,21 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, if (!ID) return nullptr; + auto RuntimeLang = + static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage()); + // Return a forward declaration if this type was imported from a clang module, // and this is not the compile unit with the implementation of the type (which // may contain hidden ivars). if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition() && !ID->getImplementation()) - return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - ID->getName(), - getDeclContextDescriptor(ID), Unit, 0); + return DBuilder.createForwardDecl( + llvm::dwarf::DW_TAG_structure_type, ID->getName(), + getDeclContextDescriptor(ID), Unit, 0, RuntimeLang); // Get overall information about the record type for the debug info. llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation()); unsigned Line = getLineNumber(ID->getLocation()); - auto RuntimeLang = - static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage()); // If this is just a forward declaration return a special forward-declaration // debug type since we won't be able to lay out the entire type. diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 2c3054605ee7..96517511b211 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -479,6 +479,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction( !isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); + if (getLangOpts().Sanitize.has(SanitizerKind::Type) && + !isInNoSanitizeList(SanitizerKind::Type, Fn, Loc)) + Fn->addFnAttr(llvm::Attribute::SanitizeType); + if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && !isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 5fccc9cbb37e..ba1cba291553 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -52,11 +52,6 @@ using namespace clang; using namespace CodeGen; -// Experiment to make sanitizers easier to debug -static llvm::cl::opt<bool> ClSanitizeDebugDeoptimization( - "ubsan-unique-traps", llvm::cl::Optional, - llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check.")); - // TODO: Introduce frontend options to enabled per sanitizers, similar to // `fsanitize-trap`. static llvm::cl::opt<bool> ClSanitizeGuardChecks( @@ -1172,7 +1167,7 @@ llvm::Value *CodeGenFunction::GetCountedByFieldExprGEP( Indices.push_back(Builder.getInt32(0)); return Builder.CreateInBoundsGEP( ConvertType(QualType(RD->getTypeForDecl(), 0)), Res, - RecIndicesTy(llvm::reverse(Indices)), "..counted_by.gep"); + RecIndicesTy(llvm::reverse(Indices)), "counted_by.gep"); } /// This method is typically called in contexts where we can't generate @@ -1187,7 +1182,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfCountedByField( const Expr *Base, const FieldDecl *FAMDecl, const FieldDecl *CountDecl) { if (llvm::Value *GEP = GetCountedByFieldExprGEP(Base, FAMDecl, CountDecl)) return Builder.CreateAlignedLoad(ConvertType(CountDecl->getType()), GEP, - getIntAlign(), "..counted_by.load"); + getIntAlign(), "counted_by.load"); return nullptr; } @@ -3546,7 +3541,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, ArrayRef<llvm::Value *> FnArgs, SanitizerHandler CheckHandler, CheckRecoverableKind RecoverKind, bool IsFatal, - llvm::BasicBlock *ContBB) { + llvm::BasicBlock *ContBB, bool NoMerge) { assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable); std::optional<ApplyDebugLocation> DL; if (!CGF.Builder.getCurrentDebugLocation()) { @@ -3581,6 +3576,10 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, llvm::AttributeList::FunctionIndex, B), /*Local=*/true); llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs); + NoMerge = NoMerge || !CGF.CGM.getCodeGenOpts().OptimizationLevel || + (CGF.CurCodeDecl && CGF.CurCodeDecl->hasAttr<OptimizeNoneAttr>()); + if (NoMerge) + HandlerCall->addFnAttr(llvm::Attribute::NoMerge); if (!MayReturn) { HandlerCall->setDoesNotReturn(); CGF.Builder.CreateUnreachable(); @@ -3602,6 +3601,7 @@ void CodeGenFunction::EmitCheck( llvm::Value *FatalCond = nullptr; llvm::Value *RecoverableCond = nullptr; llvm::Value *TrapCond = nullptr; + bool NoMerge = false; for (int i = 0, n = Checked.size(); i < n; ++i) { llvm::Value *Check = Checked[i].first; // -fsanitize-trap= overrides -fsanitize-recover=. @@ -3612,6 +3612,9 @@ void CodeGenFunction::EmitCheck( ? RecoverableCond : FatalCond; Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check; + + if (!CGM.getCodeGenOpts().SanitizeMergeHandlers.has(Checked[i].second)) + NoMerge = true; } if (ClSanitizeGuardChecks) { @@ -3626,7 +3629,7 @@ void CodeGenFunction::EmitCheck( } if (TrapCond) - EmitTrapCheck(TrapCond, CheckHandler); + EmitTrapCheck(TrapCond, CheckHandler, NoMerge); if (!FatalCond && !RecoverableCond) return; @@ -3692,7 +3695,7 @@ void CodeGenFunction::EmitCheck( // Simple case: we need to generate a single handler call, either // fatal, or non-fatal. emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, - (FatalCond != nullptr), Cont); + (FatalCond != nullptr), Cont, NoMerge); } else { // Emit two handler calls: first one for set of unrecoverable checks, // another one for recoverable. @@ -3702,10 +3705,10 @@ void CodeGenFunction::EmitCheck( Builder.CreateCondBr(FatalCond, NonFatalHandlerBB, FatalHandlerBB); EmitBlock(FatalHandlerBB); emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, true, - NonFatalHandlerBB); + NonFatalHandlerBB, NoMerge); EmitBlock(NonFatalHandlerBB); emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, false, - Cont); + Cont, NoMerge); } EmitBlock(Cont); @@ -3895,7 +3898,8 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) { } void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, - SanitizerHandler CheckHandlerID) { + SanitizerHandler CheckHandlerID, + bool NoMerge) { llvm::BasicBlock *Cont = createBasicBlock("cont"); // If we're optimizing, collapse all calls to trap down to just one per @@ -3905,9 +3909,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; - bool NoMerge = ClSanitizeDebugDeoptimization || - !CGM.getCodeGenOpts().OptimizationLevel || - (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); + NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel || + (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); if (TrapBB && !NoMerge) { auto Call = TrapBB->begin(); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 4ae8a2b22b1b..4b71bd730ce1 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2102,7 +2102,8 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { Expr *InitVector = E->getInit(0); // Initialize from another scalable vector of the same type. - if (InitVector->getType() == E->getType()) + if (InitVector->getType().getCanonicalType() == + E->getType().getCanonicalType()) return Visit(InitVector); } @@ -2369,10 +2370,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { ScalableDstTy->getElementCount().getKnownMinValue() / 8); } if (FixedSrcTy->getElementType() == ScalableDstTy->getElementType()) { - llvm::Value *UndefVec = llvm::UndefValue::get(ScalableDstTy); + llvm::Value *PoisonVec = llvm::PoisonValue::get(ScalableDstTy); llvm::Value *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty); llvm::Value *Result = Builder.CreateInsertVector( - ScalableDstTy, UndefVec, Src, Zero, "cast.scalable"); + ScalableDstTy, PoisonVec, Src, Zero, "cast.scalable"); if (Result->getType() != DstTy) Result = Builder.CreateBitCast(Result, DstTy); return Result; diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 2c293523fca8..c354e58e15f4 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -389,6 +389,11 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B, CGM.getIntrinsic(getThreadIdIntrinsic()); return buildVectorInput(B, ThreadIDIntrinsic, Ty); } + if (D.hasAttr<HLSLSV_GroupThreadIDAttr>()) { + llvm::Function *GroupThreadIDIntrinsic = + CGM.getIntrinsic(getGroupThreadIdIntrinsic()); + return buildVectorInput(B, GroupThreadIDIntrinsic, Ty); + } if (D.hasAttr<HLSLSV_GroupIDAttr>()) { llvm::Function *GroupIDIntrinsic = CGM.getIntrinsic(Intrinsic::dx_group_id); return buildVectorInput(B, GroupIDIntrinsic, Ty); @@ -507,13 +512,17 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() { IP = Token->getNextNode(); } IRBuilder<> B(IP); - for (auto *Fn : CtorFns) - B.CreateCall(FunctionCallee(Fn), {}, OB); + for (auto *Fn : CtorFns) { + auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB); + CI->setCallingConv(Fn->getCallingConv()); + } // Insert global dtors before the terminator of the last instruction B.SetInsertPoint(F.back().getTerminator()); - for (auto *Fn : DtorFns) - B.CreateCall(FunctionCallee(Fn), {}, OB); + for (auto *Fn : DtorFns) { + auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB); + CI->setCallingConv(Fn->getCallingConv()); + } } // No need to keep global ctors/dtors for non-lib profile after call to diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index bb120c8b5e9e..edb87f9d5efd 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -86,11 +86,13 @@ public: GENERATE_HLSL_INTRINSIC_FUNCTION(Step, step) GENERATE_HLSL_INTRINSIC_FUNCTION(Radians, radians) GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id) + GENERATE_HLSL_INTRINSIC_FUNCTION(GroupThreadId, thread_id_in_group) GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot) GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed) GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed) + GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) @@ -101,8 +103,9 @@ public: GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp) GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp) - GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding) - GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, bufferUpdateCounter) + GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, + resource_handlefrombinding) + GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter) GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 6a5860242035..30c3834de139 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -4085,7 +4085,7 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); } else { assert(E && "Expected a non-null expression"); - LValue &PosLVal = *Pos.get<LValue *>(); + LValue &PosLVal = *cast<LValue *>(Pos); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Base = CGF.MakeAddrLValue( CGF.Builder.CreateGEP(CGF, DependenciesArray, Idx), KmpDependInfoTy); @@ -4113,7 +4113,7 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, if (unsigned *P = Pos.dyn_cast<unsigned *>()) { ++(*P); } else { - LValue &PosLVal = *Pos.get<LValue *>(); + LValue &PosLVal = *cast<LValue *>(Pos); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Idx = CGF.Builder.CreateNUWAdd(Idx, llvm::ConstantInt::get(Idx->getType(), 1)); @@ -7770,7 +7770,7 @@ private: if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) getPlainLayout(Base, Layout, /*AsBase=*/true); else - Layout.push_back(Data.get<const FieldDecl *>()); + Layout.push_back(cast<const FieldDecl *>(Data)); } } @@ -8333,9 +8333,9 @@ public: MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { - assert(CurDir.is<const OMPExecutableDirective *>() && + assert(isa<const OMPExecutableDirective *>(CurDir) && "Expect a executable directive"); - const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); + const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir); generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder, SkipVarSet); } @@ -8345,9 +8345,9 @@ public: /// in \a CombinedInfo). void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder) const { - assert(CurDir.is<const OMPDeclareMapperDecl *>() && + assert(isa<const OMPDeclareMapperDecl *>(CurDir) && "Expect a declare mapper directive"); - const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); + const auto *CurMapperDir = cast<const OMPDeclareMapperDecl *>(CurDir); generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo, OMPBuilder); } @@ -8519,9 +8519,9 @@ public: DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom, Unknown, /*IsImpicit = */ true, nullptr, nullptr); - assert(CurDir.is<const OMPExecutableDirective *>() && + assert(isa<const OMPExecutableDirective *>(CurDir) && "Expect a executable directive"); - const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); + const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir); bool HasMapBasePtr = false; bool HasMapArraySec = false; for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { @@ -9042,337 +9042,69 @@ void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, return; ASTContext &C = CGM.getContext(); QualType Ty = D->getType(); - QualType PtrTy = C.getPointerType(Ty).withRestrict(); - QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); auto *MapperVarDecl = cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); - SourceLocation Loc = D->getLocation(); CharUnits ElementSize = C.getTypeSizeInChars(Ty); llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMem(Ty); - // Prepare mapper function arguments and attributes. - ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.VoidPtrTy, ImplicitParamKind::Other); - ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamKind::Other); - ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.VoidPtrTy, ImplicitParamKind::Other); - ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, - ImplicitParamKind::Other); - ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, - ImplicitParamKind::Other); - ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamKind::Other); - FunctionArgList Args; - Args.push_back(&HandleArg); - Args.push_back(&BaseArg); - Args.push_back(&BeginArg); - Args.push_back(&SizeArg); - Args.push_back(&TypeArg); - Args.push_back(&NameArg); - const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); + CodeGenFunction MapperCGF(CGM); + MappableExprsHandler::MapCombinedInfoTy CombinedInfo; + auto PrivatizeAndGenMapInfoCB = + [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI, + llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & { + MapperCGF.Builder.restoreIP(CodeGenIP); + + // Privatize the declared variable of mapper to be the current array + // element. + Address PtrCurrent( + PtrPHI, ElemTy, + Address(BeginArg, MapperCGF.VoidPtrTy, CGM.getPointerAlign()) + .getAlignment() + .alignmentOfArrayElement(ElementSize)); + CodeGenFunction::OMPPrivateScope Scope(MapperCGF); + Scope.addPrivate(MapperVarDecl, PtrCurrent); + (void)Scope.Privatize(); + + // Get map clause information. + MappableExprsHandler MEHandler(*D, MapperCGF); + MEHandler.generateAllInfoForMapper(CombinedInfo, OMPBuilder); + + auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { + return emitMappingInformation(MapperCGF, OMPBuilder, MapExpr); + }; + if (CGM.getCodeGenOpts().getDebugInfo() != + llvm::codegenoptions::NoDebugInfo) { + CombinedInfo.Names.resize(CombinedInfo.Exprs.size()); + llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(), + FillInfoMap); + } + + return CombinedInfo; + }; + + auto CustomMapperCB = [&](unsigned I, llvm::Function **MapperFunc) { + if (CombinedInfo.Mappers[I]) { + // Call the corresponding mapper function. + *MapperFunc = getOrCreateUserDefinedMapperFunc( + cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); + assert(*MapperFunc && "Expect a valid mapper function is available."); + return true; + } + return false; + }; + SmallString<64> TyStr; llvm::raw_svector_ostream Out(TyStr); CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out); std::string Name = getName({"omp_mapper", TyStr, D->getName()}); - auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, - Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); - Fn->removeFnAttr(llvm::Attribute::OptimizeNone); - // Start the mapper function code generation. - CodeGenFunction MapperCGF(CGM); - MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); - // Compute the starting and end addresses of array elements. - llvm::Value *Size = MapperCGF.EmitLoadOfScalar( - MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, - C.getPointerType(Int64Ty), Loc); - // Prepare common arguments for array initiation and deletion. - llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( - MapperCGF.GetAddrOfLocalVar(&HandleArg), - /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); - llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( - MapperCGF.GetAddrOfLocalVar(&BaseArg), - /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); - llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( - MapperCGF.GetAddrOfLocalVar(&BeginArg), - /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); - // Convert the size in bytes into the number of array elements. - Size = MapperCGF.Builder.CreateExactUDiv( - Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); - llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( - BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy)); - llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(ElemTy, PtrBegin, Size); - llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( - MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, - C.getPointerType(Int64Ty), Loc); - llvm::Value *MapName = MapperCGF.EmitLoadOfScalar( - MapperCGF.GetAddrOfLocalVar(&NameArg), - /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); - - // Emit array initiation if this is an array section and \p MapType indicates - // that memory allocation is required. - llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); - emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, - MapName, ElementSize, HeadBB, /*IsInit=*/true); - - // Emit a for loop to iterate through SizeArg of elements and map all of them. - - // Emit the loop header block. - MapperCGF.EmitBlock(HeadBB); - llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); - llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); - // Evaluate whether the initial condition is satisfied. - llvm::Value *IsEmpty = - MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); - MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); - llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); - - // Emit the loop body block. - MapperCGF.EmitBlock(BodyBB); - llvm::BasicBlock *LastBB = BodyBB; - llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( - PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); - PtrPHI->addIncoming(PtrBegin, EntryBB); - Address PtrCurrent(PtrPHI, ElemTy, - MapperCGF.GetAddrOfLocalVar(&BeginArg) - .getAlignment() - .alignmentOfArrayElement(ElementSize)); - // Privatize the declared variable of mapper to be the current array element. - CodeGenFunction::OMPPrivateScope Scope(MapperCGF); - Scope.addPrivate(MapperVarDecl, PtrCurrent); - (void)Scope.Privatize(); - // Get map clause information. Fill up the arrays with all mapped variables. - MappableExprsHandler::MapCombinedInfoTy Info; - MappableExprsHandler MEHandler(*D, MapperCGF); - MEHandler.generateAllInfoForMapper(Info, OMPBuilder); - - // Call the runtime API __tgt_mapper_num_components to get the number of - // pre-existing components. - llvm::Value *OffloadingArgs[] = {Handle}; - llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( - OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), - OMPRTL___tgt_mapper_num_components), - OffloadingArgs); - llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( - PreviousSize, - MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); - - // Fill up the runtime mapper handle for all components. - for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { - llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( - Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); - llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( - Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); - llvm::Value *CurSizeArg = Info.Sizes[I]; - llvm::Value *CurNameArg = - (CGM.getCodeGenOpts().getDebugInfo() == - llvm::codegenoptions::NoDebugInfo) - ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy) - : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]); - - // Extract the MEMBER_OF field from the map type. - llvm::Value *OriMapType = MapperCGF.Builder.getInt64( - static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - Info.Types[I])); - llvm::Value *MemberMapType = - MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); - - // Combine the map type inherited from user-defined mapper with that - // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM - // bits of the \a MapType, which is the input argument of the mapper - // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM - // bits of MemberMapType. - // [OpenMP 5.0], 1.2.6. map-type decay. - // | alloc | to | from | tofrom | release | delete - // ---------------------------------------------------------- - // alloc | alloc | alloc | alloc | alloc | release | delete - // to | alloc | to | alloc | to | release | delete - // from | alloc | alloc | from | from | release | delete - // tofrom | alloc | to | from | tofrom | release | delete - llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( - MapType, - MapperCGF.Builder.getInt64( - static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_TO | - OpenMPOffloadMappingFlags::OMP_MAP_FROM))); - llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); - llvm::BasicBlock *AllocElseBB = - MapperCGF.createBasicBlock("omp.type.alloc.else"); - llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); - llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); - llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); - llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); - llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); - MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); - // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. - MapperCGF.EmitBlock(AllocBB); - llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( - MemberMapType, - MapperCGF.Builder.getInt64( - ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_TO | - OpenMPOffloadMappingFlags::OMP_MAP_FROM))); - MapperCGF.Builder.CreateBr(EndBB); - MapperCGF.EmitBlock(AllocElseBB); - llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( - LeftToFrom, - MapperCGF.Builder.getInt64( - static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_TO))); - MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); - // In case of to, clear OMP_MAP_FROM. - MapperCGF.EmitBlock(ToBB); - llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( - MemberMapType, - MapperCGF.Builder.getInt64( - ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_FROM))); - MapperCGF.Builder.CreateBr(EndBB); - MapperCGF.EmitBlock(ToElseBB); - llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( - LeftToFrom, - MapperCGF.Builder.getInt64( - static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_FROM))); - MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); - // In case of from, clear OMP_MAP_TO. - MapperCGF.EmitBlock(FromBB); - llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( - MemberMapType, - MapperCGF.Builder.getInt64( - ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_TO))); - // In case of tofrom, do nothing. - MapperCGF.EmitBlock(EndBB); - LastBB = EndBB; - llvm::PHINode *CurMapType = - MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); - CurMapType->addIncoming(AllocMapType, AllocBB); - CurMapType->addIncoming(ToMapType, ToBB); - CurMapType->addIncoming(FromMapType, FromBB); - CurMapType->addIncoming(MemberMapType, ToElseBB); - - llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, - CurSizeArg, CurMapType, CurNameArg}; - if (Info.Mappers[I]) { - // Call the corresponding mapper function. - llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( - cast<OMPDeclareMapperDecl>(Info.Mappers[I])); - assert(MapperFunc && "Expect a valid mapper function is available."); - MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); - } else { - // Call the runtime API __tgt_push_mapper_component to fill up the runtime - // data structure. - MapperCGF.EmitRuntimeCall( - OMPBuilder.getOrCreateRuntimeFunction( - CGM.getModule(), OMPRTL___tgt_push_mapper_component), - OffloadingArgs); - } - } - - // Update the pointer to point to the next element that needs to be mapped, - // and check whether we have mapped all elements. - llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( - ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); - PtrPHI->addIncoming(PtrNext, LastBB); - llvm::Value *IsDone = - MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); - llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); - MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); - - MapperCGF.EmitBlock(ExitBB); - // Emit array deletion if this is an array section and \p MapType indicates - // that deletion is required. - emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, - MapName, ElementSize, DoneBB, /*IsInit=*/false); - - // Emit the function exit block. - MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); - MapperCGF.FinishFunction(); - UDMMap.try_emplace(D, Fn); + auto *NewFn = OMPBuilder.emitUserDefinedMapper(PrivatizeAndGenMapInfoCB, + ElemTy, Name, CustomMapperCB); + UDMMap.try_emplace(D, NewFn); if (CGF) FunctionUDMMap[CGF->CurFn].push_back(D); } -/// Emit the array initialization or deletion portion for user-defined mapper -/// code generation. First, it evaluates whether an array section is mapped and -/// whether the \a MapType instructs to delete this section. If \a IsInit is -/// true, and \a MapType indicates to not delete this array, array -/// initialization code is generated. If \a IsInit is false, and \a MapType -/// indicates to not this array, array deletion code is generated. -void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( - CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, - llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, - llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB, - bool IsInit) { - StringRef Prefix = IsInit ? ".init" : ".del"; - - // Evaluate if this is an array section. - llvm::BasicBlock *BodyBB = - MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); - llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT( - Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); - llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( - MapType, - MapperCGF.Builder.getInt64( - static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_DELETE))); - llvm::Value *DeleteCond; - llvm::Value *Cond; - if (IsInit) { - // base != begin? - llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateICmpNE(Base, Begin); - // IsPtrAndObj? - llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd( - MapType, - MapperCGF.Builder.getInt64( - static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ))); - PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit); - BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit); - Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin); - DeleteCond = MapperCGF.Builder.CreateIsNull( - DeleteBit, getName({"omp.array", Prefix, ".delete"})); - } else { - Cond = IsArray; - DeleteCond = MapperCGF.Builder.CreateIsNotNull( - DeleteBit, getName({"omp.array", Prefix, ".delete"})); - } - Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond); - MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB); - - MapperCGF.EmitBlock(BodyBB); - // Get the array size by multiplying element size and element number (i.e., \p - // Size). - llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( - Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); - // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves - // memory allocation/deletion purpose only. - llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( - MapType, - MapperCGF.Builder.getInt64( - ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_TO | - OpenMPOffloadMappingFlags::OMP_MAP_FROM))); - MapTypeArg = MapperCGF.Builder.CreateOr( - MapTypeArg, - MapperCGF.Builder.getInt64( - static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>( - OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))); - - // Call the runtime API __tgt_push_mapper_component to fill up the runtime - // data structure. - llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, - ArraySize, MapTypeArg, MapName}; - MapperCGF.EmitRuntimeCall( - OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), - OMPRTL___tgt_push_mapper_component), - OffloadingArgs); -} - llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( const OMPDeclareMapperDecl *D) { auto I = UDMMap.find(D); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 56d502d92806..8ab5ee70a19f 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -559,15 +559,6 @@ protected: llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc); - /// Emit the array initialization or deletion portion for user-defined mapper - /// code generation. - void emitUDMapperArrayInitOrDel(CodeGenFunction &MapperCGF, - llvm::Value *Handle, llvm::Value *BasePtr, - llvm::Value *Ptr, llvm::Value *Size, - llvm::Value *MapType, llvm::Value *MapName, - CharUnits ElementSize, - llvm::BasicBlock *ExitBB, bool IsInit); - struct TaskResultTy { llvm::Value *NewTask = nullptr; llvm::Function *TaskEntry = nullptr; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 698baf853507..3974739d2abb 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -458,6 +458,27 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) { case Stmt::OpenACCCombinedConstructClass: EmitOpenACCCombinedConstruct(cast<OpenACCCombinedConstruct>(*S)); break; + case Stmt::OpenACCDataConstructClass: + EmitOpenACCDataConstruct(cast<OpenACCDataConstruct>(*S)); + break; + case Stmt::OpenACCEnterDataConstructClass: + EmitOpenACCEnterDataConstruct(cast<OpenACCEnterDataConstruct>(*S)); + break; + case Stmt::OpenACCExitDataConstructClass: + EmitOpenACCExitDataConstruct(cast<OpenACCExitDataConstruct>(*S)); + break; + case Stmt::OpenACCHostDataConstructClass: + EmitOpenACCHostDataConstruct(cast<OpenACCHostDataConstruct>(*S)); + break; + case Stmt::OpenACCWaitConstructClass: + EmitOpenACCWaitConstruct(cast<OpenACCWaitConstruct>(*S)); + break; + case Stmt::OpenACCInitConstructClass: + EmitOpenACCInitConstruct(cast<OpenACCInitConstruct>(*S)); + break; + case Stmt::OpenACCShutdownConstructClass: + EmitOpenACCShutdownConstruct(cast<OpenACCShutdownConstruct>(*S)); + break; } } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 2bc10cdd2d34..af58fa64f865 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -837,6 +837,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); if (SanOpts.has(SanitizerKind::Thread)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); + if (SanOpts.has(SanitizerKind::Type)) + Fn->addFnAttr(llvm::Attribute::SanitizeType); if (SanOpts.has(SanitizerKind::NumericalStability)) Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability); if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index eaea0d8a08ac..1a5c42f8f974 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4094,6 +4094,45 @@ public: EmitStmt(S.getLoop()); } + void EmitOpenACCDataConstruct(const OpenACCDataConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // simply emitting its structured block, but in the future we will implement + // some sort of IR. + EmitStmt(S.getStructuredBlock()); + } + + void EmitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // but in the future we will implement some sort of IR. + } + + void EmitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // but in the future we will implement some sort of IR. + } + + void EmitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // simply emitting its structured block, but in the future we will implement + // some sort of IR. + EmitStmt(S.getStructuredBlock()); + } + + void EmitOpenACCWaitConstruct(const OpenACCWaitConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // but in the future we will implement some sort of IR. + } + + void EmitOpenACCInitConstruct(const OpenACCInitConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // but in the future we will implement some sort of IR. + } + + void EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // but in the future we will implement some sort of IR. + } + //===--------------------------------------------------------------------===// // LValue Expression Emission //===--------------------------------------------------------------------===// @@ -5142,7 +5181,8 @@ public: /// Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. - void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID); + void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, + bool NoMerge = false); /// Emit a call to trap or debugtrap and attach function attribute /// "trap-func-name" if specified. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d3d5c0743a52..c49f76314882 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -397,8 +397,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, if (LangOpts.HLSL) createHLSLRuntime(); - // Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0. - if (LangOpts.Sanitize.has(SanitizerKind::Thread) || + // Enable TBAA unless it's suppressed. TSan and TySan need TBAA even at O0. + if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Thread | SanitizerKind::Type) || (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0)) TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts, getLangOpts())); @@ -1218,6 +1218,9 @@ void CodeGenModule::Release() { getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1); if (getTriple().isOSLinux()) { + if (LangOpts.PointerAuthCalls) + getModule().addModuleFlag(llvm::Module::Min, "ptrauth-sign-personality", + 1); assert(getTriple().isOSBinFormatELF()); using namespace llvm::ELF; uint64_t PAuthABIVersion = @@ -4280,7 +4283,7 @@ void CodeGenModule::emitMultiVersionFunctions() { getContext().forEachMultiversionedFunctionVersion( FD, [&](const FunctionDecl *CurFD) { llvm::SmallVector<StringRef, 8> Feats; - bool IsDefined = CurFD->doesThisDeclarationHaveABody(); + bool IsDefined = CurFD->getDefinition() != nullptr; if (const auto *TA = CurFD->getAttr<TargetAttr>()) { assert(getTarget().getTriple().isX86() && "Unsupported target"); diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 6eed8e1d2b67..75e66bae79af 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -314,8 +314,10 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { } llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) { - // At -O0 or relaxed aliasing, TBAA is not emitted for regular types. - if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing) + // At -O0 or relaxed aliasing, TBAA is not emitted for regular types (unless + // we're running TypeSanitizer). + if (!Features.Sanitize.has(SanitizerKind::Type) && + (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)) return nullptr; // If the type has the may_alias attribute (even on a typedef), it is diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp index 549d5dd66b12..ddbf3ef74337 100644 --- a/clang/lib/CodeGen/ConstantInitBuilder.cpp +++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp @@ -20,10 +20,10 @@ using namespace CodeGen; llvm::Type *ConstantInitFuture::getType() const { assert(Data && "dereferencing null future"); - if (Data.is<llvm::Constant*>()) { - return Data.get<llvm::Constant*>()->getType(); + if (const auto *C = dyn_cast<llvm::Constant *>(Data)) { + return C->getType(); } else { - return Data.get<ConstantInitBuilderBase*>()->Buffer[0]->getType(); + return cast<ConstantInitBuilderBase *>(Data)->Buffer[0]->getType(); } } @@ -37,10 +37,10 @@ void ConstantInitFuture::abandon() { void ConstantInitFuture::installInGlobal(llvm::GlobalVariable *GV) { assert(Data && "installing null future"); - if (Data.is<llvm::Constant*>()) { - GV->setInitializer(Data.get<llvm::Constant*>()); + if (auto *C = dyn_cast<llvm::Constant *>(Data)) { + GV->setInitializer(C); } else { - auto &builder = *Data.get<ConstantInitBuilderBase*>(); + auto &builder = *cast<ConstantInitBuilderBase *>(Data); assert(builder.Buffer.size() == 1); builder.setGlobalInitializer(GV, builder.Buffer[0]); builder.Buffer.clear(); diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 96c89b2728e5..cda218eac34a 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1146,12 +1146,15 @@ struct CounterCoverageMappingBuilder /// Create a Branch Region around a SwitchCase for code coverage /// and add it to the function's SourceRegions. - void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt) { + /// Returns Counter that corresponds to SC. + Counter createSwitchCaseRegion(const SwitchCase *SC, Counter ParentCount) { // Push region onto RegionStack but immediately pop it (which adds it to // the function's SourceRegions) because it doesn't apply to any other // source other than the SwitchCase. + Counter TrueCnt = getRegionCounter(SC); popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), - Counter::getZero())); + subtractCounters(ParentCount, TrueCnt))); + return TrueCnt; } /// Check whether a region with bounds \c StartLoc and \c EndLoc @@ -1863,16 +1866,22 @@ struct CounterCoverageMappingBuilder const SwitchCase *Case = S->getSwitchCaseList(); for (; Case; Case = Case->getNextSwitchCase()) { HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case); - auto CaseCount = getRegionCounter(Case); + auto CaseCount = createSwitchCaseRegion(Case, ParentCount); CaseCountSum = addCounters(CaseCountSum, CaseCount, /*Simplify=*/false); - createSwitchCaseRegion(Case, CaseCount); } // If no explicit default case exists, create a branch region to represent // the hidden branch, which will be added later by the CodeGen. This region // will be associated with the switch statement's condition. if (!HasDefaultCase) { - Counter DefaultCount = subtractCounters(ParentCount, CaseCountSum); - createBranchRegion(S->getCond(), Counter::getZero(), DefaultCount); + // Simplify is skipped while building the counters above: it can get + // really slow on top of switches with thousands of cases. Instead, + // trigger simplification by adding zero to the last counter. + CaseCountSum = + addCounters(CaseCountSum, Counter::getZero(), /*Simplify=*/true); + + // This is considered as the False count on SwitchStmt. + Counter SwitchFalse = subtractCounters(ParentCount, CaseCountSum); + createBranchRegion(S->getCond(), CaseCountSum, SwitchFalse); } } @@ -2370,8 +2379,7 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName, } else { Ctx.dump(R.Count, OS); - if (R.Kind == CounterMappingRegion::BranchRegion || - R.Kind == CounterMappingRegion::MCDCBranchRegion) { + if (R.isBranch()) { OS << ", "; Ctx.dump(R.FalseCount, OS); } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 8cbd09d02c75..cf9e338236e5 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3302,6 +3302,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( CharUnits Align = CGM.getContext().getDeclAlign(VD); Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align); } + Val = Builder.CreateAddrSpaceCast(Val, Wrapper->getReturnType()); Builder.CreateRet(Val); } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index d587daac5a88..90651c3bafe2 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -3454,7 +3454,7 @@ llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion( if (inheritanceModelHasOnlyOneField(IsFunc, DstInheritance)) { Dst = FirstField; } else { - Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy)); + Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy)); unsigned Idx = 0; Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++); if (inheritanceModelHasNVOffsetField(IsFunc, DstInheritance)) diff --git a/clang/lib/CodeGen/SanitizerMetadata.cpp b/clang/lib/CodeGen/SanitizerMetadata.cpp index c1a6b223480a..61fdf3399ff3 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.cpp +++ b/clang/lib/CodeGen/SanitizerMetadata.cpp @@ -19,9 +19,10 @@ using namespace CodeGen; SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} -static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) { +static bool isAsanHwasanMemTagOrTysan(const SanitizerSet &SS) { return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::MemTag); + SanitizerKind::HWAddress | SanitizerKind::MemTag | + SanitizerKind::Type); } static SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { @@ -31,13 +32,44 @@ static SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { return Mask; } +static bool shouldTagGlobal(const llvm::GlobalVariable &G) { + // For now, don't instrument constant data, as it'll be in .rodata anyway. It + // may be worth instrumenting these in future to stop them from being used as + // gadgets. + if (G.getName().starts_with("llvm.") || G.isThreadLocal() || G.isConstant()) + return false; + + // Globals can be placed implicitly or explicitly in sections. There's two + // different types of globals that meet this criteria that cause problems: + // 1. Function pointers that are going into various init arrays (either + // explicitly through `__attribute__((section(<foo>)))` or implicitly + // through `__attribute__((constructor)))`, such as ".(pre)init(_array)", + // ".fini(_array)", ".ctors", and ".dtors". These function pointers end up + // overaligned and overpadded, making iterating over them problematic, and + // each function pointer is individually tagged (so the iteration over + // them causes SIGSEGV/MTE[AS]ERR). + // 2. Global variables put into an explicit section, where the section's name + // is a valid C-style identifier. The linker emits a `__start_<name>` and + // `__stop_<name>` symbol for the section, so that you can iterate over + // globals within this section. Unfortunately, again, these globals would + // be tagged and so iteration causes SIGSEGV/MTE[AS]ERR. + // + // To mitigate both these cases, and because specifying a section is rare + // outside of these two cases, disable MTE protection for globals in any + // section. + if (G.hasSection()) + return false; + + return true; +} + void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, SourceLocation Loc, StringRef Name, QualType Ty, SanitizerMask NoSanitizeAttrMask, bool IsDynInit) { SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize; - if (!isAsanHwasanOrMemTag(FsanitizeArgument)) + if (!isAsanHwasanMemTagOrTysan(FsanitizeArgument)) return; FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask); @@ -57,11 +89,15 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, Meta.NoHWAddress |= CGM.isInNoSanitizeList( FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty); - Meta.Memtag |= - static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals); - Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag); - Meta.Memtag &= !CGM.isInNoSanitizeList( - FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty); + if (shouldTagGlobal(*GV)) { + Meta.Memtag |= static_cast<bool>(FsanitizeArgument.Mask & + SanitizerKind::MemtagGlobals); + Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag); + Meta.Memtag &= !CGM.isInNoSanitizeList( + FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty); + } else { + Meta.Memtag = false; + } Meta.IsDynInit = IsDynInit && !Meta.NoAddress && FsanitizeArgument.has(SanitizerKind::Address) && @@ -70,11 +106,32 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, GV, Loc, Ty, "init"); GV->setSanitizerMetadata(Meta); + + if (Ty.isNull() || !CGM.getLangOpts().Sanitize.has(SanitizerKind::Type) || + NoSanitizeAttrMask & SanitizerKind::Type) + return; + + llvm::MDNode *TBAAInfo = CGM.getTBAATypeInfo(Ty); + if (!TBAAInfo || TBAAInfo == CGM.getTBAATypeInfo(CGM.getContext().CharTy)) + return; + + llvm::Metadata *GlobalMetadata[] = {llvm::ConstantAsMetadata::get(GV), + TBAAInfo}; + + // Metadata for the global already registered. + if (llvm::MDNode::getIfExists(CGM.getLLVMContext(), GlobalMetadata)) + return; + + llvm::MDNode *ThisGlobal = + llvm::MDNode::get(CGM.getLLVMContext(), GlobalMetadata); + llvm::NamedMDNode *TysanGlobals = + CGM.getModule().getOrInsertNamedMetadata("llvm.tysan.globals"); + TysanGlobals->addOperand(ThisGlobal); } void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, bool IsDynInit) { - if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) + if (!isAsanHwasanMemTagOrTysan(CGM.getLangOpts().Sanitize)) return; std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -88,6 +145,9 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, for (auto *Attr : D.specific_attrs<NoSanitizeAttr>()) NoSanitizeMask |= Attr->getMask(); + if (D.hasExternalStorage()) + NoSanitizeMask |= SanitizerKind::Type; + return NoSanitizeMask; }; diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index be33e26f0478..0680b4828b6d 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -52,6 +52,7 @@ private: bool isIllegalVectorType(QualType Ty) const; + bool passAsAggregateType(QualType Ty) const; bool passAsPureScalableType(QualType Ty, unsigned &NV, unsigned &NP, SmallVectorImpl<llvm::Type *> &CoerceToSeq) const; @@ -337,6 +338,10 @@ ABIArgInfo AArch64ABIInfo::coerceAndExpandPureScalableAggregate( NSRN += NVec; NPRN += NPred; + // Handle SVE vector tuples. + if (Ty->isSVESizelessBuiltinType()) + return ABIArgInfo::getDirect(); + llvm::Type *UnpaddedCoerceToType = UnpaddedCoerceToSeq.size() == 1 ? UnpaddedCoerceToSeq[0] @@ -362,7 +367,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, if (isIllegalVectorType(Ty)) return coerceIllegalVector(Ty, NSRN, NPRN); - if (!isAggregateTypeForABI(Ty)) { + if (!passAsAggregateType(Ty)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs<EnumType>()) Ty = EnumTy->getDecl()->getIntegerType(); @@ -417,7 +422,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, // elsewhere for GNU compatibility. uint64_t Size = getContext().getTypeSize(Ty); bool IsEmpty = isEmptyRecord(getContext(), Ty, true); - if (IsEmpty || Size == 0) { + if (!Ty->isSVESizelessBuiltinType() && (IsEmpty || Size == 0)) { if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS()) return ABIArgInfo::getIgnore(); @@ -504,7 +509,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) return getNaturalAlignIndirect(RetTy); - if (!isAggregateTypeForABI(RetTy)) { + if (!passAsAggregateType(RetTy)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) RetTy = EnumTy->getDecl()->getIntegerType(); @@ -519,7 +524,8 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, } uint64_t Size = getContext().getTypeSize(RetTy); - if (isEmptyRecord(getContext(), RetTy, true) || Size == 0) + if (!RetTy->isSVESizelessBuiltinType() && + (isEmptyRecord(getContext(), RetTy, true) || Size == 0)) return ABIArgInfo::getIgnore(); const Type *Base = nullptr; @@ -654,6 +660,15 @@ bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() return true; } +bool AArch64ABIInfo::passAsAggregateType(QualType Ty) const { + if (Kind == AArch64ABIKind::AAPCS && Ty->isSVESizelessBuiltinType()) { + const auto *BT = Ty->castAs<BuiltinType>(); + return !BT->isSVECount() && + getContext().getBuiltinVectorTypeInfo(BT).NumVectors > 1; + } + return isAggregateTypeForABI(Ty); +} + // Check if a type needs to be passed in registers as a Pure Scalable Type (as // defined by AAPCS64). Return the number of data vectors and the number of // predicate vectors in the type, into `NVec` and `NPred`, respectively. Upon @@ -719,37 +734,38 @@ bool AArch64ABIInfo::passAsPureScalableType( return true; } - const auto *VT = Ty->getAs<VectorType>(); - if (!VT) - return false; + if (const auto *VT = Ty->getAs<VectorType>()) { + if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) { + ++NPred; + if (CoerceToSeq.size() + 1 > 12) + return false; + CoerceToSeq.push_back(convertFixedToScalableVectorType(VT)); + return true; + } - if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) { - ++NPred; - if (CoerceToSeq.size() + 1 > 12) - return false; - CoerceToSeq.push_back(convertFixedToScalableVectorType(VT)); - return true; - } + if (VT->getVectorKind() == VectorKind::SveFixedLengthData) { + ++NVec; + if (CoerceToSeq.size() + 1 > 12) + return false; + CoerceToSeq.push_back(convertFixedToScalableVectorType(VT)); + return true; + } - if (VT->getVectorKind() == VectorKind::SveFixedLengthData) { - ++NVec; - if (CoerceToSeq.size() + 1 > 12) - return false; - CoerceToSeq.push_back(convertFixedToScalableVectorType(VT)); - return true; + return false; } - if (!VT->isBuiltinType()) + if (!Ty->isBuiltinType()) return false; - switch (cast<BuiltinType>(VT)->getKind()) { + bool isPredicate; + switch (Ty->getAs<BuiltinType>()->getKind()) { #define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \ case BuiltinType::Id: \ - ++NVec; \ + isPredicate = false; \ break; #define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \ case BuiltinType::Id: \ - ++NPred; \ + isPredicate = true; \ break; #define SVE_TYPE(Name, Id, SingletonId) #include "clang/Basic/AArch64SVEACLETypes.def" @@ -761,6 +777,10 @@ bool AArch64ABIInfo::passAsPureScalableType( getContext().getBuiltinVectorTypeInfo(cast<BuiltinType>(Ty)); assert(Info.NumVectors > 0 && Info.NumVectors <= 4 && "Expected 1, 2, 3 or 4 vectors!"); + if (isPredicate) + NPred += Info.NumVectors; + else + NVec += Info.NumVectors; auto VTy = llvm::ScalableVectorType::get(CGT.ConvertType(Info.ElementType), Info.EC.getKnownMinValue()); diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index b04e436c665f..873e696e1328 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -495,13 +495,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, return getNaturalAlignIndirect(Ty, /*ByVal=*/false); } - ABIArgInfo Info = ABIArgInfo::getDirect(); - - // If it is tuple type, it can't be flattened. - if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty))) - Info.setCanBeFlattened(!STy->containsHomogeneousScalableVectorTypes()); - - return Info; + return ABIArgInfo::getDirect(); } if (const VectorType *VT = Ty->getAs<VectorType>()) |
