[clang] [clang][c++20] Fix code coverage mapping crash with generalized NTTPs (PR #85837)
https://github.com/efriedma-quic closed https://github.com/llvm/llvm-project/pull/85837 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][c++20] Fix code coverage mapping crash with generalized NTTPs (PR #85837)
https://github.com/efriedma-quic approved this pull request. LGTM (In the future, please leave a note on the pull request when you push an update; as far as I can tell, GitHub doesn't generate a notification when you force-push to the branch.) https://github.com/llvm/llvm-project/pull/85837 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Macro for constant rounding mode (PR #92699)
https://github.com/efriedma-quic approved this pull request. LGTM, but maybe wait a few days to merge in case someone else has comments. https://github.com/llvm/llvm-project/pull/92699 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Macro for constant rounding mode (PR #92699)
@@ -965,6 +965,16 @@ void Preprocessor::Lex(Token ) { LastTokenWasAt = Result.is(tok::at); --LexLevel; + if (Result.is(tok::l_brace)) { +CurlyBraceLevel++; + } else if (Result.is(tok::r_brace)) { +if (!RoundingPragmas.empty() && efriedma-quic wrote: Maybe we can move the `!RoundingPragmas.empty()` outside the if statement, so we can skip a little more of the code if the user isn't using any pragmas? I mean, it probably doesn't make a big difference, but Lex() is performance-sensitive. https://github.com/llvm/llvm-project/pull/92699 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Macro for constant rounding mode (PR #92699)
https://github.com/efriedma-quic commented: This approach seems much better. https://github.com/llvm/llvm-project/pull/92699 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Macro for constant rounding mode (PR #92699)
https://github.com/efriedma-quic edited https://github.com/llvm/llvm-project/pull/92699 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class, and related issues (PR #93115)
@@ -48,10 +48,13 @@ uint8x16x4_t test_vld4q_u8(const uint8_t *addr) // CHECK-LABEL: @test_vst2q_u32( // CHECK-NEXT: entry: -// CHECK-NEXT:[[VALUE_COERCE_FCA_0_0_EXTRACT:%.*]] = extractvalue [[STRUCT_UINT32X4X2_T:%.*]] [[VALUE_COERCE:%.*]], 0, 0 -// CHECK-NEXT:[[VALUE_COERCE_FCA_0_1_EXTRACT:%.*]] = extractvalue [[STRUCT_UINT32X4X2_T]] [[VALUE_COERCE]], 0, 1 -// CHECK-NEXT:call void @llvm.arm.mve.vst2q.p0.v4i32(ptr [[ADDR:%.*]], <4 x i32> [[VALUE_COERCE_FCA_0_0_EXTRACT]], <4 x i32> [[VALUE_COERCE_FCA_0_1_EXTRACT]], i32 0) -// CHECK-NEXT:call void @llvm.arm.mve.vst2q.p0.v4i32(ptr [[ADDR]], <4 x i32> [[VALUE_COERCE_FCA_0_0_EXTRACT]], <4 x i32> [[VALUE_COERCE_FCA_0_1_EXTRACT]], i32 1) +// CHECK-NEXT:[[TMP0:%.*]] = extractvalue [[STRUCT_UINT32X4X2_T:%.*]] [[VALUE_COERCE:%.*]], 0 efriedma-quic wrote: Apparently I've stumbled over some limitation of instcombine. https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class, and related issues (PR #93115)
@@ -44,20 +44,20 @@ struct S1 f1(struct S1 s1) { return s1; } // CHECK-SOFT: define{{.*}} void @_Z2f22S2(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S2) align 8 %agg.result, [4 x i32] %s2.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f22S2([2 x <2 x i32>] returned %s2.coerce) -// CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S2 @_Z2f22S2(%struct.S2 returned %s2.coerce) +// CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S2 @_Z2f22S2(%struct.S2 %s2.coerce) efriedma-quic wrote: This is also the instcombine issue. https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class, and related issues (PR #93115)
@@ -46,9 +46,9 @@ int mane() { char1 f1{1}; char1 f2{1}; -// CHECK: [[TMP:%.+]] = alloca i16 efriedma-quic wrote: The revised version of casting integers is a bit more aggressive; it's hard to make it precisely match the old code while still preserving the correct semantics. https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class, and related issues (PR #93115)
@@ -177,7 +179,12 @@ kernel void KernelTwoMember(struct StructTwoMember u) { // AMDGCN-LABEL: define{{.*}} amdgpu_kernel void @KernelLargeTwoMember // AMDGCN-SAME: (%struct.LargeStructTwoMember %[[u_coerce:.*]]) // AMDGCN: %[[u:.*]] = alloca %struct.LargeStructTwoMember, align 8, addrspace(5) -// AMDGCN: store %struct.LargeStructTwoMember %[[u_coerce]], ptr addrspace(5) %[[u]] +// AMDGCN: %[[U_PTR0:.*]] = getelementptr inbounds %struct.LargeStructTwoMember, ptr addrspace(5) %[[u]], i32 0, i32 0 efriedma-quic wrote: Unifying the codepaths makes FCA promotion happen more often. https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class, and related issues (PR #93115)
https://github.com/efriedma-quic edited https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class, and related issues (PR #93115)
https://github.com/efriedma-quic edited https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class. (PR #93115)
https://github.com/efriedma-quic updated https://github.com/llvm/llvm-project/pull/93115 >From 19f3b677d92ed88b825b455d738055da05f91e0d Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 23 May 2024 18:38:04 -0700 Subject: [PATCH] Fix codegen of consteval functions returning an empty class, and related issues If a class is empty, don't store it to memory: the store might overwrite useful data. Similarly, if a class has tail padding that might overlap other fields, don't store the tail padding to memory. The problem here turned out a bit more general than I initially thought: basically all uses of EmitAggregateStore were broken. Call lowering had a method that did mostly the right thing, though: CreateCoercedStore. Adapt CreateCoercedStore so it always does the conservatively right thing, and use it for both calls and ConstantExpr. Also, along the way, fix the "overlap" bit in AggValueSlot: the bit was set incorrectly for empty classes in some cases. Fixes #93040. --- clang/lib/CodeGen/CGCall.cpp | 138 -- clang/lib/CodeGen/CGExprAgg.cpp | 23 +-- clang/lib/CodeGen/CodeGenFunction.h | 3 +- clang/test/CodeGen/arm-mve-intrinsics/vld24.c | 43 -- clang/test/CodeGen/arm-vfp16-arguments2.cpp | 10 +- .../amdgpu-kernel-arg-pointer-type.cu | 11 +- clang/test/CodeGenCUDA/builtins-amdgcn.cu | 121 +++ .../CodeGenCXX/address-space-cast-coerce.cpp | 6 +- clang/test/CodeGenCXX/cxx2a-consteval.cpp | 24 ++- clang/test/CodeGenCXX/trivial_abi.cpp | 20 +++ clang/test/CodeGenHIP/dpp-const-fold.hip | 8 +- .../CodeGenOpenCL/addr-space-struct-arg.cl| 11 +- .../amdgpu-abi-struct-arg-byref.cl| 42 -- 13 files changed, 253 insertions(+), 207 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 97449a5e51e73..db6feb4bf1d79 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1336,75 +1336,54 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, return CGF.Builder.CreateLoad(Tmp); } -// Function to store a first-class aggregate into memory. We prefer to -// store the elements rather than the aggregate to be more friendly to -// fast-isel. -// FIXME: Do we need to recurse here? -void CodeGenFunction::EmitAggregateStore(llvm::Value *Val, Address Dest, - bool DestIsVolatile) { - // Prefer scalar stores to first-class aggregate stores. - if (llvm::StructType *STy = dyn_cast(Val->getType())) { -for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - Address EltPtr = Builder.CreateStructGEP(Dest, i); - llvm::Value *Elt = Builder.CreateExtractValue(Val, i); - Builder.CreateStore(Elt, EltPtr, DestIsVolatile); -} - } else { -Builder.CreateStore(Val, Dest, DestIsVolatile); - } -} - /// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src, /// where the source and destination may have different types. The /// destination is known to be aligned to \arg DstAlign bytes. /// /// This safely handles the case when the src type is larger than the /// destination type; the upper bits of the src will be lost. -static void CreateCoercedStore(llvm::Value *Src, - Address Dst, - bool DstIsVolatile, - CodeGenFunction ) { - llvm::Type *SrcTy = Src->getType(); - llvm::Type *DstTy = Dst.getElementType(); - if (SrcTy == DstTy) { -CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); -return; - } - - llvm::TypeSize SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy); - - if (llvm::StructType *DstSTy = dyn_cast(DstTy)) { -Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy, - SrcSize.getFixedValue(), CGF); -DstTy = Dst.getElementType(); - } - - llvm::PointerType *SrcPtrTy = llvm::dyn_cast(SrcTy); - llvm::PointerType *DstPtrTy = llvm::dyn_cast(DstTy); - if (SrcPtrTy && DstPtrTy && - SrcPtrTy->getAddressSpace() != DstPtrTy->getAddressSpace()) { -Src = CGF.Builder.CreateAddrSpaceCast(Src, DstTy); -CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); +void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst, + llvm::TypeSize DstSize, + bool DstIsVolatile) { + if (!DstSize) return; - } - // If the source and destination are integer or pointer types, just do an - // extension or truncation to the desired type. - if ((isa(SrcTy) || isa(SrcTy)) && - (isa(DstTy) || isa(DstTy))) { -Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF); -CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); -return; + llvm::Type *SrcTy = Src->getType(); + llvm::TypeSize SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy); + + // GEP into structs to try to
[clang] [Clang][objectsize] Generate object size calculation for sub-objects (PR #86858)
@@ -1062,6 +1063,159 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +class ObjectSizeVisitor +: public ConstStmtVisitor { + bool SkipASE; + +public: + ObjectSizeVisitor(bool SkipASE = false) : SkipASE(SkipASE) {} + + const Expr *Visit(const Expr *E) { +return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { +return SkipASE ? Visit(E->getBase()) : E; + } + + const Expr *VisitCastExpr(const CastExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { efriedma-quic wrote: `IgnoreParens()` will give you better coverage of things we're supposed to treat like parentheses. https://github.com/llvm/llvm-project/pull/86858 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][objectsize] Generate object size calculation for sub-objects (PR #86858)
@@ -1052,6 +1053,165 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +class ObjectSizeVisitor +: public ConstStmtVisitor { + bool SkipASE; + +public: + ObjectSizeVisitor(bool SkipASE = false) : SkipASE(SkipASE) {} + + const Expr *Visit(const Expr *E) { +return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { +return SkipASE ? Visit(E->getBase()) : E; + } + + const Expr *VisitCastExpr(const CastExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryAddrOf(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryDeref(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); + } +}; + +} // end anonymous namespace + +/// getLastDecl - Return the last FieldDecl in the struct. +static const FieldDecl *getLastDecl(const RecordDecl *RD) { + const Decl *LastDecl = nullptr; + for (const Decl *D : RD->decls()) +if (isa(D) || isa(D)) + LastDecl = D; + + if (const auto *LastRD = dyn_cast(LastDecl)) { +LastDecl = getLastDecl(LastRD); + } else if (const auto *LastFD = dyn_cast(LastDecl)) { +QualType Ty = LastFD->getType(); +if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + +if (const RecordDecl *Rec = Ty->getAsRecordDecl()) + // The last FieldDecl is a structure. Look into that struct to find its + // last FieldDecl. + LastDecl = getLastDecl(Rec); + } + + return dyn_cast_if_present(LastDecl); +} + +/// tryToCalculateSubObjectSize - It may be possible to calculate the +/// sub-object size of an array and skip the generation of the llvm.objectsize +/// intrinsic. This avoids the complication in conveying the sub-object's +/// information to the backend. This calculation works for an N-dimentional +/// array. +llvm::Value * +CodeGenFunction::tryToCalculateSubObjectSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType) { + if ((Type & 0x01) != 1) +// Only support sub-object calculation. +return nullptr; + + const Expr *ObjectRef = ObjectSizeVisitor().Visit(E); + if (!ObjectRef) +return nullptr; + + QualType ObjectRefType = ObjectRef->getType(); + if (ObjectRefType->isPointerType()) +ObjectRefType = ObjectRefType->getPointeeType(); + + // Collect the base and index from the array. + QualType ObjectBaseRefTy; + const Expr *ArrayIdx = nullptr; + + if (const auto *ASE = dyn_cast(ObjectRef)) { +ArrayIdx = ASE->getIdx()->IgnoreParenImpCasts(); + +const Expr *ArrayRefBase = ASE->getBase()->IgnoreParenImpCasts(); +if (isa(ArrayRefBase)) { + ObjectBaseRefTy = ArrayRefBase->getType(); + if (ObjectBaseRefTy->isPointerType()) +ObjectBaseRefTy = ObjectBaseRefTy->getPointeeType(); +} + } + + ASTContext = getContext(); + if (!ArrayIdx || ArrayIdx->HasSideEffects(Ctx)) +return nullptr; + + // Check to see if the Decl is a flexible array member. Processing of the + // 'counted_by' attribute is done by now. So we don't have any information on + // its size, so return MAX_INT. + // + // Rerun the visitor to find the base expr: MemberExpr or DeclRefExpr. + ObjectRef = ObjectSizeVisitor(true).Visit(ObjectRef); + if (!ObjectRef) +return nullptr; + + if (const auto *ME = dyn_cast(ObjectRef)) { +if (const auto *FD = dyn_cast(ME->getMemberDecl())) { + const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + getLangOpts().getStrictFlexArraysLevel(); + const RecordDecl *OuterRD = + FD->getParent()->getOuterLexicalRecordContext(); + const FieldDecl *LastFD = getLastDecl(OuterRD); + + if (LastFD == FD && Decl::isFlexibleArrayMemberLike( + Ctx, FD, FD->getType(), StrictFlexArraysLevel, + /*IgnoreTemplateOrMacroSubstitution=*/true)) +return ConstantInt::get(ResType, -1, /*isSigned=*/true); +} + } + + if (ObjectBaseRefTy.isNull()) { +ObjectBaseRefTy = ObjectRef->getType(); +if (ObjectBaseRefTy->isPointerType()) + ObjectBaseRefTy = ObjectBaseRefTy->getPointeeType(); + } + + // Generate the calculation: + // + // S Object[n_1][n_2]...[n_m]; /* M-dimentional array */ + // + // ObjectRef = Object[n_1]...[n_x]; /* 0 < x < m */ + // ObjectBaseRef = Object[n_1]...[n_{x-1}]; + // + // ArrayRefSize = sizeof( typeof( ObjectRef ) ); + // ArrayRefBaseSize = sizeof( typeof( ObjectBaseRef ) ); + // + // Size = ArrayRefSize -
[clang] [Clang][objectsize] Generate object size calculation for sub-objects (PR #86858)
@@ -1062,6 +1063,159 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +class ObjectSizeVisitor +: public ConstStmtVisitor { + bool SkipASE; + +public: + ObjectSizeVisitor(bool SkipASE = false) : SkipASE(SkipASE) {} + + const Expr *Visit(const Expr *E) { +return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { +return SkipASE ? Visit(E->getBase()) : E; + } + + const Expr *VisitCastExpr(const CastExpr *E) { +return Visit(E->getSubExpr()); efriedma-quic wrote: Can we restrict this to specific CastKinds? I can see why you'd want to look through certain casts, but some casts drastically change the meaning of the expression. https://github.com/llvm/llvm-project/pull/86858 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][objectsize] Generate object size calculation for sub-objects (PR #86858)
@@ -1062,6 +1063,159 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +class ObjectSizeVisitor +: public ConstStmtVisitor { + bool SkipASE; + +public: + ObjectSizeVisitor(bool SkipASE = false) : SkipASE(SkipASE) {} + + const Expr *Visit(const Expr *E) { +return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { +return SkipASE ? Visit(E->getBase()) : E; + } + + const Expr *VisitCastExpr(const CastExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryAddrOf(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); efriedma-quic wrote: For this kind of recursion, it probably makes sense to track whether we're looking at an lvalue or an rvalue. If "x" is an `int*`, `__bdos(x)` is very different from `__bdos()`. https://github.com/llvm/llvm-project/pull/86858 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class. (PR #93115)
@@ -135,6 +135,17 @@ class AggExprEmitter : public StmtVisitor { EnsureDest(E->getType()); if (llvm::Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) { + // An empty record can overlap other data (if declared with + // no_unique_address); omit the store for such types - as there is no efriedma-quic wrote: See what, exactly? Given the derived class, computing the address of the base class doesn't take any instructions, because it's the same address. https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class. (PR #93115)
efriedma-quic wrote: I didn't think so at first glance... but yes, we do, in certain obscure cases: ``` #include struct A { char c; A(); }; struct __attribute((packed)) S { char a; int x; __attribute((aligned(2))) char y; consteval S() : x(1), a(3), y(2) {} }; struct S2 { [[no_unique_address]] S s; [[no_unique_address]] A a; }; static_assert(sizeof(S)==8 && sizeof(S2)==8); void f2(S2 *s) { new (>s) S; } ``` I'll look into reworking this. https://github.com/llvm/llvm-project/pull/93115 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix codegen of consteval functions returning an empty class. (PR #93115)
https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/93115 If a class is empty, don't store it to memory: the store might overwrite useful data. (See also d60c3d08.) Fixes #93040. >From bdfcc729c309fc5b1092b67d7c3c803c852ae251 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 22 May 2024 17:30:41 -0700 Subject: [PATCH] Fix codegen of consteval functions returning an empty class. If a class is empty, don't store it to memory: the store might overwrite useful data. (See also d60c3d08.) Fixes #93040. --- clang/lib/CodeGen/CGExprAgg.cpp | 11 +++ clang/test/CodeGenCXX/cxx2a-consteval.cpp | 24 ++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index bba00257fd4f0..b1638fa318270 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -135,6 +135,17 @@ class AggExprEmitter : public StmtVisitor { EnsureDest(E->getType()); if (llvm::Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) { + // An empty record can overlap other data (if declared with + // no_unique_address); omit the store for such types - as there is no + // actual data to store. + if (CGF.getLangOpts().CPlusPlus) { +if (const RecordType *RT = E->getType()->getAs()) { + CXXRecordDecl *Record = cast(RT->getDecl()); + if (Record->isEmpty()) +return; +} + } + Address StoreDest = Dest.getAddress(); // The emitted value is guaranteed to have the same size as the // destination but can have a different type. Just do a bitcast in this diff --git a/clang/test/CodeGenCXX/cxx2a-consteval.cpp b/clang/test/CodeGenCXX/cxx2a-consteval.cpp index 075cab58358ab..5d5a62f9928fe 100644 --- a/clang/test/CodeGenCXX/cxx2a-consteval.cpp +++ b/clang/test/CodeGenCXX/cxx2a-consteval.cpp @@ -1,4 +1,3 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll // RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s // RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s @@ -275,3 +274,26 @@ void f() { // EVAL-FN: call void @_ZN7GH821542S3C2Ei } } + +namespace GH93040 { +struct C { char c = 1; }; +struct Empty { consteval Empty() {} }; +struct Test : C, Empty { + [[no_unique_address]] Empty e; +}; + +void f() { + Test test; + +// Make sure we don't overwrite the initialization of c. + +// EVAL-FN-LABEL: define {{.*}} void @_ZN7GH930404TestC2Ev +// EVAL-FN: entry: +// EVAL-FN-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// EVAL-FN-NEXT: store ptr {{.*}}, ptr [[THIS_ADDR]], align 8 +// EVAL-FN-NEXT: [[THIS:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// EVAL-FN-NEXT: call void @_ZN7GH930401CC2Ev(ptr noundef nonnull align 1 dereferenceable(1) [[THIS]]) +// EVAL-FN-NEXT: %0 = getelementptr inbounds i8, ptr [[THIS]], i64 1 +// EVAL-FN-NEXT: ret void +} +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix PS "selective" DLL import/export of vtable & typeinfo (PR #92579)
@@ -1793,6 +1793,37 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction , ThisTy, VTT, VTTTy, nullptr); } +// Check if any non-inline method has the specified attribute. +template +static bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD) { + for (const auto *D : RD->noload_decls()) { +if (const auto *FD = dyn_cast(D)) { + if (FD->isInlineSpecified() || FD->doesThisDeclarationHaveABody() || efriedma-quic wrote: It's probably fine to merge as-is, sure; inline functions marked with import/export attributes should be pretty rare in any case. https://github.com/llvm/llvm-project/pull/92579 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][FMV] Allow declaration of function versions in namespaces. (PR #93044)
@@ -11868,8 +11868,10 @@ static bool CheckMultiVersionFunction(Sema , FunctionDecl *NewFD, return false; if (!OldDecl || !OldDecl->getAsFunction() || - OldDecl->getDeclContext()->getRedeclContext() != - NewFD->getDeclContext()->getRedeclContext()) { + (OldDecl->getDeclContext()->getRedeclContext() != + NewFD->getDeclContext()->getRedeclContext() && + OldDecl->getDeclContext()->getEnclosingNamespaceContext() != + NewFD->getDeclContext()->getEnclosingNamespaceContext())) { efriedma-quic wrote: ```suggestion !OldDecl->getDeclContext()->getRedeclContext()->Equals( NewFD->getDeclContext()->getRedeclContext())) { ``` https://github.com/llvm/llvm-project/pull/93044 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Remove parameter that shouldn't be there (PR #93086)
efriedma-quic wrote: Looks fine. https://github.com/llvm/llvm-project/pull/93086 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix PS "selective" DLL import/export of vtable & typeinfo (PR #92579)
https://github.com/efriedma-quic edited https://github.com/llvm/llvm-project/pull/92579 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix PS "selective" DLL import/export of vtable & typeinfo (PR #92579)
@@ -1793,6 +1793,37 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction , ThisTy, VTT, VTTTy, nullptr); } +// Check if any non-inline method has the specified attribute. +template +static bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD) { + for (const auto *D : RD->noload_decls()) { +if (const auto *FD = dyn_cast(D)) { + if (FD->isInlineSpecified() || FD->doesThisDeclarationHaveABody() || efriedma-quic wrote: "isInlineSpecified()" specifically refers to the keyword. `isInlined()` is what the C++ standard calls an "inlined function", and it includes some other stuff: constexpr functions, and functions where the body is written inside the class definition. https://github.com/llvm/llvm-project/pull/92579 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] solve crash due to function overloading. (PR #90255)
https://github.com/efriedma-quic closed https://github.com/llvm/llvm-project/pull/90255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix PS "selective" DLL import/export of vtable & typeinfo (PR #92579)
@@ -1793,6 +1793,37 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction , ThisTy, VTT, VTTTy, nullptr); } +// Check if any non-inline method has the specified attribute. +template +static bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD) { + for (const auto *D : RD->noload_decls()) { +if (const auto *FD = dyn_cast(D)) { + if (FD->isInlineSpecified() || FD->doesThisDeclarationHaveABody() || efriedma-quic wrote: Is there some reason you're not using `FD->isInlined()` here? https://github.com/llvm/llvm-project/pull/92579 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [IR] Avoid creating icmp/fcmp constant expressions (PR #92885)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/92885 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64][SVE] Allow write to SVE vector elements using the subscript operator (PR #91965)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/91965 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] add unnamed_addr function attribute (PR #92499)
efriedma-quic wrote: I think the underlying functionality is pretty clearly useful: identical code folding gives significant codesize reductions. In fact, on Windows, the linker does this kind of folding automatically by default (despite the fact that it isn't standards-compliant). I imagine if we had this implemented, libc++ would want to use it. https://github.com/llvm/llvm-project/pull/92499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][NFC] Use ptrmask for vaarg stack alignment (PR #92836)
https://github.com/efriedma-quic approved this pull request. Please don't use "NFC" markings for patches that change the emitted IR, even if it doesn't significantly impact the resulting assembly in most cases. That said, LGTM https://github.com/llvm/llvm-project/pull/92836 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [CodeGen][AArch64] Added -mno-va-float to skip FP save in variadic functions (PR #92827)
efriedma-quic wrote: This patch, as proposed, doesn't seem like a good idea: it's very likely to miscompile user code without any diagnostic. Are you sure you don't want one of the following? - A soft-float ABI (-mabi=aapcs-soft) - Completely forbidding the use of floating-point values (-mgeneral-regs-only). - An optimization that opportunistically skips saving float registers if we can prove it isn't necessary. (Not currently implemented, but not something you'd add a compiler option for; you'd just make it work automatically. I can write up an outline of how to implement this if you're interested.) https://github.com/llvm/llvm-project/pull/92827 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] solve crash due to function overloading. (PR #90255)
efriedma-quic wrote: Bot is unreliable, so copy-pasting: > ⚠️ We detected that you are using a GitHub private e-mail address to > contribute to the repo. Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account. See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information. https://github.com/llvm/llvm-project/pull/90255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] solve crash due to function overloading. (PR #90255)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/90255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenCL] Fix an infinite loop in builidng AddrSpaceQualType (PR #92612)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/92612 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [BPF] Fix linking issues in static map initializers (PR #91310)
@@ -1950,8 +1950,22 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase ) { if (D->hasAttr()) return CGM.GetWeakRefReference(D).getPointer(); -if (auto FD = dyn_cast(D)) - return CGM.GetAddrOfFunction(FD); +if (auto FD = dyn_cast(D)) { + auto *C = CGM.GetAddrOfFunction(FD); + + // we don't normally emit debug info for extern fns referenced via + // variable initialisers; BPF needs it since it generates BTF from + // debug info and bpftool demands BTF for every symbol linked + if (CGM.getTarget().getTriple().isBPF() && FD->getStorageClass() == SC_Extern) { efriedma-quic wrote: Current approach seems fine. > Sema::ActOnEndOfTranslationUnit checks whether a declaration is used (does it > mean referenced?) "Used" in this context corresponds to odr-used in the C++ standard... which is stuff that Sema thinks the code generator might need to emit. In some cases we manage to skip actually emitting some declarations due to optimizations. https://github.com/llvm/llvm-project/pull/91310 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Emit lifetime markers for non-aggregate temporary allocas (PR #90849)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/90849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Macro for constant rounding mode (PR #92699)
@@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -emit-llvm -triple i386-linux -Wno-unknown-pragmas %s -o - | FileCheck %s efriedma-quic wrote: Is there some reason the preprocessor can't parse FENV_ROUND? Breaking code with -save-temps etc. seems bad. https://github.com/llvm/llvm-project/pull/92699 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor handling of vector subscript expressions (NFC) (PR #92778)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/92778 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Macro for constant rounding mode (PR #92699)
@@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -emit-llvm -triple i386-linux -Wno-unknown-pragmas %s -o - | FileCheck %s efriedma-quic wrote: Since this is a preprocessor testcase, can you just use -E? https://github.com/llvm/llvm-project/pull/92699 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenCL] Fix an infinite loop in builidng AddrSpaceQualType (PR #92612)
@@ -3054,6 +3054,13 @@ QualType ASTContext::removeAddrSpaceQualType(QualType T) const { if (!T.hasAddressSpace()) return T; + // For arrays, strip the qualifier off the element type, then reconstruct the + // array type + if (T.getTypePtr()->isArrayType()) { +Qualifiers Qualfs; +return getUnqualifiedArrayType(T, Qualfs); efriedma-quic wrote: You need to preserve the non-address-space qualifiers, the same way the code after the loop does. Actually, I'd just recommend restructuring to use the existing code, something like: ``` if (T.getTypePtr()->isArrayType()) { getUnqualifiedArrayType() } else { while (T.hasAddressSpace()) { [...] } } ``` https://github.com/llvm/llvm-project/pull/92612 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenCL] Fix an infinite loop in builidng AddrSpaceQualType (PR #92612)
@@ -537,8 +537,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, elementType.isTriviallyCopyableType(CGF.getContext())) { CodeGen::CodeGenModule = CGF.CGM; ConstantEmitter Emitter(CGF); +Qualifiers Quals; QualType GVArrayQTy = CGM.getContext().getAddrSpaceQualType( -CGM.getContext().removeAddrSpaceQualType(ArrayQTy), +CGM.getContext().getUnqualifiedArrayType(ArrayQTy, Quals), efriedma-quic wrote: Something like that, yes. https://github.com/llvm/llvm-project/pull/92612 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenCL] Fix an infinite loop in builidng AddrSpaceQualType (PR #92612)
@@ -537,8 +537,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, elementType.isTriviallyCopyableType(CGF.getContext())) { CodeGen::CodeGenModule = CGF.CGM; ConstantEmitter Emitter(CGF); +Qualifiers Quals; QualType GVArrayQTy = CGM.getContext().getAddrSpaceQualType( -CGM.getContext().removeAddrSpaceQualType(ArrayQTy), +CGM.getContext().getUnqualifiedArrayType(ArrayQTy, Quals), efriedma-quic wrote: I see two issues with this fix: 1. It leaves removeAddrSpaceQualType broken for anyone else who tries to use it. Ideally, removeAddrSpaceQualType should do what it says. 2. This drops other qualifiers on the floor; they might be relevant in some cases. https://github.com/llvm/llvm-project/pull/92612 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64][SVE] Allow write to SVE vector elements using the subscript operator (PR #91965)
@@ -4180,8 +4180,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // If the base is a vector type, then we are forming a vector element lvalue // with this subscript. - if (E->getBase()->getType()->isVectorType() && - !isa(E->getBase())) { + if (QualType BaseTy = E->getBase()->getType(); + (BaseTy->isVectorType() && !isa(E->getBase())) || + (BaseTy->isBuiltinType() && + BaseTy->getAs()->isSveVLSBuiltinType())) { efriedma-quic wrote: In that case, it might make sense to introduce a helper Type::isSubscriptableVectorType() helper to types, so we can easily find all the places that care about this. https://github.com/llvm/llvm-project/pull/91965 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] add unnamed_addr function attribute (PR #92499)
efriedma-quic wrote: If we're going to do this, it should probably also work for constants. Also, I think I'd prefer to sort out the situation with the C++ standard's rules for constant merging before we start extending those rules. See #63628. https://github.com/llvm/llvm-project/pull/92499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CodeGen] Support arrays with initializers of 64-bit size (PR #92473)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/92473 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64] Use __clang_arm_builtin_alias for overloaded svreinterpret's (PR #92427)
efriedma-quic wrote: clang specifically diagnoses always_inline functions. So for example, say you want to write something like: ``` #include __attribute__((always_inline, target("+sve"))) static inline void f(void* p) __arm_streaming_compatible { *(svuint32_t*)p = svmul_m(svptrue_b32(), *(svuint32_t*)p, *(svuint32_t*)p); } // void g(void* p) __arm_streaming { f(p); } ``` Conceptually, this should be fine, but currently it's an error. (You can sort of approximate it with an `#ifdef __ARM_FEATURE_SVE`, but that's pretty ugly.) But regardless of the diagnostics, if the user specifies "+sve" on a target that doesn't actually have SVE, we could miscompile; for example, if you call a versioned function, clang uses the features specified in the caller. https://github.com/llvm/llvm-project/pull/92427 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CodeGen] Support arrays with initializers of 64-bit size (PR #92473)
@@ -949,11 +949,11 @@ tryEmitGlobalCompoundLiteral(ConstantEmitter , static llvm::Constant * EmitArrayConstant(CodeGenModule , llvm::ArrayType *DesiredType, - llvm::Type *CommonElementType, unsigned ArrayBound, + llvm::Type *CommonElementType, uint64_t ArrayBound, SmallVectorImpl , llvm::Constant *Filler) { // Figure out how long the initial prefix of non-zero elements is. - unsigned NonzeroLength = ArrayBound; + uint64_t NonzeroLength = ArrayBound; if (Elements.size() < NonzeroLength && Filler->isNullValue()) NonzeroLength = Elements.size(); if (NonzeroLength == Elements.size()) { efriedma-quic wrote: Do we also need to fix the type of `TrailingZeroes`? https://github.com/llvm/llvm-project/pull/92473 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenCL] Put constant initializer globals into constant addrspace (PR #90048)
@@ -535,20 +535,23 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, elementType.isTriviallyCopyableType(CGF.getContext())) { CodeGen::CodeGenModule = CGF.CGM; ConstantEmitter Emitter(CGF); -LangAS AS = ArrayQTy.getAddressSpace(); +QualType GVArrayQTy = CGM.getContext().getAddrSpaceQualType( +CGM.getContext().removeAddrSpaceQualType(ArrayQTy), efriedma-quic wrote: I think it's a bug in removeAddrSpaceQualType(): it needs to special-case arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. So it needs to strip the qualifier off the element type, then reconstruct the array type. Maybe it can use ASTContext::getUnqualifiedArrayType. https://github.com/llvm/llvm-project/pull/90048 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64] Use __clang_arm_builtin_alias for overloaded svreinterpret's (PR #92427)
efriedma-quic wrote: > Thinking about it a bit more, maybe we can just do some magic to make things > work? Say, if you specify `__attribute__((target("sve"))) > __arm_streaming_compatible`, and the caller is in streaming mode, allow the > call even if the caller doesn't have SVE proper. Thinking a bit more, this is probably not quite what we want: even if the function body itself is streaming compatible, it might call non-streaming functions that require SVE. Maybe spell this something like `__attribute__((target("sve-or-streaming"))) __arm_streaming_compatible`. https://github.com/llvm/llvm-project/pull/92427 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64] Use __clang_arm_builtin_alias for overloaded svreinterpret's (PR #92427)
efriedma-quic wrote: The key here is that `__arm_streaming_compatible` is the only way to write code that runs in both streaming and non-streaming mode; outside of `__arm_streaming_compatible`, there generally isn't an issue. If you know you're not in streaming mode, you can just check directly for SVE/SVE2, and if you know you're in streaming mode, you can check directly for SME/SME2. Thinking about it a bit more, maybe we can just do some magic to make things work? Say, if you specify `__attribute__((target("sve"))) __arm_streaming_compatible`, and the caller is in streaming mode, allow the call even if the caller doesn't have SVE proper. https://github.com/llvm/llvm-project/pull/92427 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64] Use __clang_arm_builtin_alias for overloaded svreinterpret's (PR #92427)
https://github.com/efriedma-quic edited https://github.com/llvm/llvm-project/pull/92427 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix P2564 handling of variable initializers (PR #89565)
efriedma-quic wrote: clang already generates certain diagnostics from ExprConstant; expanding the set of diagnostics could be reasonable. Alternatively, we could try to add some sort of cooperation between DiagRuntimeBehavior and constant evaluation, to try to avoid having to diagnose everything twice: basically, Sema makes a list of constant-evaluated expressions it wants to warn about, then if ExprConstant prints a warning if it sees one of those expressions. https://github.com/llvm/llvm-project/pull/89565 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] support packoffset in clang codeGen (PR #91999)
efriedma-quic wrote: > The data layout will insert 4-bytes of padding between the float and the > vector because the vector needs to be properly aligned. You can use `type <{ float, <2 x float>}>` if you need the tightly-packed layout. https://github.com/llvm/llvm-project/pull/91999 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64] Use __clang_arm_builtin_alias for overloaded svreinterpret's (PR #92427)
efriedma-quic wrote: However we choose to emit this particular builtin, should we provide a way to write a function like this? Like, the caller has to either support sve, or have streaming enabled. Maybe call it __arm_streaming_compatible_requires_sve. https://github.com/llvm/llvm-project/pull/92427 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Add __builtin_selectvector and use it for AVX512 intrinsics (PR #91306)
efriedma-quic wrote: clang already supports `?:` with a vector condition; does this add anything new on top of that? https://github.com/llvm/llvm-project/pull/91306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Coverage] Handle array decomposition correctly (PR #88881)
https://github.com/efriedma-quic closed https://github.com/llvm/llvm-project/pull/1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Coverage] Handle `CoroutineSuspendExpr` correctly (PR #88898)
https://github.com/efriedma-quic closed https://github.com/llvm/llvm-project/pull/88898 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Coverage] Handle `CoroutineSuspendExpr` correctly (PR #88898)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/88898 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Coverage] Handle array decomposition correctly (PR #88881)
https://github.com/efriedma-quic approved this pull request. LGTM. I'm not completely convinced by your argument here... but let's try to move forward and land this and #88898 so we can do the refactor to use isUnique(). Then we can revisit later if necessary. https://github.com/llvm/llvm-project/pull/1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Emit lifetime markers for non-aggregate temporary allocas (PR #90849)
@@ -1,13 +1,15 @@ -// RUN: %clang_cc1 -emit-llvm -triple arm64-- -o - %s -O0 | FileCheck %s --check-prefix=CHECK-O0 -// RUN: %clang_cc1 -emit-llvm -disable-llvm-optzns -triple arm64-- -o - %s -O3 | FileCheck %s --check-prefix=CHECK-O3 +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 efriedma-quic wrote: It looks like the existing checks didn't get regenerated? Did you modify the output of update_cc_test_checks hand? (Don't do that; someone will regenerate the test at some point and destroy your customizations.) https://github.com/llvm/llvm-project/pull/90849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)
@@ -6088,6 +6088,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, StringRef Prefix = llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch()); if (!Prefix.empty()) { +if (Prefix == "spv" && +getTarget().getTriple().getOS() == llvm::Triple::OSType::AMDHSA) + Prefix = "amdgcn"; efriedma-quic wrote: We can look at it as a followup, sure; the code in its current form seems okay for now. https://github.com/llvm/llvm-project/pull/89796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64][SME] Save VG for unwind info when changing streaming-mode (PR #83301)
@@ -8287,6 +8289,13 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo , SDValue InGlue; if (RequiresSMChange) { + +if (Subtarget->hasSVE()) { efriedma-quic wrote: I'm not sure I follow what the issue is... I think we discussed before that we want debuggers to be able to unwind the stack even if a function is nounwind. https://github.com/llvm/llvm-project/pull/83301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64][SME] Save VG for unwind info when changing streaming-mode (PR #83301)
@@ -3768,6 +3768,12 @@ def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; def err_sme_streaming_cannot_be_multiversioned : Error< "streaming function cannot be multi-versioned">; +def err_sme_streaming_mode_change_no_sve : Error< + "function requires a streaming-mode change, unwinding is not possible without 'sve'. " + "Consider marking this function as 'noexcept' or '__attribute__((nothrow))'">; efriedma-quic wrote: If we call new functions, they need to be part of the ABI. If you're happy to work with your ABI people to document the new interface, I guess it's not a problem. https://github.com/llvm/llvm-project/pull/83301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][objectsize] Generate object size calculation for sub-objects (PR #86858)
@@ -1052,6 +1053,165 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +class ObjectSizeVisitor +: public ConstStmtVisitor { + bool SkipASE; + +public: + ObjectSizeVisitor(bool SkipASE = false) : SkipASE(SkipASE) {} + + const Expr *Visit(const Expr *E) { +return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { +return SkipASE ? Visit(E->getBase()) : E; + } + + const Expr *VisitCastExpr(const CastExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryAddrOf(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryDeref(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); + } +}; + +} // end anonymous namespace + +/// getLastDecl - Return the last FieldDecl in the struct. +static const FieldDecl *getLastDecl(const RecordDecl *RD) { + const Decl *LastDecl = nullptr; + for (const Decl *D : RD->decls()) +if (isa(D) || isa(D)) efriedma-quic wrote: Why are you visiting RecordDecls? https://github.com/llvm/llvm-project/pull/86858 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][objectsize] Generate object size calculation for sub-objects (PR #86858)
@@ -1052,6 +1053,165 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +class ObjectSizeVisitor +: public ConstStmtVisitor { + bool SkipASE; + +public: + ObjectSizeVisitor(bool SkipASE = false) : SkipASE(SkipASE) {} + + const Expr *Visit(const Expr *E) { +return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { +return SkipASE ? Visit(E->getBase()) : E; + } + + const Expr *VisitCastExpr(const CastExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryAddrOf(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryDeref(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); efriedma-quic wrote: This recursion seems too aggressive; if you have __bdos(x), is "x" really relevant? https://github.com/llvm/llvm-project/pull/86858 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][objectsize] Generate object size calculation for sub-objects (PR #86858)
@@ -1052,6 +1053,165 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +class ObjectSizeVisitor +: public ConstStmtVisitor { + bool SkipASE; + +public: + ObjectSizeVisitor(bool SkipASE = false) : SkipASE(SkipASE) {} + + const Expr *Visit(const Expr *E) { +return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { +return SkipASE ? Visit(E->getBase()) : E; + } + + const Expr *VisitCastExpr(const CastExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryAddrOf(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryDeref(const clang::UnaryOperator *E) { +return Visit(E->getSubExpr()); + } +}; + +} // end anonymous namespace + +/// getLastDecl - Return the last FieldDecl in the struct. +static const FieldDecl *getLastDecl(const RecordDecl *RD) { + const Decl *LastDecl = nullptr; + for (const Decl *D : RD->decls()) +if (isa(D) || isa(D)) + LastDecl = D; + + if (const auto *LastRD = dyn_cast(LastDecl)) { +LastDecl = getLastDecl(LastRD); + } else if (const auto *LastFD = dyn_cast(LastDecl)) { +QualType Ty = LastFD->getType(); +if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + +if (const RecordDecl *Rec = Ty->getAsRecordDecl()) + // The last FieldDecl is a structure. Look into that struct to find its + // last FieldDecl. + LastDecl = getLastDecl(Rec); + } + + return dyn_cast_if_present(LastDecl); +} + +/// tryToCalculateSubObjectSize - It may be possible to calculate the +/// sub-object size of an array and skip the generation of the llvm.objectsize +/// intrinsic. This avoids the complication in conveying the sub-object's +/// information to the backend. This calculation works for an N-dimentional +/// array. +llvm::Value * +CodeGenFunction::tryToCalculateSubObjectSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType) { + if ((Type & 0x01) != 1) +// Only support sub-object calculation. +return nullptr; + + const Expr *ObjectRef = ObjectSizeVisitor().Visit(E); + if (!ObjectRef) +return nullptr; + + QualType ObjectRefType = ObjectRef->getType(); + if (ObjectRefType->isPointerType()) +ObjectRefType = ObjectRefType->getPointeeType(); + + // Collect the base and index from the array. + QualType ObjectBaseRefTy; + const Expr *ArrayIdx = nullptr; + + if (const auto *ASE = dyn_cast(ObjectRef)) { +ArrayIdx = ASE->getIdx()->IgnoreParenImpCasts(); + +const Expr *ArrayRefBase = ASE->getBase()->IgnoreParenImpCasts(); +if (isa(ArrayRefBase)) { + ObjectBaseRefTy = ArrayRefBase->getType(); + if (ObjectBaseRefTy->isPointerType()) +ObjectBaseRefTy = ObjectBaseRefTy->getPointeeType(); +} + } + + ASTContext = getContext(); + if (!ArrayIdx || ArrayIdx->HasSideEffects(Ctx)) +return nullptr; + + // Check to see if the Decl is a flexible array member. Processing of the + // 'counted_by' attribute is done by now. So we don't have any information on + // its size, so return MAX_INT. + // + // Rerun the visitor to find the base expr: MemberExpr or DeclRefExpr. + ObjectRef = ObjectSizeVisitor(true).Visit(ObjectRef); + if (!ObjectRef) +return nullptr; + + if (const auto *ME = dyn_cast(ObjectRef)) { +if (const auto *FD = dyn_cast(ME->getMemberDecl())) { + const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + getLangOpts().getStrictFlexArraysLevel(); + const RecordDecl *OuterRD = + FD->getParent()->getOuterLexicalRecordContext(); + const FieldDecl *LastFD = getLastDecl(OuterRD); + + if (LastFD == FD && Decl::isFlexibleArrayMemberLike( + Ctx, FD, FD->getType(), StrictFlexArraysLevel, + /*IgnoreTemplateOrMacroSubstitution=*/true)) +return ConstantInt::get(ResType, -1, /*isSigned=*/true); +} + } + + if (ObjectBaseRefTy.isNull()) { +ObjectBaseRefTy = ObjectRef->getType(); +if (ObjectBaseRefTy->isPointerType()) + ObjectBaseRefTy = ObjectBaseRefTy->getPointeeType(); + } + + // Generate the calculation: + // + // S Object[n_1][n_2]...[n_m]; /* M-dimentional array */ + // + // ObjectRef = Object[n_1]...[n_x]; /* 0 < x < m */ + // ObjectBaseRef = Object[n_1]...[n_{x-1}]; + // + // ArrayRefSize = sizeof( typeof( ObjectRef ) ); + // ArrayRefBaseSize = sizeof( typeof( ObjectBaseRef ) ); + // + // Size = ArrayRefSize -
[clang] [Clang] Fix incorrect passing of _BitInt args (PR #90741)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/90741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)
@@ -6088,6 +6088,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, StringRef Prefix = llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch()); if (!Prefix.empty()) { +if (Prefix == "spv" && +getTarget().getTriple().getOS() == llvm::Triple::OSType::AMDHSA) + Prefix = "amdgcn"; efriedma-quic wrote: If we want to allow this choice to be target-specific, we can just make the "IntrinsicPrefix" a property of the TargetInfo, instead of trying to derive it directly from the target triple. The default constructor would derive it from the triple, but specific targets could override the field. I'm more concerned this is going to prevent us from using builtins which shoud be usable; do we need to getIntrinsicForClangBuiltin() for both "spv" and "amdgcn"? https://github.com/llvm/llvm-project/pull/89796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64][SVE] Allow write to SVE vector elements using the subscript operator (PR #91965)
@@ -88,3 +88,13 @@ float subscript_float32(svfloat32_t a, size_t b) { double subscript_float64(svfloat64_t a, size_t b) { return a[b]; } + +// CHECK-LABEL: @subscript_write_float32( +// CHECK-NEXT: entry: +// CHECK-NEXT:[[VECINS:%.*]] = insertelement [[A:%.*]], float 1.00e+00, i64 [[B:%.*]] +// CHECK-NEXT:ret [[VECINS]] +// +svfloat32_t subscript_write_float32(svfloat32_t a, size_t b) { + a[b] = 1.0f; efriedma-quic wrote: Please also add a test for a compound op (`a[b]+=1.f`). https://github.com/llvm/llvm-project/pull/91965 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64][SVE] Allow write to SVE vector elements using the subscript operator (PR #91965)
@@ -4180,8 +4180,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // If the base is a vector type, then we are forming a vector element lvalue // with this subscript. - if (E->getBase()->getType()->isVectorType() && - !isa(E->getBase())) { + if (QualType BaseTy = E->getBase()->getType(); + (BaseTy->isVectorType() && !isa(E->getBase())) || + (BaseTy->isBuiltinType() && + BaseTy->getAs()->isSveVLSBuiltinType())) { efriedma-quic wrote: isSizelessVectorType()? https://github.com/llvm/llvm-project/pull/91965 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [BPF] Fix linking issues in static map initializers (PR #91310)
@@ -1950,8 +1950,22 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase ) { if (D->hasAttr()) return CGM.GetWeakRefReference(D).getPointer(); -if (auto FD = dyn_cast(D)) - return CGM.GetAddrOfFunction(FD); +if (auto FD = dyn_cast(D)) { + auto *C = CGM.GetAddrOfFunction(FD); + + // we don't normally emit debug info for extern fns referenced via + // variable initialisers; BPF needs it since it generates BTF from + // debug info and bpftool demands BTF for every symbol linked + if (CGM.getTarget().getTriple().isBPF() && FD->getStorageClass() == SC_Extern) { efriedma-quic wrote: Looking at the code again, I guess the ultimate question is whether we want to emit debug info for all external functions/variables, or only functions/variables that are actually referenced. If we want all functions/variables, we want to extend ExternalDeclarations to include them. Maybe put the code in Sema::ActOnFunctionDeclarator, or something like that. If you just want referenced functions/variables, probably the code should be in GetAddrOfFunction() (and something similar for variables). https://github.com/llvm/llvm-project/pull/91310 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86][vectorcall] Pass built types byval when xmm0~6 exhausted (PR #91846)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/91846 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86][vectorcall] Pass built types byval when xmm0~6 exhausted (PR #91846)
@@ -792,7 +792,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState , return ABIArgInfo::getDirect(); return ABIArgInfo::getExpand(); } -return getIndirectResult(Ty, /*ByVal=*/false, State); +return getIndirectResult(Ty, IsVectorCall && Ty->isBuiltinType(), State); efriedma-quic wrote: Maybe try to avoid byval overhead: ``` if (IsVectorCall && Ty->isBuiltinType()) return ABIArgInfo::getDirect(); return getIndirectResult(Ty, /*ByVal=*/false, State); ``` https://github.com/llvm/llvm-project/pull/91846 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix incorrect passing of _BitInt args (PR #90741)
@@ -0,0 +1,14 @@ +// REQUIRES: arm-registered-target +// RUN: %clang_cc1 -triple aarch64-none-elf \ +// RUN: -O2 \ +// RUN: -emit-llvm -fexperimental-max-bitint-width=1024 -o - %s | FileCheck %s efriedma-quic wrote: Digging a bit into the history, I found clang/test/CodeGen/ext-int-cc.c . Which apparently has broken CHECK-NOT lines. https://github.com/llvm/llvm-project/pull/90741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix handling of fields with initializers in nested anonymous unions. (PR #91692)
https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/91692 Make sure we count the anonymous union as an initialized field, so we properly construct the AST. Included bonus testcase Test3, which shows a remaining gap: an anonymous union can contain a partially initialized anonymous struct, and we handle that inconsistently. Fixes #91257 >From 44c9e4b9920ab23db93a8a716695a6e712edcf01 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 9 May 2024 19:40:46 -0700 Subject: [PATCH] [Sema] Fix handling of fields with initializers in nested anonymous unions. Make sure we count the anonymous union as an initialized field, so we properly construct the AST. Included bonus testcase Test3, which shows a remaining gap: an anonymous union can contain a partially initialized anonymous struct, and we handle that inconsistently. Fixes #91257 --- clang/lib/Sema/SemaInit.cpp | 19 +- .../test/AST/ast-dump-APValue-anon-union.cpp | 2 +- .../SemaCXX/cxx1y-initializer-aggregates.cpp | 35 +++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 7d9eaf6720461..0a3d3ea019b1c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -813,19 +813,13 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity , if (const RecordType *RType = ILE->getType()->getAs()) { const RecordDecl *RDecl = RType->getDecl(); -if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) +if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) { FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE, RequiresSecondPass, FillWithNoInit); -else if (RDecl->isUnion() && isa(RDecl) && - cast(RDecl)->hasInClassInitializer()) { - for (auto *Field : RDecl->fields()) { -if (Field->hasInClassInitializer()) { - FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass, - FillWithNoInit); - break; -} - } } else { + assert((!RDecl->isUnion() || !isa(RDecl) || + !cast(RDecl)->hasInClassInitializer()) && + "We should have computed initialized fields already"); // The fields beyond ILE->getNumInits() are default initialized, so in // order to leave them uninitialized, the ILE is expanded and the extra // fields are then filled with NoInitExpr. @@ -2163,12 +2157,15 @@ void InitListChecker::CheckStructUnionTypes( return; for (RecordDecl::field_iterator FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { -if (Field->hasInClassInitializer()) { +if (Field->hasInClassInitializer() || +(Field->isAnonymousStructOrUnion() && + Field->getType()->getAsCXXRecordDecl()->hasInClassInitializer())) { StructuredList->setInitializedFieldInUnion(*Field); // FIXME: Actually build a CXXDefaultInitExpr? return; } } + llvm_unreachable("Couldn't find in-class initializer"); } // Value-initialize the first member of the union that isn't an unnamed diff --git a/clang/test/AST/ast-dump-APValue-anon-union.cpp b/clang/test/AST/ast-dump-APValue-anon-union.cpp index 0e6466ee1fd73..ffe14ed7322de 100644 --- a/clang/test/AST/ast-dump-APValue-anon-union.cpp +++ b/clang/test/AST/ast-dump-APValue-anon-union.cpp @@ -36,7 +36,7 @@ void Test() { constexpr U0 u0a{}; // CHECK: | `-VarDecl {{.*}} col:{{.*}} u0a 'const U0' constexpr listinit - // CHECK-NEXT: | |-value: Union None + // CHECK-NEXT: | |-value: Union .U0::(anonymous union at {{.*}}) Union .f Float 3.141500e+00 constexpr U0 u0b{3.1415f}; // CHECK: | `-VarDecl {{.*}} col:{{.*}} u0b 'const U0' constexpr listinit diff --git a/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp index 3d5e7726a17e5..ca60cf513b4a2 100644 --- a/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp +++ b/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp @@ -77,3 +77,38 @@ namespace use_self { int fib(int n) { return FibTree{n}.v; } } + +namespace nested_union { + union Test1 { +union { + int inner { 42 }; +}; +int outer; + }; + static_assert(Test1{}.inner == 42, ""); + struct Test2 { +union { + struct { +int inner : 32 { 42 }; // expected-warning {{C++20 extension}} + }; + int outer; +}; + }; + static_assert(Test2{}.inner == 42, ""); + struct Int { int x; }; + struct Test3 { +int x; +union { + struct { +const int& y; +int inner : 32 { 42 }; // expected-warning {{C++20 extension}} + }; + int outer; +}; + }; + constexpr char f(Test3) { return 1; } // expected-note {{candidate function}} + constexpr char f(Int) { return
[clang] [Clang] Fix incorrect passing of _BitInt args (PR #90741)
@@ -0,0 +1,14 @@ +// REQUIRES: arm-registered-target +// RUN: %clang_cc1 -triple aarch64-none-elf \ +// RUN: -O2 \ +// RUN: -emit-llvm -fexperimental-max-bitint-width=1024 -o - %s | FileCheck %s efriedma-quic wrote: Can we integrate this into some existing test file for aarch64 calling conventions? https://github.com/llvm/llvm-project/pull/90741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64][SME] Save VG for unwind info when changing streaming-mode (PR #83301)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/83301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AArch64] Fixed incorrect _BitInt alignment (PR #90602)
https://github.com/efriedma-quic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/90602 ___ 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)
efriedma-quic wrote: You're suggesting we should fork ConvertTypeForMem into two functions? So there's actually three types: the "register" type, the "load/store" type, and the "in-memory" type. I guess that makes sense from a theoretical perspective, but... as a practical matter, I'm not sure how many places need to call the proposed "ConvertTypeForLoadStore". In EmitLoadOfScalar(), instead of checking for BitInt, you just unconditionally do `Addr = Addr.withElementType(ConvertTypeForLoadStore(Ty));`. Logical cleanup, I guess. In EmitStoreOfScalar, you don't really need the interface because you can assume the result of EmitToMemory() has the load/store type. And then... what else calls it? 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] [llvm] [clang][hlsl] Add tan intrinsic part 1 (PR #90276)
https://github.com/efriedma-quic approved this pull request. Okay. I mostly just want to make sure the plan isn't "land all the intrinsics from the RFC, then eventually investigate the constrained intrinsics". LGTM https://github.com/llvm/llvm-project/pull/90276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][hlsl] Add tan intrinsic part 1 (PR #90276)
efriedma-quic wrote: > I didn't want the current set of changes to go stale. How many changes are we talking about here? If it's just the tan() ones, that's fine; it probably makes sense to land constrained-tan separately anyway. https://github.com/llvm/llvm-project/pull/90276 ___ 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)
@@ -529,9 +529,325 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, return false; } +//===--===// +// z/OS XPLINK ABI Implementation +//===--===// + +namespace { + +class ZOSXPLinkABIInfo : public ABIInfo { + static const unsigned GPRBits = 64; + bool HasVector; + +public: + ZOSXPLinkABIInfo(CodeGenTypes , bool HV) : ABIInfo(CGT), HasVector(HV) {} + + bool isPromotableIntegerType(QualType Ty) const; + bool isCompoundType(QualType Ty) const; + bool isVectorArgumentType(QualType Ty) const; + bool isFPArgumentType(QualType Ty) const; + QualType GetSingleElementType(QualType Ty) const; + bool IsLikeComplexType(QualType Ty) const; + + ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const; + + void computeInfo(CGFunctionInfo ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , bool HasVector) + : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) { +SwiftInfo = +std::make_unique(CGT, /*SwiftErrorInRegister=*/false); + } +}; + +} // namespace + +// Return true if the ABI requires Ty to be passed sign- or zero- +// extended to 64 bits. +bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const { + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs()) +Ty = EnumTy->getDecl()->getIntegerType(); + + // Promotable integer types are required to be promoted by the ABI. + if (getContext().isPromotableIntegerType(Ty)) +return true; + + // In addition to the usual promotable integer types, we also need to + // extend all 32-bit types, since the ABI requires promotion to 64 bits. + if (const BuiltinType *BT = Ty->getAs()) +switch (BT->getKind()) { +case BuiltinType::Int: +case BuiltinType::UInt: + return true; +default: + break; +} + + return false; +} + +bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const { + return (Ty->isAnyComplexType() || Ty->isVectorType() || + isAggregateTypeForABI(Ty)); +} + +bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const { + return (HasVector && Ty->isVectorType() && + getContext().getTypeSize(Ty) <= 128); +} + +bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const { + if (const BuiltinType *BT = Ty->getAs()) +switch (BT->getKind()) { +case BuiltinType::Float: +case BuiltinType::Double: +case BuiltinType::LongDouble: + return true; +default: + return false; +} + + return false; +} + +QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const { + if (const RecordType *RT = Ty->getAsStructureType()) { +const RecordDecl *RD = RT->getDecl(); +QualType Found; + +// If this is a C++ record, check the bases first. +if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) + for (const auto : CXXRD->bases()) { +QualType Base = I.getType(); + +// Empty bases don't affect things either way. +if (isEmptyRecord(getContext(), Base, true)) + continue; + +if (!Found.isNull()) + return Ty; +Found = GetSingleElementType(Base); + } + +// Check the fields. +for (const auto *FD : RD->fields()) { + // For compatibility with GCC, ignore empty bitfields in C++ mode. + // Unlike isSingleElementStruct(), empty structure and array fields + // do count. So do anonymous bitfields that aren't zero-sized. + if (getContext().getLangOpts().CPlusPlus && + FD->isZeroLengthBitField(getContext())) +continue; + + // Unlike isSingleElementStruct(), arrays do not count. + // Nested structures still do though. + if (!Found.isNull()) +return Ty; + Found = GetSingleElementType(FD->getType()); +} + +// Unlike isSingleElementStruct(), trailing padding is allowed. +// An 8-byte aligned struct s { float f; } is passed as a double. +if (!Found.isNull()) + return Found; + } + + return Ty; +} + +bool ZOSXPLinkABIInfo::IsLikeComplexType(QualType Ty) const { + if (const RecordType *RT = Ty->getAsStructureType()) { +const RecordDecl *RD = RT->getDecl(); +int i = 0; +clang::BuiltinType::Kind elemKind; + +// Check for exactly two elements with
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
https://github.com/efriedma-quic commented: At first glance, making a separate ABI seemed weird, but I guess it's pretty different from the normal SystemZ ABI. 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] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -529,9 +529,325 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, return false; } +//===--===// +// z/OS XPLINK ABI Implementation +//===--===// + +namespace { + +class ZOSXPLinkABIInfo : public ABIInfo { + static const unsigned GPRBits = 64; + bool HasVector; + +public: + ZOSXPLinkABIInfo(CodeGenTypes , bool HV) : ABIInfo(CGT), HasVector(HV) {} + + bool isPromotableIntegerType(QualType Ty) const; + bool isCompoundType(QualType Ty) const; + bool isVectorArgumentType(QualType Ty) const; + bool isFPArgumentType(QualType Ty) const; + QualType GetSingleElementType(QualType Ty) const; + bool IsLikeComplexType(QualType Ty) const; + + ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const; + + void computeInfo(CGFunctionInfo ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , bool HasVector) + : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) { +SwiftInfo = +std::make_unique(CGT, /*SwiftErrorInRegister=*/false); + } +}; + +} // namespace + +// Return true if the ABI requires Ty to be passed sign- or zero- +// extended to 64 bits. +bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const { + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs()) +Ty = EnumTy->getDecl()->getIntegerType(); + + // Promotable integer types are required to be promoted by the ABI. + if (getContext().isPromotableIntegerType(Ty)) +return true; + + // In addition to the usual promotable integer types, we also need to + // extend all 32-bit types, since the ABI requires promotion to 64 bits. + if (const BuiltinType *BT = Ty->getAs()) +switch (BT->getKind()) { +case BuiltinType::Int: +case BuiltinType::UInt: + return true; +default: + break; +} + + return false; +} + +bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const { + return (Ty->isAnyComplexType() || Ty->isVectorType() || + isAggregateTypeForABI(Ty)); +} + +bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const { + return (HasVector && Ty->isVectorType() && + getContext().getTypeSize(Ty) <= 128); +} + +bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const { + if (const BuiltinType *BT = Ty->getAs()) +switch (BT->getKind()) { +case BuiltinType::Float: +case BuiltinType::Double: +case BuiltinType::LongDouble: + return true; +default: + return false; +} + + return false; +} + +QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const { + if (const RecordType *RT = Ty->getAsStructureType()) { +const RecordDecl *RD = RT->getDecl(); +QualType Found; + +// If this is a C++ record, check the bases first. +if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) + for (const auto : CXXRD->bases()) { +QualType Base = I.getType(); + +// Empty bases don't affect things either way. +if (isEmptyRecord(getContext(), Base, true)) + continue; + +if (!Found.isNull()) + return Ty; +Found = GetSingleElementType(Base); + } + +// Check the fields. +for (const auto *FD : RD->fields()) { + // For compatibility with GCC, ignore empty bitfields in C++ mode. + // Unlike isSingleElementStruct(), empty structure and array fields + // do count. So do anonymous bitfields that aren't zero-sized. + if (getContext().getLangOpts().CPlusPlus && + FD->isZeroLengthBitField(getContext())) +continue; + + // Unlike isSingleElementStruct(), arrays do not count. + // Nested structures still do though. + if (!Found.isNull()) +return Ty; + Found = GetSingleElementType(FD->getType()); +} + +// Unlike isSingleElementStruct(), trailing padding is allowed. +// An 8-byte aligned struct s { float f; } is passed as a double. +if (!Found.isNull()) + return Found; + } + + return Ty; +} + +bool ZOSXPLinkABIInfo::IsLikeComplexType(QualType Ty) const { + if (const RecordType *RT = Ty->getAsStructureType()) { +const RecordDecl *RD = RT->getDecl(); +int i = 0; +clang::BuiltinType::Kind elemKind; + +// Check for exactly two elements with
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -529,9 +529,325 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, return false; } +//===--===// +// z/OS XPLINK ABI Implementation +//===--===// + +namespace { + +class ZOSXPLinkABIInfo : public ABIInfo { + static const unsigned GPRBits = 64; + bool HasVector; + +public: + ZOSXPLinkABIInfo(CodeGenTypes , bool HV) : ABIInfo(CGT), HasVector(HV) {} + + bool isPromotableIntegerType(QualType Ty) const; + bool isCompoundType(QualType Ty) const; + bool isVectorArgumentType(QualType Ty) const; + bool isFPArgumentType(QualType Ty) const; + QualType GetSingleElementType(QualType Ty) const; + bool IsLikeComplexType(QualType Ty) const; + + ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const; + + void computeInfo(CGFunctionInfo ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , bool HasVector) + : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) { +SwiftInfo = +std::make_unique(CGT, /*SwiftErrorInRegister=*/false); + } +}; + +} // namespace + +// Return true if the ABI requires Ty to be passed sign- or zero- +// extended to 64 bits. +bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const { + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs()) +Ty = EnumTy->getDecl()->getIntegerType(); + + // Promotable integer types are required to be promoted by the ABI. + if (getContext().isPromotableIntegerType(Ty)) +return true; + + // In addition to the usual promotable integer types, we also need to + // extend all 32-bit types, since the ABI requires promotion to 64 bits. + if (const BuiltinType *BT = Ty->getAs()) +switch (BT->getKind()) { +case BuiltinType::Int: +case BuiltinType::UInt: + return true; +default: + break; +} + + return false; +} + +bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const { + return (Ty->isAnyComplexType() || Ty->isVectorType() || + isAggregateTypeForABI(Ty)); +} + +bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const { + return (HasVector && Ty->isVectorType() && + getContext().getTypeSize(Ty) <= 128); +} + +bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const { + if (const BuiltinType *BT = Ty->getAs()) +switch (BT->getKind()) { +case BuiltinType::Float: +case BuiltinType::Double: +case BuiltinType::LongDouble: + return true; +default: + return false; +} + + return false; +} + +QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const { + if (const RecordType *RT = Ty->getAsStructureType()) { +const RecordDecl *RD = RT->getDecl(); +QualType Found; + +// If this is a C++ record, check the bases first. +if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) + for (const auto : CXXRD->bases()) { +QualType Base = I.getType(); + +// Empty bases don't affect things either way. +if (isEmptyRecord(getContext(), Base, true)) + continue; + +if (!Found.isNull()) + return Ty; +Found = GetSingleElementType(Base); + } + +// Check the fields. +for (const auto *FD : RD->fields()) { + // For compatibility with GCC, ignore empty bitfields in C++ mode. + // Unlike isSingleElementStruct(), empty structure and array fields + // do count. So do anonymous bitfields that aren't zero-sized. + if (getContext().getLangOpts().CPlusPlus && + FD->isZeroLengthBitField(getContext())) +continue; + + // Unlike isSingleElementStruct(), arrays do not count. + // Nested structures still do though. + if (!Found.isNull()) +return Ty; + Found = GetSingleElementType(FD->getType()); +} + +// Unlike isSingleElementStruct(), trailing padding is allowed. +// An 8-byte aligned struct s { float f; } is passed as a double. +if (!Found.isNull()) + return Found; + } + + return Ty; +} + +bool ZOSXPLinkABIInfo::IsLikeComplexType(QualType Ty) const { + if (const RecordType *RT = Ty->getAsStructureType()) { +const RecordDecl *RD = RT->getDecl(); +int i = 0; +clang::BuiltinType::Kind elemKind; + +// Check for exactly two elements with
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
https://github.com/efriedma-quic edited 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] [llvm] [BPF] Fix linking issues in static map initializers (PR #91310)
https://github.com/efriedma-quic edited https://github.com/llvm/llvm-project/pull/91310 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [BPF] Fix linking issues in static map initializers (PR #91310)
https://github.com/efriedma-quic commented: Is it possible you could put this code into CompleteExternalDeclaration(), instead of writing it out in every place that can refer to the address of a function? https://github.com/llvm/llvm-project/pull/91310 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [BPF] Fix linking issues in static map initializers (PR #91310)
@@ -1950,8 +1950,22 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase ) { if (D->hasAttr()) return CGM.GetWeakRefReference(D).getPointer(); -if (auto FD = dyn_cast(D)) - return CGM.GetAddrOfFunction(FD); +if (auto FD = dyn_cast(D)) { + auto *C = CGM.GetAddrOfFunction(FD); + + // we don't normally emit debug info for extern fns referenced via + // variable initialisers; BPF needs it since it generates BTF from + // debug info and bpftool demands BTF for every symbol linked + if (CGM.getTarget().getTriple().isBPF() && FD->getStorageClass() == SC_Extern) { efriedma-quic wrote: There's an existing hook allowDebugInfoForExternalRef() for which targets want this. You almost never want getStorageClass(); if you care about linkage, we have different methods for that. https://github.com/llvm/llvm-project/pull/91310 ___ 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)
efriedma-quic wrote: I don't think FPGA folks will run into any practical issue with this; this only impacts the in-memory types, and backends shouldn't really be using in-memory types for anything anyways. 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)
efriedma-quic wrote: > It seems to me this is a case where we're trying to work -around an llvm bug? > Should we just be fixing that instead? You mean, revert https://reviews.llvm.org/D86310 ? Making any changes in LLVM here is painful; I'd rather not revisit that. CC @hvdijk @rnk 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)
@@ -5348,6 +5348,13 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { return llvm::UndefValue::get(ArgTy); } + if (const auto *BIT = Ty->getAs()) { +if (BIT->getNumBits() > 128) { efriedma-quic wrote: This seems a little fragile; specifically for _BitInt, we assume the pointer is wrong and the return type is right, but in other cases, we assume the pointer is right and we need to do some sort of conversion. Can we fix the interface of EmitVAArg so we can just EmitLoadOfScalar() here? 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)
https://github.com/efriedma-quic commented: Maybe add a helper somewhere to check "is this type a bitint wider than 128 bits"? 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)
https://github.com/efriedma-quic edited 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)
@@ -1774,6 +1774,18 @@ llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule , return Res; } + if (const auto *BIT = destType->getAs()) { +if (BIT->getNumBits() > 128) { + // Long _BitInt has array of bytes as in-memory type. + ConstantAggregateBuilder Builder(CGM); + llvm::Type *DesiredTy = CGM.getTypes().ConvertTypeForMem(destType); + auto *CI = cast(C); efriedma-quic wrote: I'm not sure this cast is guaranteed to succeed? At least in some cases, we emit constant expressions involving a ptrtoint. Maybe at the widths in question, that can't happen, but this deserves a comment explaining what's going on. 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][AArch64] Fixed incorrect _BitInt alignment (PR #90602)
@@ -518,6 +518,16 @@ class TargetInfo : public TransferrableTargetInfo, /// getInt128Align() - Returns the alignment of Int128. unsigned getInt128Align() const { return Int128Align; } + /// getBitIntAlign/Width - Return aligned size of '_BitInt' and + /// 'unsigned _BitInt' for this target, in bits. + unsigned getBitIntWidth(unsigned NumBits) const { +return llvm::alignTo(NumBits, getBitIntAlign(NumBits)); + } + virtual unsigned getBitIntAlign(unsigned NumBits) const { efriedma-quic wrote: ``` unsigned getBitIntMaxAlign() { return BitIntMaxAlign.or(LongLongAlign); } unsigned getBitIntAlign(unsigned NumBits) const { return std::clamp(llvm::PowerOf2Ceil(NumBits), getCharWidth(), getBitIntMaxAlign()); } ``` https://github.com/llvm/llvm-project/pull/90602 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Arm64EC] Fix compilation of arm_acle.h (PR #91281)
https://github.com/efriedma-quic closed https://github.com/llvm/llvm-project/pull/91281 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Arm64EC] Fix compilation of arm_acle.h (PR #91281)
https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/91281 None >From 5a5512aa5a84e2c89efd9e9ade043061d73d25fb Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 3 May 2024 21:13:32 -0700 Subject: [PATCH] [Arm64EC] Fix compilation of arm_acle.h --- clang/lib/Headers/arm_acle.h | 2 +- clang/test/Headers/arm-acle-header.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h index 6e557eda1dddca..5785954c9171ab 100644 --- a/clang/lib/Headers/arm_acle.h +++ b/clang/lib/Headers/arm_acle.h @@ -109,7 +109,7 @@ __swp(uint32_t __x, volatile uint32_t *__p) { #endif /* 7.7 NOP */ -#if !defined(_MSC_VER) || !defined(__aarch64__) +#if !defined(_MSC_VER) || (!defined(__aarch64__) && !defined(__arm64ec__)) static __inline__ void __attribute__((__always_inline__, __nodebug__)) __nop(void) { __builtin_arm_nop(); } diff --git a/clang/test/Headers/arm-acle-header.c b/clang/test/Headers/arm-acle-header.c index f04c7e1f0f35f7..fea8472183c871 100644 --- a/clang/test/Headers/arm-acle-header.c +++ b/clang/test/Headers/arm-acle-header.c @@ -7,6 +7,7 @@ // RUN: %clang_cc1 -x c++ -triple thumbv7-windows -target-cpu cortex-a15 -fsyntax-only -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=19.11 %s // RUN: %clang_cc1 -x c++ -triple aarch64-windows -target-cpu cortex-a53 -fsyntax-only -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=19.11 %s // RUN: %clang_cc1 -x c++ -triple arm64-apple-ios -target-cpu apple-a7 -fsyntax-only -ffreestanding -fms-extensions %s +// RUN: %clang_cc1 -x c++ -triple arm64ec-windows -target-cpu cortex-a53 -fsyntax-only -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=19.11 %s // expected-no-diagnostics #include ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [ARM] Save floating point registers and status registers with save_fp function attribute (PR #89654)
@@ -2239,6 +2239,20 @@ The semantics are as follows: }]; } +def ARMInterruptSaveFPDocs : Documentation { +let Category = DocCatFunction; + let Heading = "interrupt_save_fp (ARM)"; + let Content = [{ +Clang supports the GNU style ``__attribute__((interrupt_save_fp("TYPE")))`` +on ARM targets. This attribute behaves the same way as the ARM interrupt +attribute, except the general purpose floating point registers are also saved. +If the FPEXC or FPSCR are needed, that state must be saved manually. Note, even efriedma-quic wrote: This says FPSCR isn't saved... but some of the tests show FPSCR getting saved. Which is right? https://github.com/llvm/llvm-project/pull/89654 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits