diff --git a/clang/test/CodeGenCXX/LoongArch/abi-lp64d-empty-struct.cpp b/clang/test/CodeGenCXX/LoongArch/abi-lp64d-empty-struct.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/LoongArch/abi-lp64d-empty-struct.cpp @@ -0,0 +1,157 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define" --version 2 +// RUN: %clang_cc1 -triple loongarch64 -target-feature +f -target-feature +d -target-abi lp64d \ +// RUN: -emit-llvm %s -o - | FileCheck %s + +/// Treat the empty struct as char in C++ mode (sizeof(empty_s) = 1). +/// If the empty struct is a struct's member, will be treated as +/// fixed-point member. +/// WOA: Bit width of the argument. +/// FIXME: Empty struct is always passed or returned in C++ mode. + +/// 1. 0 < WOA <= GRLEN +/// 1.a. Only fixed-point members. + +struct empty_s {}; +// CHECK-LABEL: define dso_local void @_Z12empty_struct7empty_s +// CHECK-SAME: () #[[ATTR0:[0-9]+]] { +struct empty_s empty_struct(struct empty_s e) { + return e; +} + +struct empty_char_s { + struct empty_s e; + char c; +}; +// CHECK-LABEL: define dso_local i64 @_Z18empty_float_struct12empty_char_s +// CHECK-SAME: (i64 [[S_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_char_s empty_float_struct(struct empty_char_s s) { + return s; +} + +/// 1.b. Only floating-point members. +/// Nothing to do. The empty struct treated as fixed-point member. + +/// 1.c. Both fixed-point and floating-point members. +/// 1.c.i. Multiple fixed-point members. + +struct empty_char_float_s { + struct empty_s e1; + char c; + float f32; +}; +// CHECK-LABEL: define dso_local { i8, float } @_Z23empty_char_float_struct18empty_char_float_s +// CHECK-SAME: (i8 [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_char_float_s empty_char_float_struct(struct empty_char_float_s s) { + return s; +} + +/// 1.c.ii. One fixed-point member. + +struct empty_float_s { + struct empty_s e; + float f32; +}; +// CHECK-LABEL: define dso_local float @_Z18empty_float_struct13empty_float_s +// CHECK-SAME: (float [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_float_s empty_float_struct(struct empty_float_s s) { + return s; +} + +struct float_empty_s { + float f32; + struct empty_s e; +}; + +// CHECK-LABEL: define dso_local float @_Z18float_empty_struct13float_empty_s +// CHECK-SAME: (float [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +struct float_empty_s float_empty_struct(struct float_empty_s s) { + return s; +} + +/// 2. GRLEN < WOA <= 2*GRLEN + +/// 2.a. Only fixed-point members. +struct empty_long_s { + struct empty_s e; + long l; +}; +// CHECK-LABEL: define dso_local [2 x i64] @_Z17empty_long_struct12empty_long_s +// CHECK-SAME: ([2 x i64] [[S_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_long_s empty_long_struct(struct empty_long_s s) { + return s; +} + +/// 2.b. Only floating-point members. +/// Nothing to do. + +/// 2.c. Both fixed-point and floating-point members. +/// 2.c.i. The structure has one floating-point member and only one fixed-point +/// member. + +struct empty_double_s { + struct empty_s e; + double f64; +}; +// CHECK-LABEL: define dso_local double @_Z19empty_double_struct14empty_double_s +// CHECK-SAME: (double [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_double_s empty_double_struct(struct empty_double_s s) { + return s; +} + +struct double_empty_s { + double f64; + struct empty_s e; +}; +// CHECK-LABEL: define dso_local double @_Z19double_empty_struct14double_empty_s +// CHECK-SAME: (double [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +struct double_empty_s double_empty_struct(struct double_empty_s s) { + return s; +} + +/// 2.c.ii. Others + +struct empty_float_char_s { + struct empty_s e1; + float f32; + char c; +}; +// CHECK-LABEL: define dso_local { float, i8 } @_Z23empty_float_char_struct18empty_float_char_s +// CHECK-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_float_char_s empty_float_char_struct(struct empty_float_char_s s) { + return s; +} + +struct empty_float_double_s { + struct empty_s e1; + float f32; + double f64; +}; +// CHECK-LABEL: define dso_local { float, double } @_Z25empty_float_double_struct20empty_float_double_s +// CHECK-SAME: (float [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_float_double_s empty_float_double_struct(struct empty_float_double_s s) { + return s; +} + +/// 3 WOA > 2*GRLEN + +struct empty_long_empty_s { + struct empty_s e1; + long l; + struct empty_s e2; +}; +// CHECK-LABEL: define dso_local void @_Z23empty_long_empty_struct18empty_long_empty_s +// CHECK-SAME: (ptr noalias sret([[STRUCT_EMPTY_LONG_EMPTY_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[S:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_long_empty_s empty_long_empty_struct(struct empty_long_empty_s s) { + return s; +} + +struct empty_double_empty_s { + struct empty_s e1; + double f64; + struct empty_s e2; +}; +// CHECK-LABEL: define dso_local double @_Z25empty_double_empty_struct20empty_double_empty_s +// CHECK-SAME: (double [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +struct empty_double_empty_s empty_double_empty_struct(struct empty_double_empty_s s) { + return s; +}