[clang] [Clang] Add __builtin_counted_by_ref builtin (PR #114495)
Yeoul Na via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 4 15:51:18 PST 2024
================
@@ -0,0 +1,182 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=X86_64
+// RUN: %clang_cc1 -triple i386-unknown-unknown -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=I386
+
+struct a {
+ char x;
+ short count;
+ int array[] __attribute__((counted_by(count)));
+};
+
+// X86_64-LABEL: define dso_local noalias noundef ptr @test1(
+// X86_64-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// X86_64-NEXT: [[ENTRY:.*:]]
+// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64
+// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2
+// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4
+// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3:[0-9]+]]
+// X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[SIZE]] to i16
+// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 2
+// X86_64-NEXT: store i16 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA2:![0-9]+]]
+// X86_64-NEXT: ret ptr [[CALL]]
+//
+// I386-LABEL: define dso_local noalias noundef ptr @test1(
+// I386-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// I386-NEXT: [[ENTRY:.*:]]
+// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2
+// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4
+// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3:[0-9]+]]
+// I386-NEXT: [[CONV:%.*]] = trunc i32 [[SIZE]] to i16
+// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i32 2
+// I386-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA3:![0-9]+]]
+// I386-NEXT: ret ptr [[CALL]]
+//
+struct a *test1(int size) {
+ struct a *p = __builtin_malloc(sizeof(struct a) + sizeof(int) * size);
+
+ *__builtin_counted_by_ref(p->array) = size;
+ *__builtin_counted_by_ref(&p->array[0]) = size;
+ return p;
+}
+
+struct b {
+ int _filler;
+ struct {
+ int __filler;
+ struct {
+ int ___filler;
+ struct {
+ char count;
+ };
+ };
+ };
+ struct {
+ int filler_;
+ struct {
+ int filler__;
+ struct {
+ long array[] __attribute__((counted_by(count)));
+ };
+ };
+ };
+};
+
+// X86_64-LABEL: define dso_local noalias noundef ptr @test2(
+// X86_64-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// X86_64-NEXT: [[ENTRY:.*:]]
+// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64
+// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2
+// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4
+// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3]]
+// X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[SIZE]] to i8
+// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 12
+// X86_64-NEXT: store i8 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 1, !tbaa [[TBAA6:![0-9]+]]
+// X86_64-NEXT: ret ptr [[CALL]]
+//
+// I386-LABEL: define dso_local noalias noundef ptr @test2(
+// I386-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// I386-NEXT: [[ENTRY:.*:]]
+// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2
+// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4
+// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3]]
+// I386-NEXT: [[CONV:%.*]] = trunc i32 [[SIZE]] to i8
+// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i32 12
+// I386-NEXT: store i8 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 1, !tbaa [[TBAA7:![0-9]+]]
+// I386-NEXT: ret ptr [[CALL]]
+//
+struct b *test2(int size) {
+ struct b *p = __builtin_malloc(sizeof(struct a) + sizeof(int) * size);
+
+ *__builtin_counted_by_ref(p->array) = size;
+ *__builtin_counted_by_ref(&p->array[0]) = size;
+ return p;
+}
+
+struct c {
+ char x;
+ short count;
+ int array[];
+};
+
+// X86_64-LABEL: define dso_local noalias noundef ptr @test3(
+// X86_64-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// X86_64-NEXT: [[ENTRY:.*:]]
+// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64
+// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2
+// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4
+// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3]]
+// X86_64-NEXT: ret ptr [[CALL]]
+//
+// I386-LABEL: define dso_local noalias noundef ptr @test3(
+// I386-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// I386-NEXT: [[ENTRY:.*:]]
+// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2
+// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4
+// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3]]
+// I386-NEXT: ret ptr [[CALL]]
+//
+struct c *test3(int size) {
+ struct c *p = __builtin_malloc(sizeof(struct c) + sizeof(int) * size);
+ unsigned long int __ignored;
+
+ *_Generic(
+ __builtin_counted_by_ref(&p->array[0]),
+ void *: &__ignored,
+ default: __builtin_counted_by_ref(&p->array[0])) = size;
+
+ return p;
+}
+
+struct d {
+ char x;
+ short count;
+ int array[] __attribute__((counted_by(count)));
+};
+
+// X86_64-LABEL: define dso_local noalias noundef ptr @test4(
+// X86_64-SAME: i32 noundef [[SIZE:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// X86_64-NEXT: [[ENTRY:.*:]]
+// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64
+// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2
+// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4
+// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3]]
+// X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[SIZE]] to i16
+// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 2
+// X86_64-NEXT: store i16 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA2]]
+// X86_64-NEXT: ret ptr [[CALL]]
+//
+// I386-LABEL: define dso_local noalias noundef ptr @test4(
+// I386-SAME: i32 noundef [[SIZE:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// I386-NEXT: [[ENTRY:.*:]]
+// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2
+// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4
+// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3]]
+// I386-NEXT: [[CONV:%.*]] = trunc i32 [[SIZE]] to i16
+// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i32 2
+// I386-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA3]]
+// I386-NEXT: ret ptr [[CALL]]
+//
+struct d *test4(int size, int idx) {
+ struct d *p = __builtin_malloc(sizeof(struct d) + sizeof(int) * size);
+ unsigned long int __ignored;
+
+ *_Generic(
+ __builtin_counted_by_ref(&p->array[0]),
+ void *: &__ignored,
+ default: __builtin_counted_by_ref(&p->array[idx++])) = size;
----------------
rapidsna wrote:
Yes, upgrading to an error sounds good to me! Also, the message might need to be updated (since the side effect is not actually ignored).
https://github.com/llvm/llvm-project/pull/114495
More information about the cfe-commits
mailing list