| // To test IR generation of the builtin without evaluating the LLVM intrinsic, |
| // we set the mode to a stateful mode, which prohibits constant evaluation. |
| // RUN: %clang_cc1 -triple x86_64-linux-gnu -Werror -std=c++20 -emit-llvm -falloc-token-mode=random -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-CODEGEN |
| // RUN: %clang_cc1 -triple x86_64-linux-gnu -Werror -std=c++20 -emit-llvm -falloc-token-max=2 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LOWER |
| |
| extern "C" void *my_malloc(unsigned long, unsigned long); |
| |
| struct NoPtr { |
| int x; |
| long y; |
| }; |
| |
| struct WithPtr { |
| int a; |
| char *buf; |
| }; |
| |
| int unevaluated_fn(); |
| |
| // CHECK-LABEL: @_Z16test_builtin_intv( |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_INT:[0-9]+]]) |
| // CHECK-LOWER: ret i64 0 |
| unsigned long test_builtin_int() { |
| return __builtin_infer_alloc_token(sizeof(1)); |
| } |
| |
| // CHECK-LABEL: @_Z16test_builtin_ptrv( |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_PTR:[0-9]+]]) |
| // CHECK-LOWER: ret i64 1 |
| unsigned long test_builtin_ptr() { |
| return __builtin_infer_alloc_token(sizeof(int *)); |
| } |
| |
| // CHECK-LABEL: @_Z25test_builtin_struct_noptrv( |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_NOPTR:[0-9]+]]) |
| // CHECK-LOWER: ret i64 0 |
| unsigned long test_builtin_struct_noptr() { |
| return __builtin_infer_alloc_token(sizeof(NoPtr)); |
| } |
| |
| // CHECK-LABEL: @_Z25test_builtin_struct_w_ptrv( |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_WITHPTR:[0-9]+]]) |
| // CHECK-LOWER: ret i64 1 |
| unsigned long test_builtin_struct_w_ptr() { |
| return __builtin_infer_alloc_token(sizeof(WithPtr), 123); |
| } |
| |
| // CHECK-LABEL: @_Z24test_builtin_unevaluatedv( |
| // CHECK-NOT: call{{.*}}unevaluated_fn |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_INT:[0-9]+]]) |
| // CHECK-LOWER: ret i64 0 |
| unsigned long test_builtin_unevaluated() { |
| return __builtin_infer_alloc_token(sizeof(int) * unevaluated_fn()); |
| } |
| |
| // CHECK-LABEL: @_Z36test_builtin_unsequenced_unevaluatedi( |
| // CHECK: add nsw |
| // CHECK-NOT: add nsw |
| // CHECK-CODEGEN: %[[REG:[0-9]+]] = call i64 @llvm.alloc.token.id.i64(metadata ![[META_UNKNOWN:[0-9]+]]) |
| // CHECK-CODEGEN: call{{.*}}@my_malloc({{.*}}, i64 noundef %[[REG]]) |
| // CHECK-LOWER: call{{.*}}@my_malloc({{.*}}, i64 noundef 0) |
| void test_builtin_unsequenced_unevaluated(int x) { |
| my_malloc(++x, __builtin_infer_alloc_token(++x)); |
| } |
| |
| // CHECK-LABEL: @_Z20test_builtin_unknownv( |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_UNKNOWN:[0-9]+]]) |
| // CHECK-LOWER: ret i64 0 |
| unsigned long test_builtin_unknown() { |
| return __builtin_infer_alloc_token(4096); |
| } |
| |
| // Test template instantiation. |
| template <typename T> |
| constexpr unsigned long get_token() { |
| return __builtin_infer_alloc_token(sizeof(T)); |
| } |
| |
| // CHECK-LABEL: @_Z13get_token_intv() |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_INT]]) |
| // CHECK-LOWER: ret i64 0 |
| unsigned long get_token_int() { |
| return get_token<int>(); |
| } |
| |
| // CHECK-LABEL: @_Z13get_token_ptrv() |
| // CHECK-CODEGEN: call i64 @llvm.alloc.token.id.i64(metadata ![[META_PTR]]) |
| // CHECK-LOWER: ret i64 1 |
| unsigned long get_token_ptr() { |
| return get_token<int *>(); |
| } |
| |
| // CHECK-CODEGEN: ![[META_INT]] = !{!"int", i1 false} |
| // CHECK-CODEGEN: ![[META_PTR]] = !{!"int *", i1 true} |
| // CHECK-CODEGEN: ![[META_NOPTR]] = !{!"NoPtr", i1 false} |
| // CHECK-CODEGEN: ![[META_WITHPTR]] = !{!"WithPtr", i1 true} |
| // CHECK-CODEGEN: ![[META_UNKNOWN]] = !{} |