| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,78 +1,102 @@ | ||
| // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ | ||
| // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ | ||
| // RUN: --check-prefixes=CHECK,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF | ||
| // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ | ||
| // RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXIL_CHECK,NO_HALF,DXIL_NO_HALF | ||
| // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ | ||
| // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ | ||
| // RUN: --check-prefixes=CHECK,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK | ||
| // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ | ||
| // RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_NO_HALF,SPIR_CHECK | ||
|
|
||
|
|
||
| // DXIL_NATIVE_HALF: %hlsl.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) | ||
| // SPIR_NATIVE_HALF: %hlsl.lerp = call half @llvm.spv.lerp.f16(half %0, half %1, half %2) | ||
| // NATIVE_HALF: ret half %hlsl.lerp | ||
| // DXIL_NO_HALF: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) | ||
| // SPIR_NO_HALF: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) | ||
| // NO_HALF: ret float %hlsl.lerp | ||
| half test_lerp_half(half p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) | ||
| // SPIR_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.spv.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) | ||
| // NATIVE_HALF: ret <2 x half> %hlsl.lerp | ||
| // DXIL_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) | ||
| // SPIR_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) | ||
| // NO_HALF: ret <2 x float> %hlsl.lerp | ||
| half2 test_lerp_half2(half2 p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) | ||
| // SPIR_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.spv.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) | ||
| // NATIVE_HALF: ret <3 x half> %hlsl.lerp | ||
| // DXIL_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) | ||
| // SPIR_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) | ||
| // NO_HALF: ret <3 x float> %hlsl.lerp | ||
| half3 test_lerp_half3(half3 p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) | ||
| // SPIR_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.spv.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) | ||
| // NATIVE_HALF: ret <4 x half> %hlsl.lerp | ||
| // DXIL_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) | ||
| // SPIR_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) | ||
| // NO_HALF: ret <4 x float> %hlsl.lerp | ||
| half4 test_lerp_half4(half4 p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_CHECK: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) | ||
| // SPIR_CHECK: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) | ||
| // CHECK: ret float %hlsl.lerp | ||
| float test_lerp_float(float p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) | ||
| // SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) | ||
| // CHECK: ret <2 x float> %hlsl.lerp | ||
| float2 test_lerp_float2(float2 p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) | ||
| // SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) | ||
| // CHECK: ret <3 x float> %hlsl.lerp | ||
| float3 test_lerp_float3(float3 p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) | ||
| // SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) | ||
| // CHECK: ret <4 x float> %hlsl.lerp | ||
| float4 test_lerp_float4(float4 p0) { return lerp(p0, p0, p0); } | ||
|
|
||
| // DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) | ||
| // SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) | ||
| // CHECK: ret <2 x float> %hlsl.lerp | ||
| float2 test_lerp_float2_splat(float p0, float2 p1) { return lerp(p0, p1, p1); } | ||
|
|
||
| // DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) | ||
| // SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) | ||
| // CHECK: ret <3 x float> %hlsl.lerp | ||
| float3 test_lerp_float3_splat(float p0, float3 p1) { return lerp(p0, p1, p1); } | ||
|
|
||
| // DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) | ||
| // SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) | ||
| // CHECK: ret <4 x float> %hlsl.lerp | ||
| float4 test_lerp_float4_splat(float p0, float4 p1) { return lerp(p0, p1, p1); } | ||
|
|
||
| // CHECK: %conv = sitofp i32 %2 to float | ||
| // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 | ||
| // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer | ||
| // DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) | ||
| // SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) | ||
| // CHECK: ret <2 x float> %hlsl.lerp | ||
| float2 test_lerp_float2_int_splat(float2 p0, int p1) { | ||
| return lerp(p0, p0, p1); | ||
| } | ||
|
|
||
| // CHECK: %conv = sitofp i32 %2 to float | ||
| // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 | ||
| // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer | ||
| // DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) | ||
| // SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) | ||
| // CHECK: ret <3 x float> %hlsl.lerp | ||
| float3 test_lerp_float3_int_splat(float3 p0, int p1) { | ||
| return lerp(p0, p0, p1); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name statement-expression.c %s | ||
|
|
||
| // No crash for the following examples, where GNU Statement Expression extension | ||
| // could introduce region terminators (break, goto etc) before implicit | ||
| // initializers in a struct or an array. | ||
| // See https://github.com/llvm/llvm-project/pull/89564 | ||
|
|
||
| struct Foo { | ||
| int field1; | ||
| int field2; | ||
| }; | ||
|
|
||
| void f1(void) { | ||
| struct Foo foo = { | ||
| .field1 = ({ | ||
| switch (0) { | ||
| case 0: | ||
| break; // A region terminator | ||
| } | ||
| 0; | ||
| }), | ||
| // ImplicitValueInitExpr introduced here for .field2 | ||
| }; | ||
| } | ||
|
|
||
| void f2(void) { | ||
| int arr[3] = { | ||
| [0] = ({ | ||
| goto L0; // A region terminator | ||
| L0: | ||
| 0; | ||
| }), | ||
| // ImplicitValueInitExpr introduced here for subscript [1] | ||
| [2] = 0, | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,23 @@ | ||
| // RUN: %clang_cc1 -std=c17 -fsyntax-only -verify=ext -Wno-unused %s | ||
| // RUN: %clang_cc1 -std=c2x -fsyntax-only -verify=compat -Wpre-c2x-compat -Wno-unused %s | ||
| // RUN: %clang_cc1 -fsyntax-only -verify=cpp -Wbit-int-extension -Wno-unused -x c++ %s | ||
|
|
||
| #if 18446744073709551615uwb // ext-warning {{'_BitInt' suffix for literals is a C23 extension}} \ | ||
| compat-warning {{'_BitInt' suffix for literals is incompatible with C standards before C23}} \ | ||
| cpp-error {{invalid suffix 'uwb' on integer constant}} | ||
| #endif | ||
|
|
||
| #if 18446744073709551615__uwb // ext-error {{invalid suffix '__uwb' on integer constant}} \ | ||
| compat-error {{invalid suffix '__uwb' on integer constant}} \ | ||
| cpp-warning {{'_BitInt' suffix for literals is a Clang extension}} | ||
| #endif | ||
|
|
||
| void func(void) { | ||
| 18446744073709551615wb; // ext-warning {{'_BitInt' suffix for literals is a C23 extension}} \ | ||
| compat-warning {{'_BitInt' suffix for literals is incompatible with C standards before C23}} \ | ||
| cpp-error {{invalid suffix 'wb' on integer constant}} | ||
|
|
||
| 18446744073709551615__wb; // ext-error {{invalid suffix '__wb' on integer constant}} \ | ||
| compat-error {{invalid suffix '__wb' on integer constant}} \ | ||
| cpp-warning {{'_BitInt' suffix for literals is a Clang extension}} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| // RUN: %clang_cc1 -triple aarch64-unknown-unknown -fsyntax-only -verify -Wno-unused %s | ||
|
|
||
| // Test that the preprocessor behavior makes sense. | ||
| #if 1__wb != 1 | ||
| #error "wb suffix must be recognized by preprocessor" | ||
| #endif | ||
| #if 1__uwb != 1 | ||
| #error "uwb suffix must be recognized by preprocessor" | ||
| #endif | ||
| #if !(-1__wb < 0) | ||
| #error "wb suffix must be interpreted as signed" | ||
| #endif | ||
| #if !(-1__uwb > 0) | ||
| #error "uwb suffix must be interpreted as unsigned" | ||
| #endif | ||
|
|
||
| #if 18446744073709551615__uwb != 18446744073709551615ULL | ||
| #error "expected the max value for uintmax_t to compare equal" | ||
| #endif | ||
|
|
||
| // Test that the preprocessor gives appropriate diagnostics when the | ||
| // literal value is larger than what can be stored in a [u]intmax_t. | ||
| #if 18446744073709551616__wb != 0ULL // expected-error {{integer literal is too large to be represented in any integer type}} | ||
| #error "never expected to get here due to error" | ||
| #endif | ||
| #if 18446744073709551616__uwb != 0ULL // expected-error {{integer literal is too large to be represented in any integer type}} | ||
| #error "never expected to get here due to error" | ||
| #endif | ||
|
|
||
| // Despite using a bit-precise integer, this is expected to overflow | ||
| // because all preprocessor arithmetic is done in [u]intmax_t, so this | ||
| // should result in the value 0. | ||
| #if 18446744073709551615__uwb + 1 != 0ULL | ||
| #error "expected modulo arithmetic with uintmax_t width" | ||
| #endif | ||
|
|
||
| // Because this bit-precise integer is signed, it will also overflow, | ||
| // but Clang handles that by converting to uintmax_t instead of | ||
| // intmax_t. | ||
| #if 18446744073709551615__wb + 1 != 0LL // expected-warning {{integer literal is too large to be represented in a signed integer type, interpreting as unsigned}} | ||
| #error "expected modulo arithmetic with uintmax_t width" | ||
| #endif | ||
|
|
||
| // Test that just because the preprocessor can't figure out the bit | ||
| // width doesn't mean we can't form the constant, it just means we | ||
| // can't use the value in a preprocessor conditional. | ||
| unsigned _BitInt(65) Val = 18446744073709551616__uwb; | ||
| // UDL test to make sure underscore parsing is correct | ||
| unsigned operator ""_(const char *); | ||
|
|
||
| void ValidSuffix(void) { | ||
| // Decimal literals. | ||
| 1__wb; | ||
| 1__WB; | ||
| -1__wb; | ||
| _Static_assert((int)1__wb == 1, "not 1?"); | ||
| _Static_assert((int)-1__wb == -1, "not -1?"); | ||
|
|
||
| 1__uwb; | ||
| 1__uWB; | ||
| 1__Uwb; | ||
| 1__UWB; | ||
| 1u__wb; | ||
| 1__WBu; | ||
| 1U__WB; | ||
| _Static_assert((unsigned int)1__uwb == 1u, "not 1?"); | ||
|
|
||
| 1'2__wb; | ||
| 1'2__uwb; | ||
| _Static_assert((int)1'2__wb == 12, "not 12?"); | ||
| _Static_assert((unsigned int)1'2__uwb == 12u, "not 12?"); | ||
|
|
||
| // Hexadecimal literals. | ||
| 0x1__wb; | ||
| 0x1__uwb; | ||
| 0x0'1'2'3__wb; | ||
| 0xA'B'c'd__uwb; | ||
| _Static_assert((int)0x0'1'2'3__wb == 0x0123, "not 0x0123"); | ||
| _Static_assert((unsigned int)0xA'B'c'd__uwb == 0xABCDu, "not 0xABCD"); | ||
|
|
||
| // Binary literals. | ||
| 0b1__wb; | ||
| 0b1__uwb; | ||
| 0b1'0'1'0'0'1__wb; | ||
| 0b0'1'0'1'1'0__uwb; | ||
| _Static_assert((int)0b1__wb == 1, "not 1?"); | ||
| _Static_assert((unsigned int)0b1__uwb == 1u, "not 1?"); | ||
|
|
||
| // Octal literals. | ||
| 01__wb; | ||
| 01__uwb; | ||
| 0'6'0__wb; | ||
| 0'0'1__uwb; | ||
| 0__wbu; | ||
| 0__WBu; | ||
| 0U__wb; | ||
| 0U__WB; | ||
| 0__wb; | ||
| _Static_assert((int)0__wb == 0, "not 0?"); | ||
| _Static_assert((unsigned int)0__wbu == 0u, "not 0?"); | ||
|
|
||
| // Imaginary or Complex. These are allowed because _Complex can work with any | ||
| // integer type, and that includes _BitInt. | ||
| 1__wbi; | ||
| 1i__wb; | ||
| 1__wbj; | ||
|
|
||
| //UDL test as single underscore | ||
| unsigned i = 1.0_; | ||
| } | ||
|
|
||
| void InvalidSuffix(void) { | ||
| // Can't mix the case of wb or WB, and can't rearrange the letters. | ||
| 0__wB; // expected-error {{invalid suffix '__wB' on integer constant}} | ||
| 0__Wb; // expected-error {{invalid suffix '__Wb' on integer constant}} | ||
| 0__bw; // expected-error {{invalid suffix '__bw' on integer constant}} | ||
| 0__BW; // expected-error {{invalid suffix '__BW' on integer constant}} | ||
|
|
||
| // Trailing digit separators should still diagnose. | ||
| 1'2'__wb; // expected-error {{digit separator cannot appear at end of digit sequence}} | ||
| 1'2'__uwb; // expected-error {{digit separator cannot appear at end of digit sequence}} | ||
|
|
||
| // Long. | ||
| 1l__wb; // expected-error {{invalid suffix}} | ||
| 1__wbl; // expected-error {{invalid suffix}} | ||
| 1l__uwb; // expected-error {{invalid suffix}} | ||
| 1__l; // expected-error {{invalid suffix}} | ||
| 1ul__wb; // expected-error {{invalid suffix}} | ||
|
|
||
| // Long long. | ||
| 1ll__wb; // expected-error {{invalid suffix}} | ||
| 1__uwbll; // expected-error {{invalid suffix}} | ||
|
|
||
| // Floating point. | ||
| 0.1__wb; // expected-error {{invalid suffix}} | ||
| 0.1f__wb; // expected-error {{invalid suffix}} | ||
|
|
||
| // Repetitive suffix. | ||
| 1__wb__wb; // expected-error {{invalid suffix}} | ||
| 1__uwbuwb; // expected-error {{invalid suffix}} | ||
| 1__wbuwb; // expected-error {{invalid suffix}} | ||
| 1__uwbwb; // expected-error {{invalid suffix}} | ||
|
|
||
| // Missing or extra characters in suffix. | ||
| 1__; // expected-error {{invalid suffix}} | ||
| 1__u; // expected-error {{invalid suffix}} | ||
| 1___; // expected-error {{invalid suffix}} | ||
| 1___WB; // expected-error {{invalid suffix}} | ||
| 1__wb__; // expected-error {{invalid suffix}} | ||
| 1__w; // expected-error {{invalid suffix}} | ||
| 1__b; // expected-error {{invalid suffix}} | ||
| } | ||
|
|
||
| void ValidSuffixInvalidValue(void) { | ||
| // This is a valid suffix, but the value is larger than one that fits within | ||
| // the width of BITINT_MAXWIDTH. When this value changes in the future, the | ||
| // test cases should pick a new value that can't be represented by a _BitInt, | ||
| // but also add a test case that a 129-bit literal still behaves as-expected. | ||
| _Static_assert(__BITINT_MAXWIDTH__ <= 128, | ||
| "Need to pick a bigger constant for the test case below."); | ||
| 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1__wb; // expected-error {{integer literal is too large to be represented in any signed integer type}} | ||
| 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1__uwb; // expected-error {{integer literal is too large to be represented in any integer type}} | ||
| } | ||
|
|
||
| void TestTypes(void) { | ||
| // 2 value bits, one sign bit | ||
| _Static_assert(__is_same(decltype(3__wb), _BitInt(3))); | ||
| // 2 value bits, one sign bit | ||
| _Static_assert(__is_same(decltype(-3__wb), _BitInt(3))); | ||
| // 2 value bits, no sign bit | ||
| _Static_assert(__is_same(decltype(3__uwb), unsigned _BitInt(2))); | ||
| // 4 value bits, one sign bit | ||
| _Static_assert(__is_same(decltype(0xF__wb), _BitInt(5))); | ||
| // 4 value bits, one sign bit | ||
| _Static_assert(__is_same(decltype(-0xF__wb), _BitInt(5))); | ||
| // 4 value bits, no sign bit | ||
| _Static_assert(__is_same(decltype(0xF__uwb), unsigned _BitInt(4))); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| // RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s | ||
|
|
||
| // GH87641 noticed that integer promotion of a bit-field of bit-precise integer | ||
| // type was promoting to int rather than the type of the bit-field. | ||
| struct S { | ||
| unsigned _BitInt(7) x : 2; | ||
| unsigned _BitInt(2) y : 2; | ||
| unsigned _BitInt(72) z : 28; | ||
| _BitInt(31) a : 12; | ||
| _BitInt(33) b : 33; | ||
| }; | ||
|
|
||
| // We don't have to worry about promotion cases where the bit-precise type is | ||
| // smaller than the width of the bit-field; that can't happen. | ||
| struct T { | ||
| unsigned _BitInt(28) oh_no : 72; // expected-error {{width of bit-field 'oh_no' (72 bits) exceeds the width of its type (28 bits)}} | ||
| }; | ||
|
|
||
| static_assert( | ||
| _Generic(+(struct S){}.x, | ||
| int : 0, | ||
| unsigned _BitInt(7) : 1, | ||
| unsigned _BitInt(2) : 2 | ||
| ) == 1); | ||
|
|
||
| static_assert( | ||
| _Generic(+(struct S){}.y, | ||
| int : 0, | ||
| unsigned _BitInt(7) : 1, | ||
| unsigned _BitInt(2) : 2 | ||
| ) == 2); | ||
|
|
||
| static_assert( | ||
| _Generic(+(struct S){}.z, | ||
| int : 0, | ||
| unsigned _BitInt(72) : 1, | ||
| unsigned _BitInt(28) : 2 | ||
| ) == 1); | ||
|
|
||
| static_assert( | ||
| _Generic(+(struct S){}.a, | ||
| int : 0, | ||
| _BitInt(31) : 1, | ||
| _BitInt(12) : 2, | ||
| unsigned _BitInt(31) : 3 | ||
| ) == 1); | ||
|
|
||
| static_assert( | ||
| _Generic(+(struct S){}.b, | ||
| int : 0, | ||
| long long : 1, | ||
| _BitInt(33) : 2, | ||
| unsigned _BitInt(33) : 3 | ||
| ) == 2); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // RUN: %clang --target=x86_64-pc-linux -S -fno-discard-value-names -emit-llvm -o - %s | FileCheck %s | ||
|
|
||
| namespace std { | ||
| using size_t = decltype(sizeof(int)); | ||
| }; | ||
| void* operator new[](std::size_t, void*) noexcept; | ||
|
|
||
| // CHECK: call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 8, i1 false) | ||
| // CHECK: call void @llvm.memset.p0.i64(ptr align 16 %x, i8 0, i64 32, i1 false) | ||
| template <typename TYPE> | ||
| void f() | ||
| { | ||
| typedef TYPE TArray[8]; | ||
|
|
||
| TArray x; | ||
| new(&x) TArray(); | ||
| } | ||
|
|
||
| template <typename T> | ||
| void f1() { | ||
| int (*x)[1] = new int[1][1]; | ||
| } | ||
| template void f1<char>(); | ||
| void f2() { | ||
| int (*x)[1] = new int[1][1]; | ||
| } | ||
|
|
||
| int main() | ||
| { | ||
| f<char>(); | ||
| f<int>(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| // RUN: %clang_cc1 %s -fopenacc -verify | ||
|
|
||
| short getS(); | ||
| void Test() { | ||
| #pragma acc kernels num_gangs(1) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(1) | ||
| while(1); | ||
|
|
||
| #pragma acc parallel num_gangs(1) | ||
| while(1); | ||
|
|
||
| // expected-error@+2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'kernels' directive}} | ||
| // expected-note@+1{{previous clause is here}} | ||
| #pragma acc kernels num_gangs(1) num_gangs(2) | ||
| while(1); | ||
|
|
||
| // expected-error@+2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'parallel' directive}} | ||
| // expected-note@+1{{previous clause is here}} | ||
| #pragma acc parallel num_gangs(1) num_gangs(2) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'kernels' directive expects maximum of 1, 2 were provided}} | ||
| #pragma acc kernels num_gangs(1, getS()) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(1, getS()) | ||
| while(1); | ||
| #pragma acc parallel num_gangs(1, getS()) | ||
| while(1); | ||
|
|
||
| struct NotConvertible{} NC; | ||
| // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| #pragma acc parallel num_gangs(NC) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| #pragma acc parallel num_gangs(1, NC) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| #pragma acc parallel num_gangs(NC, 1) | ||
| while(1); | ||
|
|
||
| #pragma acc parallel num_gangs(getS(), 1, getS()) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'parallel' directive expects maximum of 3, 4 were provided}} | ||
| #pragma acc parallel num_gangs(getS(), 1, getS(), 1) | ||
| while(1); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| // RUN: %clang_cc1 %s -fopenacc -verify | ||
|
|
||
| struct NotConvertible{} NC; | ||
| struct Incomplete *SomeIncomplete; // #INCOMPLETE | ||
| enum E{} SomeE; | ||
| enum class E2{} SomeE2; | ||
|
|
||
| struct CorrectConvert { | ||
| operator int(); | ||
| } Convert; | ||
|
|
||
| struct ExplicitConvertOnly { | ||
| explicit operator int() const; // #EXPL_CONV | ||
| } Explicit; | ||
|
|
||
| struct AmbiguousConvert{ | ||
| operator int(); // #AMBIG_INT | ||
| operator short(); // #AMBIG_SHORT | ||
| operator float(); | ||
| } Ambiguous; | ||
|
|
||
| short some_short(); | ||
| int some_int(); | ||
| long some_long(); | ||
|
|
||
| void Test() { | ||
| #pragma acc kernels num_gangs(1) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(1) | ||
| while(1); | ||
|
|
||
| #pragma acc parallel num_gangs(1) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(some_short(), some_int(), some_long()) | ||
| while(1); | ||
|
|
||
| #pragma acc parallel num_gangs(some_short(), some_int(), some_long()) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(some_short(), some_int(), some_long(), SomeE) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'parallel' directive expects maximum of 3, 4 were provided}} | ||
| #pragma acc parallel num_gangs(some_short(), some_int(), some_long(), SomeE) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'kernels' directive expects maximum of 1, 2 were provided}} | ||
| #pragma acc kernels num_gangs(1, 2) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(1, 2) | ||
| while(1); | ||
|
|
||
| #pragma acc parallel num_gangs(1, 2) | ||
| while(1); | ||
|
|
||
| // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} | ||
| // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} | ||
| // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} | ||
| #pragma acc parallel num_gangs(Ambiguous) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| #pragma acc parallel num_gangs(NC, SomeE) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| #pragma acc parallel num_gangs(SomeE, NC) | ||
| while(1); | ||
|
|
||
| // expected-error@+3{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} | ||
| // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} | ||
| // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| #pragma acc parallel num_gangs(Explicit, NC) | ||
| while(1); | ||
|
|
||
| // expected-error@+4{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} | ||
| // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} | ||
| // expected-error@+2{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(Explicit, NC) | ||
| while(1); | ||
|
|
||
| // expected-error@+6{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} | ||
| // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} | ||
| // expected-error@+4{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} | ||
| // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} | ||
| // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} | ||
| #pragma acc parallel num_gangs(Explicit, NC, Ambiguous) | ||
| while(1); | ||
|
|
||
| // expected-error@+7{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} | ||
| // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} | ||
| // expected-error@+5{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} | ||
| // expected-error@+4{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} | ||
| // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} | ||
| // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} | ||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(Explicit, NC, Ambiguous) | ||
| while(1); | ||
| // TODO | ||
| } | ||
|
|
||
| struct HasInt { | ||
| using IntTy = int; | ||
| using ShortTy = short; | ||
| static constexpr int value = 1; | ||
| static constexpr AmbiguousConvert ACValue; | ||
| static constexpr ExplicitConvertOnly EXValue; | ||
|
|
||
| operator char(); | ||
| }; | ||
|
|
||
| template <typename T> | ||
| void TestInst() { | ||
| // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} | ||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(HasInt::Invalid) | ||
| while(1); | ||
|
|
||
| // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} | ||
| // expected-note@#INST{{in instantiation of function template specialization}} | ||
| #pragma acc parallel num_gangs(T::Invalid) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{no member named 'Invalid' in 'HasInt'}} | ||
| #pragma acc parallel num_gangs(1, HasInt::Invalid) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{no member named 'Invalid' in 'HasInt'}} | ||
| #pragma acc parallel num_gangs(T::Invalid, 1) | ||
| while(1); | ||
|
|
||
| // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} | ||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(1, HasInt::Invalid) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(T::Invalid, 1) | ||
| while(1); | ||
|
|
||
| #pragma acc parallel num_gangs(T::value, typename T::IntTy{}) | ||
| while(1); | ||
|
|
||
| // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} | ||
| #pragma acc serial num_gangs(T::value, typename T::IntTy{}) | ||
| while(1); | ||
| } | ||
|
|
||
| void Inst() { | ||
| TestInst<HasInt>(); // #INST | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| add_compiler_rt_component(ctx_profile) | ||
|
|
||
| set(CTX_PROFILE_SOURCES | ||
| CtxInstrProfiling.cpp | ||
| ) | ||
|
|
||
| set(CTX_PROFILE_HEADERS | ||
| CtxInstrProfiling.h | ||
| ) | ||
|
|
||
| include_directories(..) | ||
| include_directories(../../include) | ||
|
|
||
| # We don't use the C++ Standard Library here, so avoid including it by mistake. | ||
| append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ EXTRA_FLAGS) | ||
|
|
||
| if(COMPILER_RT_INCLUDE_TESTS) | ||
| add_subdirectory(tests) | ||
| endif() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| //===- CtxInstrProfiling.cpp - contextual instrumented PGO ----------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "CtxInstrProfiling.h" | ||
| #include "sanitizer_common/sanitizer_allocator_internal.h" | ||
| #include "sanitizer_common/sanitizer_common.h" | ||
| #include "sanitizer_common/sanitizer_dense_map.h" | ||
| #include "sanitizer_common/sanitizer_mutex.h" | ||
| #include "sanitizer_common/sanitizer_placement_new.h" | ||
| #include "sanitizer_common/sanitizer_thread_safety.h" | ||
|
|
||
| #include <assert.h> | ||
|
|
||
| using namespace __ctx_profile; | ||
|
|
||
| // FIXME(mtrofin): use malloc / mmap instead of sanitizer common APIs to reduce | ||
| // the dependency on the latter. | ||
| Arena *Arena::allocateNewArena(size_t Size, Arena *Prev) { | ||
| assert(!Prev || Prev->Next == nullptr); | ||
| Arena *NewArena = | ||
| new (__sanitizer::InternalAlloc(Size + sizeof(Arena))) Arena(Size); | ||
| if (Prev) | ||
| Prev->Next = NewArena; | ||
| return NewArena; | ||
| } | ||
|
|
||
| void Arena::freeArenaList(Arena *&A) { | ||
| assert(A); | ||
| for (auto *I = A; I != nullptr;) { | ||
| auto *Current = I; | ||
| I = I->Next; | ||
| __sanitizer::InternalFree(Current); | ||
| } | ||
| A = nullptr; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /*===- CtxInstrProfiling.h- Contextual instrumentation-based PGO ---------===*\ | ||
| |* | ||
| |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| |* See https://llvm.org/LICENSE.txt for license information. | ||
| |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| |* | ||
| \*===----------------------------------------------------------------------===*/ | ||
|
|
||
| #ifndef CTX_PROFILE_CTXINSTRPROFILING_H_ | ||
| #define CTX_PROFILE_CTXINSTRPROFILING_H_ | ||
|
|
||
| #include <sanitizer/common_interface_defs.h> | ||
|
|
||
| namespace __ctx_profile { | ||
|
|
||
| /// Arena (bump allocator) forming a linked list. Intentionally not thread safe. | ||
| /// Allocation and de-allocation happen using sanitizer APIs. We make that | ||
| /// explicit. | ||
| class Arena final { | ||
| public: | ||
| // When allocating a new Arena, optionally specify an existing one to append | ||
| // to, assumed to be the last in the Arena list. We only need to support | ||
| // appending to the arena list. | ||
| static Arena *allocateNewArena(size_t Size, Arena *Prev = nullptr); | ||
| static void freeArenaList(Arena *&A); | ||
|
|
||
| uint64_t size() const { return Size; } | ||
|
|
||
| // Allocate S bytes or return nullptr if we don't have that many available. | ||
| char *tryBumpAllocate(size_t S) { | ||
| if (Pos + S > Size) | ||
| return nullptr; | ||
| Pos += S; | ||
| return start() + (Pos - S); | ||
| } | ||
|
|
||
| Arena *next() const { return Next; } | ||
|
|
||
| // the beginning of allocatable memory. | ||
| const char *start() const { return const_cast<Arena *>(this)->start(); } | ||
| const char *pos() const { return start() + Pos; } | ||
|
|
||
| private: | ||
| explicit Arena(uint32_t Size) : Size(Size) {} | ||
| ~Arena() = delete; | ||
|
|
||
| char *start() { return reinterpret_cast<char *>(&this[1]); } | ||
|
|
||
| Arena *Next = nullptr; | ||
| uint64_t Pos = 0; | ||
| const uint64_t Size; | ||
| }; | ||
|
|
||
| } // namespace __ctx_profile | ||
| #endif // CTX_PROFILE_CTXINSTRPROFILING_H_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| include(CheckCXXCompilerFlag) | ||
| include(CompilerRTCompile) | ||
| include(CompilerRTLink) | ||
|
|
||
| set(CTX_PROFILE_UNITTEST_CFLAGS | ||
| ${COMPILER_RT_UNITTEST_CFLAGS} | ||
| ${COMPILER_RT_GTEST_CFLAGS} | ||
| ${COMPILER_RT_GMOCK_CFLAGS} | ||
| ${SANITIZER_TEST_CXX_CFLAGS} | ||
| -I${COMPILER_RT_SOURCE_DIR}/lib/ | ||
| -DSANITIZER_COMMON_NO_REDEFINE_BUILTINS | ||
| -O2 | ||
| -g | ||
| -fno-rtti | ||
| -Wno-pedantic | ||
| -fno-omit-frame-pointer) | ||
|
|
||
| # Suppress warnings for gmock variadic macros for clang and gcc respectively. | ||
| append_list_if(SUPPORTS_GNU_ZERO_VARIADIC_MACRO_ARGUMENTS_FLAG -Wno-gnu-zero-variadic-macro-arguments CTX_PROFILE_UNITTEST_CFLAGS) | ||
| append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros CTX_PROFILE_UNITTEST_CFLAGS) | ||
|
|
||
| file(GLOB CTX_PROFILE_HEADERS ../*.h) | ||
|
|
||
| set(CTX_PROFILE_SOURCES | ||
| ../CtxInstrProfiling.cpp) | ||
|
|
||
| set(CTX_PROFILE_UNITTESTS | ||
| CtxInstrProfilingTest.cpp | ||
| driver.cpp) | ||
|
|
||
| include_directories(../../../include) | ||
|
|
||
| set(CTX_PROFILE_UNITTEST_HEADERS | ||
| ${CTX_PROFILE_HEADERS}) | ||
|
|
||
| set(CTX_PROFILE_UNITTEST_LINK_FLAGS | ||
| ${COMPILER_RT_UNITTEST_LINK_FLAGS}) | ||
|
|
||
| list(APPEND CTX_PROFILE_UNITTEST_LINK_FLAGS -pthread) | ||
|
|
||
| set(CTX_PROFILE_UNITTEST_DEPS) | ||
| if (TARGET cxx-headers OR HAVE_LIBCXX) | ||
| list(APPEND CTX_PROFILE_UNITTEST_DEPS cxx-headers) | ||
| endif() | ||
|
|
||
| set(CTX_PROFILE_UNITTEST_LINK_LIBRARIES | ||
| ${COMPILER_RT_UNWINDER_LINK_LIBS} | ||
| ${SANITIZER_TEST_CXX_LIBRARIES}) | ||
| append_list_if(COMPILER_RT_HAS_LIBDL -ldl CTX_PROFILE_UNITTEST_LINK_LIBRARIES) | ||
|
|
||
| macro (add_ctx_profile_tests_for_arch arch) | ||
| set(CTX_PROFILE_TEST_RUNTIME_OBJECTS | ||
| $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> | ||
| $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> | ||
| $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> | ||
| $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> | ||
| $<TARGET_OBJECTS:RTSanitizerCommonSymbolizerInternal.${arch}> | ||
| ) | ||
| set(CTX_PROFILE_TEST_RUNTIME RTCtxProfileTest.${arch}) | ||
| add_library(${CTX_PROFILE_TEST_RUNTIME} STATIC ${CTX_PROFILE_TEST_RUNTIME_OBJECTS}) | ||
| set_target_properties(${CTX_PROFILE_TEST_RUNTIME} PROPERTIES | ||
| ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | ||
| FOLDER "Compiler-RT Runtime tests") | ||
| set(CTX_PROFILE_TEST_OBJECTS) | ||
| generate_compiler_rt_tests(CTX_PROFILE_TEST_OBJECTS | ||
| CtxProfileUnitTests "CtxProfile-${arch}-UnitTest" ${arch} | ||
| RUNTIME ${CTX_PROFILE_TEST_RUNTIME} | ||
| DEPS ${CTX_PROFILE_UNITTEST_DEPS} | ||
| SOURCES ${CTX_PROFILE_UNITTESTS} ${CTX_PROFILE_SOURCES} ${COMPILER_RT_GTEST_SOURCE} | ||
| COMPILE_DEPS ${CTX_PROFILE_UNITTEST_HEADERS} | ||
| CFLAGS ${CTX_PROFILE_UNITTEST_CFLAGS} | ||
| LINK_FLAGS ${CTX_PROFILE_UNITTEST_LINK_FLAGS} ${CTX_PROFILE_UNITTEST_LINK_LIBRARIES}) | ||
| endmacro() | ||
|
|
||
| add_custom_target(CtxProfileUnitTests) | ||
| set_target_properties(CtxProfileUnitTests PROPERTIES FOLDER "Compiler-RT Tests") | ||
| if(COMPILER_RT_CAN_EXECUTE_TESTS AND COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST CTX_PROFILE_SUPPORTED_ARCH) | ||
| # CtxProfile unit tests are only run on the host machine. | ||
| foreach(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) | ||
| add_ctx_profile_tests_for_arch(${arch}) | ||
| endforeach() | ||
| endif() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #include "../CtxInstrProfiling.h" | ||
| #include "gtest/gtest.h" | ||
|
|
||
| using namespace __ctx_profile; | ||
|
|
||
| TEST(ArenaTest, Basic) { | ||
| Arena *A = Arena::allocateNewArena(1024); | ||
| EXPECT_EQ(A->size(), 1024U); | ||
| EXPECT_EQ(A->next(), nullptr); | ||
|
|
||
| auto *M1 = A->tryBumpAllocate(1020); | ||
| EXPECT_NE(M1, nullptr); | ||
| auto *M2 = A->tryBumpAllocate(4); | ||
| EXPECT_NE(M2, nullptr); | ||
| EXPECT_EQ(M1 + 1020, M2); | ||
| EXPECT_EQ(A->tryBumpAllocate(1), nullptr); | ||
| Arena *A2 = Arena::allocateNewArena(2024, A); | ||
| EXPECT_EQ(A->next(), A2); | ||
| EXPECT_EQ(A2->next(), nullptr); | ||
| Arena::freeArenaList(A); | ||
| EXPECT_EQ(A, nullptr); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,14 @@ | ||
| //===-- driver.cpp ----------------------------------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "gtest/gtest.h" | ||
|
|
||
| int main(int argc, char **argv) { | ||
| testing::InitGoogleTest(&argc, argv); | ||
| return RUN_ALL_TESTS(); | ||
| } | ||