CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
225 lines
10 KiB
HLSL
225 lines
10 KiB
HLSL
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -verify -o - %s -DERROR=1
|
|
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -Wno-conversion -ast-dump %s | FileCheck %s
|
|
|
|
// This test verifies floating point type implicit conversion ranks for overload
|
|
// resolution. In HLSL the built-in type ranks are half < float < double. This
|
|
// applies to both scalar and vector types.
|
|
|
|
// HLSL allows implicit truncation fo types, so it differentiates between
|
|
// promotions (converting to larger types) and conversions (converting to
|
|
// smaller types). Promotions are preferred over conversions. Promotions prefer
|
|
// promoting to the next lowest type in the ranking order. Conversions prefer
|
|
// converting to the next highest type in the ranking order.
|
|
|
|
void HalfFloatDouble(double2 D);
|
|
void HalfFloatDouble(float2 F);
|
|
void HalfFloatDouble(half2 H);
|
|
|
|
// CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (double2)'
|
|
// CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (float2)'
|
|
// CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (half2)'
|
|
|
|
void FloatDouble(double2 D); // expected-note {{candidate function}}
|
|
void FloatDouble(float2 F); // expected-note {{candidate function}}
|
|
|
|
// CHECK: FunctionDecl {{.*}} used FloatDouble 'void (double2)'
|
|
// CHECK: FunctionDecl {{.*}} used FloatDouble 'void (float2)'
|
|
|
|
void HalfDouble(double2 D);
|
|
void HalfDouble(half2 H);
|
|
|
|
// CHECK: FunctionDecl {{.*}} used HalfDouble 'void (double2)'
|
|
// CHECK: FunctionDecl {{.*}} used HalfDouble 'void (half2)'
|
|
|
|
void HalfFloat(float2 F); // expected-note {{candidate function}}
|
|
void HalfFloat(half2 H); // expected-note {{candidate function}}
|
|
|
|
// CHECK: FunctionDecl {{.*}} used HalfFloat 'void (float2)'
|
|
// CHECK: FunctionDecl {{.*}} used HalfFloat 'void (half2)'
|
|
|
|
void Double(double2 D);
|
|
void Float(float2 F);
|
|
void Half(half2 H);
|
|
|
|
// CHECK: FunctionDecl {{.*}} used Double 'void (double2)'
|
|
// CHECK: FunctionDecl {{.*}} used Float 'void (float2)'
|
|
// CHECK: FunctionDecl {{.*}} used Half 'void (half2)'
|
|
|
|
// Case 1: A function declared with overloads for half float and double types.
|
|
// (a) When called with half, it will resolve to half because half is an exact
|
|
// match.
|
|
// (b) When called with float it will resolve to float because float is an
|
|
// exact match.
|
|
// (c) When called with double it will resolve to double because it is an
|
|
// exact match.
|
|
|
|
// CHECK-LABEL: FunctionDecl {{.*}} Case1 'void (half2, float2, double2)'
|
|
void Case1(half2 H, float2 F, double2 D) {
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (half2)'
|
|
HalfFloatDouble(H);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (float2)'
|
|
HalfFloatDouble(F);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (double2)'
|
|
HalfFloatDouble(D);
|
|
}
|
|
|
|
// Case 2: A function declared with double and float overlaods.
|
|
// (a) When called with half, it fails to resulve the ambiguous promotion.
|
|
// (b) When called with float it will resolve to float because float is an
|
|
// exact match.
|
|
// (c) When called with double it will resolve to double because it is an
|
|
// exact match.
|
|
|
|
// CHECK-LABEL: FunctionDecl {{.*}} Case2 'void (half2, float2, double2)'
|
|
void Case2(half2 H, float2 F, double2 D) {
|
|
#if ERROR
|
|
FloatDouble(H); // expected-error {{call to 'FloatDouble' is ambiguous}}
|
|
#endif
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'FloatDouble' 'void (float2)'
|
|
FloatDouble(F);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'FloatDouble' 'void (double2)'
|
|
FloatDouble(D);
|
|
}
|
|
|
|
// Case 3: A function declared with half and double overloads
|
|
// (a) When called with half, it will resolve to half because it is an exact
|
|
// match.
|
|
// (b) When called with flaot, it will resolve to double because double is a
|
|
// valid promotion.
|
|
// (c) When called with double, it will resolve to double because it is an
|
|
// exact match.
|
|
|
|
// CHECK-LABEL: FunctionDecl {{.*}} Case3 'void (half2, float2, double2)'
|
|
void Case3(half2 H, float2 F, double2 D) {
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'HalfDouble' 'void (half2)'
|
|
HalfDouble(H);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfDouble' 'void (double2)'
|
|
HalfDouble(F);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfDouble' 'void (double2)'
|
|
HalfDouble(D);
|
|
}
|
|
|
|
// Case 4: A function declared with half and float overloads.
|
|
// (a) When called with half, it will resolve to half because half is an exact
|
|
// match.
|
|
// (b) When called with float it will resolve to float because float is an
|
|
// exact match.
|
|
// (c) When called with double it fails to resolve the ambigjuous conversion.
|
|
|
|
// CHECK-LABEL: FunctionDecl {{.*}} Case4 'void (half2, float2, double2)'
|
|
void Case4(half2 H, float2 F, double2 D) {
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'HalfFloat' 'void (half2)'
|
|
HalfFloat(H);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'HalfFloat' 'void (float2)'
|
|
HalfFloat(F);
|
|
|
|
#if ERROR
|
|
HalfFloat(D); // expected-error{{call to 'HalfFloat' is ambiguous}}
|
|
#endif
|
|
}
|
|
|
|
// Case 5: A function declared with only a double overload.
|
|
// (a) When called with half, it will resolve to double because double is a
|
|
// valid promotion.
|
|
// (b) When called with float it will resolve to double because double is a
|
|
// valid promotion.
|
|
// (c) When called with double it will resolve to double because it is an
|
|
// exact match.
|
|
|
|
// CHECK-LABEL: FunctionDecl {{.*}} Case5 'void (half2, float2, double2)'
|
|
void Case5(half2 H, float2 F, double2 D) {
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'Double' 'void (double2)'
|
|
Double(H);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'Double' 'void (double2)'
|
|
Double(F);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'Double' 'void (double2)'
|
|
Double(D);
|
|
}
|
|
|
|
// Case 6: A function declared with only a float overload.
|
|
// (a) When called with half, it will resolve to float because float is a
|
|
// valid promotion.
|
|
// (b) When called with float it will resolve to float because float is an
|
|
// exact match.
|
|
// (c) When called with double it will resolve to float because it is a
|
|
// valid conversion.
|
|
|
|
// CHECK-LABEL: FunctionDecl {{.*}} Case6 'void (half2, float2, double2)'
|
|
void Case6(half2 H, float2 F, double2 D) {
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'Float' 'void (float2)'
|
|
Float(H);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'Float' 'void (float2)'
|
|
Float(F);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'Float' 'void (float2)'
|
|
Float(D); // expected-warning{{implicit conversion loses floating-point precision: 'double2' (aka 'vector<double, 2>') to 'vector<float, 2>' (vector of 2 'float' values)}}
|
|
}
|
|
|
|
// Case 7: A function declared with only a half overload.
|
|
// (a) When called with half, it will resolve to half because half is an
|
|
// exact match
|
|
// (b) When called with float it will resolve to half because half is a
|
|
// valid conversion.
|
|
// (c) When called with double it will resolve to float because it is a
|
|
// valid conversion.
|
|
|
|
// CHECK-LABEL: FunctionDecl {{.*}} Case7 'void (half2, float2, double2)'
|
|
void Case7(half2 H, float2 F, double2 D) {
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'Half' 'void (half2)'
|
|
Half(H);
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'Half' 'void (half2)'
|
|
Half(F); // expected-warning{{implicit conversion loses floating-point precision: 'float2' (aka 'vector<float, 2>') to 'vector<half, 2>' (vector of 2 'half' values)}}
|
|
|
|
// CHECK: CallExpr {{.*}} 'void'
|
|
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay>
|
|
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'Half' 'void (half2)'
|
|
Half(D); // expected-warning{{implicit conversion loses floating-point precision: 'double2' (aka 'vector<double, 2>') to 'vector<half, 2>' (vector of 2 'half' values)}}
|
|
}
|