https://github.com/amaanq updated https://github.com/llvm/llvm-project/pull/228309
>From 9073e8a8e729ea0bc7c5334b6f888c6d98208312 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi <[email protected]> Date: Thu, 1 Oct 2026 21:36:18 -0400 Subject: [PATCH] [Clang][counted_by] Load the count through unions by byte offset `getGEPIndicesToField()` indexed into a union with 0 and kept walking the counter's struct field numbers, but the union's IR type is its largest member, so the count was loaded from inside that member instead. In Linux, `landlock_domain` hits this and FORTIFY panics on every nested `landlock_restrict_self()` on kernel 7.3.0-rc5-next as of this writing. Assisted-by: Claude --- clang/lib/CodeGen/CGExpr.cpp | 82 ++++++------------- .../CodeGen/attr-counted-by-issue200014.c | 22 ++--- .../CodeGen/attr-counted-by-nested-structs.c | 8 +- .../CodeGen/attr-counted-by-union-storage.c | 34 ++++++++ clang/test/CodeGen/builtin-counted-by-ref.c | 32 ++++---- 5 files changed, 89 insertions(+), 89 deletions(-) create mode 100644 clang/test/CodeGen/attr-counted-by-union-storage.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 8acf4b95f3e77..48ec98d346fb4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1064,8 +1064,8 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, /// Returns true if \p Field is reachable from \p RD either as a direct field or /// through a chain of nested record fields (including anonymous -/// structs/unions). This mirrors the GEP path that getGEPIndicesToField builds, -/// and is used to identify the right anchor expression in Base. +/// structs/unions). This mirrors the path that getFieldOffsetInBits walks, and +/// is used to identify the right anchor expression in Base. static bool RecordContainsField(const RecordDecl *RD, const FieldDecl *Field) { for (const FieldDecl *FD : RD->fields()) { if (FD == Field) @@ -1192,34 +1192,28 @@ class StructAccessBase } // end anonymous namespace -using RecIndicesTy = SmallVector<llvm::Value *, 8>; +/// The offset of a field from the beginning of the record. +static bool getFieldOffsetInBits(CodeGenFunction &CGF, const RecordDecl *RD, + const FieldDecl *Field, int64_t &Offset) { + ASTContext &Ctx = CGF.getContext(); + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + unsigned FieldNo = 0; -static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD, - const FieldDecl *Field, - RecIndicesTy &Indices) { - const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD); - int64_t FieldNo = -1; for (const FieldDecl *FD : RD->fields()) { - if (!Layout.containsFieldDecl(FD)) - // This could happen if the field has a struct type that's empty. I don't - // know why either. - continue; - - FieldNo = Layout.getLLVMFieldNo(FD); if (FD == Field) { - Indices.emplace_back(CGF.Builder.getInt32(FieldNo)); + Offset += Layout.getFieldOffset(FieldNo); return true; } QualType Ty = FD->getType(); - if (Ty->isRecordType()) { - if (getGEPIndicesToField(CGF, Ty->getAsRecordDecl(), Field, Indices)) { - if (RD->isUnion()) - FieldNo = 0; - Indices.emplace_back(CGF.Builder.getInt32(FieldNo)); + if (Ty->isRecordType()) + if (getFieldOffsetInBits(CGF, Ty->getAsRecordDecl(), Field, Offset)) { + Offset += Layout.getFieldOffset(FieldNo); return true; } - } + + if (!RD->isUnion()) + ++FieldNo; } return false; @@ -1228,8 +1222,8 @@ static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD, llvm::Value *CodeGenFunction::GetCountedByFieldExprGEP( const Expr *Base, const FieldDecl *FAMDecl, const FieldDecl *CountDecl) { // Walk Base to find the deepest sub-expression whose struct type transitively - // contains CountDecl. This is our GEP anchor — getGEPIndicesToField then - // builds the field indices from that struct down to CountDecl, handling any + // contains CountDecl. This is our GEP anchor — getFieldOffsetInBits then + // computes the offset from that struct down to CountDecl, handling any // intermediate nesting without requiring us to pre-compute a RecordDecl from // Base's type or from CountDecl's parent chain. const Expr *StructBase = StructAccessBase(CountDecl).Visit(Base); @@ -1258,16 +1252,15 @@ llvm::Value *CodeGenFunction::GetCountedByFieldExprGEP( return nullptr; } - RecIndicesTy Indices; - getGEPIndicesToField(*this, RD, CountDecl, Indices); - if (Indices.empty()) + // Struct GEP indices can't reach a count inside a union, because the union + // lowers to its largest member and the indices would walk that one instead. + int64_t Offset = 0; + if (!getFieldOffsetInBits(*this, RD, CountDecl, Offset)) return nullptr; - Indices.push_back(Builder.getInt32(0)); - CanQualType T = CGM.getContext().getCanonicalTagType(RD); - return Builder.CreateInBoundsGEP(ConvertType(T), Res, - RecIndicesTy(llvm::reverse(Indices)), - "counted_by.gep"); + return Builder.CreateInBoundsGEP( + Int8Ty, Res, Builder.getSize(getContext().toCharUnitsFromBits(Offset)), + "counted_by.gep"); } /// This method is typically called in contexts where we can't generate @@ -5007,33 +5000,6 @@ struct StructFieldAccess } // end anonymous namespace -/// The offset of a field from the beginning of the record. -static bool getFieldOffsetInBits(CodeGenFunction &CGF, const RecordDecl *RD, - const FieldDecl *Field, int64_t &Offset) { - ASTContext &Ctx = CGF.getContext(); - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); - unsigned FieldNo = 0; - - for (const FieldDecl *FD : RD->fields()) { - if (FD == Field) { - Offset += Layout.getFieldOffset(FieldNo); - return true; - } - - QualType Ty = FD->getType(); - if (Ty->isRecordType()) - if (getFieldOffsetInBits(CGF, Ty->getAsRecordDecl(), Field, Offset)) { - Offset += Layout.getFieldOffset(FieldNo); - return true; - } - - if (!RD->isUnion()) - ++FieldNo; - } - - return false; -} - /// Returns the relative offset difference between \p FD1 and \p FD2. /// \code /// offsetof(struct foo, FD1) - offsetof(struct foo, FD2) diff --git a/clang/test/CodeGen/attr-counted-by-issue200014.c b/clang/test/CodeGen/attr-counted-by-issue200014.c index e514ba1815229..6b672fdee0bf9 100644 --- a/clang/test/CodeGen/attr-counted-by-issue200014.c +++ b/clang/test/CodeGen/attr-counted-by-issue200014.c @@ -84,7 +84,7 @@ extern size_t sink; // FRONTEND-NEXT: store i64 [[TMP1]], ptr @sink, align 8 // FRONTEND-NEXT: [[FAM1:%.*]] = getelementptr inbounds nuw [[STRUCT_ANNOTATED_FLEX]], ptr [[AF]], i32 0, i32 2 // FRONTEND-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM1]], i64 0, i64 0 -// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED_FLEX]], ptr [[AF]], i32 0, i32 0 +// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[AF]], i64 0 // FRONTEND-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i64, ptr [[COUNTED_BY_GEP]], align 4 // FRONTEND-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNTED_BY_LOAD]], 1 // FRONTEND-NEXT: [[TMP2:%.*]] = icmp sgt i64 [[FLEXIBLE_ARRAY_MEMBER_SIZE]], -1 @@ -98,7 +98,7 @@ extern size_t sink; // O2-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[AF]]) #[[ATTR6:[0-9]+]] // O2-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[AF]], i64 9 // O2-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64 -// O2-NEXT: store i64 [[TMP1]], ptr @sink, align 8, !tbaa [[LONG_TBAA5:![0-9]+]] +// O2-NEXT: store i64 [[TMP1]], ptr @sink, align 8, !tbaa [[LONG_TBAA6:![0-9]+]] // O2-NEXT: [[TMP2:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) // O2-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[AF]]) #[[ATTR6]] // O2-NEXT: ret i64 [[TMP2]] @@ -129,7 +129,7 @@ size_t local_fam(size_t n) { // FRONTEND-NEXT: store i64 [[TMP1]], ptr @sink, align 8 // FRONTEND-NEXT: [[FAM1:%.*]] = getelementptr inbounds nuw [[STRUCT_ANNOTATED_FLEX]], ptr [[AF]], i32 0, i32 2 // FRONTEND-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM1]], i64 0, i64 2 -// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED_FLEX]], ptr [[AF]], i32 0, i32 0 +// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[AF]], i64 0 // FRONTEND-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i64, ptr [[COUNTED_BY_GEP]], align 4 // FRONTEND-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNTED_BY_LOAD]], 1 // FRONTEND-NEXT: [[RESULT:%.*]] = sub nuw i64 [[FLEXIBLE_ARRAY_MEMBER_SIZE]], 2 @@ -145,7 +145,7 @@ size_t local_fam(size_t n) { // O2-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[AF]]) #[[ATTR6]] // O2-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[AF]], i64 11 // O2-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[ARRAYIDX]] to i64 -// O2-NEXT: store i64 [[TMP0]], ptr @sink, align 8, !tbaa [[LONG_TBAA5]] +// O2-NEXT: store i64 [[TMP0]], ptr @sink, align 8, !tbaa [[LONG_TBAA6]] // O2-NEXT: [[RESULT:%.*]] = add i64 [[N]], -2 // O2-NEXT: [[TMP1:%.*]] = call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0) // O2-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[AF]]) #[[ATTR6]] @@ -185,7 +185,7 @@ size_t local_subscript(size_t n) { // O2-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[AF]]) #[[ATTR6]] // O2-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[AF]], i64 9 // O2-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64 -// O2-NEXT: store i64 [[TMP1]], ptr @sink, align 8, !tbaa [[LONG_TBAA5]] +// O2-NEXT: store i64 [[TMP1]], ptr @sink, align 8, !tbaa [[LONG_TBAA6]] // O2-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[AF]]) #[[ATTR6]] // O2-NEXT: ret i64 7 // @@ -274,7 +274,7 @@ size_t global_addrof(void) { // FRONTEND-NEXT: [[ENTRY:.*:]] // FRONTEND-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_ANNOTATED_FLEX:%.*]], ptr [[P]], i32 0, i32 2 // FRONTEND-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM]], i64 0, i64 0 -// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED_FLEX]], ptr [[P]], i32 0, i32 0 +// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 0 // FRONTEND-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i64, ptr [[COUNTED_BY_GEP]], align 4 // FRONTEND-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNTED_BY_LOAD]], 1 // FRONTEND-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[FLEXIBLE_ARRAY_MEMBER_SIZE]], -1 @@ -300,7 +300,7 @@ size_t ptr_fam(struct annotated_flex *p) { // FRONTEND-NEXT: [[ENTRY:.*:]] // FRONTEND-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_ANNOTATED_FLEX:%.*]], ptr [[P]], i32 0, i32 2 // FRONTEND-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM]], i64 0, i64 3 -// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED_FLEX]], ptr [[P]], i32 0, i32 0 +// FRONTEND-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 0 // FRONTEND-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i64, ptr [[COUNTED_BY_GEP]], align 4 // FRONTEND-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNTED_BY_LOAD]], 1 // FRONTEND-NEXT: [[RESULT:%.*]] = sub nuw i64 [[FLEXIBLE_ARRAY_MEMBER_SIZE]], 3 @@ -340,8 +340,8 @@ size_t ptr_addrof(struct annotated_flex *p) { return __builtin_dynamic_object_size(&p->fam, 1); } //. -// O2: [[META3:![0-9]+]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0} -// O2: [[META4]] = !{!"Simple C/C++ TBAA"} -// O2: [[LONG_TBAA5]] = !{[[META6:![0-9]+]], [[META6]], i64 0} -// O2: [[META6]] = !{!"long", [[META3]], i64 0} +// O2: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0} +// O2: [[META5]] = !{!"Simple C/C++ TBAA"} +// O2: [[LONG_TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0} +// O2: [[META7]] = !{!"long", [[META4]], i64 0} //. diff --git a/clang/test/CodeGen/attr-counted-by-nested-structs.c b/clang/test/CodeGen/attr-counted-by-nested-structs.c index 9f715add35872..0c9f349e82a8b 100644 --- a/clang/test/CodeGen/attr-counted-by-nested-structs.c +++ b/clang/test/CodeGen/attr-counted-by-nested-structs.c @@ -43,7 +43,7 @@ struct quad_nested { // CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw [[STRUCT_SINGLE_NESTED:%.*]], ptr [[TMP0]], i32 0, i32 1 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[BUF1:%.*]] = getelementptr inbounds nuw [[STRUCT_SINGLE_NESTED]], ptr [[TMP1]], i32 0, i32 1 -// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_FLEX:%.*]], ptr [[BUF1]], i32 0, i32 0 +// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[BUF1]], i64 0 // CHECK-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4 // CHECK-NEXT: [[COUNT:%.*]] = zext i32 [[COUNTED_BY_LOAD]] to i64 // CHECK-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNT]], 1 @@ -66,7 +66,7 @@ unsigned test_size_of_single_nested(struct single_nested *p) { // CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw [[STRUCT_DOUBLE_NESTED:%.*]], ptr [[TMP0]], i32 0, i32 1 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[BUF1:%.*]] = getelementptr inbounds nuw [[STRUCT_DOUBLE_NESTED]], ptr [[TMP1]], i32 0, i32 1 -// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_SINGLE_NESTED:%.*]], ptr [[BUF1]], i32 0, i32 1, i32 0 +// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[BUF1]], i64 4 // CHECK-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4 // CHECK-NEXT: [[COUNT:%.*]] = zext i32 [[COUNTED_BY_LOAD]] to i64 // CHECK-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNT]], 1 @@ -89,7 +89,7 @@ unsigned test_size_of_double_nested(struct double_nested *p) { // CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw [[STRUCT_TRIPLE_NESTED:%.*]], ptr [[TMP0]], i32 0, i32 1 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[BUF1:%.*]] = getelementptr inbounds nuw [[STRUCT_TRIPLE_NESTED]], ptr [[TMP1]], i32 0, i32 1 -// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_DOUBLE_NESTED:%.*]], ptr [[BUF1]], i32 0, i32 1, i32 1, i32 0 +// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[BUF1]], i64 8 // CHECK-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4 // CHECK-NEXT: [[COUNT:%.*]] = zext i32 [[COUNTED_BY_LOAD]] to i64 // CHECK-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNT]], 1 @@ -112,7 +112,7 @@ unsigned test_size_of_triple_nested(struct triple_nested *p) { // CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw [[STRUCT_QUAD_NESTED:%.*]], ptr [[TMP0]], i32 0, i32 1 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[BUF1:%.*]] = getelementptr inbounds nuw [[STRUCT_QUAD_NESTED]], ptr [[TMP1]], i32 0, i32 1 -// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_TRIPLE_NESTED:%.*]], ptr [[BUF1]], i32 0, i32 1, i32 1, i32 1, i32 0 +// CHECK-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[BUF1]], i64 12 // CHECK-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4 // CHECK-NEXT: [[COUNT:%.*]] = zext i32 [[COUNTED_BY_LOAD]] to i64 // CHECK-NEXT: [[FLEXIBLE_ARRAY_MEMBER_SIZE:%.*]] = mul nuw i64 [[COUNT]], 1 diff --git a/clang/test/CodeGen/attr-counted-by-union-storage.c b/clang/test/CodeGen/attr-counted-by-union-storage.c new file mode 100644 index 0000000000000..585cc87244dc7 --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by-union-storage.c @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -emit-llvm -o - %s | FileCheck %s + +// The union's IR type is struct work, so num_layers has to be reached by byte +// offset rather than through struct work's field indices. + +struct list { + struct list *next, *prev; +}; + +struct work { + long data; + struct list entry; + void (*func)(void); +}; + +struct domain { + void *rules[3]; + void *hierarchy; + union { + struct work work_free; + struct { + int usage; + unsigned int num_layers; + unsigned int masks[] __attribute__((counted_by(num_layers))); + }; + }; +}; + +// CHECK-LABEL: define {{.*}} @test_bdos( +// CHECK: [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr %d, i64 36 +// CHECK: load i32, ptr [[GEP]] +unsigned long test_bdos(struct domain *d) { + return __builtin_dynamic_object_size(d->masks, 1); +} diff --git a/clang/test/CodeGen/builtin-counted-by-ref.c b/clang/test/CodeGen/builtin-counted-by-ref.c index 8b1ef0edb8bd9..b79eb168e88da 100644 --- a/clang/test/CodeGen/builtin-counted-by-ref.c +++ b/clang/test/CodeGen/builtin-counted-by-ref.c @@ -23,8 +23,8 @@ struct a { // X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 // X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP1]] to i16 // X86_64-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 8 -// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[TMP2]], i32 0, i32 1 -// X86_64-NEXT: store i16 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 2 +// X86_64-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 2 +// X86_64-NEXT: store i16 [[CONV1]], ptr [[COUNTED_BY_GEP]], align 2 // X86_64-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 8 // X86_64-NEXT: ret ptr [[TMP3]] // @@ -42,8 +42,8 @@ struct a { // I386-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 // I386-NEXT: [[CONV:%.*]] = trunc i32 [[TMP1]] to i16 // I386-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 4 -// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[TMP2]], i32 0, i32 1 -// I386-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2 +// I386-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i32 2 +// I386-NEXT: store i16 [[CONV]], ptr [[COUNTED_BY_GEP]], align 2 // I386-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 4 // I386-NEXT: ret ptr [[TMP3]] // @@ -91,8 +91,8 @@ struct b { // X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 // X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP1]] to i8 // X86_64-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 8 -// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[TMP2]], i32 0, i32 1, i32 1, i32 1, i32 0 -// X86_64-NEXT: store i8 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 1 +// X86_64-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 12 +// X86_64-NEXT: store i8 [[CONV1]], ptr [[COUNTED_BY_GEP]], align 1 // X86_64-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 8 // X86_64-NEXT: ret ptr [[TMP3]] // @@ -110,8 +110,8 @@ struct b { // I386-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 // I386-NEXT: [[CONV:%.*]] = trunc i32 [[TMP1]] to i8 // I386-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 4 -// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[TMP2]], i32 0, i32 1, i32 1, i32 1, i32 0 -// I386-NEXT: store i8 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 1 +// I386-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i32 12 +// I386-NEXT: store i8 [[CONV]], ptr [[COUNTED_BY_GEP]], align 1 // I386-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 4 // I386-NEXT: ret ptr [[TMP3]] // @@ -200,8 +200,8 @@ struct d { // X86_64-NEXT: [[TMP2:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 // X86_64-NEXT: [[CONV:%.*]] = trunc i32 [[TMP2]] to i16 // X86_64-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 8 -// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[TMP3]], i32 0, i32 1 -// X86_64-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2 +// X86_64-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 4 +// X86_64-NEXT: store i16 [[CONV]], ptr [[COUNTED_BY_GEP]], align 2 // X86_64-NEXT: [[TMP4:%.*]] = load ptr, ptr [[P]], align 8 // X86_64-NEXT: ret ptr [[TMP4]] // @@ -222,8 +222,8 @@ struct d { // I386-NEXT: [[TMP2:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 // I386-NEXT: [[CONV:%.*]] = trunc i32 [[TMP2]] to i16 // I386-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 4 -// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[TMP3]], i32 0, i32 1 -// I386-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2 +// I386-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i32 4 +// I386-NEXT: store i16 [[CONV]], ptr [[COUNTED_BY_GEP]], align 2 // I386-NEXT: [[TMP4:%.*]] = load ptr, ptr [[P]], align 4 // I386-NEXT: ret ptr [[TMP4]] // @@ -246,13 +246,13 @@ struct outer { // X86_64-LABEL: define dso_local ptr @test5( // X86_64-SAME: i32 noundef [[COUNT:%.*]]) #[[ATTR0]] { -// X86_64: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_INNER:%.*]], ptr {{%.*}}, i32 0, i32 0 -// X86_64-NEXT: store i32 [[TMP1:%.*]], ptr [[DOT_COUNTED_BY_GEP]], align 4 +// X86_64: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr {{%.*}}, i64 0 +// X86_64-NEXT: store i32 [[TMP1:%.*]], ptr [[COUNTED_BY_GEP]], align 4 // // I386-LABEL: define dso_local ptr @test5( // I386-SAME: i32 noundef [[COUNT:%.*]]) #[[ATTR0]] { -// I386: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_INNER:%.*]], ptr {{%.*}}, i32 0, i32 0 -// I386-NEXT: store i32 [[TMP1:%.*]], ptr [[DOT_COUNTED_BY_GEP]], align 4 +// I386: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr {{%.*}}, i32 0 +// I386-NEXT: store i32 [[TMP1:%.*]], ptr [[COUNTED_BY_GEP]], align 4 // struct inner *test5(int count) { struct inner *entries = __builtin_malloc(sizeof(*entries) + count * sizeof(*entries->ent)); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
