; Test passing variable argument lists in 64-bit calls on z/OS. ; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z10 | FileCheck %s ; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z14 | FileCheck %s -check-prefix=ARCH12 ; CHECK-LABEL: call_vararg_double0: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 8(5) ; CHECK-NEXT: lg 5, 0(5) ; CHECK-NEXT: llihf 3, 1074118262 ; CHECK-NEXT: oilf 3, 3367254360 ; CHECK-NEXT: lghi 1, 1 ; CHECK-NEXT: lghi 2, 2 ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_double0() { entry: %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 2.718000e+00) ret i64 %retval } ; CHECK-LABEL: call_vararg_double1: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: llihf 0, 1074118262 ; CHECK-NEXT: oilf 0, 3367254360 ; CHECK-NEXT: lg 6, 8(5) ; CHECK-NEXT: lg 5, 0(5) ; CHECK-NEXT: llihf 3, 1074340036 ; CHECK-NEXT: oilf 3, 2611340116 ; CHECK-NEXT: lghi 1, 1 ; CHECK-NEXT: lghi 2, 2 ; CHECK-NEXT: stg 0, 2200(4) ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_double1() { entry: %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 3.141000e+00, double 2.718000e+00) ret i64 %retval } ; CHECK-LABEL: call_vararg_double2: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 24(5) ; CHECK-NEXT: lg 5, 16(5) ; CHECK-NEXT: llihf 2, 1074118262 ; CHECK-NEXT: oilf 2, 3367254360 ; CHECK-NEXT: lghi 1, 8200 ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_double2() { entry: %retval = call i64 (i64, ...) @pass_vararg2(i64 8200, double 2.718000e+00) ret i64 %retval } ; CHECK-LABEL: call_vararg_double3: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: llihf 0, 1072703839 ; CHECK-NEXT: oilf 0, 2861204133 ; CHECK-NEXT: lg 6, 40(5) ; CHECK-NEXT: lg 5, 32(5) ; CHECK-NEXT: llihf 1, 1074118262 ; CHECK-NEXT: oilf 1, 3367254360 ; CHECK-NEXT: llihf 2, 1074340036 ; CHECK-NEXT: oilf 2, 2611340116 ; CHECK-NEXT: llihf 3, 1073127358 ; CHECK-NEXT: oilf 3, 1992864825 ; CHECK-NEXT: stg 0, 2200(4) ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_double3() { entry: %retval = call i64 (...) @pass_vararg3(double 2.718000e+00, double 3.141000e+00, double 1.414000e+00, double 1.010101e+00) ret i64 %retval } ; CHECK-LABEL: call_vararg_both0: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 40(5) ; CHECK-NEXT: lg 5, 32(5) ; CHECK-NEXT: lgr 2, 1 ; CHECK-NEXT: lgdr 1, 0 ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_both0(i64 %arg0, double %arg1) { %retval = call i64(...) @pass_vararg3(double %arg1, i64 %arg0) ret i64 %retval } ; CHECK-LABEL: call_vararg_long_double0: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: larl 1, @CPI5_0 ; CHECK-NEXT: ld 0, 0(1) ; CHECK-NEXT: ld 2, 8(1) ; CHECK-NEXT: lg 6, 8(5) ; CHECK-NEXT: lg 5, 0(5) ; CHECK-NEXT: lgdr 3, 0 ; CHECK-NEXT: lghi 1, 1 ; CHECK-NEXT: lghi 2, 2 ; CHECK-NEXT: std 0, 2192(4) ; CHECK-NEXT: std 2, 2200(4) ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_long_double0() { entry: %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 0xLE0FC1518450562CD4000921FB5444261) ret i64 %retval } ; CHECK-LABEL: call_vararg_long_double1: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 8(5) ; CHECK-NEXT: lg 5, 0(5) ; CHECK-NEXT: lgdr 3, 0 ; CHECK-NEXT: lghi 1, 1 ; CHECK-NEXT: lghi 2, 2 ; CHECK-NEXT: std 0, 2192(4) ; CHECK-NEXT: std 2, 2200(4) ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_long_double1(fp128 %arg0) { entry: %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0) ret i64 %retval } ; CHECK-LABEL: call_vararg_long_double2 ; CHECK-LABEL: call_vararg_long_double2: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: std 4, 2208(4) ; CHECK-NEXT: std 6, 2216(4) ; CHECK-NEXT: lg 6, 8(5) ; CHECK-NEXT: lg 5, 0(5) ; CHECK-NEXT: lgdr 3, 0 ; CHECK-NEXT: lghi 1, 1 ; CHECK-NEXT: lghi 2, 2 ; CHECK-NEXT: std 0, 2192(4) ; CHECK-NEXT: std 2, 2200(4) ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_long_double2(fp128 %arg0, fp128 %arg1) { entry: %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0, fp128 %arg1) ret i64 %retval } ; CHECK-LABEL: call_vararg_long_double3: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 40(5) ; CHECK-NEXT: lg 5, 32(5) ; CHECK-NEXT: lgdr 3, 2 ; CHECK-NEXT: lgdr 2, 0 ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_long_double3(fp128 %arg0) { entry: %retval = call i64 (...) @pass_vararg3(fp128 %arg0) ret i64 %retval } ; ARCH12-LABEL: call_vec_vararg_test0 ; ARCH12: vlgvg 3, 24, 1 ; ARCH12: vlgvg 2, 24, 0 ; ARCH12: lghi 1, 1 define void @call_vec_vararg_test0(<2 x double> %v) { %retval = call i64(i64, ...) @pass_vararg2(i64 1, <2 x double> %v) ret void } ; ARCH12-LABEL: call_vec_vararg_test1 ; ARCH12: larl 1, @CPI10_0 ; ARCH12: vl 0, 0(1), 3 ; ARCH12: vlgvg 3, 24, 0 ; ARCH12: vrepg 2, 0, 1 ; ARCH12: vst 25, 2208(4), 3 ; ARCH12: vst 24, 2192(4), 3 define void @call_vec_vararg_test1(<4 x i32> %v, <2 x i64> %w) { %retval = call i64(fp128, ...) @pass_vararg1(fp128 0xLE0FC1518450562CD4000921FB5444261, <4 x i32> %v, <2 x i64> %w) ret void } ; ARCH12-LABEL: call_vec_char_vararg_straddle ; ARCH12: vlgvg 3, 24, 0 ; ARCH12: lghi 1, 1 ; ARCH12: lghi 2, 2 ; ARCH12: vst 24, 2192(4), 3 define void @call_vec_char_vararg_straddle(<16 x i8> %v) { %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <16 x i8> %v) ret void } ; ARCH12-LABEL: call_vec_short_vararg_straddle ; ARCH12: vlgvg 3, 24, 0 ; ARCH12: lghi 1, 1 ; ARCH12: lghi 2, 2 ; ARCH12: vst 24, 2192(4), 3 define void @call_vec_short_vararg_straddle(<8 x i16> %v) { %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <8 x i16> %v) ret void } ; ARCH12-LABEL: call_vec_int_vararg_straddle ; ARCH12: vlgvg 3, 24, 0 ; ARCH12: lghi 1, 1 ; ARCH12: lghi 2, 2 ; ARCH12: vst 24, 2192(4), 3 define void @call_vec_int_vararg_straddle(<4 x i32> %v) { %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <4 x i32> %v) ret void } ; ARCH12-LABEL: call_vec_double_vararg_straddle ; ARCH12: vlgvg 3, 24, 0 ; ARCH12: lghi 1, 1 ; ARCH12: lghi 2, 2 ; ARCH12: vst 24, 2192(4), 3 define void @call_vec_double_vararg_straddle(<2 x double> %v) { %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <2 x double> %v) ret void } ; CHECK-LABEL: call_vararg_integral0: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 0, 2392(4) ; CHECK-NEXT: lg 6, 40(5) ; CHECK-NEXT: lg 5, 32(5) ; CHECK-NEXT: stg 0, 2200(4) ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_integral0(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) { entry: %retval = call i64(...) @pass_vararg3(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) ret i64 %retval } ; CHECK-LABEL: call_vararg_float0: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 24(5) ; CHECK-NEXT: lg 5, 16(5) ; CHECK-NEXT: lghi 1, 1 ; CHECK-NEXT: llihf 2, 1073692672 ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_float0() { entry: %retval = call i64 (i64, ...) @pass_vararg2(i64 1, float 1.953125) ret i64 %retval } ; CHECK-LABEL: call_vararg_float1: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 72(5) ; CHECK-NEXT: lg 5, 64(5) ; CHECK-NEXT: larl 1, @CPI17_0 ; CHECK-NEXT: le 0, 0(1) ; CHECK-NEXT: llihf 0, 1073692672 ; CHECK-NEXT: llihh 2, 16384 ; CHECK-NEXT: llihh 3, 16392 ; CHECK-NEXT: stg 0, 2200(4) ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 192 ; CHECK-NEXT: b 2(7) define i64 @call_vararg_float1() { entry: %retval = call i64 (float, ...) @pass_vararg4(float 1.0, float 2.0, float 3.0, float 1.953125) ret i64 %retval } ; Derived from C source: ; #define _VARARG_EXT_ ; #include ; ; long pass(long x, ...) { ; va_list va; ; va_start(va, x); ; long ret = va_arg(va, long); ; va_end(va); ; return ret; ; } ; ; CHECK-LABEL: pass_vararg: ; CHECK: stmg 6, 7, 1904(4) ; CHECK-NEXT: aghi 4, -160 ; CHECK-NEXT: stg 2, 2344(4) ; CHECK-NEXT: stg 3, 2352(4) ; CHECK-NEXT: la 0, 2352(4) ; CHECK-NEXT: stg 0, 2200(4) ; CHECK-NEXT: lg 3, 2344(4) ; CHECK-NEXT: lg 7, 2072(4) ; CHECK-NEXT: aghi 4, 160 ; CHECK-NEXT: b 2(7) define hidden i64 @pass_vararg(i64 %x, ...) { entry: %va = alloca ptr, align 8 call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va, align 8 %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 8 store ptr %argp.next, ptr %va, align 8 %ret = load i64, ptr %argp.cur, align 8 call void @llvm.va_end(ptr %va) ret i64 %ret } declare void @llvm.va_start(ptr) declare void @llvm.va_end(ptr) declare i64 @pass_vararg0(i64 %arg0, i64 %arg1, ...) declare i64 @pass_vararg1(fp128 %arg0, ...) declare i64 @pass_vararg2(i64 %arg0, ...) declare i64 @pass_vararg3(...) declare i64 @pass_vararg4(float, ...)