232 lines · plain
1/// Test LoongArch64 ABI rewrite of struct passed by value (BIND(C), VALUE derived types).2/// This test test cases where the struct can be passed in registers.3/// Test cases can be roughly divided into two categories:4/// - struct with a single intrinsic component;5/// - sturct with more than one field;6/// Since the argument marshalling logic is largely the same within each category,7/// only the first example in each category checks the entire invocation process,8/// while the other examples only check the signatures.9 10// RUN: fir-opt --split-input-file --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s11 12 13/// *********************** Struct with a single intrinsic component *********************** ///14 15!ty_i16 = !fir.type<ti16{i:i16}>16!ty_i32 = !fir.type<ti32{i:i32}>17!ty_i64 = !fir.type<ti64{i:i64}>18!ty_i128 = !fir.type<ti128{i:i128}>19!ty_f16 = !fir.type<tf16{i:f16}>20!ty_f32 = !fir.type<tf32{i:f32}>21!ty_f64 = !fir.type<tf64{i:f64}>22!ty_f128 = !fir.type<tf128{i:f128}>23!ty_bf16 = !fir.type<tbf16{i:bf16}>24!ty_char1 = !fir.type<tchar1{i:!fir.char<1>}>25!ty_char2 = !fir.type<tchar2{i:!fir.char<1,2>}>26!ty_log1 = !fir.type<tlog1{i:!fir.logical<1>}>27!ty_log2 = !fir.type<tlog2{i:!fir.logical<2>}>28!ty_log4 = !fir.type<tlog4{i:!fir.logical<4>}>29!ty_log8 = !fir.type<tlog8{i:!fir.logical<8>}>30!ty_log16 = !fir.type<tlog16{i:!fir.logical<16>}>31!ty_cmplx_f32 = !fir.type<tcmplx_f32{i:complex<f32>}>32!ty_cmplx_f64 = !fir.type<tcmplx_f64{i:complex<f64>}>33 34module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", llvm.target_triple = "loongarch64-unknown-linux-gnu"} {35 36// CHECK-LABEL: func.func private @test_func_i16(i64)37func.func private @test_func_i16(%arg0: !ty_i16)38// CHECK-LABEL: func.func @test_call_i16(39// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<ti16{i:i16}>>) {40func.func @test_call_i16(%arg0: !fir.ref<!ty_i16>) {41 // CHECK: %[[IN:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.type<ti16{i:i16}>>42 // CHECK: %[[STACK:.*]] = llvm.intr.stacksave : !llvm.ptr43 // CHECK: %[[ARR:.*]] = fir.alloca i6444 // CHECK: %[[CVT:.*]] = fir.convert %[[ARR]] : (!fir.ref<i64>) -> !fir.ref<!fir.type<ti16{i:i16}>>45 // CHECK: fir.store %[[IN]] to %[[CVT]] : !fir.ref<!fir.type<ti16{i:i16}>>46 // CHECK: %[[LD:.*]] = fir.load %[[ARR]] : !fir.ref<i64>47 %in = fir.load %arg0 : !fir.ref<!ty_i16>48 // CHECK: fir.call @test_func_i16(%[[LD]]) : (i64) -> ()49 // CHECK: llvm.intr.stackrestore %[[STACK]] : !llvm.ptr50 fir.call @test_func_i16(%in) : (!ty_i16) -> ()51 // CHECK: return52 return53}54 55// CHECK-LABEL: func.func private @test_func_i32(i64)56func.func private @test_func_i32(%arg0: !ty_i32)57 58// CHECK-LABEL: func.func private @test_func_i64(i64)59func.func private @test_func_i64(%arg0: !ty_i64)60 61// CHECK-LABEL: func.func private @test_func_i128(i128)62func.func private @test_func_i128(%arg0: !ty_i128)63 64// CHECK-LABEL: func.func private @test_func_f16(i64)65func.func private @test_func_f16(%arg0: !ty_f16)66 67// CHECK-LABEL: func.func private @test_func_f32(f32)68func.func private @test_func_f32(%arg0: !ty_f32)69 70// CHECK-LABEL: func.func private @test_func_f64(f64)71func.func private @test_func_f64(%arg0: !ty_f64)72 73// CHECK-LABEL: func.func private @test_func_f128(i128)74func.func private @test_func_f128(%arg0: !ty_f128)75 76// CHECK-LABEL: func.func private @test_func_bf16(i64)77func.func private @test_func_bf16(%arg0: !ty_bf16)78 79// CHECK-LABEL: func.func private @test_func_char1(i64)80func.func private @test_func_char1(%arg0: !ty_char1)81 82// CHECK-LABEL: func.func private @test_func_char2(i64)83func.func private @test_func_char2(%arg0: !ty_char2)84 85// CHECK-LABEL: func.func private @test_func_log1(i64)86func.func private @test_func_log1(%arg0: !ty_log1)87 88// CHECK-LABEL: func.func private @test_func_log2(i64)89func.func private @test_func_log2(%arg0: !ty_log2)90 91// CHECK-LABEL: func.func private @test_func_log4(i64)92func.func private @test_func_log4(%arg0: !ty_log4)93 94// CHECK-LABEL: func.func private @test_func_log8(i64)95func.func private @test_func_log8(%arg0: !ty_log8)96 97// CHECK-LABEL: func.func private @test_func_log16(i128)98func.func private @test_func_log16(%arg0: !ty_log16)99 100// CHECK-LABEL: func.func private @test_func_cmplx_f32(f32, f32)101func.func private @test_func_cmplx_f32(%arg0: !ty_cmplx_f32)102 103// CHECK-LABEL: func.func private @test_func_cmplx_f64(f64, f64)104func.func private @test_func_cmplx_f64(%arg0: !ty_cmplx_f64)105}106 107 108/// *************************** Struct with more than one field **************************** ///109 110// -----111 112!ty_i32_f32 = !fir.type<ti32_f32{i:i32,j:f32}>113!ty_i32_f64 = !fir.type<ti32_f64{i:i32,j:f64}>114!ty_i64_f32 = !fir.type<ti64_f32{i:i64,j:f32}>115!ty_i64_f64 = !fir.type<ti64_f64{i:i64,j:f64}>116!ty_f64_i64 = !fir.type<tf64_i64{i:f64,j:i64}>117!ty_f16_f16 = !fir.type<tf16_f16{i:f16,j:f16}>118!ty_f32_f32 = !fir.type<tf32_f32{i:f32,j:f32}>119!ty_f64_f64 = !fir.type<tf64_f64{i:f64,j:f64}>120!ty_f32_i32_i32 = !fir.type<tf32_i32_i32{i:f32,j:i32,k:i32}>121!ty_f32_f32_i32 = !fir.type<tf32_f32_i32{i:f32,j:f32,k:i32}>122!ty_f32_f32_f32 = !fir.type<tf32_f32_f32{i:f32,j:f32,k:f32}>123 124!ty_i8_a8 = !fir.type<ti8_a8{i:!fir.array<8xi8>}>125!ty_i8_a16 = !fir.type<ti8_a16{i:!fir.array<16xi8>}>126!ty_f32_a2 = !fir.type<tf32_a2{i:!fir.array<2xf32>}>127!ty_f64_a2 = !fir.type<tf64_a2{i:!fir.array<2xf64>}>128!ty_nested_i32_f32 = !fir.type<t11{i:!ty_i32_f32}>129!ty_nested_i8_a8_i32 = !fir.type<t12{i:!ty_i8_a8, j:i32}>130!ty_char1_a8 = !fir.type<t_char_a8{i:!fir.array<8x!fir.char<1>>}>131 132module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", llvm.target_triple = "loongarch64-unknown-linux-gnu"} {133 134// CHECK-LABEL: func.func private @test_func_i32_f32(i32, f32)135func.func private @test_func_i32_f32(%arg0: !ty_i32_f32)136// CHECK-LABEL: func.func @test_call_i32_f32(137// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>) {138func.func @test_call_i32_f32(%arg0: !fir.ref<!ty_i32_f32>) {139 // CHECK: %[[IN:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>140 // CHECK: %[[STACK:.*]] = llvm.intr.stacksave : !llvm.ptr141 // CHECK: %[[ARR:.*]] = fir.alloca tuple<i32, f32>142 // CHECK: %[[CVT:.*]] = fir.convert %[[ARR]] : (!fir.ref<tuple<i32, f32>>) -> !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>143 // CHECK: fir.store %[[IN]] to %[[CVT]] : !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>144 // CHECK: %[[LD:.*]] = fir.load %[[ARR]] : !fir.ref<tuple<i32, f32>>145 // CHECK: %[[VAL_0:.*]] = fir.extract_value %[[LD]], [0 : i32] : (tuple<i32, f32>) -> i32146 // CHECK: %[[VAL_1:.*]] = fir.extract_value %[[LD]], [1 : i32] : (tuple<i32, f32>) -> f32147 %in = fir.load %arg0 : !fir.ref<!ty_i32_f32>148 // CHECK: fir.call @test_func_i32_f32(%[[VAL_0]], %[[VAL_1]]) : (i32, f32) -> ()149 // CHECK: llvm.intr.stackrestore %[[STACK]] : !llvm.ptr150 fir.call @test_func_i32_f32(%in) : (!ty_i32_f32) -> ()151 // CHECK: return152 return153}154 155// CHECK-LABEL: func.func private @test_func_i32_f64(i32, f64)156func.func private @test_func_i32_f64(%arg0: !ty_i32_f64)157 158// CHECK-LABEL: func.func private @test_func_i64_f32(i64, f32)159func.func private @test_func_i64_f32(%arg0: !ty_i64_f32)160 161// CHECK-LABEL: func.func private @test_func_i64_f64(i64, f64)162func.func private @test_func_i64_f64(%arg0: !ty_i64_f64)163 164// CHECK-LABEL: func.func private @test_func_f64_i64(f64, i64)165func.func private @test_func_f64_i64(%arg0: !ty_f64_i64)166 167// CHECK-LABEL: func.func private @test_func_f16_f16(i64)168func.func private @test_func_f16_f16(%arg0: !ty_f16_f16)169 170// CHECK-LABEL: func.func private @test_func_f32_f32(f32, f32)171func.func private @test_func_f32_f32(%arg0: !ty_f32_f32)172 173// CHECK-LABEL: func.func private @test_func_f64_f64(f64, f64)174func.func private @test_func_f64_f64(%arg0: !ty_f64_f64)175 176// CHECK-LABEL: func.func private @test_func_f32_i32_i32(!fir.array<2xi64>)177func.func private @test_func_f32_i32_i32(%arg0: !ty_f32_i32_i32)178 179// CHECK-LABEL: func.func private @test_func_f32_f32_i32(!fir.array<2xi64>)180func.func private @test_func_f32_f32_i32(%arg0: !ty_f32_f32_i32)181 182// CHECK-LABEL: func.func private @test_func_f32_f32_f32(!fir.array<2xi64>)183func.func private @test_func_f32_f32_f32(%arg0: !ty_f32_f32_f32)184 185// CHECK-LABEL: func.func private @test_func_i8_a8(i64)186func.func private @test_func_i8_a8(%arg0: !ty_i8_a8)187 188// CHECK-LABEL: func.func private @test_func_i8_a16(!fir.array<2xi64>)189func.func private @test_func_i8_a16(%arg0: !ty_i8_a16)190 191// CHECK-LABEL: func.func private @test_func_f32_a2(f32, f32)192func.func private @test_func_f32_a2(%arg0: !ty_f32_a2)193 194// CHECK-LABEL: func.func private @test_func_f64_a2(f64, f64)195func.func private @test_func_f64_a2(%arg0: !ty_f64_a2)196 197// CHECK-LABEL: func.func private @test_func_nested_i32_f32(i32, f32)198func.func private @test_func_nested_i32_f32(%arg0: !ty_nested_i32_f32)199 200// CHECK-LABEL: func.func private @test_func_nested_i8_a8_i32(!fir.array<2xi64>)201func.func private @test_func_nested_i8_a8_i32(%arg0: !ty_nested_i8_a8_i32)202 203 204// CHECK: func.func private @not_enough_int_reg_1(i32, i32, i32, i32, i32, i32, i32, i32, i64)205func.func private @not_enough_int_reg_1(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32,206 %arg5: i32, %arg6: i32, %arg7: i32, %arg8: !ty_i32_f32)207 208// CHECK: func.func private @not_enough_int_reg_1b(!fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, i64)209func.func private @not_enough_int_reg_1b(%arg0: !fir.ref<i32>, %arg1: !fir.ref<i32>, %arg2: !fir.ref<i32>, %arg3: !fir.ref<i32>, %arg4: !fir.ref<i32>,210 %arg5: !fir.ref<i32>, %arg6: !fir.ref<i32>, %arg7: !fir.ref<i32>, %arg8: !ty_i32_f32)211 212// CHECK: func.func private @not_enough_int_reg_2(i32, i32, i32, i32, i32, i32, i32, i32, !fir.array<2xi64>)213func.func private @not_enough_int_reg_2(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32,214 %arg5: i32, %arg6: i32, %arg7: i32, %arg8: !ty_i64_f64)215 216// CHECK: func.func private @not_enough_fp_reg_1(f32, f32, f32, f32, f32, f32, f32, f32, i64)217func.func private @not_enough_fp_reg_1(%arg0: f32, %arg1: f32, %arg2: f32, %arg3: f32, %arg4: f32,218 %arg5: f32, %arg6: f32, %arg7: f32, %arg8: !ty_i32_f32)219 220// CHECK: func.func private @not_enough_fp_reg_1b(!fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, i64)221func.func private @not_enough_fp_reg_1b(%arg0: !fir.ref<f32>, %arg1: !fir.ref<f32>, %arg2: !fir.ref<f32>, %arg3: !fir.ref<f32>, %arg4: !fir.ref<f32>,222 %arg5: !fir.ref<f32>, %arg6: !fir.ref<f32>, %arg7: !fir.ref<f32>, %arg8: !ty_i32_f32)223 224// CHECK: func.func private @not_enough_fp_reg_2(f32, f32, f32, f32, f32, f32, f32, f32, !fir.array<2xi64>)225func.func private @not_enough_fp_reg_2(%arg0: f32, %arg1: f32, %arg2: f32, %arg3: f32, %arg4: f32,226 %arg5: f32, %arg6: f32, %arg7: f32, %arg8: !ty_i64_f64)227 228// CHECK: func.func private @char_not_enough_int_reg(i32, i32, i32, i32, i32, i32, i32, i32, i64)229func.func private @char_not_enough_int_reg(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32,230 %arg5: i32, %arg6: i32, %arg7: i32, %arg8: !ty_char1_a8)231}232