blob: b0eb76af2809e584f8603c6b444d445b1c425e4a [file] [edit]
// RUN: %clang_cc1 -triple mips-none-linux-gnu -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR,GPR32
// RUN: %clang_cc1 -triple mipsel-none-linux-gnu -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR,GPR32
// RUN: %clang_cc1 -triple mips64-none-linux-gnu -target-abi n32 -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR,GPR64
// RUN: %clang_cc1 -triple mips64-none-linux-gnu -target-abi n64 -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR,GPR64
// RUN: %clang_cc1 -triple mips64el-none-linux-gnu -target-abi n64 -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR,GPR64
// RUN: %clang_cc1 -triple mips-none-linux-gnu -fclang-abi-compat=23 -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=COMPAT23,COMPAT23-GPR32
// RUN: %clang_cc1 -triple mips64-none-linux-gnu -target-abi n64 -fclang-abi-compat=23 \
// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=COMPAT23,COMPAT23-GPR64
// Test how MIPS passes and returns `_Complex` values.
// With Clang 23 and before, `_Complex {integer}` was returned in 2 registers.
// Later versions are compatible with GCC and pack such types into a single
// GPR if possible.
// GPR-LABEL: define{{.*}} i16 @ret_complex_char(
// COMPAT23-LABEL: define{{.*}} { i8, i8 } @ret_complex_char(
_Complex char ret_complex_char(void) { return 0; }
// GPR-LABEL: define{{.*}} i32 @ret_complex_short(
// COMPAT23-LABEL: define{{.*}} { i16, i16 } @ret_complex_short(
_Complex short ret_complex_short(void) { return 0; }
// GPR32-LABEL: define{{.*}} { i32, i32 } @ret_complex_int(
// GPR64-LABEL: define{{.*}} i64 @ret_complex_int(
// COMPAT23-LABEL: define{{.*}} { i32, i32 } @ret_complex_int(
_Complex int ret_complex_int(void) { return 0; }
// GPR-LABEL: define{{.*}} { i64, i64 } @ret_complex_long_long(
// COMPAT23-LABEL: define{{.*}} { i64, i64 } @ret_complex_long_long(
_Complex long long ret_complex_long_long(void) { return 0; }
// A `_Complex` value with a floating-point element type is returned in FPRs.
// GPR-LABEL: define{{.*}} { float, float } @ret_complex_float(
// COMPAT23-LABEL: define{{.*}} { float, float } @ret_complex_float(
_Complex float ret_complex_float(void) { return 0; }
// GPR-LABEL: define{{.*}} { double, double } @ret_complex_double(
// COMPAT23-LABEL: define{{.*}} { double, double } @ret_complex_double(
_Complex double ret_complex_double(void) { return 0; }
// GPR32-LABEL: define{{.*}} { double, double } @ret_complex_long_double(
// COMPAT23-GPR32-LABEL: define{{.*}} { double, double } @ret_complex_long_double(
// GPR64-LABEL: define{{.*}} void @ret_complex_long_double(ptr {{.*}}sret({ fp128, fp128 })
// COMPAT23-GPR64-LABEL: define{{.*}} void @ret_complex_long_double(ptr {{.*}}sret({ fp128, fp128 })
_Complex long double ret_complex_long_double(void) { return 0; }
// Arguments
// GPR-LABEL: define{{.*}} void @arg_complex_char(i16 inreg noundef %c.coerce)
void arg_complex_char(_Complex char c) {}
// GPR-LABEL: define{{.*}} void @arg_complex_short(i32 inreg noundef %c.coerce)
void arg_complex_short(_Complex short c) {}
// GPR32-LABEL: define{{.*}} void @arg_complex_int(i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1)
// GPR64-LABEL: define{{.*}} void @arg_complex_int(i64 inreg noundef %c.coerce)
void arg_complex_int(_Complex int c) {}
// GPR32-LABEL: define{{.*}} void @arg_complex_long_long(i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1, i32 inreg noundef %c.coerce2, i32 inreg noundef %c.coerce3)
// GPR64-LABEL: define{{.*}} void @arg_complex_long_long(i64 inreg noundef %c.coerce0, i64 inreg noundef %c.coerce1)
void arg_complex_long_long(_Complex long long c) {}
// GPR32-LABEL: define{{.*}} void @arg_complex_float(i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1)
// GPR64-LABEL: define{{.*}} void @arg_complex_float(float inreg noundef %c.coerce0, float inreg noundef %c.coerce1)
void arg_complex_float(_Complex float c) {}
// GPR32-LABEL: define{{.*}} void @arg_complex_double(i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1, i32 inreg noundef %c.coerce2, i32 inreg noundef %c.coerce3)
// GPR64-LABEL: define{{.*}} void @arg_complex_double(double inreg noundef %c.coerce0, double inreg noundef %c.coerce1)
void arg_complex_double(_Complex double c) {}
// GPR32-LABEL: define{{.*}} void @arg_complex_long_double(i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1, i32 inreg noundef %c.coerce2, i32 inreg noundef %c.coerce3)
// GPR64-LABEL: define{{.*}} void @arg_complex_long_double(fp128 inreg noundef %c.coerce0, fp128 inreg noundef %c.coerce1)
void arg_complex_long_double(_Complex long double c) {}
// Straddling the FPR/GPR border
// With Clang 23 and before, `_Complex float` and `_Complex` double were passed as two floats or doubles,
// even when that would not fit in the remaining float registers. Later versions match GCC, which will
// cast to one (float) or two (double) i64 values which are passed via GPRs (or the stack).
// Just padding to fill the slots.
#define SIX_SLOTS long long a0, long long a1, long long a2, \
long long a3, long long a4, long long a5
#define SEVEN_SLOTS SIX_SLOTS, long long a6
// Six slots used, so two are still free and the FPR pair is still used.
// GPR32-LABEL: define{{.*}} @arg_complex_float_6slots(i64{{.*}}, i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1)
// GPR64-LABEL: define{{.*}} @arg_complex_float_6slots(i64{{.*}}, float inreg noundef %c.coerce0, float inreg noundef %c.coerce1)
// COMPAT23-GPR64-LABEL: define{{.*}} @arg_complex_float_6slots(i64{{.*}}, float inreg noundef %c.coerce0, float inreg noundef %c.coerce1)
void arg_complex_float_6slots(SIX_SLOTS, _Complex float c) {}
// GPR32-LABEL: define{{.*}} @arg_complex_double_6slots(i64{{.*}}, i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1, i32 inreg noundef %c.coerce2, i32 inreg noundef %c.coerce3)
// GPR64-LABEL: define{{.*}} @arg_complex_double_6slots(i64{{.*}}, double inreg noundef %c.coerce0, double inreg noundef %c.coerce1)
// COMPAT23-GPR64-LABEL: define{{.*}} @arg_complex_double_6slots(i64{{.*}}, double inreg noundef %c.coerce0, double inreg noundef %c.coerce1)
void arg_complex_double_6slots(SIX_SLOTS, _Complex double c) {}
// GPR32-LABEL: define{{.*}} @arg_complex_float_7slots(i64{{.*}}, i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1)
// GPR64-LABEL: define{{.*}} @arg_complex_float_7slots(i64{{.*}}, i64 inreg noundef %c.coerce)
// COMPAT23-GPR64-LABEL: define{{.*}} @arg_complex_float_7slots(i64{{.*}}, float inreg noundef %c.coerce0, float inreg noundef %c.coerce1)
void arg_complex_float_7slots(SEVEN_SLOTS, _Complex float c) {}
// GPR32-LABEL: define{{.*}} @arg_complex_double_7slots(i64{{.*}}, i32 inreg noundef %c.coerce0, i32 inreg noundef %c.coerce1, i32 inreg noundef %c.coerce2, i32 inreg noundef %c.coerce3)
// GPR64-LABEL: define{{.*}} @arg_complex_double_7slots(i64{{.*}}, i64 inreg noundef %c.coerce0, i64 inreg noundef %c.coerce1)
// COMPAT23-GPR64-LABEL: define{{.*}} @arg_complex_double_7slots(i64{{.*}}, double inreg noundef %c.coerce0, double inreg noundef %c.coerce1)
void arg_complex_double_7slots(SEVEN_SLOTS, _Complex double c) {}
// GPR64-LABEL: define{{.*}} @arg_complex_float_after_3({{.*}}, float inreg noundef %c.coerce0, float inreg noundef %c.coerce1)
void arg_complex_float_after_3(_Complex float p0, _Complex float p1, _Complex float p2, _Complex float c) {}
// GPR64-LABEL: define{{.*}} @arg_complex_float_after_4({{.*}}, i64 inreg noundef %c.coerce)
void arg_complex_float_after_4(_Complex float p0, _Complex float p1, _Complex float p2, _Complex float p3, _Complex float c) {}
// GPR64-LABEL: define{{.*}} @arg_complex_long_double_7slots(i64{{.*}}, fp128 inreg noundef %c.coerce0, fp128 inreg noundef %c.coerce1)
// COMPAT23-GPR64-LABEL: define{{.*}} @arg_complex_long_double_7slots(i64{{.*}}, fp128 inreg noundef %c.coerce0, fp128 inreg noundef %c.coerce1)
void arg_complex_long_double_7slots(SEVEN_SLOTS, _Complex long double c) {}