| // REQUIRES: riscv-registered-target | |
| // RUN: %clang_cc1 -std=c++11 -triple riscv64-none-linux-gnu -target-feature +v \ | |
| // RUN: -mvscale-min=4 -mvscale-max=4 -emit-llvm -o - %s | FileCheck %s | |
| #include <riscv_vector.h> | |
| typedef vint32m1_t fixed_int32m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen))); | |
| //===----------------------------------------------------------------------===// | |
| // Eligible cases work in C++ the same as C | |
| //===----------------------------------------------------------------------===// | |
| struct st_1field { fixed_int32m1_t x; }; | |
| // CHECK-LABEL: @test_1field( | |
| // CHECK-SAME: <vscale x 2 x i32> | |
| extern "C" void test_1field(st_1field s) {} | |
| struct st_2field { fixed_int32m1_t x; fixed_int32m1_t y; }; | |
| // CHECK-LABEL: @test_2field( | |
| // CHECK-SAME: target("riscv.vector.tuple", <vscale x 8 x i8>, 2) | |
| extern "C" void test_2field(st_2field s) {} | |
| //===----------------------------------------------------------------------===// | |
| // Ineligible: struct with base class → passed indirectly | |
| // | |
| // detectHomogeneousRVVFixedLengthStruct rejects any struct with base classes | |
| // to avoid having to reason about their layout contribution. | |
| //===----------------------------------------------------------------------===// | |
| struct empty_base {}; | |
| struct derived_1field : empty_base { fixed_int32m1_t x; }; | |
| // CHECK-LABEL: @test_base_class( | |
| // CHECK-SAME: ptr | |
| extern "C" void test_base_class(derived_1field s) {} | |
| //===----------------------------------------------------------------------===// | |
| // Ineligible: non-trivial copy constructor → passed indirectly | |
| // | |
| // Handled by getRecordArgABI before detectHomogeneousRVVFixedLengthStruct | |
| // is ever consulted. | |
| //===----------------------------------------------------------------------===// | |
| struct nontrivial_copy { | |
| fixed_int32m1_t x; | |
| nontrivial_copy(const nontrivial_copy &) {} | |
| }; | |
| // CHECK-LABEL: @test_nontrivial_copy( | |
| // CHECK-SAME: ptr | |
| extern "C" void test_nontrivial_copy(nontrivial_copy s) {} | |
| //===----------------------------------------------------------------------===// | |
| // Ineligible: non-trivial destructor → passed indirectly | |
| // | |
| // Also handled by getRecordArgABI before reaching our function. | |
| //===----------------------------------------------------------------------===// | |
| struct nontrivial_dtor { | |
| fixed_int32m1_t x; | |
| ~nontrivial_dtor() {} | |
| }; | |
| // CHECK-LABEL: @test_nontrivial_dtor( | |
| // CHECK-SAME: ptr | |
| extern "C" void test_nontrivial_dtor(nontrivial_dtor s) {} |