[clang] [analyzer] New optin.taint.TaintedAlloc checker for catching unbounded memory allocation calls (PR #92420)
@@ -938,6 +938,53 @@ optin.portability.UnixAPI " Finds implementation-defined behavior in UNIX/Posix functions. +.. _optin-taint-TaintedAlloc: + +optin.taint.TaintedAlloc (C, C++) +""" steakhal wrote: ```suggestion " ``` https://github.com/llvm/llvm-project/pull/92420 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Factor out NoOwnershipChangeVisitor (PR #94357)
steakhal wrote: Is this NFC? https://github.com/llvm/llvm-project/pull/94357 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [mlir] [Flang]Fix for changed code at the end of AllocaIP. (PR #92430)
@@ -0,0 +1,23 @@ +!! The main point of this test is to check that the code compiles at all, so the Leporacanthicus wrote: I have created an internal ticket to improve the code generation. It's just a much bigger task than this one started out as. I then found more problems, so this took much longer than I expected. https://github.com/llvm/llvm-project/pull/92430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Fix feature flags dependecies (PR #90612)
paulwalker-arm wrote: @momchil-velikov's commentary applies globally and is not specific to FPMR. Which is to say, Arm switched a while back from "all system register need to be protected by their feature flag" to "only protect system registers where there is a need". The rational is that we see it as being unnecessarily burdensome to asm writers to force them to use a feature flag in order to use the pretty printed version of an instruction they can already emit (this is especially true when dynamic feature detection is used, rather than wanting to explicitly say the feature must be present) . We've no direct plans to revisit all previously implemented system registers unless there's a specific need. https://github.com/llvm/llvm-project/pull/90612 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 1ea5688 - [clang][Interp][NFC] Mark failed globals as uninitialized
Author: Timm Bäder Date: 2024-06-05T13:10:18+02:00 New Revision: 1ea568895aa106a61e84607edfd52c3ebf4b59bc URL: https://github.com/llvm/llvm-project/commit/1ea568895aa106a61e84607edfd52c3ebf4b59bc DIFF: https://github.com/llvm/llvm-project/commit/1ea568895aa106a61e84607edfd52c3ebf4b59bc.diff LOG: [clang][Interp][NFC] Mark failed globals as uninitialized This happens automatically if anything _before_ the Ret op fails, but in this case we have to un-initialize it again. Added: Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp Removed: diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 3eb7e7544df71..3671c41ae7039 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3080,12 +3080,22 @@ bool ByteCodeExprGen::visitDecl(const VarDecl *VD) { } } - // Return the value - if (VarT) -return this->emitRet(*VarT, VD); - - // Return non-primitive values as pointers here. - return this->emitRet(PT_Ptr, VD); + // Return the value. + if (!this->emitRet(VarT.value_or(PT_Ptr), VD)) { +// If the Ret above failed and this is a global variable, mark it as +// uninitialized, even everything else succeeded. +if (Context::shouldBeGloballyIndexed(VD)) { + auto GlobalIndex = P.getGlobal(VD); + assert(GlobalIndex); + Block *GlobalBlock = P.getGlobal(*GlobalIndex); + InlineDescriptor &ID = + *reinterpret_cast(GlobalBlock->rawData()); + ID.IsInitialized = false; + GlobalBlock->invokeDtor(); +} +return false; + } + return true; } template ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
https://github.com/skatrak edited https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
https://github.com/skatrak commented: Thank you Pranav, I think this looks good. I just have a few minor comments. https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -5252,6 +5660,8 @@ static void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, // emitKernelLaunch auto &&EmitTargetCallFallbackCB = [&](OpenMPIRBuilder::InsertPointTy IP) -> OpenMPIRBuilder::InsertPointTy { +LLVM_DEBUG(dbgs() << "EmitTargetCallFallbackCB::Builder = " << &Builder + << "\n"); skatrak wrote: Nit: Is this addition intentional? https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -5572,6 +5999,8 @@ void OpenMPIRBuilder::emitOffloadingArrays( return; Builder.restoreIP(AllocaIP); + LLVM_DEBUG(dbgs() << "Basicblock before emitOffloadingArrays\n" +<< *(Builder.GetInsertBlock()) << "\n"); skatrak wrote: Nit: Is this addition intentional? https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -5212,6 +5273,78 @@ static Function *createOutlinedFunction( return Func; } +// Create an entry point for a target task with the following. +// It'll have the following signature +// void @.omp_target_task_proxy_func(i32 %thread.id, ptr %task) +// This function is called from emitTargetTask once the +// code to launch the target kernel has been outlined already. +static Function *emitProxyTaskFunction(OpenMPIRBuilder &OMPBuilder, skatrak wrote: I agree with the comment by @ergawy, though I'd rather suggest `emitTargetTaskProxyFunction`, since that's what the emitted function is named. Feel free to ignore if you disagree. https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -0,0 +1,37 @@ +! Offloading test checking the use of the depend clause on +! the target construct +! REQUIRES: flang, amdgcn-amd-amdhsa +! UNSUPPORTED: nvptx64-nvidia-cuda +! UNSUPPORTED: nvptx64-nvidia-cuda-LTO +! UNSUPPORTED: aarch64-unknown-linux-gnu +! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +! UNSUPPORTED: x86_64-pc-linux-gnu +! UNSUPPORTED: x86_64-pc-linux-gnu-LTO + +! RUN: %libomptarget-compile-fortran-run-and-check-generic +program main + integer :: a = 0 + call foo(5, a) + print*, "=== FORTRAN Test passed! ===" + print*, "foo(5) returned ", a, ", expected 6\n" + ! stop 0 +end program main +subroutine foo(N, r) + integer, intent(in) :: N + integer, intent(out) :: r + integer :: z + + z = 1 + !$omp task depend(out: z) shared(z) + z = N skatrak wrote: Would it make sense to perhaps add a relatively long-running loop before setting the value of `z` here? Just to make sure that the target task below has had to wait for the first to finish (rather than being able to assume it did because it possibly runs so fast that it always finishes before the next task starts running). https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -5272,36 +5682,53 @@ static void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Value *DynCGGroupMem = Builder.getInt32(0); bool HasNoWait = false; + bool HasDependencies = Dependencies.size() > 0; + bool RequiresOuterTargetTask = HasNoWait || HasDependencies; OpenMPIRBuilder::TargetKernelArgs KArgs(NumTargetItems, RTArgs, NumIterations, NumTeamsVal, NumThreadsVal, DynCGGroupMem, HasNoWait); - Builder.restoreIP(OMPBuilder.emitKernelLaunch( - Builder, OutlinedFn, OutlinedFnID, EmitTargetCallFallbackCB, KArgs, - DeviceID, RTLoc, AllocaIP)); + // The presence of certain clauses on the target directive require the + // explicit generation of the target task. + if (RequiresOuterTargetTask) { +OMPBuilder.emitTargetTask(OutlinedFn, OutlinedFnID, skatrak wrote: Is a call to `Builder.restoreIP()` missing? https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -792,6 +792,9 @@ void OpenMPIRBuilder::finalize(Function *Fn) { if (!OffloadInfoManager.empty()) createOffloadEntriesAndInfoMetadata(ErrorReportFn); + + LLVM_DEBUG(dbgs() << "Module after OMPIRBuilder::finalize\n"); + LLVM_DEBUG(dbgs() << M << "\n"); skatrak wrote: Nit: Is this addition intentional? https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -1698,6 +1701,64 @@ void OpenMPIRBuilder::createTaskyield(const LocationDescription &Loc) { emitTaskyieldImpl(Loc); } +// Processes the dependencies in Dependencies and does the following +// - Allocates space on the stack of an array of DependInfo objects +// - Populates each DependInfo object with relevant information of +// the corresponding dependence. +// - All code is inserted in the entry block of the current function. +static Value * +emitDepArray(OpenMPIRBuilder &OMPBuilder, skatrak wrote: ```suggestion emitTargetTaskDependenciesArray(OpenMPIRBuilder &OMPBuilder, ``` Nit: I think it's best to try avoiding arbitrary abbreviations in function names for readability. Perhaps the name I'm suggesting can be shortened if it's also intended for general tasks (`emitTaskDependenciesArray`), but it looks like it's only used for target tasks at the moment. https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [OMPIRBuilder] - Handle dependencies in `createTarget` (PR #93977)
@@ -705,28 +728,9 @@ convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder, }; SmallVector dds; - if (!taskOp.getDependVars().empty() && taskOp.getDepends()) { -for (auto dep : - llvm::zip(taskOp.getDependVars(), taskOp.getDepends()->getValue())) { - llvm::omp::RTLDependenceKindTy type; - switch ( - cast(std::get<1>(dep)).getValue()) { - case mlir::omp::ClauseTaskDepend::taskdependin: -type = llvm::omp::RTLDependenceKindTy::DepIn; -break; - // The OpenMP runtime requires that the codegen for 'depend' clause for - // 'out' dependency kind must be the same as codegen for 'depend' clause - // with 'inout' dependency. - case mlir::omp::ClauseTaskDepend::taskdependout: - case mlir::omp::ClauseTaskDepend::taskdependinout: -type = llvm::omp::RTLDependenceKindTy::DepInOut; -break; - }; - llvm::Value *depVal = moduleTranslation.lookupValue(std::get<0>(dep)); - llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal); - dds.emplace_back(dd); -} - } + if (!taskOp.getDependVars().empty() && taskOp.getDepends()) skatrak wrote: Nit: I'd suggest moving this check into `buildDependData`, since it always needs to be done. It would just return without adding anything to `dds` if the condition is not met. https://github.com/llvm/llvm-project/pull/93977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Decouple feature dependency expansion. (PR #94279)
https://github.com/labrinea updated https://github.com/llvm/llvm-project/pull/94279 >From a413428bb0fdcd45b4a251e385b6cc00ff6a0a2c Mon Sep 17 00:00:00 2001 From: Alexandros Lamprineas Date: Mon, 3 Jun 2024 19:57:49 +0100 Subject: [PATCH 1/2] [AArch64] Decouple feature dependency expansion. The dependency expansion step which was introduced by FMV has been erroneously used for non-FMV features, for example when parsing the target attribute. The PR #93695 has rectified most of the tests which were relying on dependency expansion of target features specified on the -cc1 command line. In this patch I am decoupling the dependency expansion of features specified on the target attribute from FMV. To do that first I am expanding FMV dependencies before passing the list of target features to initFeatureMap(). Similarly when parsing the target attribute I am reconstructing an ExtensionSet from the list of target features which was created during the command line option parsing. The attribute parsing may toggle bits of that ExtensionSet and at the end it is converted to a list of target features. Those are passed to initFeatureMap(), which no longer requires an override. A side effect of this refactoring is that features specified on the target_version attribute now supersede the command line options, which is what should be happening in the first place. --- clang/include/clang/AST/ASTContext.h | 3 - clang/lib/AST/ASTContext.cpp | 53 - clang/lib/Basic/Targets/AArch64.cpp | 99 + clang/lib/Basic/Targets/AArch64.h | 4 - .../CodeGen/aarch64-cpu-supports-target.c | 2 +- .../aarch64-sme-attrs.cpp | 2 +- clang/test/CodeGen/aarch64-targetattr.c | 41 --- clang/test/CodeGen/attr-target-version.c | 46 clang/test/Sema/aarch64-neon-target.c | 4 +- clang/test/Sema/builtin-cpu-supports.c| 2 +- .../llvm/TargetParser/AArch64TargetParser.h | 104 +++--- llvm/lib/Target/AArch64/AArch64Features.td| 2 +- llvm/lib/TargetParser/AArch64TargetParser.cpp | 53 ++--- 13 files changed, 201 insertions(+), 214 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a1d1d1c51cd41..8bce4812f0d48 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3203,9 +3203,6 @@ class ASTContext : public RefCountedBase { /// valid feature names. ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; - std::vector - filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const; - void getFunctionFeatureMap(llvm::StringMap &FeatureMap, const FunctionDecl *) const; void getFunctionFeatureMap(llvm::StringMap &FeatureMap, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 73d3b152c49f1..6b7cfbe48796a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -87,6 +87,7 @@ #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/AArch64TargetParser.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -13663,17 +13664,18 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { } } -std::vector ASTContext::filterFunctionTargetVersionAttrs( -const TargetVersionAttr *TV) const { - assert(TV != nullptr); - llvm::SmallVector Feats; - std::vector ResFeats; - TV->getFeatures(Feats); - for (auto &Feature : Feats) -if (Target->validateCpuSupports(Feature.str())) - // Use '?' to mark features that came from TargetVersion. - ResFeats.push_back("?" + Feature.str()); - return ResFeats; +// Given a list of FMV features, add each of their backend features to the list. +static void +getFMVBackendFeaturesFor(const llvm::SmallVectorImpl &FMVFeatStrings, + std::vector &BackendFeats) { + for (StringRef F : FMVFeatStrings) { +if (auto FMVExt = llvm::AArch64::parseArchExtension(F)) { + SmallVector Feats; + FMVExt->DependentFeatures.split(Feats, ',', -1, false); + for (StringRef F : Feats) +BackendFeats.push_back(F.str()); +} + } } ParsedTargetAttr @@ -13708,10 +13710,12 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, // Make a copy of the features as passed on the command line into the // beginning of the additional features from the function to override. -ParsedAttr.Features.insert( -ParsedAttr.Features.begin(), -Target->getTargetOpts().FeaturesAsWritten.begin(), -Target->getTargetOpts().FeaturesAsWritten.end()); +// AArch64 handles command line option features in parseTargetAttr(). +if (!Target->getTriple().isAArch64()) + ParsedAttr.Features.insert( + ParsedAttr.Features.begin(), +
[clang] [llvm] [AArch64] set AppleA14 architecture version to v8.4-a (PR #92600)
@@ -718,12 +718,16 @@ def ProcessorFeatures { list AppleA13 = [HasV8_4aOps, FeatureCrypto, FeatureFPARMv8, FeatureNEON, FeaturePerfMon, FeatureFullFP16, FeatureFP16FML, FeatureSHA3]; + // Apple A14 and M1 chips are based on Armv8.5-a but without BTI. Since there tmatheson-arm wrote: As you point out, the only publicly available documentation is the optimization guide, and lists these cores as "8.5 without BTI". Here in the tablegen file it is written as 8.4 plus all of the features from 8.5 which are supported. A comment explaining the discrepancy seems reasonable to me. It also alerts people that if any new backend feature is introduced that models something in 8.5, they need to manually add it to the list for these cores. https://github.com/llvm/llvm-project/pull/92600 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] set AppleA14 architecture version to v8.4-a (PR #92600)
@@ -286,7 +286,6 @@ void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts, void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ARM_FEATURE_FRINT", "1"); - Builder.defineMacro("__ARM_FEATURE_BTI", "1"); tmatheson-arm wrote: Maybe in a separate PR. https://github.com/llvm/llvm-project/pull/92600 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] New optin.taint.TaintedAlloc checker for catching unbounded memory allocation calls (PR #92420)
https://github.com/dkrupp updated https://github.com/llvm/llvm-project/pull/92420 >From f6fdd544a90b865e5e0e530930db87cad405216e Mon Sep 17 00:00:00 2001 From: Daniel Krupp Date: Tue, 30 Apr 2024 15:20:52 +0200 Subject: [PATCH 1/8] [analyzer] Adding taint analysis capability to unix.Malloc checker unix.Malloc checker will warn if a memory allocation function (malloc, calloc, realloc, alloca) is called with a tainted (attacker controlled) size parameter. A large, maliciously set size value can trigger memory exhaustion. To get this warning, the alpha.security.taint.TaintPropagation checker also needs to be switched on. The warning will only be emitted, if the analyzer cannot prove that the size is below reasonable bounds (https://wiki.sei.cmu.edu/confluence/display/c/INT04-C.+Enforce+limits+on+integer+values+originating+from+tainted+sources>`_. + +You can silence this warning either by bound checking the ``size`` parameter, or +by explicitly marking the ``size`` parameter as sanitized. See the +:ref:`alpha-security-taint-TaintPropagation` checker for more details. + +.. code-block:: c + + void t1(void) { +size_t size; +scanf("%zu", &size); +int *p = malloc(size); // warn: malloc is called with a tainted (potentially attacker controlled) value +free(p); + } + + void t3(void) { +size_t size; +scanf("%zu", &size); +if (1024 BT_MismatchedDealloc; mutable std::unique_ptr BT_OffsetFree[CK_NumCheckKinds]; mutable std::unique_ptr BT_UseZerroAllocated[CK_NumCheckKinds]; + mutable std::unique_ptr BT_TaintedAlloc[CK_NumCheckKinds]; #define CHECK_FN(NAME) \ void NAME(const CallEvent &Call, CheckerContext &C) const; @@ -462,6 +464,13 @@ class MallocChecker }; bool isMemCall(const CallEvent &Call) const; + void reportTaintBug(StringRef Msg, ProgramStateRef State, CheckerContext &C, + llvm::ArrayRef TaintedSyms, + AllocationFamily Family, const Expr *SizeEx) const; + + void CheckTaintedness(CheckerContext &C, const CallEvent &Call, +const SVal SizeSVal, ProgramStateRef State, +AllocationFamily Family) const; // TODO: Remove mutable by moving the initializtaion to the registry function. mutable std::optional KernelZeroFlagVal; @@ -521,9 +530,9 @@ class MallocChecker /// malloc leaves it undefined. /// \param [in] State The \c ProgramState right before allocation. /// \returns The ProgramState right after allocation. - [[nodiscard]] static ProgramStateRef + [[nodiscard]] ProgramStateRef MallocMemAux(CheckerContext &C, const CallEvent &Call, const Expr *SizeEx, - SVal Init, ProgramStateRef State, AllocationFamily Family); + SVal Init, ProgramStateRef State, AllocationFamily Family) const; /// Models memory allocation. /// @@ -534,9 +543,10 @@ class MallocChecker /// malloc leaves it undefined. /// \param [in] State The \c ProgramState right before allocation. /// \returns The ProgramState right after allocation. - [[nodiscard]] static ProgramStateRef - MallocMemAux(CheckerContext &C, const CallEvent &Call, SVal Size, SVal Init, - ProgramStateRef State, AllocationFamily Family); + [[nodiscard]] ProgramStateRef MallocMemAux(CheckerContext &C, + const CallEvent &Call, SVal Size, + SVal Init, ProgramStateRef State, + AllocationFamily Family) const; // Check if this malloc() for special flags. At present that means M_ZERO or // __GFP_ZERO (in which case, treat it like calloc). @@ -649,8 +659,9 @@ class MallocChecker /// \param [in] Call The expression that reallocated memory /// \param [in] State The \c ProgramState right before reallocation. /// \returns The ProgramState right after allocation. - [[nodiscard]] static ProgramStateRef - CallocMem(CheckerContext &C, const CallEvent &Call, ProgramStateRef State); + [[nodiscard]] ProgramStateRef CallocMem(CheckerContext &C, + const CallEvent &Call, + ProgramStateRef State) const; /// See if deallocation happens in a suspicious context. If so, escape the /// pointers that otherwise would have been deallocated and return true. @@ -1779,7 +1790,7 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, const CallEvent &Call, const Expr *SizeEx, SVal Init, ProgramStateRef State, -AllocationFamily Family) { +AllocationFamily Family) const { if (!State) return nullptr; @@ -1787,10 +1798,71 @@ ProgramStateRef MallocChecker:
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/86512 >From 0eec9639530a137da6c4c4b2cc4249a3f9dd9939 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 25 Mar 2024 15:10:51 +0100 Subject: [PATCH] [clang] Implement a bitwise_copyable builtin type trait. This patch implements a `__is_bitwise_copyable` builtin in clang. The bitwise copyable types act as the trivially copyable types, but they support a wider range of types (e.g. classes with virtual methods) -- their underlying types can be safely copied by `memcopy` or `memmove`, the clang compiler guarantees that both source and destination objects have the same *object* representations after the copy operation, and the lifetime of the destination object implicitly starts. A particular use case of this builtin is to clone an object via memcopy (without running the constructor): ``` Message* clone(const Message* src, char* buffer, int size) { if constexpr __is_bitwise_copyable(Message) { // bitwise copy to buffer __builtin_memcpy(buffer, src, size); // using __builtin_launder to prevent miscompile for -fstrict-vtable-pointers. return __builtin_launder(reinterpret_cast(buffer)); } // Fallback the operator new, which calls the constructor to start the lifetime. return new(buffer) Message(src); } ``` Note that the definition of bitwise copyable is not tied to the Rule Of Five, so users of this builtin must guarantee that program semantic constraints are satisfied, e.g. no double resource deallocations. Context: https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy --- clang/docs/LanguageExtensions.rst | 24 clang/docs/ReleaseNotes.rst | 3 ++ clang/include/clang/AST/Type.h| 14 +++ clang/include/clang/Basic/TokenKinds.def | 2 + clang/lib/AST/Type.cpp| 37 +++ clang/lib/Sema/SemaExprCXX.cpp| 3 ++ ...builtin-is-bitwise-cloneable-fsanitize.cpp | 34 + .../SemaCXX/builtin-is-bitwise-cloneable.cpp | 8 clang/test/SemaObjCXX/arc-type-traits.mm | 9 + 9 files changed, 134 insertions(+) create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable-fsanitize.cpp create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable.cpp diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 46f99d0bbdd06..a49e4122ffc10 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -4016,6 +4016,30 @@ Note that the `size` argument must be a compile time constant. Note that this intrinsic cannot yet be called in a ``constexpr`` context. +``__is_bitwise_cloneable`` +-- + +A type trait is used to check whether a type can be safely copied by memcpy. + +**Syntax**: + +.. code-block:: c++ + + bool __is_bitwise_cloneable(Type) + +**Description**: + +Objects of bitwise cloneable types can be bitwise copied by memcpy/memmove. The +Clang compiler warrants that this behavior is well defined, and won't be +broken by compiler optimizations and sanitizers. + +For implicit-lifetime types, the lifetime of the new object is implicitly +started after the copy. For other types (e.g., classes with virtual methods), +the lifetime isn't started, and using the object results in undefined behavior +according to the C++ Standard. + +This builtin can be used in constant expressions. + Atomic Min/Max builtins with memory ordering diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 39a9013c75a41..cc2ff9920b5c1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -337,6 +337,9 @@ Non-comprehensive list of changes in this release ``-Winvalid-constexpr`` is not enabled for the function definition, which should result in mild compile-time performance improvements. +- Added ``__buitlin_bitwise_clonable`` which is used to check whether a type + can be safely copied by memcpy/memmove. + New Compiler Flags -- - ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 263b632df23ce..4bb3a18102ebb 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1120,6 +1120,20 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext &Context) const; + /// Return true if the type is safe to bitwise copy using memcpy/memmove. + /// + /// This is an extension in clang: bitwise clonable types act as trivially + /// copyable types, meaning their underlying bytes can be safely copied by + /// memcpy or memmove. After the copy, the destination object has the same + /// object representation. + /// + /// However, there are cases where it
[clang] 5f2aa91 - [clang][Interp][NFC] Don't try to dump uninitialized global variables
Author: Timm Bäder Date: 2024-06-05T13:24:22+02:00 New Revision: 5f2aa912766e4d48a5b46afa7ad9e99a41a51ee8 URL: https://github.com/llvm/llvm-project/commit/5f2aa912766e4d48a5b46afa7ad9e99a41a51ee8 DIFF: https://github.com/llvm/llvm-project/commit/5f2aa912766e4d48a5b46afa7ad9e99a41a51ee8.diff LOG: [clang][Interp][NFC] Don't try to dump uninitialized global variables They don't contain anything useful. Added: Modified: clang/lib/AST/Interp/Disasm.cpp Removed: diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp index ccdc96a79436d..e442c6c709f14 100644 --- a/clang/lib/AST/Interp/Disasm.cpp +++ b/clang/lib/AST/Interp/Disasm.cpp @@ -150,7 +150,7 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const { } Desc->dump(OS); OS << "\n"; -if (Desc->isPrimitive() && !Desc->isDummy()) { +if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) { OS << " "; { ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false}); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 145815c - [clang][Interp][NFC] Move EvaluationResult::dump() to Disasm.cpp
Author: Timm Bäder Date: 2024-06-05T13:24:22+02:00 New Revision: 145815c180fc82c5a55bf568d01d98d250490a55 URL: https://github.com/llvm/llvm-project/commit/145815c180fc82c5a55bf568d01d98d250490a55 DIFF: https://github.com/llvm/llvm-project/commit/145815c180fc82c5a55bf568d01d98d250490a55.diff LOG: [clang][Interp][NFC] Move EvaluationResult::dump() to Disasm.cpp Where all the other dump() functions live. Added: Modified: clang/lib/AST/Interp/Disasm.cpp clang/lib/AST/Interp/EvaluationResult.cpp Removed: diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp index e442c6c709f14..3f8a92ed2f0bd 100644 --- a/clang/lib/AST/Interp/Disasm.cpp +++ b/clang/lib/AST/Interp/Disasm.cpp @@ -11,6 +11,8 @@ //===--===// #include "Boolean.h" +#include "Context.h" +#include "EvaluationResult.h" #include "Floating.h" #include "Function.h" #include "FunctionPointer.h" @@ -305,3 +307,43 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const { OS << " Extern: " << IsExtern << "\n"; OS << " Initialized: " << IsInitialized << "\n"; } + +LLVM_DUMP_METHOD void EvaluationResult::dump() const { + assert(Ctx); + auto &OS = llvm::errs(); + const ASTContext &ASTCtx = Ctx->getASTContext(); + + switch (Kind) { + case Empty: +OS << "Empty\n"; +break; + case RValue: +OS << "RValue: "; +std::get(Value).dump(OS, ASTCtx); +break; + case LValue: { +assert(Source); +QualType SourceType; +if (const auto *D = Source.dyn_cast()) { + if (const auto *VD = dyn_cast(D)) +SourceType = VD->getType(); +} else if (const auto *E = Source.dyn_cast()) { + SourceType = E->getType(); +} + +OS << "LValue: "; +if (const auto *P = std::get_if(&Value)) + P->toAPValue().printPretty(OS, ASTCtx, SourceType); +else if (const auto *FP = std::get_if(&Value)) // Nope + FP->toAPValue().printPretty(OS, ASTCtx, SourceType); +OS << "\n"; +break; + } + case Invalid: +OS << "Invalid\n"; +break; + case Valid: +OS << "Valid\n"; +break; + } +} diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index 150a793da881d..c04b0fc0a1121 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -7,7 +7,6 @@ //===--===// #include "EvaluationResult.h" -#include "Context.h" #include "InterpState.h" #include "Record.h" #include "clang/AST/ExprCXX.h" @@ -159,45 +158,5 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S, return CheckArrayInitialized(S, InitLoc, Ptr, CAT); } -void EvaluationResult::dump() const { - assert(Ctx); - auto &OS = llvm::errs(); - const ASTContext &ASTCtx = Ctx->getASTContext(); - - switch (Kind) { - case Empty: -OS << "Empty\n"; -break; - case RValue: -OS << "RValue: "; -std::get(Value).dump(OS, ASTCtx); -break; - case LValue: { -assert(Source); -QualType SourceType; -if (const auto *D = Source.dyn_cast()) { - if (const auto *VD = dyn_cast(D)) -SourceType = VD->getType(); -} else if (const auto *E = Source.dyn_cast()) { - SourceType = E->getType(); -} - -OS << "LValue: "; -if (const auto *P = std::get_if(&Value)) - P->toAPValue().printPretty(OS, ASTCtx, SourceType); -else if (const auto *FP = std::get_if(&Value)) // Nope - FP->toAPValue().printPretty(OS, ASTCtx, SourceType); -OS << "\n"; -break; - } - case Invalid: -OS << "Invalid\n"; - break; - case Valid: -OS << "Valid\n"; - break; - } -} - } // namespace interp } // namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] set AppleA14 architecture version to v8.4-a (PR #92600)
https://github.com/tmatheson-arm updated https://github.com/llvm/llvm-project/pull/92600 >From 518b83ab69c4852f7e7ea71c17df3f58e8ff50ef Mon Sep 17 00:00:00 2001 From: Tomas Matheson Date: Fri, 17 May 2024 21:39:17 +0100 Subject: [PATCH 1/4] [AArch64] set AppleA14 architecture version to 8.5 --- llvm/lib/Target/AArch64/AArch64Processors.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/AArch64/AArch64Processors.td b/llvm/lib/Target/AArch64/AArch64Processors.td index f2286ae17dba5..96422758bc618 100644 --- a/llvm/lib/Target/AArch64/AArch64Processors.td +++ b/llvm/lib/Target/AArch64/AArch64Processors.td @@ -718,7 +718,7 @@ def ProcessorFeatures { list AppleA13 = [HasV8_4aOps, FeatureCrypto, FeatureFPARMv8, FeatureNEON, FeaturePerfMon, FeatureFullFP16, FeatureFP16FML, FeatureSHA3]; - list AppleA14 = [HasV8_4aOps, FeatureCrypto, FeatureFPARMv8, + list AppleA14 = [HasV8_5aOps, FeatureCrypto, FeatureFPARMv8, FeatureNEON, FeaturePerfMon, FeatureFRInt3264, FeatureSpecRestrict, FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist, >From 74f6d426fa67b1f794a8ba2ac7c864830ee9c2b2 Mon Sep 17 00:00:00 2001 From: Tomas Matheson Date: Mon, 20 May 2024 12:38:52 +0100 Subject: [PATCH 2/4] make m1+a14 v8.4 instead --- clang/lib/Basic/Targets/AArch64.cpp| 4 +++- clang/test/Driver/aarch64-mac-cpus.c | 2 +- clang/test/Preprocessor/aarch64-target-features.c | 8 +++- .../llvm/TargetParser/AArch64TargetParser.h| 4 ++-- llvm/lib/Target/AArch64/AArch64Processors.td | 14 +- llvm/test/DebugInfo/debug_frame_symbol.ll | 2 +- .../AddressSanitizer/calls-only-smallfn.ll | 2 +- .../Instrumentation/AddressSanitizer/calls-only.ll | 2 +- llvm/unittests/TargetParser/TargetParserTest.cpp | 8 9 files changed, 29 insertions(+), 17 deletions(-) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 5db1ce78c657f..692ec58235efe 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -286,7 +286,6 @@ void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts, void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ARM_FEATURE_FRINT", "1"); - Builder.defineMacro("__ARM_FEATURE_BTI", "1"); // Also include the Armv8.4 defines getTargetDefinesARMV84A(Opts, Builder); } @@ -499,6 +498,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasPAuthLR) Builder.defineMacro("__ARM_FEATURE_PAUTH_LR", "1"); + if (HasBTI) +Builder.defineMacro("__ARM_FEATURE_BTI", "1"); + if (HasUnalignedAccess) Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); diff --git a/clang/test/Driver/aarch64-mac-cpus.c b/clang/test/Driver/aarch64-mac-cpus.c index 5179731268950..488298cfd2d24 100644 --- a/clang/test/Driver/aarch64-mac-cpus.c +++ b/clang/test/Driver/aarch64-mac-cpus.c @@ -16,7 +16,7 @@ // RUN: %clang --target=arm64-apple-macos -mcpu=apple-m1 -### -c %s 2>&1 | FileCheck --check-prefix=EXPLICIT-M1 %s // CHECK: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-m1" -// CHECK-SAME: "-target-feature" "+v8.5a" +// CHECK-SAME: "-target-feature" "+v8.4a" // EXPLICIT-A11: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a11" // EXPLICIT-A7: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a7" diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 82304a15a04a3..3f2c2929c7129 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -335,7 +335,7 @@ // CHECK-MCPU-CARMEL: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2" "-target-feature" "+neon" // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s -// CHECK-ARCH-ARM64: "-target-cpu" "apple-m1" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.5a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+complxnum" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+fp16fml" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+pauth" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sha2" "-
[clang] [llvm] [AArch64] set AppleA14 architecture version to v8.4-a (PR #92600)
https://github.com/tmatheson-arm updated https://github.com/llvm/llvm-project/pull/92600 >From 518b83ab69c4852f7e7ea71c17df3f58e8ff50ef Mon Sep 17 00:00:00 2001 From: Tomas Matheson Date: Fri, 17 May 2024 21:39:17 +0100 Subject: [PATCH 1/5] [AArch64] set AppleA14 architecture version to 8.5 --- llvm/lib/Target/AArch64/AArch64Processors.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/AArch64/AArch64Processors.td b/llvm/lib/Target/AArch64/AArch64Processors.td index f2286ae17dba5..96422758bc618 100644 --- a/llvm/lib/Target/AArch64/AArch64Processors.td +++ b/llvm/lib/Target/AArch64/AArch64Processors.td @@ -718,7 +718,7 @@ def ProcessorFeatures { list AppleA13 = [HasV8_4aOps, FeatureCrypto, FeatureFPARMv8, FeatureNEON, FeaturePerfMon, FeatureFullFP16, FeatureFP16FML, FeatureSHA3]; - list AppleA14 = [HasV8_4aOps, FeatureCrypto, FeatureFPARMv8, + list AppleA14 = [HasV8_5aOps, FeatureCrypto, FeatureFPARMv8, FeatureNEON, FeaturePerfMon, FeatureFRInt3264, FeatureSpecRestrict, FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist, >From 74f6d426fa67b1f794a8ba2ac7c864830ee9c2b2 Mon Sep 17 00:00:00 2001 From: Tomas Matheson Date: Mon, 20 May 2024 12:38:52 +0100 Subject: [PATCH 2/5] make m1+a14 v8.4 instead --- clang/lib/Basic/Targets/AArch64.cpp| 4 +++- clang/test/Driver/aarch64-mac-cpus.c | 2 +- clang/test/Preprocessor/aarch64-target-features.c | 8 +++- .../llvm/TargetParser/AArch64TargetParser.h| 4 ++-- llvm/lib/Target/AArch64/AArch64Processors.td | 14 +- llvm/test/DebugInfo/debug_frame_symbol.ll | 2 +- .../AddressSanitizer/calls-only-smallfn.ll | 2 +- .../Instrumentation/AddressSanitizer/calls-only.ll | 2 +- llvm/unittests/TargetParser/TargetParserTest.cpp | 8 9 files changed, 29 insertions(+), 17 deletions(-) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 5db1ce78c657f..692ec58235efe 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -286,7 +286,6 @@ void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts, void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ARM_FEATURE_FRINT", "1"); - Builder.defineMacro("__ARM_FEATURE_BTI", "1"); // Also include the Armv8.4 defines getTargetDefinesARMV84A(Opts, Builder); } @@ -499,6 +498,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasPAuthLR) Builder.defineMacro("__ARM_FEATURE_PAUTH_LR", "1"); + if (HasBTI) +Builder.defineMacro("__ARM_FEATURE_BTI", "1"); + if (HasUnalignedAccess) Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); diff --git a/clang/test/Driver/aarch64-mac-cpus.c b/clang/test/Driver/aarch64-mac-cpus.c index 5179731268950..488298cfd2d24 100644 --- a/clang/test/Driver/aarch64-mac-cpus.c +++ b/clang/test/Driver/aarch64-mac-cpus.c @@ -16,7 +16,7 @@ // RUN: %clang --target=arm64-apple-macos -mcpu=apple-m1 -### -c %s 2>&1 | FileCheck --check-prefix=EXPLICIT-M1 %s // CHECK: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-m1" -// CHECK-SAME: "-target-feature" "+v8.5a" +// CHECK-SAME: "-target-feature" "+v8.4a" // EXPLICIT-A11: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a11" // EXPLICIT-A7: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a7" diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 82304a15a04a3..3f2c2929c7129 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -335,7 +335,7 @@ // CHECK-MCPU-CARMEL: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2" "-target-feature" "+neon" // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s -// CHECK-ARCH-ARM64: "-target-cpu" "apple-m1" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.5a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+complxnum" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+fp16fml" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+pauth" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sha2" "-
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/86512 >From 3ce87797dbc36ae792b4d82077cd8f27f1eee53e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 25 Mar 2024 15:10:51 +0100 Subject: [PATCH] [clang] Implement a bitwise_copyable builtin type trait. This patch implements a `__is_bitwise_copyable` builtin in clang. The bitwise copyable types act as the trivially copyable types, but they support a wider range of types (e.g. classes with virtual methods) -- their underlying types can be safely copied by `memcopy` or `memmove`, the clang compiler guarantees that both source and destination objects have the same *object* representations after the copy operation, and the lifetime of the destination object implicitly starts. A particular use case of this builtin is to clone an object via memcopy (without running the constructor): ``` Message* clone(const Message* src, char* buffer, int size) { if constexpr __is_bitwise_copyable(Message) { // bitwise copy to buffer __builtin_memcpy(buffer, src, size); // using __builtin_launder to prevent miscompile for -fstrict-vtable-pointers. return __builtin_launder(reinterpret_cast(buffer)); } // Fallback the operator new, which calls the constructor to start the lifetime. return new(buffer) Message(src); } ``` Note that the definition of bitwise copyable is not tied to the Rule Of Five, so users of this builtin must guarantee that program semantic constraints are satisfied, e.g. no double resource deallocations. Context: https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy --- clang/docs/LanguageExtensions.rst | 24 clang/docs/ReleaseNotes.rst | 3 ++ clang/include/clang/AST/Type.h| 14 +++ clang/include/clang/Basic/TokenKinds.def | 2 + clang/lib/AST/Type.cpp| 37 +++ clang/lib/Sema/SemaExprCXX.cpp| 3 ++ ...builtin-is-bitwise-cloneable-fsanitize.cpp | 34 + .../SemaCXX/builtin-is-bitwise-cloneable.cpp | 8 clang/test/SemaObjCXX/arc-type-traits.mm | 9 + 9 files changed, 134 insertions(+) create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable-fsanitize.cpp create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable.cpp diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 46f99d0bbdd06..a49e4122ffc10 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -4016,6 +4016,30 @@ Note that the `size` argument must be a compile time constant. Note that this intrinsic cannot yet be called in a ``constexpr`` context. +``__is_bitwise_cloneable`` +-- + +A type trait is used to check whether a type can be safely copied by memcpy. + +**Syntax**: + +.. code-block:: c++ + + bool __is_bitwise_cloneable(Type) + +**Description**: + +Objects of bitwise cloneable types can be bitwise copied by memcpy/memmove. The +Clang compiler warrants that this behavior is well defined, and won't be +broken by compiler optimizations and sanitizers. + +For implicit-lifetime types, the lifetime of the new object is implicitly +started after the copy. For other types (e.g., classes with virtual methods), +the lifetime isn't started, and using the object results in undefined behavior +according to the C++ Standard. + +This builtin can be used in constant expressions. + Atomic Min/Max builtins with memory ordering diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 39a9013c75a41..3d54144bf9206 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -337,6 +337,9 @@ Non-comprehensive list of changes in this release ``-Winvalid-constexpr`` is not enabled for the function definition, which should result in mild compile-time performance improvements. +- Added ``__is_bitwise_cloneable`` which is used to check whether a type + can be safely copied by memcpy/memmove. + New Compiler Flags -- - ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 263b632df23ce..9eb3f6c09e3d3 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1120,6 +1120,20 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext &Context) const; + /// Return true if the type is safe to bitwise copy using memcpy/memmove. + /// + /// This is an extension in clang: bitwise cloneable types act as trivially + /// copyable types, meaning their underlying bytes can be safely copied by + /// memcpy or memmove. After the copy, the destination object has the same + /// object representation. + /// + /// However, there are cases where it is
[clang] [clang] Lower _BitInt(129+) to a different type in LLVM IR (PR #91364)
@@ -118,6 +124,37 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField) { return R; } +bool CodeGenTypes::LLVMTypeLayoutMatchesAST(QualType ASTTy, +llvm::Type *LLVMTy) { + CharUnits ASTSize = Context.getTypeSizeInChars(ASTTy); + CharUnits LLVMSize = + CharUnits::fromQuantity(getDataLayout().getTypeAllocSize(LLVMTy)); + return ASTSize == LLVMSize; +} + +llvm::Type *CodeGenTypes::convertTypeForLoadStore(QualType T, + llvm::Type *LLVMTy) { + if (!LLVMTy) +LLVMTy = ConvertType(T); + + if (!T->isBitIntType() && LLVMTy->isIntegerTy(1)) +return llvm::IntegerType::get(getLLVMContext(), + (unsigned)Context.getTypeSize(T)); + + if (T->isBitIntType()) { +llvm::Type *R = ConvertType(T); +if (!LLVMTypeLayoutMatchesAST(T, R)) + return llvm::Type::getIntNTy( + getLLVMContext(), Context.getTypeSizeInChars(T).getQuantity() * 8); hassnaaHamdi wrote: `return llvm::Type::getIntNTy( getLLVMContext(), Context.getTypeSizeInChars(T).getQuantity() * 8);` Could you plz explain the logic behind using this implementation ? do you support all types > 128 and also types < 128 ? or it's specific to the types > 128 only ? https://github.com/llvm/llvm-project/pull/91364 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Lower _BitInt(129+) to a different type in LLVM IR (PR #91364)
@@ -118,6 +124,37 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField) { return R; } +bool CodeGenTypes::LLVMTypeLayoutMatchesAST(QualType ASTTy, +llvm::Type *LLVMTy) { + CharUnits ASTSize = Context.getTypeSizeInChars(ASTTy); + CharUnits LLVMSize = + CharUnits::fromQuantity(getDataLayout().getTypeAllocSize(LLVMTy)); + return ASTSize == LLVMSize; +} + +llvm::Type *CodeGenTypes::convertTypeForLoadStore(QualType T, + llvm::Type *LLVMTy) { + if (!LLVMTy) +LLVMTy = ConvertType(T); + + if (!T->isBitIntType() && LLVMTy->isIntegerTy(1)) +return llvm::IntegerType::get(getLLVMContext(), + (unsigned)Context.getTypeSize(T)); + + if (T->isBitIntType()) { +llvm::Type *R = ConvertType(T); +if (!LLVMTypeLayoutMatchesAST(T, R)) + return llvm::Type::getIntNTy( + getLLVMContext(), Context.getTypeSizeInChars(T).getQuantity() * 8); Fznamznon wrote: We intend to support all types. In general, _BitInt(N) is lowered to iN type in LLVM IR. However it is not possible for certain sizes and some targets now due to different alignment defined for iN and _BitInt(N). This now happens for _BitInt(>=129) for x86_64 targets. `LLVMTypeLayoutMatchesAST` checks for this mismatch. If there is mismatch, say NBytes = sizeof(_BitInt(N)), we use [i8 x NBytes] as in-memory type. It is better to load and store value using iNBytes type instead of an array type since it is better for optimization and guarantees that all bits of the loaded/stores value is valid. For more info, please refer to https://github.com/llvm/llvm-project/pull/91364#issuecomment-2099351151 as well. https://github.com/llvm/llvm-project/pull/91364 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] New optin.taint.TaintedAlloc checker for catching unbounded memory allocation calls (PR #92420)
https://github.com/steakhal approved this pull request. https://github.com/llvm/llvm-project/pull/92420 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 3388c5a - [clang][Interp][NFC] Add missing assertion to Block ctor
Author: Timm Bäder Date: 2024-06-05T13:57:23+02:00 New Revision: 3388c5aadd8583b5a596576c52be886104d557f2 URL: https://github.com/llvm/llvm-project/commit/3388c5aadd8583b5a596576c52be886104d557f2 DIFF: https://github.com/llvm/llvm-project/commit/3388c5aadd8583b5a596576c52be886104d557f2.diff LOG: [clang][Interp][NFC] Add missing assertion to Block ctor We have this assertion in all the other constructors. Added: Modified: clang/lib/AST/Interp/InterpBlock.h Removed: diff --git a/clang/lib/AST/Interp/InterpBlock.h b/clang/lib/AST/Interp/InterpBlock.h index 506034e880d0b..2bb195648a9a9 100644 --- a/clang/lib/AST/Interp/InterpBlock.h +++ b/clang/lib/AST/Interp/InterpBlock.h @@ -125,13 +125,15 @@ class Block final { void dump() const { dump(llvm::errs()); } void dump(llvm::raw_ostream &OS) const; -protected: +private: friend class Pointer; friend class DeadBlock; friend class InterpState; Block(const Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead) - : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {} + : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) { +assert(Desc); + } /// Deletes a dead block at the end of its lifetime. void cleanup(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] a16d33e - [clang][Interp][NFC] Don't invoke block dtor on uninitialized globals
Author: Timm Bäder Date: 2024-06-05T13:57:23+02:00 New Revision: a16d33eaebb3fdbc9435c125c206372c8a7374d5 URL: https://github.com/llvm/llvm-project/commit/a16d33eaebb3fdbc9435c125c206372c8a7374d5 DIFF: https://github.com/llvm/llvm-project/commit/a16d33eaebb3fdbc9435c125c206372c8a7374d5.diff LOG: [clang][Interp][NFC] Don't invoke block dtor on uninitialized globals That can't ever work. Added: Modified: clang/lib/AST/Interp/Program.h Removed: diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h index 36b5a1faa513a..ec7c0744b8856 100644 --- a/clang/lib/AST/Interp/Program.h +++ b/clang/lib/AST/Interp/Program.h @@ -45,7 +45,8 @@ class Program final { // but primitive arrays might have an InitMap* heap allocated and // that needs to be freed. for (Global *G : Globals) - G->block()->invokeDtor(); + if (Block *B = G->block(); B->isInitialized()) +B->invokeDtor(); // Records might actually allocate memory themselves, but they // are allocated using a BumpPtrAllocator. Call their desctructors ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] c70fa55 - [clang][Interp][NFC] Add cleanup() infrastructure to EvalEmitter
Author: Timm Bäder Date: 2024-06-05T13:57:23+02:00 New Revision: c70fa55bed45fc0cc0063e9f0bf93f163b5a1962 URL: https://github.com/llvm/llvm-project/commit/c70fa55bed45fc0cc0063e9f0bf93f163b5a1962 DIFF: https://github.com/llvm/llvm-project/commit/c70fa55bed45fc0cc0063e9f0bf93f163b5a1962.diff LOG: [clang][Interp][NFC] Add cleanup() infrastructure to EvalEmitter Unused for now. Added: Modified: clang/lib/AST/Interp/Context.cpp clang/lib/AST/Interp/EvalEmitter.cpp clang/lib/AST/Interp/EvalEmitter.h clang/lib/AST/Interp/InterpState.cpp clang/lib/AST/Interp/InterpState.h Removed: diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index 4ecfa0f9bfd75..b0b22b059b77a 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -46,6 +46,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue()); if (Res.isInvalid()) { +C.cleanup(); Stk.clear(); return false; } @@ -70,6 +71,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) { auto Res = C.interpretExpr(E); if (Res.isInvalid()) { +C.cleanup(); Stk.clear(); return false; } @@ -97,6 +99,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, (VD->getType()->isRecordType() || VD->getType()->isArrayType()); auto Res = C.interpretDecl(VD, CheckGlobalInitialized); if (Res.isInvalid()) { +C.cleanup(); Stk.clear(); return false; } diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp index 388c3612f292b..6d8aa3f20f01f 100644 --- a/clang/lib/AST/Interp/EvalEmitter.cpp +++ b/clang/lib/AST/Interp/EvalEmitter.cpp @@ -32,6 +32,11 @@ EvalEmitter::~EvalEmitter() { } } +/// Clean up all our resources. This needs to done in failed evaluations before +/// we call InterpStack::clear(), because there might be a Pointer on the stack +/// pointing into a Block in the EvalEmitter. +void EvalEmitter::cleanup() { S.cleanup(); } + EvaluationResult EvalEmitter::interpretExpr(const Expr *E, bool ConvertResultToRValue) { S.setEvalLocation(E->getExprLoc()); diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/Interp/EvalEmitter.h index 116f1d6fc134a..98d6026bbcce4 100644 --- a/clang/lib/AST/Interp/EvalEmitter.h +++ b/clang/lib/AST/Interp/EvalEmitter.h @@ -38,6 +38,9 @@ class EvalEmitter : public SourceMapper { bool ConvertResultToRValue = false); EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized); + /// Clean up all resources. + void cleanup(); + InterpState &getState() { return S; } protected: diff --git a/clang/lib/AST/Interp/InterpState.cpp b/clang/lib/AST/Interp/InterpState.cpp index 2cb87ef07fe58..550bc9f1a84b9 100644 --- a/clang/lib/AST/Interp/InterpState.cpp +++ b/clang/lib/AST/Interp/InterpState.cpp @@ -33,6 +33,8 @@ InterpState::~InterpState() { } } +void InterpState::cleanup() {} + Frame *InterpState::getCurrentFrame() { if (Current && Current->Caller) return Current; diff --git a/clang/lib/AST/Interp/InterpState.h b/clang/lib/AST/Interp/InterpState.h index d483c60c58e24..0938a723a76d0 100644 --- a/clang/lib/AST/Interp/InterpState.h +++ b/clang/lib/AST/Interp/InterpState.h @@ -39,6 +39,8 @@ class InterpState final : public State, public SourceMapper { ~InterpState(); + void cleanup(); + InterpState(const InterpState &) = delete; InterpState &operator=(const InterpState &) = delete; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
AaronBallman wrote: So are we in a chicken-and-egg situation where we need some support in-tree in order to have a reason to set up a postcommit test bot but we don't want to land untested changes? At the end of the day, if we're claiming support for something, we need it to be tested and this seems like a situation where we'd need an actual buildbot specific for the need. So we may want to proceed here in a few stages: 1) push up these changes without testing, 2) get a bot set up and have it test these changes, once it's green and we're happy then we publicly claim support, 3) if we don't get a bot set up within some reasonable timeframe, we agree to remove these changes so we don't leave untested code in the repo. WDYT? https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Static and explicit object member functions with the same parameter-type-lists (PR #93430)
https://github.com/AaronBallman approved this pull request. LGTM! https://github.com/llvm/llvm-project/pull/93430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Static and explicit object member functions with the same parameter-type-lists (PR #93430)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/93430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix-it hint for `++this` -> `++*this` when deref is modifiable (PR #94159)
@@ -13367,6 +13367,8 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E, if (!DiagnosticEmitted) { S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstVariable << VD << VD->getType(); + S.Diag(Loc, diag::note_typecheck_expression_not_modifiable_lvalue) + << E->getSourceRange(); Sirraide wrote: Yup, the diagnostic should not be issued in this case since `j` is not of pointer type; that’s pretty much exactly what I meant by ‘make sure that the failures actually make sense’. https://github.com/llvm/llvm-project/pull/94159 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
vgvassilev wrote: That would make sense. I am not sure if we can set a post commit bot though. @argentite what do you think? https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
vgvassilev wrote: @AaronBallman, to be fair, clang is testing the wasm features in terms of output. So this is wiring up a bunch of tested features that will allow execution. Clang generally does not test execution but output, so we are not creating a precedent here since that PR can be considered plumbing for downstream consumers. https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
AaronBallman wrote: > @AaronBallman, to be fair, clang is testing the wasm features in terms of > output. So this is wiring up a bunch of tested features that will allow > execution. Clang generally does not test execution but output, so we are not > creating a precedent here since that PR can be considered plumbing for > downstream consumers. If we don't have community test coverage, we'll regress that plumbing for downstream consumers. In general, we shouldn't claim we support something we don't test. However, if there is a downstream consumer that agrees to be actively responsible for repairing breakages, we sometimes allow it (e.g., https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
vgvassilev wrote: > > @AaronBallman, to be fair, clang is testing the wasm features in terms of > > output. So this is wiring up a bunch of tested features that will allow > > execution. Clang generally does not test execution but output, so we are > > not creating a precedent here since that PR can be considered plumbing for > > downstream consumers. > > If we don't have community test coverage, we'll regress that plumbing for > downstream consumers. In general, we shouldn't claim we support something we > don't test. However, if there is a downstream consumer that agrees to be > actively responsible for repairing breakages, we sometimes allow it (e.g., > https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) I am not sure if we have the same definition for "claim". FWIW I am not saying we should put any of this on the website or elsewhere. We have a downstream consumer which intergrates the emscripten version of wasm [here](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/llvm). @derthorsten is my go-to person when it comes to emscripten and llvm. I believe they are quite sensitive about breakages. In any case we will develop tests in the CppInterOp project, too. https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
AaronBallman wrote: > > > @AaronBallman, to be fair, clang is testing the wasm features in terms of > > > output. So this is wiring up a bunch of tested features that will allow > > > execution. Clang generally does not test execution but output, so we are > > > not creating a precedent here since that PR can be considered plumbing > > > for downstream consumers. > > > > > > If we don't have community test coverage, we'll regress that plumbing for > > downstream consumers. In general, we shouldn't claim we support something > > we don't test. However, if there is a downstream consumer that agrees to be > > actively responsible for repairing breakages, we sometimes allow it (e.g., > > https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) > > I am not sure if we have the same definition for "claim". FWIW I am not > saying we should put any of this on the website or elsewhere. We have a > downstream consumer which intergrates the emscripten version of wasm > [here](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/llvm). > @DerThorsten is my go-to person when it comes to emscripten and llvm. I > believe they are quite sensitive about breakages. In any case we will develop > tests in the CppInterOp project, too. I wouldn't focus on "claim" too heavily. We should not have code in-tree that's not tested except in exceptional situations and it's not clear to me that this is (or isn't) such an exceptional situation. https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [Flang][OpenMP] Add -fopenmp-force-usm option to flang (PR #94359)
https://github.com/skatrak updated https://github.com/llvm/llvm-project/pull/94359 >From 88a2553168b4fd3ad1b65b855c2bdf5aba09d126 Mon Sep 17 00:00:00 2001 From: Sergio Afonso Date: Tue, 4 Jun 2024 15:26:38 +0100 Subject: [PATCH 1/2] [Flang][OpenMP] Add -fopenmp-force-usm option to flang This patch enables the `-fopenmp-force-usm` option to be passed to the flang driver, which forwards it to the compiler frontend. This flag, when set, results in the introduction of the `unified_shared_memory` bit to the `omp.requires` attribute of the top-level module operation. This is later combined with any other target device-related REQUIRES clauses that may have been explicitly set in the compilation unit. --- clang/include/clang/Driver/Options.td | 2 +- clang/lib/Driver/ToolChains/Flang.cpp | 2 ++ flang/include/flang/Frontend/LangOptions.def | 2 ++ flang/include/flang/Tools/CrossToolHelpers.h | 20 --- flang/lib/Frontend/CompilerInvocation.cpp | 3 +++ flang/lib/Lower/OpenMP/OpenMP.cpp | 4 +++- flang/test/Driver/omp-driver-offload.f90 | 20 +++ flang/test/Lower/OpenMP/force-usm.f90 | 12 +++ .../test/Lower/OpenMP/requires-force-usm.f90 | 15 ++ flang/tools/bbc/bbc.cpp | 15 +- 10 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 flang/test/Lower/OpenMP/force-usm.f90 create mode 100644 flang/test/Lower/OpenMP/requires-force-usm.f90 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 5ab2d49c7a497..f04c220d6e1db 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3592,7 +3592,7 @@ def fopenmp_offload_mandatory : Flag<["-"], "fopenmp-offload-mandatory">, Group< HelpText<"Do not create a host fallback if offloading to the device fails.">, MarshallingInfoFlag>; def fopenmp_force_usm : Flag<["-"], "fopenmp-force-usm">, Group, - Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>, + Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Force behvaior as if the user specified pragma omp requires unified_shared_memory.">, MarshallingInfoFlag>; def fopenmp_target_jit : Flag<["-"], "fopenmp-target-jit">, Group, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 42ca060186fd8..b7abe7b1c19bc 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -766,6 +766,8 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ); // FIXME: Clang supports a whole bunch more flags here. + if (Args.hasArg(options::OPT_fopenmp_force_usm)) +CmdArgs.push_back("-fopenmp-force-usm"); break; default: // By default, if Clang doesn't know how to generate useful OpenMP code diff --git a/flang/include/flang/Frontend/LangOptions.def b/flang/include/flang/Frontend/LangOptions.def index 2bf10826120a8..d3e1e972d1519 100644 --- a/flang/include/flang/Frontend/LangOptions.def +++ b/flang/include/flang/Frontend/LangOptions.def @@ -42,6 +42,8 @@ LANGOPT(OpenMPVersion, 32, 0) LANGOPT(OpenMPIsTargetDevice, 1, false) /// Generate OpenMP target code only for GPUs LANGOPT(OpenMPIsGPU, 1, false) +/// Generate OpenMP target code only for GPUs +LANGOPT(OpenMPForceUSM, 1, false) /// Enable debugging in the OpenMP offloading device RTL LANGOPT(OpenMPTargetDebug, 32, 0) /// Assume work-shared loops do not have more iterations than participating diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h index 77b68fc6187fa..26fbe51d329c7 100644 --- a/flang/include/flang/Tools/CrossToolHelpers.h +++ b/flang/include/flang/Tools/CrossToolHelpers.h @@ -130,16 +130,16 @@ struct OffloadModuleOpts { OffloadModuleOpts(uint32_t OpenMPTargetDebug, bool OpenMPTeamSubscription, bool OpenMPThreadSubscription, bool OpenMPNoThreadState, bool OpenMPNoNestedParallelism, bool OpenMPIsTargetDevice, - bool OpenMPIsGPU, uint32_t OpenMPVersion, std::string OMPHostIRFile = {}, - bool NoGPULib = false) + bool OpenMPIsGPU, bool OpenMPForceUSM, uint32_t OpenMPVersion, + std::string OMPHostIRFile = {}, bool NoGPULib = false) : OpenMPTargetDebug(OpenMPTargetDebug), OpenMPTeamSubscription(OpenMPTeamSubscription), OpenMPThreadSubscription(OpenMPThreadSubscription), OpenMPNoThreadState(OpenMPNoThreadState), OpenMPNoNestedParallelism(OpenMPNoNestedParallelism), OpenMPIsTargetDevice(OpenMPIsTargetDevice), OpenMPIsGPU(OpenMPIsGPU), -OpenMPVersion(OpenMPVersion), OMPHostIRFile(OMPHostIRFile), -NoGPULib(NoGPULib) {} +OpenMPForceUSM(OpenMPForceUSM), OpenMPVersion(OpenMPVersion), +OMPHostIRFile(OMPHostIRFile
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -259,9 +258,9 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { .bind("blockStmt"); }; - Finder->addMatcher(LocalVarCopiedFrom(anyOf(isConstRefReturningFunctionCall(), - isConstRefReturningMethodCall( - ExcludedContainerTypes))), + Finder->addMatcher(LocalVarCopiedFrom(anyOf( + isConstRefReturningFunctionCall(), + isRefReturningMethodCall(ExcludedContainerTypes))), fberger wrote: Could we call this `isRefReturningMethodCallWithConstOverloads()`? https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
vgvassilev wrote: > > > > @AaronBallman, to be fair, clang is testing the wasm features in terms > > > > of output. So this is wiring up a bunch of tested features that will > > > > allow execution. Clang generally does not test execution but output, so > > > > we are not creating a precedent here since that PR can be considered > > > > plumbing for downstream consumers. > > > > > > > > > If we don't have community test coverage, we'll regress that plumbing for > > > downstream consumers. In general, we shouldn't claim we support something > > > we don't test. However, if there is a downstream consumer that agrees to > > > be actively responsible for repairing breakages, we sometimes allow it > > > (e.g., > > > https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) > > > > > > I am not sure if we have the same definition for "claim". FWIW I am not > > saying we should put any of this on the website or elsewhere. We have a > > downstream consumer which intergrates the emscripten version of wasm > > [here](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/llvm). > > @DerThorsten is my go-to person when it comes to emscripten and llvm. I > > believe they are quite sensitive about breakages. In any case we will > > develop tests in the CppInterOp project, too. > > I wouldn't focus on "claim" too heavily. Ok. > We should not have code in-tree that's not tested except in exceptional > situations and it's not clear to me that this is (or isn't) such an > exceptional situation. Well, as of today I do not see how we can test execution of jit-based wasm in tree. I am not a wasm expert but IIUC, testing would require a browser and compiling llvm for emscripten and somehow running some remote execution service... My worry is that we are losing the forest for the trees because this work has stayed as a patch since maybe more than a year. It'd be a pity to wait more because that blocks downstream consumers in practice... https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: @vgvassilev The reland d999ce0302f06d250f6d496b56a5a5f2dc331e61 makes the clang reject the valid code now: ``` $ cat /tmp/t33.cpp #include #include int main() { } $ ./bin/clang -Xclang -fsyntax-only -Xclang=-fincremental-extensions -stdlib=libc++ /tmp/t33.cpp <<< In file included from /tmp/t33.cpp:2: In file included from /usr/include/c++/v1/algorithm:1712: In file included from /usr/include/c++/v1/memory:877: In file included from /usr/include/c++/v1/iterator:684: In file included from /usr/include/c++/v1/__iterator/common_iterator.h:22: /usr/include/c++/v1/variant:1024:43: error: use of undeclared identifier '__arg'; did you mean '_pthread_cleanup_buffer::__arg'? 1024 | } __impl{this, _VSTD::forward<_Arg>(__arg)}; | ^ /usr/include/pthread.h:162:9: note: '_pthread_cleanup_buffer::__arg' declared here 162 | void *__arg;/* Its argument. */ | ^ In file included from /tmp/t33.cpp:2: In file included from /usr/include/c++/v1/algorithm:1861: In file included from /usr/include/c++/v1/__algorithm/ranges_stable_partition.h:15: /usr/include/c++/v1/__algorithm/stable_partition.h:246:18: error: use of undeclared label '__second_half_done' 246 | goto __second_half_done; | ^ 2 errors generated. ``` Can you take a look? https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Comments] Support for parsing headers in Doxygen \par commands (PR #91100)
@@ -149,6 +149,63 @@ class TextTokenRetokenizer { addToken(); } + /// Check if this line starts with @par or \par + bool startsWithParCommand() { +unsigned Offset = 1; + +/// Skip all whitespace characters at the beginning. +/// This needs to backtrack because Pos has already advanced past the +/// actual \par or @par command by the time this function is called. +while (isWhitespace(*(Pos.BufferPtr - Offset))) + Offset++; AaronBallman wrote: Rather than backtracking, can't we still do a peek ahead? e.g., once we've seen `@par`, we can do a peek to see if the next token is a newline or not (or do a scan through the buffer to see if there is a non-whitespace character or only whitespace ending with a newline/eof)? https://github.com/llvm/llvm-project/pull/91100 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
vgvassilev wrote: @hokein, ah, that's annoying. Can you provide the entire proprocessed file that does not work? I'd like to bisect and debug. https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { fberger wrote: It looks like we look up by name, do we also need to confirm that the return types are the same, or would overloading otherwise not be allowed and that's why it's implied? https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { + return candidate; +} + } + return nullptr; +} + +// Returns true if both types refer to the same to the same type, +// ignoring the const-qualifier. +bool isSameTypeIgnoringConst(QualType A, QualType B) { + A = A.getCanonicalType(); + B = B.getCanonicalType(); + A.addConst(); + B.addConst(); + return A == B; +} + +// Returns true if both types are pointers or reference to the same type, +// ignoring the const-qualifier. +bool pointsToSameTypeIgnoringConst(QualType A, QualType B) { + assert(A->isPointerType() || A->isReferenceType()); + assert(B->isPointerType() || B->isReferenceType()); + return isSameTypeIgnoringConst(A->getPointeeType(), B->getPointeeType()); +} + +// Return true if non-const member function `M` likely does not mutate `*this`. +// +// Note that if the member call selects a method/operator `f` that +// is not const-qualified, then we also consider that the object is +// not mutated if: +// - (A) there is a const-qualified overload `cf` of `f` that has +// the +//same ref-qualifiers; +// - (B) * `f` returns a value, or +//* if `f` returns a `T&`, `cf` returns a `const T&` (up to +// possible aliases such as `reference` and +// `const_reference`), or +//* if `f` returns a `T*`, `cf` returns a `const T*` (up to +// possible aliases). +// - (C) the result of the call is not mutated. +// +// The assumption that `cf` has the same semantics as `f`. +// For example: +// - In `std::vector v; const T t = v[...];`, we consider that +// expression `v[...]` does not mutate `v` as +//`T& std::vector::operator[]` has a const overload +// `const T& std::vector::operator[] const`, and the +// result expression of type `T&` is only used as a `const T&`; +// - In `std::map m; V v = m.at(...);`, we consider +// `m.at(...)` to be an immutable access for the same reason. +// However: +// - In `std::map m; const V v = m[...];`, We consider that +// `m[...]` mutates `m` as `V& std::map::operator[]` does +// not have a const overload. +// - In `std::vector v; T& t = v[...];`, we consider that +// expression `v[...]` mutates `v` as the result is kept as a +// mutable reference. +// +// This function checks (A) ad (B), but the caller should make sure that the +// object is not mutated through the return value. +bool isLikelyShallowConst(const CXXMethodDecl &M) { + assert(!M.isConst()); + // The method can mutate our variable. + + // (A) + const CXXMethodDecl *ConstOverload = findConstOverload(M); + if (ConstOverload == nullptr) { +return false; + } + + // (B) + const QualType CallTy = M.getReturnType().getCanonicalType(); + const QualType OverloadTy = ConstOverload->getReturnType().getCanonicalType(); + if (CallTy->isReferenceType()) { +if (!(OverloadTy->isReferenceType() && fberger wrote: I would find: `(!isReferenceType() || !pointsToSameTypIgnoringConst())` easier to parse here. https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { + return candidate; +} + } + return nullptr; +} + +// Returns true if both types refer to the same to the same type, +// ignoring the const-qualifier. +bool isSameTypeIgnoringConst(QualType A, QualType B) { + A = A.getCanonicalType(); + B = B.getCanonicalType(); + A.addConst(); + B.addConst(); + return A == B; +} + +// Returns true if both types are pointers or reference to the same type, +// ignoring the const-qualifier. +bool pointsToSameTypeIgnoringConst(QualType A, QualType B) { + assert(A->isPointerType() || A->isReferenceType()); + assert(B->isPointerType() || B->isReferenceType()); + return isSameTypeIgnoringConst(A->getPointeeType(), B->getPointeeType()); +} + +// Return true if non-const member function `M` likely does not mutate `*this`. +// +// Note that if the member call selects a method/operator `f` that +// is not const-qualified, then we also consider that the object is +// not mutated if: +// - (A) there is a const-qualified overload `cf` of `f` that has +// the +//same ref-qualifiers; +// - (B) * `f` returns a value, or +//* if `f` returns a `T&`, `cf` returns a `const T&` (up to +// possible aliases such as `reference` and +// `const_reference`), or +//* if `f` returns a `T*`, `cf` returns a `const T*` (up to +// possible aliases). +// - (C) the result of the call is not mutated. +// +// The assumption that `cf` has the same semantics as `f`. +// For example: +// - In `std::vector v; const T t = v[...];`, we consider that +// expression `v[...]` does not mutate `v` as +//`T& std::vector::operator[]` has a const overload +// `const T& std::vector::operator[] const`, and the +// result expression of type `T&` is only used as a `const T&`; +// - In `std::map m; V v = m.at(...);`, we consider +// `m.at(...)` to be an immutable access for the same reason. +// However: +// - In `std::map m; const V v = m[...];`, We consider that +// `m[...]` mutates `m` as `V& std::map::operator[]` does +// not have a const overload. +// - In `std::vector v; T& t = v[...];`, we consider that +// expression `v[...]` mutates `v` as the result is kept as a +// mutable reference. +// +// This function checks (A) ad (B), but the caller should make sure that the +// object is not mutated through the return value. +bool isLikelyShallowConst(const CXXMethodDecl &M) { + assert(!M.isConst()); + // The method can mutate our variable. + + // (A) + const CXXMethodDecl *ConstOverload = findConstOverload(M); + if (ConstOverload == nullptr) { +return false; + } + + // (B) + const QualType CallTy = M.getReturnType().getCanonicalType(); + const QualType OverloadTy = ConstOverload->getReturnType().getCanonicalType(); + if (CallTy->isReferenceType()) { +if (!(OverloadTy->isReferenceType() && + pointsToSameTypeIgnoringConst(CallTy, OverloadTy))) { + return false; +} fberger wrote: Can we return true here early and avoid nesting below? https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { + return candidate; +} + } + return nullptr; +} + +// Returns true if both types refer to the same to the same type, fberger wrote: Nit: Remove duplicae "to the same". https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
vgvassilev wrote: I realize I do not entirely understand the role of the IdResolver chain in c++. Perhaps we are better of changing this line to: ```cpp if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC) IdResolver.RemoveDecl(D); ``` to ``` if (!PP.isIncrementalProcessingEnabled() || !getLangOpts().C) IdResolver.RemoveDecl(D); ``` This way will limit the scope to the actual intent without assuming the IdResolver changes are irrelevant for languages such as C++. Can you test if that works? https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
DerThorsten wrote: > > > @AaronBallman, to be fair, clang is testing the wasm features in terms of > > > output. So this is wiring up a bunch of tested features that will allow > > > execution. Clang generally does not test execution but output, so we are > > > not creating a precedent here since that PR can be considered plumbing > > > for downstream consumers. > > > > > > If we don't have community test coverage, we'll regress that plumbing for > > downstream consumers. In general, we shouldn't claim we support something > > we don't test. However, if there is a downstream consumer that agrees to be > > actively responsible for repairing breakages, we sometimes allow it (e.g., > > https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) > > I am not sure if we have the same definition for "claim". FWIW I am not > saying we should put any of this on the website or elsewhere. We have a > downstream consumer which intergrates the emscripten version of wasm > [here](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/llvm). > @DerThorsten is my go-to person when it comes to emscripten and llvm. I > believe they are quite sensitive about breakages. In any case we will develop > tests in the CppInterOp project, too. For emscripten-forge recipes of xeus-cpp /clang you can break whatever you want. I am sure there are no deployments / users yet https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
fanbo-meng wrote: @uweigand can you review again pls? thanks https://github.com/llvm/llvm-project/pull/91384 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenACC] Loop construct basic Sema and AST work (PR #93742)
https://github.com/erichkeane closed https://github.com/llvm/llvm-project/pull/93742 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 42f4e50 - [OpenACC] Loop construct basic Sema and AST work (#93742)
Author: Erich Keane Date: 2024-06-05T06:21:48-07:00 New Revision: 42f4e505a38480b6a714b503dd94631ae029 URL: https://github.com/llvm/llvm-project/commit/42f4e505a38480b6a714b503dd94631ae029 DIFF: https://github.com/llvm/llvm-project/commit/42f4e505a38480b6a714b503dd94631ae029.diff LOG: [OpenACC] Loop construct basic Sema and AST work (#93742) This patch implements the 'loop' construct AST, as well as the basic appertainment rule. Additionally, it sets up the 'parent' compute construct, which is necessary for codegen/other diagnostics. A 'loop' can apply to a for or range-for loop, otherwise it has no other restrictions (though some of its clauses do). Added: clang/test/AST/ast-print-openacc-loop-construct.cpp clang/test/SemaOpenACC/loop-ast.cpp clang/test/SemaOpenACC/loop-loc-and-stmt.c clang/test/SemaOpenACC/loop-loc-and-stmt.cpp Modified: clang/include/clang-c/Index.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/AST/StmtOpenACC.h clang/include/clang/AST/TextNodeDumper.h clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/StmtNodes.td clang/include/clang/Sema/SemaOpenACC.h clang/include/clang/Serialization/ASTBitCodes.h clang/lib/AST/StmtOpenACC.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/StmtProfile.cpp clang/lib/AST/TextNodeDumper.cpp clang/lib/CodeGen/CGStmt.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/Parse/ParseOpenACC.cpp clang/lib/Sema/SemaExceptionSpec.cpp clang/lib/Sema/SemaOpenACC.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/test/ParserOpenACC/parse-clauses.c clang/test/ParserOpenACC/parse-clauses.cpp clang/test/ParserOpenACC/parse-constructs.c clang/test/SemaOpenACC/compute-construct-async-clause.c clang/test/SemaOpenACC/compute-construct-attach-clause.c clang/test/SemaOpenACC/compute-construct-copy-clause.c clang/test/SemaOpenACC/compute-construct-copyin-clause.c clang/test/SemaOpenACC/compute-construct-copyout-clause.c clang/test/SemaOpenACC/compute-construct-create-clause.c clang/test/SemaOpenACC/compute-construct-default-clause.c clang/test/SemaOpenACC/compute-construct-deviceptr-clause.c clang/test/SemaOpenACC/compute-construct-firstprivate-clause.c clang/test/SemaOpenACC/compute-construct-if-clause.c clang/test/SemaOpenACC/compute-construct-no_create-clause.c clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c clang/test/SemaOpenACC/compute-construct-num_workers-clause.c clang/test/SemaOpenACC/compute-construct-present-clause.c clang/test/SemaOpenACC/compute-construct-self-clause.c clang/test/SemaOpenACC/compute-construct-vector_length-clause.c clang/test/SemaOpenACC/compute-construct-wait-clause.c clang/tools/libclang/CIndex.cpp clang/tools/libclang/CXCursor.cpp Removed: diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 365b607c74117..ce2282937f86c 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2150,7 +2150,11 @@ enum CXCursorKind { */ CXCursor_OpenACCComputeConstruct = 320, - CXCursor_LastStmt = CXCursor_OpenACCComputeConstruct, + /** OpenACC Loop Construct. + */ + CXCursor_OpenACCLoopConstruct = 321, + + CXCursor_LastStmt = CXCursor_OpenACCLoopConstruct, /** * Cursor that represents the translation unit itself. diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 99093aa17972c..aa55e2e7e8718 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -4000,6 +4000,8 @@ bool RecursiveASTVisitor::VisitOpenACCClauseList( DEF_TRAVERSE_STMT(OpenACCComputeConstruct, { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) +DEF_TRAVERSE_STMT(OpenACCLoopConstruct, + { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h index 04daf511f5871..b3aea09be03dd 100644 --- a/clang/include/clang/AST/StmtOpenACC.h +++ b/clang/include/clang/AST/StmtOpenACC.h @@ -113,6 +113,8 @@ class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt { return const_cast(this)->children(); } }; + +class OpenACCLoopConstruct; /// This class represents a compute construct, representing a 'Kind' of /// `parallel', 'serial', or 'kernel'. These constructs are associated with a /// 'structured block', defined as: @@ -165,6 +167,11 @@ class OpenACCComputeConstr
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: Thanks for the prompt response. I think limiting it to C-only will fix the issue (note that there is no `C` in `LangOpts`, you may want to use `!getLangOpts().CPlusPlus` to exclude C++). https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
pdherbemont wrote: > One question I have is whether there will be follow-up work for other thread > safety attributes (`acquire_capability`, `try_acquire_capability`, etc)? They already work fine in C so far. But if you are aware of some issues don't hesitate to let me know! https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
vgvassilev wrote: > Thanks for the prompt response. I think limiting it to C-only will fix the > issue (note that there is no `C` in `LangOpts`, you may want to use > `!getLangOpts().CPlusPlus` to exclude C++). Makes sense. If that works for you, we can check this in. I want to somehow record this breakage in the form of a test for our future selves when decide to revisit this workaround-looking code. Out of curiosity, in what context you use `-fincremental-extensions`? https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
vgvassilev wrote: > > > > @AaronBallman, to be fair, clang is testing the wasm features in terms > > > > of output. So this is wiring up a bunch of tested features that will > > > > allow execution. Clang generally does not test execution but output, so > > > > we are not creating a precedent here since that PR can be considered > > > > plumbing for downstream consumers. > > > > > > > > > If we don't have community test coverage, we'll regress that plumbing for > > > downstream consumers. In general, we shouldn't claim we support something > > > we don't test. However, if there is a downstream consumer that agrees to > > > be actively responsible for repairing breakages, we sometimes allow it > > > (e.g., > > > https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) > > > > > > I am not sure if we have the same definition for "claim". FWIW I am not > > saying we should put any of this on the website or elsewhere. We have a > > downstream consumer which intergrates the emscripten version of wasm > > [here](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/llvm). > > @DerThorsten is my go-to person when it comes to emscripten and llvm. I > > believe they are quite sensitive about breakages. In any case we will > > develop tests in the CppInterOp project, too. > > For emscripten-forge recipes of xeus-cpp /clang you can break whatever you > want. I am sure there are no deployments / users yet > > > > @AaronBallman, to be fair, clang is testing the wasm features in terms > > > > of output. So this is wiring up a bunch of tested features that will > > > > allow execution. Clang generally does not test execution but output, so > > > > we are not creating a precedent here since that PR can be considered > > > > plumbing for downstream consumers. > > > > > > > > > If we don't have community test coverage, we'll regress that plumbing for > > > downstream consumers. In general, we shouldn't claim we support something > > > we don't test. However, if there is a downstream consumer that agrees to > > > be actively responsible for repairing breakages, we sometimes allow it > > > (e.g., > > > https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) > > > > > > I am not sure if we have the same definition for "claim". FWIW I am not > > saying we should put any of this on the website or elsewhere. We have a > > downstream consumer which intergrates the emscripten version of wasm > > [here](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/llvm). > > @DerThorsten is my go-to person when it comes to emscripten and llvm. I > > believe they are quite sensitive about breakages. In any case we will > > develop tests in the CppInterOp project, too. > > For emscripten-forge recipes of xeus-cpp /clang you can break whatever you > want. I am sure there are no deployments / users yet I think Aaron's question was if we land this PR and it regresses over time, would our downstream clients be able to catch it in a timely manner. https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: > Out of curiosity, in what context you use -fincremental-extensions? The code snippet I provided is extracted from our internal test. We have an internal clang-tool (with the `incremental-extensions` on) to generate headers https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Support wasm execution (PR #86402)
AaronBallman wrote: > > > > > @AaronBallman, to be fair, clang is testing the wasm features in > > > > > terms of output. So this is wiring up a bunch of tested features that > > > > > will allow execution. Clang generally does not test execution but > > > > > output, so we are not creating a precedent here since that PR can be > > > > > considered plumbing for downstream consumers. > > > > > > > > > > > > If we don't have community test coverage, we'll regress that plumbing > > > > for downstream consumers. In general, we shouldn't claim we support > > > > something we don't test. However, if there is a downstream consumer > > > > that agrees to be actively responsible for repairing breakages, we > > > > sometimes allow it (e.g., > > > > https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073) > > > > > > > > > I am not sure if we have the same definition for "claim". FWIW I am not > > > saying we should put any of this on the website or elsewhere. We have a > > > downstream consumer which intergrates the emscripten version of wasm > > > [here](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/llvm). > > > @DerThorsten is my go-to person when it comes to emscripten and llvm. I > > > believe they are quite sensitive about breakages. In any case we will > > > develop tests in the CppInterOp project, too. > > > > > > I wouldn't focus on "claim" too heavily. > > Ok. > > > We should not have code in-tree that's not tested except in exceptional > > situations and it's not clear to me that this is (or isn't) such an > > exceptional situation. > > Well, as of today I do not see how we can test execution of jit-based wasm in > tree. I am not a wasm expert but IIUC, testing would require a browser and > compiling llvm for emscripten and somehow running some remote execution > service... Yeah, we don't have any existing test infrastructure we could lean on for it. However, this doesn't seem impossible to test; surely other projects have figured out a test harness for WASM? > My worry is that we are losing the forest for the trees because this work has > stayed as a patch since maybe more than a year. It'd be a pity to wait more > because that blocks downstream consumers in practice... Yeah, it's a tough tradeoff. The two things I'm specifically worried about are: 1) users of the downstream see a break and (eventually) report it to Clang rather than the downstream, so now we have to triage it without a way to reproduce, 2) we change internal APIs and need to update this code but have no way to determine if those updates will or won't break the functionality. If the downstream that needs this functionality can commit to be responsible for maintaining it within Clang, that would help alleviate the concerns somewhat. https://github.com/llvm/llvm-project/pull/86402 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
vgvassilev wrote: > > Out of curiosity, in what context you use -fincremental-extensions? > > The code snippet I provided is extracted from our internal test. We have an > internal clang-tool (with the `incremental-extensions` on) to generate headers I am a bit overwhelmed right now, are you willing to open a PR with that change so we can merge it -- otherwise I could look later this week :( https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [Flang][OpenMP] Add -fopenmp-force-usm option to flang (PR #94359)
skatrak wrote: Thank your for the reviews. Merging now since buildbot failure is unrelated. https://github.com/llvm/llvm-project/pull/94359 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] b954926 - [Flang][OpenMP] Add -fopenmp-force-usm option to flang (#94359)
Author: Sergio Afonso Date: 2024-06-05T14:43:58+01:00 New Revision: b9549261e218cee2ad1305fb7272b831799b7bfe URL: https://github.com/llvm/llvm-project/commit/b9549261e218cee2ad1305fb7272b831799b7bfe DIFF: https://github.com/llvm/llvm-project/commit/b9549261e218cee2ad1305fb7272b831799b7bfe.diff LOG: [Flang][OpenMP] Add -fopenmp-force-usm option to flang (#94359) This patch enables the `-fopenmp-force-usm` option to be passed to the flang driver, which forwards it to the compiler frontend. This flag, when set, results in the introduction of the `unified_shared_memory` bit to the `omp.requires` attribute of the top-level module operation. This is later combined with any other target device-related REQUIRES clauses that may have been explicitly set in the compilation unit. Added: flang/test/Lower/OpenMP/force-usm.f90 flang/test/Lower/OpenMP/requires-force-usm.f90 Modified: clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/Flang.cpp flang/include/flang/Frontend/LangOptions.def flang/include/flang/Tools/CrossToolHelpers.h flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Lower/OpenMP/OpenMP.cpp flang/test/Driver/omp-driver-offload.f90 flang/tools/bbc/bbc.cpp Removed: diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 5ab2d49c7a497..f04c220d6e1db 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3592,7 +3592,7 @@ def fopenmp_offload_mandatory : Flag<["-"], "fopenmp-offload-mandatory">, Group< HelpText<"Do not create a host fallback if offloading to the device fails.">, MarshallingInfoFlag>; def fopenmp_force_usm : Flag<["-"], "fopenmp-force-usm">, Group, - Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>, + Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Force behvaior as if the user specified pragma omp requires unified_shared_memory.">, MarshallingInfoFlag>; def fopenmp_target_jit : Flag<["-"], "fopenmp-target-jit">, Group, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 42ca060186fd8..9609a1dc65c09 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -765,6 +765,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fopenmp"); Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ); + if (Args.hasArg(options::OPT_fopenmp_force_usm)) +CmdArgs.push_back("-fopenmp-force-usm"); + // FIXME: Clang supports a whole bunch more flags here. break; default: diff --git a/flang/include/flang/Frontend/LangOptions.def b/flang/include/flang/Frontend/LangOptions.def index 2bf10826120a8..d3e1e972d1519 100644 --- a/flang/include/flang/Frontend/LangOptions.def +++ b/flang/include/flang/Frontend/LangOptions.def @@ -42,6 +42,8 @@ LANGOPT(OpenMPVersion, 32, 0) LANGOPT(OpenMPIsTargetDevice, 1, false) /// Generate OpenMP target code only for GPUs LANGOPT(OpenMPIsGPU, 1, false) +/// Generate OpenMP target code only for GPUs +LANGOPT(OpenMPForceUSM, 1, false) /// Enable debugging in the OpenMP offloading device RTL LANGOPT(OpenMPTargetDebug, 32, 0) /// Assume work-shared loops do not have more iterations than participating diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h index 77b68fc6187fa..1d890fd8e1f6f 100644 --- a/flang/include/flang/Tools/CrossToolHelpers.h +++ b/flang/include/flang/Tools/CrossToolHelpers.h @@ -130,16 +130,16 @@ struct OffloadModuleOpts { OffloadModuleOpts(uint32_t OpenMPTargetDebug, bool OpenMPTeamSubscription, bool OpenMPThreadSubscription, bool OpenMPNoThreadState, bool OpenMPNoNestedParallelism, bool OpenMPIsTargetDevice, - bool OpenMPIsGPU, uint32_t OpenMPVersion, std::string OMPHostIRFile = {}, - bool NoGPULib = false) + bool OpenMPIsGPU, bool OpenMPForceUSM, uint32_t OpenMPVersion, + std::string OMPHostIRFile = {}, bool NoGPULib = false) : OpenMPTargetDebug(OpenMPTargetDebug), OpenMPTeamSubscription(OpenMPTeamSubscription), OpenMPThreadSubscription(OpenMPThreadSubscription), OpenMPNoThreadState(OpenMPNoThreadState), OpenMPNoNestedParallelism(OpenMPNoNestedParallelism), OpenMPIsTargetDevice(OpenMPIsTargetDevice), OpenMPIsGPU(OpenMPIsGPU), -OpenMPVersion(OpenMPVersion), OMPHostIRFile(OMPHostIRFile), -NoGPULib(NoGPULib) {} +OpenMPForceUSM(OpenMPForceUSM), OpenMPVersion(OpenMPVersion), +OMPHostIRFile(OMPHostIRFile), NoGPULib(NoGPULib) {} OffloadModuleOpts(Fortran::frontend::LangOptions &Opts) : OpenMPTargetDebug(Opts.OpenMPTargetDebug), @@ -148,8 +148,9 @@ struct OffloadModuleOpts { OpenMPNoThre
[clang] [flang] [Flang][OpenMP] Add -fopenmp-force-usm option to flang (PR #94359)
https://github.com/skatrak closed https://github.com/llvm/llvm-project/pull/94359 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: > I want to somehow record this breakage in the form of a test for our future > selves when decide to revisit this workaround-looking code. This is the processed file https://gist.github.com/hokein/e4a5881329c3956494afa2de7d350476. > I am a bit overwhelmed right now, are you willing to open a PR with that > change so we can merge it -- otherwise I could look later this week :( Sure, I will prepare one. https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Decouple feature dependency expansion. (PR #94279)
https://github.com/labrinea updated https://github.com/llvm/llvm-project/pull/94279 >From a413428bb0fdcd45b4a251e385b6cc00ff6a0a2c Mon Sep 17 00:00:00 2001 From: Alexandros Lamprineas Date: Mon, 3 Jun 2024 19:57:49 +0100 Subject: [PATCH 1/3] [AArch64] Decouple feature dependency expansion. The dependency expansion step which was introduced by FMV has been erroneously used for non-FMV features, for example when parsing the target attribute. The PR #93695 has rectified most of the tests which were relying on dependency expansion of target features specified on the -cc1 command line. In this patch I am decoupling the dependency expansion of features specified on the target attribute from FMV. To do that first I am expanding FMV dependencies before passing the list of target features to initFeatureMap(). Similarly when parsing the target attribute I am reconstructing an ExtensionSet from the list of target features which was created during the command line option parsing. The attribute parsing may toggle bits of that ExtensionSet and at the end it is converted to a list of target features. Those are passed to initFeatureMap(), which no longer requires an override. A side effect of this refactoring is that features specified on the target_version attribute now supersede the command line options, which is what should be happening in the first place. --- clang/include/clang/AST/ASTContext.h | 3 - clang/lib/AST/ASTContext.cpp | 53 - clang/lib/Basic/Targets/AArch64.cpp | 99 + clang/lib/Basic/Targets/AArch64.h | 4 - .../CodeGen/aarch64-cpu-supports-target.c | 2 +- .../aarch64-sme-attrs.cpp | 2 +- clang/test/CodeGen/aarch64-targetattr.c | 41 --- clang/test/CodeGen/attr-target-version.c | 46 clang/test/Sema/aarch64-neon-target.c | 4 +- clang/test/Sema/builtin-cpu-supports.c| 2 +- .../llvm/TargetParser/AArch64TargetParser.h | 104 +++--- llvm/lib/Target/AArch64/AArch64Features.td| 2 +- llvm/lib/TargetParser/AArch64TargetParser.cpp | 53 ++--- 13 files changed, 201 insertions(+), 214 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a1d1d1c51cd41..8bce4812f0d48 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3203,9 +3203,6 @@ class ASTContext : public RefCountedBase { /// valid feature names. ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; - std::vector - filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const; - void getFunctionFeatureMap(llvm::StringMap &FeatureMap, const FunctionDecl *) const; void getFunctionFeatureMap(llvm::StringMap &FeatureMap, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 73d3b152c49f1..6b7cfbe48796a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -87,6 +87,7 @@ #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/AArch64TargetParser.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -13663,17 +13664,18 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { } } -std::vector ASTContext::filterFunctionTargetVersionAttrs( -const TargetVersionAttr *TV) const { - assert(TV != nullptr); - llvm::SmallVector Feats; - std::vector ResFeats; - TV->getFeatures(Feats); - for (auto &Feature : Feats) -if (Target->validateCpuSupports(Feature.str())) - // Use '?' to mark features that came from TargetVersion. - ResFeats.push_back("?" + Feature.str()); - return ResFeats; +// Given a list of FMV features, add each of their backend features to the list. +static void +getFMVBackendFeaturesFor(const llvm::SmallVectorImpl &FMVFeatStrings, + std::vector &BackendFeats) { + for (StringRef F : FMVFeatStrings) { +if (auto FMVExt = llvm::AArch64::parseArchExtension(F)) { + SmallVector Feats; + FMVExt->DependentFeatures.split(Feats, ',', -1, false); + for (StringRef F : Feats) +BackendFeats.push_back(F.str()); +} + } } ParsedTargetAttr @@ -13708,10 +13710,12 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, // Make a copy of the features as passed on the command line into the // beginning of the additional features from the function to override. -ParsedAttr.Features.insert( -ParsedAttr.Features.begin(), -Target->getTargetOpts().FeaturesAsWritten.begin(), -Target->getTargetOpts().FeaturesAsWritten.end()); +// AArch64 handles command line option features in parseTargetAttr(). +if (!Target->getTriple().isAArch64()) + ParsedAttr.Features.insert( + ParsedAttr.Features.begin(), +
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/94471 The incremental processing mode doesn't seem to work well for C++. >From 8457c4aa1758d10188da5978d30d2d1ed505e01e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 15:46:56 +0200 Subject: [PATCH] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f2dc331e61 The incremental processing mode doesn't seem to work well for C++. --- clang/lib/Sema/SemaDecl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a6734ef8c30aa..4b9b735f1cfb4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2288,7 +2288,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Partial translation units that are created in incremental processing must // not clean up the IdResolver because PTUs should take into account the // declarations that came from previous PTUs. -if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC) +if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC || +getLangOpts().CPlusPlus) IdResolver.RemoveDecl(D); // Warn on it if we are shadowing a declaration. ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Haojian Wu (hokein) Changes The incremental processing mode doesn't seem to work well for C++. --- Full diff: https://github.com/llvm/llvm-project/pull/94471.diff 1 Files Affected: - (modified) clang/lib/Sema/SemaDecl.cpp (+2-1) ``diff diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a6734ef8c30aa..4b9b735f1cfb4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2288,7 +2288,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Partial translation units that are created in incremental processing must // not clean up the IdResolver because PTUs should take into account the // declarations that came from previous PTUs. -if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC) +if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC || +getLangOpts().CPlusPlus) IdResolver.RemoveDecl(D); // Warn on it if we are shadowing a declaration. `` https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} Pierre-vh wrote: ```suggestion VariadicABIInfo() = default; ``` https://github.com/llvm/llvm-project/pull/93362 ___ cfe-
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); Pierre-vh wrote: ```suggestion static std::unique_ptr create(const llvm::Triple &Triple); ```
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
https://github.com/pdherbemont updated https://github.com/llvm/llvm-project/pull/94216 >From 0fd6864d7f0a85ca82f3c926a51403383c7ea0c7 Mon Sep 17 00:00:00 2001 From: Pierre d'Herbemont Date: Wed, 29 May 2024 11:11:03 +0200 Subject: [PATCH] Support [[guarded_by(mutex)]] attribute inside C struct Today, it's only supported inside C++ classes or top level C/C++ declaration. I mostly copied and adapted over the code from the [[counted_by(value)]] lookup. I had to change ast-dump-color.cpp because of the way the expression marking now marks the mutex as "used" instead of "referenced". If I change the expression parsing to use `ExpressionEvaluationContext::Unevaluated` then I get the mutex as "referenced" but I lose the C++ check for "invalid use of non-static data member". --- clang/include/clang/Basic/Attr.td | 4 +- clang/include/clang/Parse/Parser.h| 8 +++ clang/include/clang/Sema/Sema.h | 6 +- clang/lib/Parse/ParseDecl.cpp | 64 ++- clang/lib/Sema/SemaExpr.cpp | 4 +- clang/test/AST/ast-dump-color.cpp | 4 +- clang/test/Sema/warn-thread-safety-analysis.c | 10 ++- .../SemaCXX/warn-thread-safety-parsing.cpp| 6 +- 8 files changed, 90 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index c6f08860f203a..15663c9eac686 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3633,7 +3633,7 @@ def NoThreadSafetyAnalysis : InheritableAttr { def GuardedBy : InheritableAttr { let Spellings = [GNU<"guarded_by">]; let Args = [ExprArgument<"Arg">]; - let LateParsed = LateAttrParseStandard; + let LateParsed = LateAttrParseExperimentalExt; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let InheritEvenIfAlreadyPresent = 1; @@ -3644,7 +3644,7 @@ def GuardedBy : InheritableAttr { def PtGuardedBy : InheritableAttr { let Spellings = [GNU<"pt_guarded_by">]; let Args = [ExprArgument<"Arg">]; - let LateParsed = LateAttrParseStandard; + let LateParsed = LateAttrParseExperimentalExt; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let InheritEvenIfAlreadyPresent = 1; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d054b8cf0d240..39cc6b8e1fbeb 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3128,6 +3128,14 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *ScopeName, SourceLocation ScopeLoc, ParsedAttr::Form Form); + void ParseGuardedByAttribute(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + SourceLocation *EndLoc, + ParsedAttr::Form Form); + void ParseTypeofSpecifier(DeclSpec &DS); SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7dea2b6826cfd..d41557270fe31 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5078,7 +5078,7 @@ class Sema final : public SemaBase { enum ExpressionKind { EK_Decltype, EK_TemplateArgument, - EK_BoundsAttrArgument, + EK_AttrArgument, EK_Other } ExprContext; @@ -5185,10 +5185,10 @@ class Sema final : public SemaBase { return const_cast(this)->parentEvaluationContext(); }; - bool isBoundsAttrContext() const { + bool isAttrContext() const { return ExprEvalContexts.back().ExprContext == ExpressionEvaluationContextRecord::ExpressionKind:: - EK_BoundsAttrArgument; + EK_AttrArgument; } /// Increment when we find a reference; decrement when we find an ignored diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c528917437332..cfa6fa8b4926f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -671,6 +671,12 @@ void Parser::ParseGNUAttributeArgs( ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, Form); return; + } else if (AttrKind == ParsedAttr::AT_GuardedBy || + AttrKind == ParsedAttr::AT_PtGuardedBy) { +ParseGuardedByAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, +EndLoc, +Form); +return; } else if (AttrKind == ParsedAttr::AT_CXXAssume) { ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form); return; @@ -3330,6 +3336,62 @@ void Parser::DistributeCLateParsedAttrs(Decl *
[clang] [Clang] Prevent null pointer dereferences in SVE tuple functions (PR #94267)
@@ -10211,8 +10211,8 @@ Value *CodeGenFunction::EmitSVETupleSetOrGet(const SVETypeFlags &TypeFlags, "Expects TypleFlag isTupleSet or TypeFlags.isTupleSet()"); unsigned I = cast(Ops[1])->getSExtValue(); - auto *SingleVecTy = dyn_cast( - TypeFlags.isTupleSet() ? Ops[2]->getType() : Ty); + auto *SingleVecTy = cast( CarolineConcatto wrote: I am not sure we want the compile to crash that way, at least that is my impression. Should this be an if statement if(auto *SingleVecTy = cast){ value *Idx = ConstantInt::get(CGM.Int64Ty, I * SingleVecTy->getMinNumElements()); } Is it possible to add a test for this change too? https://github.com/llvm/llvm-project/pull/94267 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
https://github.com/pdherbemont updated https://github.com/llvm/llvm-project/pull/94216 >From 7d01e8aae371e02f23b118d5b92f39fcee72723f Mon Sep 17 00:00:00 2001 From: Pierre d'Herbemont Date: Wed, 29 May 2024 11:11:03 +0200 Subject: [PATCH] Support [[guarded_by(mutex)]] attribute inside C struct Today, it's only supported inside C++ classes or top level C/C++ declaration. I mostly copied and adapted over the code from the [[counted_by(value)]] lookup. I had to change ast-dump-color.cpp because of the way the expression marking now marks the mutex as "used" instead of "referenced". If I change the expression parsing to use `ExpressionEvaluationContext::Unevaluated` then I get the mutex as "referenced" but I lose the C++ check for "invalid use of non-static data member". --- clang/include/clang/Basic/Attr.td | 4 +- clang/include/clang/Parse/Parser.h| 7 +++ clang/include/clang/Sema/Sema.h | 7 +-- clang/lib/Parse/ParseDecl.cpp | 60 ++- clang/lib/Sema/SemaExpr.cpp | 4 +- clang/test/AST/ast-dump-color.cpp | 4 +- clang/test/Sema/warn-thread-safety-analysis.c | 8 +++ .../SemaCXX/warn-thread-safety-parsing.cpp| 6 +- 8 files changed, 84 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index c6f08860f203a..15663c9eac686 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3633,7 +3633,7 @@ def NoThreadSafetyAnalysis : InheritableAttr { def GuardedBy : InheritableAttr { let Spellings = [GNU<"guarded_by">]; let Args = [ExprArgument<"Arg">]; - let LateParsed = LateAttrParseStandard; + let LateParsed = LateAttrParseExperimentalExt; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let InheritEvenIfAlreadyPresent = 1; @@ -3644,7 +3644,7 @@ def GuardedBy : InheritableAttr { def PtGuardedBy : InheritableAttr { let Spellings = [GNU<"pt_guarded_by">]; let Args = [ExprArgument<"Arg">]; - let LateParsed = LateAttrParseStandard; + let LateParsed = LateAttrParseExperimentalExt; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let InheritEvenIfAlreadyPresent = 1; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d054b8cf0d240..fa60ef0515df1 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3128,6 +3128,13 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *ScopeName, SourceLocation ScopeLoc, ParsedAttr::Form Form); + void ParseGuardedByAttribute(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, SourceLocation *EndLoc, + ParsedAttr::Form Form); + void ParseTypeofSpecifier(DeclSpec &DS); SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7dea2b6826cfd..5207a03bb7853 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5078,7 +5078,7 @@ class Sema final : public SemaBase { enum ExpressionKind { EK_Decltype, EK_TemplateArgument, - EK_BoundsAttrArgument, + EK_AttrArgument, EK_Other } ExprContext; @@ -5185,10 +5185,9 @@ class Sema final : public SemaBase { return const_cast(this)->parentEvaluationContext(); }; - bool isBoundsAttrContext() const { + bool isAttrContext() const { return ExprEvalContexts.back().ExprContext == - ExpressionEvaluationContextRecord::ExpressionKind:: - EK_BoundsAttrArgument; + ExpressionEvaluationContextRecord::ExpressionKind::EK_AttrArgument; } /// Increment when we find a reference; decrement when we find an ignored diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c528917437332..a2d2522a2a6ba 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -671,6 +671,11 @@ void Parser::ParseGNUAttributeArgs( ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, Form); return; + } else if (AttrKind == ParsedAttr::AT_GuardedBy || + AttrKind == ParsedAttr::AT_PtGuardedBy) { +ParseGuardedByAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, +EndLoc, Form); +return; } else if (AttrKind == ParsedAttr::AT_CXXAssume) { ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form); return; @@ -3330,6 +3335,59 @@ void Parser::DistributeCLateParsedAttrs(Decl *Dcl, } }
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
@@ -3330,6 +3340,63 @@ void Parser::DistributeCLateParsedAttrs(Decl *Dcl, } } +/// GuardedBy attributes (e.g., guarded_by): +/// AttrName '(' expression ')' +void Parser::ParseGuardedByAttribute(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + SourceLocation *EndLoc, + ParsedAttr::Form Form) { + assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); + + BalancedDelimiterTracker Parens(*this, tok::l_paren); + Parens.consumeOpen(); + + if (Tok.is(tok::r_paren)) { +Diag(Tok.getLocation(), diag::err_argument_required_after_attribute); +Parens.consumeClose(); +return; + } + + ArgsVector ArgExprs; + // Don't evaluate argument when the attribute is ignored. + using ExpressionKind = + Sema::ExpressionEvaluationContextRecord::ExpressionKind; + EnterExpressionEvaluationContext EC( + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr, + ExpressionKind::EK_BoundsAttrArgument); + + ExprResult ArgExpr( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); + + if (ArgExpr.isInvalid()) { +Parens.skipToEnd(); +return; + } + + ArgExprs.push_back(ArgExpr.get()); + + auto RParens = Tok.getLocation(); + auto &AL = *Attrs.addNew( + &AttrName, SourceRange(AttrNameLoc, RParens), ScopeName, + ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form); + + if (EndLoc) { + *EndLoc = Tok.getLocation(); + } pdherbemont wrote: Switched to `EK_AttrArgument` and fixed the style (using the clang-format) thank you for the feedback! https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
@@ -671,6 +671,16 @@ void Parser::ParseGNUAttributeArgs( ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, Form); return; + } else if (AttrKind == ParsedAttr::AT_GuardedBy) { +ParseGuardedByAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, +EndLoc, +Form); +return; + } else if (AttrKind == ParsedAttr::AT_PtGuardedBy) { +ParseGuardedByAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, +EndLoc, +Form); +return; pdherbemont wrote: Done! https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
@@ -28,7 +28,12 @@ struct LOCKABLE Mutex {}; struct Foo { - struct Mutex *mu_; +struct Mutex *mu_; +struct Bar { +struct Mutex *other_mu; +} bar; + int a_value GUARDED_BY(mu_); pdherbemont wrote: Fixed https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Lower _BitInt(129+) to a different type in LLVM IR (PR #91364)
@@ -118,6 +124,37 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField) { return R; } +bool CodeGenTypes::LLVMTypeLayoutMatchesAST(QualType ASTTy, +llvm::Type *LLVMTy) { + CharUnits ASTSize = Context.getTypeSizeInChars(ASTTy); + CharUnits LLVMSize = + CharUnits::fromQuantity(getDataLayout().getTypeAllocSize(LLVMTy)); + return ASTSize == LLVMSize; +} + +llvm::Type *CodeGenTypes::convertTypeForLoadStore(QualType T, + llvm::Type *LLVMTy) { + if (!LLVMTy) +LLVMTy = ConvertType(T); + + if (!T->isBitIntType() && LLVMTy->isIntegerTy(1)) +return llvm::IntegerType::get(getLLVMContext(), + (unsigned)Context.getTypeSize(T)); + + if (T->isBitIntType()) { +llvm::Type *R = ConvertType(T); +if (!LLVMTypeLayoutMatchesAST(T, R)) + return llvm::Type::getIntNTy( + getLLVMContext(), Context.getTypeSizeInChars(T).getQuantity() * 8); momchil-velikov wrote: I don't understand why the choice of type is conditional. No matter of the "layout" matches or not, the stores have to produce valid in-memory representation (according to the target ABI), which in the general case means writing **all the** bits of the in-memory representation. https://github.com/llvm/llvm-project/pull/91364 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
https://github.com/Endilll commented: `Sema.h` changes look good to me. https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/vgvassilev approved this pull request. LGTM, can you include the produced errors and the steps to reproduce the failure in the commit log? Or refer to the github post describing it? https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
AaronBallman wrote: > > One question I have is whether there will be follow-up work for other > > thread safety attributes (`acquire_capability`, `try_acquire_capability`, > > etc)? > > They already work fine in C so far. But if you are aware of some issues don't > hesitate to let me know! Ah, sorry, of course I picked examples that appertain to functions rather than fields. But some of the other thread safety attributes have the same problem as `guarded_by`: https://godbolt.org/z/hWTMxzrns https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
pdherbemont wrote: > You may also want to consider making the attribute late parsed in C when > `-fexperimental-late-parse-attributes` is enabled. See > https://github.com/llvm/llvm-project/pull/93121/files#diff-ae2ec9524bdbeea1f06917607482634dd89af5bcbb929805032463e5dafe79e7R2260 > > That will allow the code like below: > > ``` > struct Foo { >int a_value GUARDED_BY(mu_); // attribute comes before `mu_` which needs > to be late parsed >struct Mutext *mu_; > } > ``` Adopted `LateAttrParseExperimentalExt`. Let me know if that looks okay. https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
pdherbemont wrote: > > > One question I have is whether there will be follow-up work for other > > > thread safety attributes (`acquire_capability`, `try_acquire_capability`, > > > etc)? > > > > > > They already work fine in C so far. But if you are aware of some issues > > don't hesitate to let me know! > > Ah, sorry, of course I picked examples that appertain to functions rather > than fields. But some of the other thread safety attributes have the same > problem as `guarded_by`: https://godbolt.org/z/hWTMxzrns Oh yes – maybe it makes sense to fix them in this commit. Let me try to look into that quickly. https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][CodeGen] Make `UnqualPtrTy` truly unqualified (PR #94388)
AlexVlx wrote: > I think the point is there are two things going on here that people think of > as unqualified: > > 1. "Give me a pointer that's whatever `void *` is" > 2. "Give me a pointer in some address space just so I can put a global in > some metadata" > > The vast majority of the time we're talking about 1, which is what most > people would think of unqualified as meaning. #93601 / #93914 are about the > three special cases that are case 2 above. But those are a special case, and > normally when people say unqualified they mean "default" address space / > `void *`. Building on the above, let me add a bit more colour I should have added from the get go: - More often than not, for case (1) above, folks probably want (knowingly or not) a `void*` that "works", with no actual concern for the address space (the "default"); - As an example, for targets which model themselves / draw inspiration from e.g. OpenCL, this'd be a generic / flat pointer, but there's no way for the FE to query that from the target (today?), and that information isn't really observably encoded in something like the DataLayout; if we were to add something like that, then unqualified would / should correspond to this, IMHO (could well happen to be 0 in practice); - We have targets that map `LangAS::Default`oddly / differently from the above expectation, and hence it appeared profitable to have `UnqualPtrTy`, which is a generally useful / everywhere usable pointer type, be different from `Int8PtrTy` / `VoidPtrTy` which are pointer types which correspond to the target's default (perhaps I am being overly cautious here though). Having said that, this change is somewhat inert at the moment beyond carving out the name / making it shorthand for calling `getUnqual()`. In the future, we could either: - extend DL to expose a target's flat/generic AS - (more intrusive / might be infeasible) make unqualified `ptr`s be generic/everywhere usable in IR, without the target exposing a flat/generic AS, letting the target figure out the legality of e.g. this or that ascast. https://github.com/llvm/llvm-project/pull/94388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits