Index: llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp +++ llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp @@ -54,24 +54,47 @@ Constant *GuardFnCFGlobal = nullptr; Constant *GuardFnGlobal = nullptr; Module *M = nullptr; + + Type *I8PtrTy; + Type *I64Ty; + Type *VoidTy; + + FunctionType *getThunkType(FunctionType *FT, AttributeList AttrList, + bool entry, raw_ostream &Out); + Type *getThunkRetType(FunctionType *FT, AttributeList AttrList, + bool EntryThunk, raw_ostream &Out); + void getThunkArgTypes(FunctionType *FT, AttributeList AttrList, + bool EntryThunk, SmallVector &ArgTypes, + raw_ostream &Out); + Type *canonicalizeThunkType(Type *T, Align Alignment, bool EntryThunk, + bool Ret, uint64_t ArgSizeBytes, + raw_ostream &Out); }; } // end anonymous namespace -Function *AArch64Arm64ECCallLowering::buildExitThunk(CallBase *CB) { - FunctionType *FT = CB->getFunctionType(); - Type *RetTy = FT->getReturnType(); - bool IsVarArg = FT->isVarArg(); - Type *PtrTy = Type::getInt8PtrTy(M->getContext()); - Type *I64Ty = Type::getInt64Ty(M->getContext()); +FunctionType *AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT, + AttributeList AttrList, + bool EntryThunk, + raw_ostream &Out) { + Out << (EntryThunk ? "$ientry_thunk$cdecl$" : "$iexit_thunk$cdecl$"); + + Type *RetTy = getThunkRetType(FT, AttrList, EntryThunk, Out); SmallVector DefArgTypes; - // The first argument to a thunk is the called function, stored in x9. - // (Normally, we won't explicitly refer to this in the assembly; it just - // gets passed on by the call.) - DefArgTypes.push_back(PtrTy); + DefArgTypes.push_back(I8PtrTy); + getThunkArgTypes(FT, AttrList, EntryThunk, DefArgTypes, Out); - if (IsVarArg) { + return FunctionType::get(RetTy, DefArgTypes, false); +} + +void AArch64Arm64ECCallLowering::getThunkArgTypes(FunctionType *FT, + AttributeList AttrList, + bool EntryThunk, + SmallVector &ArgTypes, + raw_ostream &Out) { + Out << "$"; + if (FT->isVarArg()) { // We treat the variadic function's exit thunk as a normal function // with type: // rettype exitthunk( @@ -81,20 +104,123 @@ // x0-x3 is the arguments be stored in registers. // x4 is the address of the arguments on the stack. // x5 is the size of the arguments on the stack. - DefArgTypes.push_back(PtrTy); + Out << "varargs"; + ArgTypes.push_back(I8PtrTy); for (int i = 0; i < 3; i++) - DefArgTypes.push_back(I64Ty); + ArgTypes.push_back(I64Ty); + + ArgTypes.push_back(I8PtrTy); + ArgTypes.push_back(I64Ty); + return; + } + + if (FT->getNumParams() == 0) { + Out << "v"; + return; + } + + unsigned I = 0; + if (AttrList.getParamAttr(I, Attribute::StructRet).isValid()) + I++; + + for (unsigned E = FT->getNumParams(); I != E; ++I) { + Align ParamAlign = AttrList.getParamAlignment(I).valueOrOne(); + uint64_t ArgSizeBytes = AttrList.getParamArm64ECArgSizeBytes(I); + ArgTypes.push_back(canonicalizeThunkType(FT->getParamType(I), ParamAlign, + EntryThunk, + /*Ret*/ false, ArgSizeBytes, Out)); + } +} + +Type *AArch64Arm64ECCallLowering::getThunkRetType(FunctionType *FT, + AttributeList AttrList, + bool EntryThunk, + raw_ostream &Out) { + Type *T = FT->getReturnType(); + uint64_t ArgSizeBytes = AttrList.getRetArm64ECArgSizeBytes(); + if (T->isVoidTy()) { + if (FT->getNumParams()) { + auto Attr = AttrList.getParamAttr(0, Attribute::StructRet); + if (Attr.isValid()) { + Type *SRetType = Attr.getValueAsType(); + Align SRetAlign = AttrList.getParamAlignment(0).valueOrOne(); + canonicalizeThunkType(SRetType, SRetAlign, EntryThunk, /*Ret*/ true, + ArgSizeBytes, Out); + return VoidTy; + } + } + + Out << "v"; + return VoidTy; + } + + return canonicalizeThunkType(T, Align(), EntryThunk, /*Ret*/ true, ArgSizeBytes, + Out); +} - DefArgTypes.push_back(PtrTy); - DefArgTypes.push_back(I64Ty); +Type *AArch64Arm64ECCallLowering::canonicalizeThunkType( + Type *T, Align Alignment, bool EntryThunk, bool Ret, uint64_t ArgSizeBytes, + raw_ostream &Out) { + Type *CanonicalizedTy = T; + auto &DL = M->getDataLayout(); + if (T->isFloatTy()) { + Out << "f"; + } else if (T->isDoubleTy()) { + Out << "d"; + } else if (T->isIntegerTy(128)) { + Out << "m16a16"; } else { - for (unsigned i = 0; i < CB->arg_size(); ++i) { - DefArgTypes.push_back(CB->getArgOperand(i)->getType()); + if (auto *StructTy = dyn_cast(T)) + if (StructTy->getNumElements() == 1) + CanonicalizedTy = T = StructTy->getElementType(0); + + if (T->isArrayTy()) { + Type *ElementTy = T->getArrayElementType(); + uint64_t ElementCnt = T->getArrayNumElements(); + uint64_t ElementSizePerBytes = DL.getTypeSizeInBits(ElementTy) / 8; + if (ElementTy->isFloatTy()) { + Out << "F" << ElementCnt * ElementSizePerBytes; + if (Alignment.value() >= 8 && !T->isPointerTy()) + Out << "a" << Alignment.value(); + return T; + } else if (ElementTy->isDoubleTy()) { + Out << "D" << ElementCnt * ElementSizePerBytes; + if (Alignment.value() >= 8 && !T->isPointerTy()) + Out << "a" << Alignment.value(); + return T; + } + } + + if (!Ret && !EntryThunk && ArgSizeBytes > 16) { + Out << "i8"; + CanonicalizedTy = I8PtrTy; + } else if (ArgSizeBytes || T->isArrayTy() || T->isStructTy()) { + unsigned TypeSize = ArgSizeBytes; + if (TypeSize == 0) + TypeSize = DL.getTypeSizeInBits(T) / 8; + Out << "m"; + if (TypeSize != 4) + Out << TypeSize; + if (Alignment.value() >= 8 && !T->isPointerTy()) + Out << "a" << Alignment.value(); + } else { + Out << "i8"; + CanonicalizedTy = I64Ty; } } - FunctionType *Ty = FunctionType::get(RetTy, DefArgTypes, false); + return CanonicalizedTy; +} + +Function *AArch64Arm64ECCallLowering::buildExitThunk(CallBase *CB) { + FunctionType *FT = CB->getFunctionType(); + bool IsVarArg = FT->isVarArg(); + + SmallString<256> ExitThunkName; + llvm::raw_svector_ostream Out(ExitThunkName); + FunctionType *Ty = + getThunkType(FT, CB->getAttributes(), /*EntryThunk*/ false, Out); Function *F = - Function::Create(Ty, GlobalValue::InternalLinkage, 0, "thunk", M); + Function::Create(Ty, GlobalValue::InternalLinkage, 0, ExitThunkName, M); F->setCallingConv(CallingConv::ARM64EC_Thunk_Native); // Copy MSVC, and always set up a frame pointer. (Maybe this isn't necessary.) F->addFnAttr("frame-pointer", "all"); @@ -123,6 +249,7 @@ Args.push_back(F->arg_begin()); ArgTypes.push_back(Args.back()->getType()); + Type *RetTy = Ty->getReturnType(); Type *X64RetType = RetTy; if (RetTy->isArrayTy() || RetTy->isStructTy()) { // If the return type is an array or struct, translate it. Values of size @@ -242,8 +369,11 @@ mdconst::extract_or_null(M->getModuleFlag("cfguard"))) cfguard_module_flag = MD->getZExtValue(); - Type *Int8Ptr = Type::getInt8PtrTy(M->getContext()); - GuardFnType = FunctionType::get(Int8Ptr, {Int8Ptr, Int8Ptr}, false); + I8PtrTy = Type::getInt8PtrTy(M->getContext()); + I64Ty = Type::getInt64Ty(M->getContext()); + VoidTy = Type::getVoidTy(M->getContext()); + + GuardFnType = FunctionType::get(I8PtrTy, {I8PtrTy, I8PtrTy}, false); GuardFnPtrType = PointerType::get(GuardFnType, 0); GuardFnCFGlobal = M->getOrInsertGlobal("__os_arm64x_check_icall_cfg", GuardFnPtrType); Index: llvm/test/CodeGen/AArch64/arm64ec-cfg.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64ec-cfg.ll +++ llvm/test/CodeGen/AArch64/arm64ec-cfg.ll @@ -21,7 +21,7 @@ define [2 x i64] @f4(ptr %g) { entry: - %r = call [2 x i64] %g([4 x float] zeroinitializer) + %r = call arm64ec_argsize(16) [2 x i64] %g([4 x float] zeroinitializer) ret [2 x i64] %r } @@ -43,6 +43,13 @@ ret [2 x i64] %r } +%struct.s17 = type { [17 x i8] } +define arm64ec_argsize(17) void @fvar4(ptr sret(%struct.s17) align 1 %agg.result, ptr %g) { +entry: + call arm64ec_argsize(17) void (ptr, i32, ...) %g(ptr sret(%struct.s17) align 1 %agg.result, i32 4, i32 5, i32 6, i32 8, i32 7, i32 9) + ret void +} + ; CHECK-LABEL: f: ; CHECK: .seh_proc f ; CHECK-NEXT: // %bb.0: // %entry @@ -50,8 +57,8 @@ ; CHECK-NEXT: .seh_save_reg_x x30, 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_check_icall -; CHECK-NEXT: adrp x10, thunk -; CHECK-NEXT: add x10, x10, :lo12:thunk +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$v$v) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$v$v) ; CHECK-NEXT: mov x11, x0 ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] ; CHECK-NEXT: blr x8 @@ -71,8 +78,8 @@ ; CHECK-NEXT: .seh_save_reg_x x30, 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_check_icall -; CHECK-NEXT: adrp x10, thunk.1 -; CHECK-NEXT: add x10, x10, :lo12:thunk.1 +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$v$i8i8i8i8i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$v$i8i8i8i8i8) ; CHECK-NEXT: mov x11, x0 ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] ; CHECK-NEXT: blr x8 @@ -97,8 +104,8 @@ ; CHECK-NEXT: .seh_save_reg_x x30, 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_check_icall -; CHECK-NEXT: adrp x10, thunk.2 -; CHECK-NEXT: add x10, x10, :lo12:thunk.2 +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$v$F16) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$v$F16) ; CHECK-NEXT: mov x11, x0 ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] ; CHECK-NEXT: blr x8 @@ -122,8 +129,8 @@ ; CHECK-NEXT: .seh_save_reg_x x30, 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_check_icall -; CHECK-NEXT: adrp x10, thunk.3 -; CHECK-NEXT: add x10, x10, :lo12:thunk.3 +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m16$F16) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m16$F16) ; CHECK-NEXT: mov x11, x0 ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] ; CHECK-NEXT: blr x8 @@ -147,8 +154,8 @@ ; CHECK-NEXT: .seh_save_reg_x x30, 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_check_icall -; CHECK-NEXT: adrp x10, thunk.4 -; CHECK-NEXT: add x10, x10, :lo12:thunk.4 +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$v$varargs) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$v$varargs) ; CHECK-NEXT: mov x11, x0 ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] ; CHECK-NEXT: blr x8 @@ -176,8 +183,8 @@ ; CHECK-NEXT: .seh_save_reg x30, 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_check_icall -; CHECK-NEXT: adrp x10, thunk.5 -; CHECK-NEXT: add x10, x10, :lo12:thunk.5 +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$varargs) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$varargs) ; CHECK-NEXT: mov x11, x0 ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] ; CHECK-NEXT: blr x8 @@ -211,8 +218,8 @@ ; CHECK-NEXT: .seh_save_reg x30, 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_check_icall -; CHECK-NEXT: adrp x10, thunk.6 -; CHECK-NEXT: add x10, x10, :lo12:thunk.6 +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m16$varargs) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m16$varargs) ; CHECK-NEXT: mov x11, x0 ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] ; CHECK-NEXT: blr x8 @@ -237,8 +244,43 @@ ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc ; -; CHECK-LABEL: thunk: -; CHECK: .seh_proc thunk +; CHECK-LABEL: fvar4: +; CHECK: .seh_proc fvar4 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m17$varargs) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m17$varargs) +; CHECK-NEXT: mov x11, x0 +; CHECK-NEXT: ldr x9, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x4, sp +; CHECK-NEXT: mov w9, #9 +; CHECK-NEXT: mov w10, #7 +; CHECK-NEXT: mov w0, #4 +; CHECK-NEXT: mov w1, #5 +; CHECK-NEXT: mov w2, #6 +; CHECK-NEXT: mov w3, #8 +; CHECK-NEXT: mov w5, #16 +; CHECK-NEXT: str w9, [sp, #8] +; CHECK-NEXT: str w10, [sp] +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 16 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +; +; CHECK-LABEL: $iexit_thunk$cdecl$v$v: +; CHECK: .seh_proc $iexit_thunk$cdecl$v$v ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: sub sp, sp, #48 ; CHECK-NEXT: .seh_stackalloc 48 @@ -260,8 +302,8 @@ ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc ; -; CHECK-LABEL: thunk.1: -; CHECK: .seh_proc thunk.1 +; CHECK-LABEL: $iexit_thunk$cdecl$v$i8i8i8i8i8: +; CHECK: .seh_proc $iexit_thunk$cdecl$v$i8i8i8i8i8 ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: sub sp, sp, #64 ; CHECK-NEXT: .seh_stackalloc 64 @@ -271,7 +313,7 @@ ; CHECK-NEXT: .seh_add_fp 48 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect -; CHECK-NEXT: str w4, [sp, #32] +; CHECK-NEXT: str x4, [sp, #32] ; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect] ; CHECK-NEXT: blr x8 ; CHECK-NEXT: .seh_startepilogue @@ -284,8 +326,8 @@ ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc ; -; CHECK-LABEL: thunk.2: -; CHECK: .seh_proc thunk.2 +; CHECK-LABEL: $iexit_thunk$cdecl$v$F16: +; CHECK: .seh_proc $iexit_thunk$cdecl$v$F16 ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: sub sp, sp, #64 ; CHECK-NEXT: .seh_stackalloc 64 @@ -311,8 +353,8 @@ ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc ; -; CHECK-LABEL: thunk.3: -; CHECK: .seh_proc thunk.3 +; CHECK-LABEL: $iexit_thunk$cdecl$m16$F16: +; CHECK: .seh_proc $iexit_thunk$cdecl$m16$F16 ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: sub sp, sp, #80 ; CHECK-NEXT: .seh_stackalloc 80 @@ -340,8 +382,8 @@ ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc ; -; CHECK-LABEL: thunk.4: -; CHECK: .seh_proc thunk.4 +; CHECK-LABEL: $iexit_thunk$cdecl$v$varargs: +; CHECK: .seh_proc $iexit_thunk$cdecl$v$varargs ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: stp x19, x20, [sp, #-64]! // 16-byte Folded Spill ; CHECK-NEXT: .seh_save_regp_x x19, 64 @@ -396,8 +438,8 @@ ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc ; -; CHECK-LABEL: thunk.5: -; CHECK: .seh_proc thunk.5 +; CHECK-LABEL: $iexit_thunk$cdecl$i8$varargs: +; CHECK: .seh_proc $iexit_thunk$cdecl$i8$varargs ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: stp x19, x20, [sp, #-64]! // 16-byte Folded Spill ; CHECK-NEXT: .seh_save_regp_x x19, 64 @@ -436,7 +478,7 @@ ; CHECK-NEXT: fmov d2, x2 ; CHECK-NEXT: fmov d3, x3 ; CHECK-NEXT: blr x26 -; CHECK-NEXT: mov w0, w8 +; CHECK-NEXT: mov x0, x8 ; CHECK-NEXT: .seh_startepilogue ; CHECK-NEXT: sub sp, x29, #48 ; CHECK-NEXT: .seh_add_fp 48 @@ -453,8 +495,8 @@ ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc ; -; CHECK-LABEL: thunk.6: -; CHECK: .seh_proc thunk.6 +; CHECK-LABEL: $iexit_thunk$cdecl$m16$varargs: +; CHECK: .seh_proc $iexit_thunk$cdecl$m16$varargs ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: stp x19, x20, [sp, #-64]! // 16-byte Folded Spill ; CHECK-NEXT: .seh_save_regp_x x19, 64 @@ -511,3 +553,59 @@ ; CHECK-NEXT: ret ; CHECK-NEXT: .seh_endfunclet ; CHECK-NEXT: .seh_endproc +; +; CHECK-LABEL: $iexit_thunk$cdecl$m17$varargs: +; CHECK: .seh_proc $iexit_thunk$cdecl$m17$varargs +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: stp x19, x20, [sp, #-64]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_regp_x x19, 64 +; CHECK-NEXT: stp x21, x22, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_regp x21, 16 +; CHECK-NEXT: stp x25, x26, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_regp x25, 32 +; CHECK-NEXT: stp x29, x30, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 48 +; CHECK-NEXT: add x29, sp, #48 +; CHECK-NEXT: .seh_add_fp 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov x22, x8 +; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect +; CHECK-NEXT: mov x19, x2 +; CHECK-NEXT: mov x20, x1 +; CHECK-NEXT: mov x21, x0 +; CHECK-NEXT: mov x25, x9 +; CHECK-NEXT: ldr x26, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect] +; CHECK-NEXT: add x8, x4, #47 +; CHECK-NEXT: lsr x15, x8, #4 +; CHECK-NEXT: bl __chkstk_arm64ec +; CHECK-NEXT: sub x8, sp, x15, lsl #4 +; CHECK-NEXT: add x0, x8, #32 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x1, x3 +; CHECK-NEXT: mov x2, x4 +; CHECK-NEXT: bl "#memcpy" +; CHECK-NEXT: mov x0, x22 +; CHECK-NEXT: mov x1, x21 +; CHECK-NEXT: mov x2, x20 +; CHECK-NEXT: mov x3, x19 +; CHECK-NEXT: mov x9, x25 +; CHECK-NEXT: fmov d0, x0 +; CHECK-NEXT: fmov d1, x1 +; CHECK-NEXT: fmov d2, x2 +; CHECK-NEXT: fmov d3, x3 +; CHECK-NEXT: blr x26 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: sub sp, x29, #48 +; CHECK-NEXT: .seh_add_fp 48 +; CHECK-NEXT: ldp x29, x30, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 48 +; CHECK-NEXT: ldp x25, x26, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_regp x25, 32 +; CHECK-NEXT: ldp x21, x22, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_regp x21, 16 +; CHECK-NEXT: ldp x19, x20, [sp], #64 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_regp_x x19, 64 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc Index: llvm/test/CodeGen/AArch64/arm64ec-mangle-align.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/arm64ec-mangle-align.ll @@ -0,0 +1,1052 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s + +%struct.s3 = type { [3 x i8], [61 x i8] } +%struct.s4 = type { [4 x i8], [28 x i8] } +%struct.s12 = type { [12 x i8], [52 x i8] } +%struct.s16 = type { [16 x i8], [16 x i8] } +%struct.s17 = type { [17 x i8], [47 x i8] } +%struct.s33 = type { [33 x i8], [3 x i8] } +%struct.s65 = type { [65 x i8], i8 } +%struct.s129 = type { [129 x i8], [15 x i8] } +%struct.s257 = type { [257 x i8], [31 x i8] } +%struct.f2 = type { [2 x float] } +%struct.f3 = type { [3 x float], [52 x i8] } +%struct.f4 = type { [4 x float], [16 x i8] } +%struct.f5 = type { [5 x float], [12 x i8] } +%struct.d2 = type { [2 x double], [48 x i8] } +%struct.d3 = type { [3 x double], [40 x i8] } +%struct.d4 = type { [4 x double] } +%struct.d5 = type { [5 x double], [8 x i8] } + +@pfnstruct1 = global ptr null, align 8 +@pfnstruct2 = global ptr null, align 8 +@pfnstruct3 = global ptr null, align 8 +@pfnstruct4 = global ptr null, align 8 +@pfnstruct5 = global ptr null, align 8 +@pfnstruct6 = global ptr null, align 8 +@pfnstruct7 = global ptr null, align 8 +@pfnstruct8 = global ptr null, align 8 +@pfnstruct9 = global ptr null, align 8 +@pfnstruct10 = global ptr null, align 8 +@pfnstruct11 = global ptr null, align 8 +@pfnstruct12 = global ptr null, align 8 +@pfnstruct13 = global ptr null, align 8 +@pfnstruct14 = global ptr null, align 8 +@pfnstruct15 = global ptr null, align 8 +@pfnstruct16 = global ptr null, align 8 +@pfnstruct17 = global ptr null, align 8 +@pfnstruct33 = global ptr null, align 8 +@pfnstruct65 = global ptr null, align 8 +@pfnstruct129 = global ptr null, align 8 +@pfnstruct257 = global ptr null, align 8 +@pfnstructf2 = global ptr null, align 8 +@pfnstructf3 = global ptr null, align 8 +@pfnstructf4 = global ptr null, align 8 +@pfnstructf5 = global ptr null, align 8 +@pfnstructd2 = global ptr null, align 8 +@pfnstructd3 = global ptr null, align 8 +@pfnstructd4 = global ptr null, align 8 +@pfnstructd5 = global ptr null, align 8 + + +define dso_local arm64ec_argsize(1) i8 @callstruct1(i64 arm64ec_argsize(1) %x.coerce) { +; CHECK-LABEL: callstruct1: +; CHECK: .seh_proc callstruct1 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct1 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m1$m1) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m1$m1) +; CHECK-NEXT: and x0, x0, #0xff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct1] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct1, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 255 + %call = tail call arm64ec_argsize(1) i8 %0(i64 arm64ec_argsize(1) %coerce.dive1.coerce.0.insert.ext) + ret i8 %call +} + + +declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1 immarg) + + +define dso_local arm64ec_argsize(8) i64 @callstruct2(i64 arm64ec_argsize(8) %x.coerce) { +; CHECK-LABEL: callstruct2: +; CHECK: .seh_proc callstruct2 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct2 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m8$m8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m8$m8) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct2] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct2, align 8 + %call = tail call arm64ec_argsize(8) i64 %0(i64 arm64ec_argsize(8) %x.coerce) + ret i64 %call +} + + +define dso_local arm64ec_argsize(64) void @callstruct3(ptr sret(%struct.s3) align 64 %agg.result, ptr arm64ec_argsize(64) %x) { +; CHECK-LABEL: callstruct3: +; CHECK: .seh_proc callstruct3 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #112 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct3 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct3] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m64a64$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m64a64$i8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s3, align 64 + %0 = load ptr, ptr @pfnstruct3, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 64 %agg.tmp, ptr align 64 %x, i64 64, i1 false) + call arm64ec_argsize(64) void %0(ptr sret(%struct.s3) align 64 %agg.result, ptr arm64ec_argsize(64) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(32) void @callstruct4(ptr sret(%struct.s4) align 32 %agg.result, ptr arm64ec_argsize(32) %x) { +; CHECK-LABEL: callstruct4: +; CHECK: .seh_proc callstruct4 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #48 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffe0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct4 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct4] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m32a32$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m32a32$i8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s4, align 32 + %0 = load ptr, ptr @pfnstruct4, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 32 %agg.tmp, ptr align 32 %x, i64 32, i1 false) + call arm64ec_argsize(32) void %0(ptr sret(%struct.s4) align 32 %agg.result, ptr arm64ec_argsize(32) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(6) i48 @callstruct5(i64 arm64ec_argsize(6) %x.coerce) { +; CHECK-LABEL: callstruct5: +; CHECK: .seh_proc callstruct5 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct5 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m6$m6) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m6$m6) +; CHECK-NEXT: and x0, x0, #0xffffffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct5] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct5, align 8 + %agg.tmp.coerce.0.insert.ext = and i64 %x.coerce, 281474976710655 + %call = tail call arm64ec_argsize(6) i48 %0(i64 arm64ec_argsize(6) %agg.tmp.coerce.0.insert.ext) + ret i48 %call +} + + +define dso_local arm64ec_argsize(8) i64 @callstruct6(i64 arm64ec_argsize(8) %x.coerce) { +; CHECK-LABEL: callstruct6: +; CHECK: .seh_proc callstruct6 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct6 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m8$m8.1) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m8$m8.1) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct6] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct6, align 8 + %call = tail call arm64ec_argsize(8) i64 %0(i64 arm64ec_argsize(8) %x.coerce) + ret i64 %call +} + + +define dso_local arm64ec_argsize(8) i64 @callstruct7(i64 arm64ec_argsize(8) %x.coerce) { +; CHECK-LABEL: callstruct7: +; CHECK: .seh_proc callstruct7 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct7 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m8$m8.2) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m8$m8.2) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct7] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct7, align 8 + %call = tail call arm64ec_argsize(8) i64 %0(i64 arm64ec_argsize(8) %x.coerce) + ret i64 %call +} + + +define dso_local arm64ec_argsize(16) i128 @callstruct8(i128 arm64ec_argsize(16) %x.coerce) { +; CHECK-LABEL: callstruct8: +; CHECK: .seh_proc callstruct8 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct8 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m16a16$m16a16) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m16a16$m16a16) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct8] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct8, align 8 + %call = tail call arm64ec_argsize(16) i128 %0(i128 arm64ec_argsize(16) %x.coerce) + ret i128 %call +} + + +define dso_local arm64ec_argsize(12) [2 x i64] @callstruct9([2 x i64] arm64ec_argsize(12) %x.coerce) { +; CHECK-LABEL: callstruct9: +; CHECK: .seh_proc callstruct9 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct9 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m12$m12) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m12$m12) +; CHECK-NEXT: and x1, x1, #0xffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct9] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffffffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct9, align 8 + %agg.tmp.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 4294967295 + %.fca.1.insert3 = insertvalue [2 x i64] %x.coerce, i64 %agg.tmp.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(12) [2 x i64] %0([2 x i64] arm64ec_argsize(12) %.fca.1.insert3) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %retval.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 4294967295 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %retval.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(10) [2 x i64] @callstruct10([2 x i64] arm64ec_argsize(10) %x.coerce) { +; CHECK-LABEL: callstruct10: +; CHECK: .seh_proc callstruct10 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct10 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m10$m10) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m10$m10) +; CHECK-NEXT: and x1, x1, #0xffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct10] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct10, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 65535 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(10) [2 x i64] %0([2 x i64] arm64ec_argsize(10) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 65535 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(11) [2 x i64] @callstruct11([2 x i64] arm64ec_argsize(11) %x.coerce) { +; CHECK-LABEL: callstruct11: +; CHECK: .seh_proc callstruct11 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct11 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m11$m11) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m11$m11) +; CHECK-NEXT: and x1, x1, #0xffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct11] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct11, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 16777215 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(11) [2 x i64] %0([2 x i64] arm64ec_argsize(11) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 16777215 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(64) void @callstruct12(ptr sret(%struct.s12) align 64 %agg.result, ptr arm64ec_argsize(64) %x) { +; CHECK-LABEL: callstruct12: +; CHECK: .seh_proc callstruct12 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #112 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct12 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct12] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m64a64$i8.3) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m64a64$i8.3) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s12, align 64 + %0 = load ptr, ptr @pfnstruct12, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 64 %agg.tmp, ptr align 64 %x, i64 64, i1 false) + call arm64ec_argsize(64) void %0(ptr sret(%struct.s12) align 64 %agg.result, ptr arm64ec_argsize(64) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(16) [2 x i64] @callstruct13([2 x i64] arm64ec_argsize(16) %x.coerce) { +; CHECK-LABEL: callstruct13: +; CHECK: .seh_proc callstruct13 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct13 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m16$m16) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m16$m16) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct13] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct13, align 8 + %call = tail call arm64ec_argsize(16) [2 x i64] %0([2 x i64] arm64ec_argsize(16) %x.coerce) + ret [2 x i64] %call +} + + +define dso_local arm64ec_argsize(16) [2 x i64] @callstruct14([2 x i64] arm64ec_argsize(16) %x.coerce) { +; CHECK-LABEL: callstruct14: +; CHECK: .seh_proc callstruct14 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct14 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m16$m16.4) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m16$m16.4) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct14] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct14, align 8 + %call = tail call arm64ec_argsize(16) [2 x i64] %0([2 x i64] arm64ec_argsize(16) %x.coerce) + ret [2 x i64] %call +} + + +define dso_local arm64ec_argsize(16) i128 @callstruct15(i128 arm64ec_argsize(16) %x.coerce) { +; CHECK-LABEL: callstruct15: +; CHECK: .seh_proc callstruct15 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct15 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m16a16$m16a16.5) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m16a16$m16a16.5) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct15] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct15, align 8 + %call = tail call arm64ec_argsize(16) i128 %0(i128 arm64ec_argsize(16) %x.coerce) + ret i128 %call +} + + +define dso_local arm64ec_argsize(32) void @callstruct16(ptr sret(%struct.s16) align 32 %agg.result, ptr arm64ec_argsize(32) %x) { +; CHECK-LABEL: callstruct16: +; CHECK: .seh_proc callstruct16 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #48 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffe0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct16 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct16] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m32a32$i8.6) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m32a32$i8.6) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s16, align 32 + %0 = load ptr, ptr @pfnstruct16, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 32 %agg.tmp, ptr align 32 %x, i64 32, i1 false) + call arm64ec_argsize(32) void %0(ptr sret(%struct.s16) align 32 %agg.result, ptr arm64ec_argsize(32) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(64) void @callstruct17(ptr sret(%struct.s17) align 64 %agg.result, ptr arm64ec_argsize(64) %x) { +; CHECK-LABEL: callstruct17: +; CHECK: .seh_proc callstruct17 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #112 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct17 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct17] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m64a64$i8.7) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m64a64$i8.7) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s17, align 64 + %0 = load ptr, ptr @pfnstruct17, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 64 %agg.tmp, ptr align 64 %x, i64 64, i1 false) + call arm64ec_argsize(64) void %0(ptr sret(%struct.s17) align 64 %agg.result, ptr arm64ec_argsize(64) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(36) void @callstruct33(ptr sret(%struct.s33) align 4 %agg.result, ptr arm64ec_argsize(36) %x) { +; CHECK-LABEL: callstruct33: +; CHECK: .seh_proc callstruct33 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: str x30, [sp, #48] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct33 +; CHECK-NEXT: ldr w10, [x0, #32] +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: str w10, [sp, #32] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m36$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m36$i8) +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct33] +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 48 +; CHECK-NEXT: add sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s33, align 4 + %0 = load ptr, ptr @pfnstruct33, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %x, i64 36, i1 false) + call arm64ec_argsize(36) void %0(ptr sret(%struct.s33) align 4 %agg.result, ptr arm64ec_argsize(36) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(66) void @callstruct65(ptr sret(%struct.s65) align 2 %agg.result, ptr arm64ec_argsize(66) %x) { +; CHECK-LABEL: callstruct65: +; CHECK: .seh_proc callstruct65 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #96 +; CHECK-NEXT: .seh_stackalloc 96 +; CHECK-NEXT: str x30, [sp, #80] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 80 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct65 +; CHECK-NEXT: ldrh w10, [x0, #64] +; CHECK-NEXT: ldp q0, q1, [x0, #32] +; CHECK-NEXT: adrp x12, __os_arm64x_check_icall +; CHECK-NEXT: strh w10, [sp, #64] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m66$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m66$i8) +; CHECK-NEXT: ldp q3, q2, [x0] +; CHECK-NEXT: stp q0, q1, [sp, #32] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct65] +; CHECK-NEXT: stp q3, q2, [sp] +; CHECK-NEXT: ldr x9, [x12, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #80] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 80 +; CHECK-NEXT: add sp, sp, #96 +; CHECK-NEXT: .seh_stackalloc 96 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s65, align 2 + %0 = load ptr, ptr @pfnstruct65, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 2 %agg.tmp, ptr align 2 %x, i64 66, i1 false) + call arm64ec_argsize(66) void %0(ptr sret(%struct.s65) align 2 %agg.result, ptr arm64ec_argsize(66) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(144) void @callstruct129(ptr sret(%struct.s129) align 16 %agg.result, ptr arm64ec_argsize(144) %x) { +; CHECK-LABEL: callstruct129: +; CHECK: .seh_proc callstruct129 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #160 +; CHECK-NEXT: .seh_stackalloc 160 +; CHECK-NEXT: str x30, [sp, #144] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 144 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: ldp q0, q1, [x0, #96] +; CHECK-NEXT: adrp x9, pfnstruct129 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldr q2, [x0, #128] +; CHECK-NEXT: stp q0, q1, [sp, #96] +; CHECK-NEXT: ldp q3, q0, [x0, #16] +; CHECK-NEXT: str q2, [sp, #128] +; CHECK-NEXT: ldp q4, q2, [x0, #48] +; CHECK-NEXT: stp q0, q4, [sp, #32] +; CHECK-NEXT: ldr q1, [x0, #80] +; CHECK-NEXT: ldr q0, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct129] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m144a16$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m144a16$i8) +; CHECK-NEXT: stp q0, q3, [sp] +; CHECK-NEXT: stp q2, q1, [sp, #64] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #144] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 144 +; CHECK-NEXT: add sp, sp, #160 +; CHECK-NEXT: .seh_stackalloc 160 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s129, align 16 + %0 = load ptr, ptr @pfnstruct129, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 16 %agg.tmp, ptr align 16 %x, i64 144, i1 false) + call arm64ec_argsize(144) void %0(ptr sret(%struct.s129) align 16 %agg.result, ptr arm64ec_argsize(144) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(288) void @callstruct257(ptr sret(%struct.s257) align 32 %agg.result, ptr arm64ec_argsize(288) %x) { +; CHECK-LABEL: callstruct257: +; CHECK: .seh_proc callstruct257 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x19, x20, [sp, #-48]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_regp_x x19, 48 +; CHECK-NEXT: str x27, [sp, #16] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x27, 16 +; CHECK-NEXT: stp x29, x30, [sp, #24] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 24 +; CHECK-NEXT: add x29, sp, #24 +; CHECK-NEXT: .seh_add_fp 24 +; CHECK-NEXT: sub x9, sp, #304 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffe0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov x19, x8 +; CHECK-NEXT: adrp x8, pfnstruct257 +; CHECK-NEXT: mov x1, x0 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: mov w2, #288 +; CHECK-NEXT: ldr x20, [x8, :lo12:pfnstruct257] +; CHECK-NEXT: bl "#memcpy" +; CHECK-NEXT: adrp x8, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m288a32$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m288a32$i8) +; CHECK-NEXT: mov x11, x20 +; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: mov x8, x19 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: sub sp, x29, #24 +; CHECK-NEXT: .seh_add_fp 24 +; CHECK-NEXT: ldp x29, x30, [sp, #24] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 24 +; CHECK-NEXT: ldr x27, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x27, 16 +; CHECK-NEXT: ldp x19, x20, [sp], #48 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_regp_x x19, 48 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s257, align 32 + %0 = load ptr, ptr @pfnstruct257, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 32 %agg.tmp, ptr align 32 %x, i64 288, i1 false) + call arm64ec_argsize(288) void %0(ptr sret(%struct.s257) align 32 %agg.result, ptr arm64ec_argsize(288) %agg.tmp) + ret void +} + +define dso_local arm64ec_argsize(8) %struct.f2 @callstructf2([2 x float] arm64ec_argsize(8) %x.coerce) { +; CHECK-LABEL: callstructf2: +; CHECK: .seh_proc callstructf2 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstructf2 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$F8$F8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$F8$F8) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstructf2] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstructf2, align 8 + %call = tail call arm64ec_argsize(8) %struct.f2 %0([2 x float] arm64ec_argsize(8) %x.coerce) #2 + %1 = extractvalue %struct.f2 %call, 0 + %.fca.0.extract = extractvalue [2 x float] %1, 0 + %.fca.1.extract = extractvalue [2 x float] %1, 1 + %.fca.0.0.insert = insertvalue %struct.f2 poison, float %.fca.0.extract, 0, 0 + %.fca.0.1.insert = insertvalue %struct.f2 %.fca.0.0.insert, float %.fca.1.extract, 0, 1 + ret %struct.f2 %.fca.0.1.insert +} + +define dso_local arm64ec_argsize(64) void @callstructf3(ptr sret(%struct.f3) align 64 %agg.result, ptr arm64ec_argsize(64) %x) { +; CHECK-LABEL: callstructf3: +; CHECK: .seh_proc callstructf3 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #112 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstructf3 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstructf3] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m64a64$i8.8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m64a64$i8.8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.f3, align 64 + %0 = load ptr, ptr @pfnstructf3, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 64 %agg.tmp, ptr align 64 %x, i64 64, i1 false) + call arm64ec_argsize(64) void %0(ptr sret(%struct.f3) align 64 %agg.result, ptr arm64ec_argsize(64) %agg.tmp) #2 + ret void +} + +define dso_local arm64ec_argsize(32) void @callstructf4(ptr sret(%struct.f4) align 32 %agg.result, ptr arm64ec_argsize(32) %x) { +; CHECK-LABEL: callstructf4: +; CHECK: .seh_proc callstructf4 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #48 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffe0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstructf4 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstructf4] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m32a32$i8.9) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m32a32$i8.9) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.f4, align 32 + %0 = load ptr, ptr @pfnstructf4, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 32 %agg.tmp, ptr align 32 %x, i64 32, i1 false) + call arm64ec_argsize(32) void %0(ptr sret(%struct.f4) align 32 %agg.result, ptr arm64ec_argsize(32) %agg.tmp) #2 + ret void +} + +define dso_local arm64ec_argsize(32) void @callstructf5(ptr sret(%struct.f5) align 32 %agg.result, ptr arm64ec_argsize(32) %x) { +; CHECK-LABEL: callstructf5: +; CHECK: .seh_proc callstructf5 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #48 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffe0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstructf5 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstructf5] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m32a32$i8.10) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m32a32$i8.10) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.f5, align 32 + %0 = load ptr, ptr @pfnstructf5, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 32 %agg.tmp, ptr align 32 %x, i64 32, i1 false) + call arm64ec_argsize(32) void %0(ptr sret(%struct.f5) align 32 %agg.result, ptr arm64ec_argsize(32) %agg.tmp) #2 + ret void +} + +define dso_local arm64ec_argsize(64) void @callstructd2(ptr sret(%struct.d2) align 64 %agg.result, ptr arm64ec_argsize(64) %x) { +; CHECK-LABEL: callstructd2: +; CHECK: .seh_proc callstructd2 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #112 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstructd2 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstructd2] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m64a64$i8.11) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m64a64$i8.11) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.d2, align 64 + %0 = load ptr, ptr @pfnstructd2, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 64 %agg.tmp, ptr align 64 %x, i64 64, i1 false) + call arm64ec_argsize(64) void %0(ptr sret(%struct.d2) align 64 %agg.result, ptr arm64ec_argsize(64) %agg.tmp) #2 + ret void +} + +define dso_local arm64ec_argsize(64) void @callstructd3(ptr sret(%struct.d3) align 64 %agg.result, ptr arm64ec_argsize(64) %x) { +; CHECK-LABEL: callstructd3: +; CHECK: .seh_proc callstructd3 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: sub x9, sp, #112 +; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstructd3 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstructd3] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m64a64$i8.12) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m64a64$i8.12) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.d3, align 64 + %0 = load ptr, ptr @pfnstructd3, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 64 %agg.tmp, ptr align 64 %x, i64 64, i1 false) + call arm64ec_argsize(64) void %0(ptr sret(%struct.d3) align 64 %agg.result, ptr arm64ec_argsize(64) %agg.tmp) #2 + ret void +} Index: llvm/test/CodeGen/AArch64/arm64ec-mangle-basic.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/arm64ec-mangle-basic.ll @@ -0,0 +1,293 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s + +@pfnbool = global ptr null, align 8 +@pfnchar = global ptr null, align 8 +@pfnshort = global ptr null, align 8 +@pfnwchar_t = global ptr null, align 8 +@pfnint = global ptr null, align 8 +@pfni64 = global ptr null, align 8 +@pfnfloat = global ptr null, align 8 +@pfndouble = global ptr null, align 8 +@pfnlongdouble = global ptr null, align 8 +@pfnVOIDP = global ptr null, align 8 + + +define dso_local i1 @callbool(i1 %x) { +; CHECK-LABEL: callbool: +; CHECK: .seh_proc callbool +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnbool +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnbool] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnbool, align 8 + %call = tail call i1 %0(i1 %x) + ret i1 %call +} + + +define dso_local i8 @callchar(i8 %x) { +; CHECK-LABEL: callchar: +; CHECK: .seh_proc callchar +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnchar +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$i8.1) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8.1) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnchar] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnchar, align 8 + %call = tail call i8 %0(i8 %x) + ret i8 %call +} + + +define dso_local i16 @callshort(i16 %x) { +; CHECK-LABEL: callshort: +; CHECK: .seh_proc callshort +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnshort +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$i8.2) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8.2) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnshort] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnshort, align 8 + %call = tail call i16 %0(i16 %x) + ret i16 %call +} + + +define dso_local i16 @callwchar_t(i16 %x) { +; CHECK-LABEL: callwchar_t: +; CHECK: .seh_proc callwchar_t +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnwchar_t +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$i8.3) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8.3) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnwchar_t] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnwchar_t, align 8 + %call = tail call i16 %0(i16 %x) + ret i16 %call +} + + +define dso_local i32 @callint(i32 %x) { +; CHECK-LABEL: callint: +; CHECK: .seh_proc callint +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnint +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$i8.4) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8.4) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnint] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnint, align 8 + %call = tail call i32 %0(i32 %x) + ret i32 %call +} + + +define dso_local i64 @calli64(i64 %x) { +; CHECK-LABEL: calli64: +; CHECK: .seh_proc calli64 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfni64 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$i8.5) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8.5) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfni64] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfni64, align 8 + %call = tail call i64 %0(i64 %x) + ret i64 %call +} + + +define dso_local float @callfloat(float %x) { +; CHECK-LABEL: callfloat: +; CHECK: .seh_proc callfloat +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnfloat +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$f$f) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$f$f) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnfloat] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnfloat, align 8 + %call = tail call float %0(float %x) + ret float %call +} + + +define dso_local double @calldouble(double %x) { +; CHECK-LABEL: calldouble: +; CHECK: .seh_proc calldouble +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfndouble +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$d$d) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$d$d) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfndouble] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfndouble, align 8 + %call = tail call double %0(double %x) + ret double %call +} + + +define dso_local double @calllongdouble(double %x) { +; CHECK-LABEL: calllongdouble: +; CHECK: .seh_proc calllongdouble +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnlongdouble +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$d$d.6) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$d$d.6) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnlongdouble] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnlongdouble, align 8 + %call = tail call double %0(double %x) + ret double %call +} + + +define dso_local ptr @callVOIDP(ptr %x) { +; CHECK-LABEL: callVOIDP: +; CHECK: .seh_proc callVOIDP +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnVOIDP +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$i8$i8.7) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8.7) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnVOIDP] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnVOIDP, align 8 + %call = tail call ptr %0(ptr %x) + ret ptr %call +} Index: llvm/test/CodeGen/AArch64/arm64ec-mangle-struct.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/arm64ec-mangle-struct.ll @@ -0,0 +1,1365 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s + +%struct.s17 = type { [17 x i8] } +%struct.s32 = type { [32 x i8] } +%struct.s33 = type { [33 x i8] } +%struct.s64 = type { [64 x i8] } +%struct.s65 = type { [65 x i8] } +%struct.s128 = type { [128 x i8] } +%struct.s133 = type { [133 x i8] } +%struct.s192 = type { [192 x i8] } +%struct.s223 = type { [223 x i8] } +%struct.s256 = type { [256 x i8] } +%struct.s257 = type { [257 x i8] } +%struct.f2 = type { [2 x float] } +%struct.f3 = type { [3 x float] } +%struct.f4 = type { [4 x float] } +%struct.d2 = type { [2 x double] } +%struct.d3 = type { [3 x double] } +%struct.d4 = type { [4 x double] } +%struct.f5 = type { [5 x float] } +%struct.d5 = type { [5 x double] } + +@pfnstruct1 = global ptr null, align 8 +@pfnstruct2 = global ptr null, align 8 +@pfnstruct3 = global ptr null, align 8 +@pfnstruct4 = global ptr null, align 8 +@pfnstruct5 = global ptr null, align 8 +@pfnstruct6 = global ptr null, align 8 +@pfnstruct7 = global ptr null, align 8 +@pfnstruct8 = global ptr null, align 8 +@pfnstruct9 = global ptr null, align 8 +@pfnstruct10 = global ptr null, align 8 +@pfnstruct11 = global ptr null, align 8 +@pfnstruct12 = global ptr null, align 8 +@pfnstruct13 = global ptr null, align 8 +@pfnstruct14 = global ptr null, align 8 +@pfnstruct15 = global ptr null, align 8 +@pfnstruct16 = global ptr null, align 8 +@pfnstruct17 = global ptr null, align 8 +@pfnstruct32 = global ptr null, align 8 +@pfnstruct33 = global ptr null, align 8 +@pfnstruct64 = global ptr null, align 8 +@pfnstruct65 = global ptr null, align 8 +@pfnstruct128 = global ptr null, align 8 +@pfnstruct133 = global ptr null, align 8 +@pfnstruct192 = global ptr null, align 8 +@pfnstruct223 = global ptr null, align 8 +@pfnstruct256 = global ptr null, align 8 +@pfnstruct257 = global ptr null, align 8 +@pfnstructf2 = global ptr null, align 8 +@pfnstructf3 = global ptr null, align 8 +@pfnstructf4 = global ptr null, align 8 +@pfnstructf5 = global ptr null, align 8 +@pfnstructd2 = global ptr null, align 8 +@pfnstructd3 = global ptr null, align 8 +@pfnstructd4 = global ptr null, align 8 +@pfnstructd5 = global ptr null, align 8 + +define dso_local arm64ec_argsize(1) i8 @callstruct1(i64 arm64ec_argsize(1) %x.coerce) { +; CHECK-LABEL: callstruct1: +; CHECK: .seh_proc callstruct1 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct1 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m1$m1) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m1$m1) +; CHECK-NEXT: and x0, x0, #0xff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct1] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct1, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 255 + %call = tail call arm64ec_argsize(1) i8 %0(i64 arm64ec_argsize(1) %coerce.dive1.coerce.0.insert.ext) + ret i8 %call +} + + +declare void @llvm.memcpy.p0.p0.i64(ptr writeonly, ptr, i64, i1 immarg) + + +define dso_local arm64ec_argsize(2) i16 @callstruct2(i64 arm64ec_argsize(2) %x.coerce) { +; CHECK-LABEL: callstruct2: +; CHECK: .seh_proc callstruct2 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct2 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m2$m2) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m2$m2) +; CHECK-NEXT: and x0, x0, #0xffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct2] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct2, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 65535 + %call = tail call arm64ec_argsize(2) i16 %0(i64 arm64ec_argsize(2) %coerce.dive1.coerce.0.insert.ext) + ret i16 %call +} + + +define dso_local arm64ec_argsize(3) i24 @callstruct3(i64 arm64ec_argsize(3) %x.coerce) { +; CHECK-LABEL: callstruct3: +; CHECK: .seh_proc callstruct3 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct3 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m3$m3) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m3$m3) +; CHECK-NEXT: and x0, x0, #0xffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct3] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct3, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 16777215 + %call = tail call arm64ec_argsize(3) i24 %0(i64 arm64ec_argsize(3) %coerce.dive1.coerce.0.insert.ext) + ret i24 %call +} + + +define dso_local arm64ec_argsize(4) i32 @callstruct4(i64 arm64ec_argsize(4) %x.coerce) { +; CHECK-LABEL: callstruct4: +; CHECK: .seh_proc callstruct4 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct4 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m$m) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m$m) +; CHECK-NEXT: and x0, x0, #0xffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct4] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct4, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 4294967295 + %call = tail call arm64ec_argsize(4) i32 %0(i64 arm64ec_argsize(4) %coerce.dive1.coerce.0.insert.ext) + ret i32 %call +} + + +define dso_local arm64ec_argsize(5) i40 @callstruct5(i64 arm64ec_argsize(5) %x.coerce) { +; CHECK-LABEL: callstruct5: +; CHECK: .seh_proc callstruct5 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct5 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m5$m5) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m5$m5) +; CHECK-NEXT: and x0, x0, #0xffffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct5] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct5, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 1099511627775 + %call = tail call arm64ec_argsize(5) i40 %0(i64 arm64ec_argsize(5) %coerce.dive1.coerce.0.insert.ext) + ret i40 %call +} + + +define dso_local arm64ec_argsize(6) i48 @callstruct6(i64 arm64ec_argsize(6) %x.coerce) { +; CHECK-LABEL: callstruct6: +; CHECK: .seh_proc callstruct6 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct6 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m6$m6) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m6$m6) +; CHECK-NEXT: and x0, x0, #0xffffffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct6] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct6, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 281474976710655 + %call = tail call arm64ec_argsize(6) i48 %0(i64 arm64ec_argsize(6) %coerce.dive1.coerce.0.insert.ext) + ret i48 %call +} + + +define dso_local arm64ec_argsize(7) i56 @callstruct7(i64 arm64ec_argsize(7) %x.coerce) { +; CHECK-LABEL: callstruct7: +; CHECK: .seh_proc callstruct7 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct7 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m7$m7) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m7$m7) +; CHECK-NEXT: and x0, x0, #0xffffffffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct7] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct7, align 8 + %coerce.dive1.coerce.0.insert.ext = and i64 %x.coerce, 72057594037927935 + %call = tail call arm64ec_argsize(7) i56 %0(i64 arm64ec_argsize(7) %coerce.dive1.coerce.0.insert.ext) + ret i56 %call +} + + +define dso_local arm64ec_argsize(8) i64 @callstruct8(i64 arm64ec_argsize(8) %x.coerce) { +; CHECK-LABEL: callstruct8: +; CHECK: .seh_proc callstruct8 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct8 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m8$m8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m8$m8) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct8] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct8, align 8 + %call = tail call arm64ec_argsize(8) i64 %0(i64 arm64ec_argsize(8) %x.coerce) + ret i64 %call +} + + +define dso_local arm64ec_argsize(9) [2 x i64] @callstruct9([2 x i64] arm64ec_argsize(9) %x.coerce) { +; CHECK-LABEL: callstruct9: +; CHECK: .seh_proc callstruct9 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct9 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m9$m9) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m9$m9) +; CHECK-NEXT: and x1, x1, #0xff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct9] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct9, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 255 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(9) [2 x i64] %0([2 x i64] arm64ec_argsize(9) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 255 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(10) [2 x i64] @callstruct10([2 x i64] arm64ec_argsize(10) %x.coerce) { +; CHECK-LABEL: callstruct10: +; CHECK: .seh_proc callstruct10 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct10 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m10$m10) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m10$m10) +; CHECK-NEXT: and x1, x1, #0xffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct10] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct10, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 65535 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(10) [2 x i64] %0([2 x i64] arm64ec_argsize(10) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 65535 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(11) [2 x i64] @callstruct11([2 x i64] arm64ec_argsize(11) %x.coerce) { +; CHECK-LABEL: callstruct11: +; CHECK: .seh_proc callstruct11 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct11 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m11$m11) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m11$m11) +; CHECK-NEXT: and x1, x1, #0xffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct11] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct11, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 16777215 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(11) [2 x i64] %0([2 x i64] arm64ec_argsize(11) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 16777215 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(12) [2 x i64] @callstruct12([2 x i64] arm64ec_argsize(12) %x.coerce) { +; CHECK-LABEL: callstruct12: +; CHECK: .seh_proc callstruct12 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct12 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m12$m12) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m12$m12) +; CHECK-NEXT: and x1, x1, #0xffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct12] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffffffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct12, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 4294967295 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(12) [2 x i64] %0([2 x i64] arm64ec_argsize(12) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 4294967295 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(13) [2 x i64] @callstruct13([2 x i64] arm64ec_argsize(13) %x.coerce) { +; CHECK-LABEL: callstruct13: +; CHECK: .seh_proc callstruct13 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct13 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m13$m13) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m13$m13) +; CHECK-NEXT: and x1, x1, #0xffffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct13] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffffffffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct13, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 1099511627775 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(13) [2 x i64] %0([2 x i64] arm64ec_argsize(13) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 1099511627775 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(14) [2 x i64] @callstruct14([2 x i64] arm64ec_argsize(14) %x.coerce) { +; CHECK-LABEL: callstruct14: +; CHECK: .seh_proc callstruct14 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct14 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m14$m14) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m14$m14) +; CHECK-NEXT: and x1, x1, #0xffffffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct14] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffffffffffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct14, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 281474976710655 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(14) [2 x i64] %0([2 x i64] arm64ec_argsize(14) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 281474976710655 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(15) [2 x i64] @callstruct15([2 x i64] arm64ec_argsize(15) %x.coerce) { +; CHECK-LABEL: callstruct15: +; CHECK: .seh_proc callstruct15 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct15 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m15$m15) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m15$m15) +; CHECK-NEXT: and x1, x1, #0xffffffffffffff +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct15] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: and x1, x1, #0xffffffffffffff +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %x.coerce.fca.1.extract = extractvalue [2 x i64] %x.coerce, 1 + %0 = load ptr, ptr @pfnstruct15, align 8 + %coerce.dive1.coerce.sroa.2.0.insert.ext = and i64 %x.coerce.fca.1.extract, 72057594037927935 + %.fca.1.insert6 = insertvalue [2 x i64] %x.coerce, i64 %coerce.dive1.coerce.sroa.2.0.insert.ext, 1 + %call = tail call arm64ec_argsize(15) [2 x i64] %0([2 x i64] arm64ec_argsize(15) %.fca.1.insert6) + %call.fca.1.extract = extractvalue [2 x i64] %call, 1 + %coerce.dive4.coerce.sroa.2.0.insert.ext = and i64 %call.fca.1.extract, 72057594037927935 + %.fca.1.insert = insertvalue [2 x i64] %call, i64 %coerce.dive4.coerce.sroa.2.0.insert.ext, 1 + ret [2 x i64] %.fca.1.insert +} + + +define dso_local arm64ec_argsize(16) [2 x i64] @callstruct16([2 x i64] arm64ec_argsize(16) %x.coerce) { +; CHECK-LABEL: callstruct16: +; CHECK: .seh_proc callstruct16 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstruct16 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m16$m16) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m16$m16) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstruct16] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstruct16, align 8 + %call = tail call arm64ec_argsize(16) [2 x i64] %0([2 x i64] arm64ec_argsize(16) %x.coerce) + ret [2 x i64] %call +} + + +define dso_local arm64ec_argsize(17) void @callstruct17(ptr sret(%struct.s17) align 1 %agg.result, ptr arm64ec_argsize(17) %x) { +; CHECK-LABEL: callstruct17: +; CHECK: .seh_proc callstruct17 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #48 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 32 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct17 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldr q0, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct17] +; CHECK-NEXT: ldrb w9, [x0, #16] +; CHECK-NEXT: str q0, [sp] +; CHECK-NEXT: ldr x12, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m17$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m17$i8) +; CHECK-NEXT: strb w9, [sp, #16] +; CHECK-NEXT: blr x12 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 32 +; CHECK-NEXT: add sp, sp, #48 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s17, align 1 + %0 = load ptr, ptr @pfnstruct17, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 17, i1 false) + call arm64ec_argsize(17) void %0(ptr sret(%struct.s17) align 1 %agg.result, ptr arm64ec_argsize(17) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(32) void @callstruct32(ptr sret(%struct.s32) align 1 %agg.result, ptr arm64ec_argsize(32) %x) { +; CHECK-LABEL: callstruct32: +; CHECK: .seh_proc callstruct32 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #48 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 32 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct32 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m32$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m32$i8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 32 +; CHECK-NEXT: add sp, sp, #48 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s32, align 1 + %0 = load ptr, ptr @pfnstruct32, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 32, i1 false) + call arm64ec_argsize(32) void %0(ptr sret(%struct.s32) align 1 %agg.result, ptr arm64ec_argsize(32) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(33) void @callstruct33(ptr sret(%struct.s33) align 1 %agg.result, ptr arm64ec_argsize(33) %x) { +; CHECK-LABEL: callstruct33: +; CHECK: .seh_proc callstruct33 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: str x30, [sp, #48] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct33 +; CHECK-NEXT: ldrb w10, [x0, #32] +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: strb w10, [sp, #32] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m33$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m33$i8) +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct33] +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 48 +; CHECK-NEXT: add sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s33, align 1 + %0 = load ptr, ptr @pfnstruct33, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 33, i1 false) + call arm64ec_argsize(33) void %0(ptr sret(%struct.s33) align 1 %agg.result, ptr arm64ec_argsize(33) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(64) void @callstruct64(ptr sret(%struct.s64) align 1 %agg.result, ptr arm64ec_argsize(64) %x) { +; CHECK-LABEL: callstruct64: +; CHECK: .seh_proc callstruct64 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #80 +; CHECK-NEXT: .seh_stackalloc 80 +; CHECK-NEXT: str x30, [sp, #64] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 64 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct64 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct64] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m64$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m64$i8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #64] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 64 +; CHECK-NEXT: add sp, sp, #80 +; CHECK-NEXT: .seh_stackalloc 80 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s64, align 1 + %0 = load ptr, ptr @pfnstruct64, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 64, i1 false) + call arm64ec_argsize(64) void %0(ptr sret(%struct.s64) align 1 %agg.result, ptr arm64ec_argsize(64) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(65) void @callstruct65(ptr sret(%struct.s65) align 1 %agg.result, ptr arm64ec_argsize(65) %x) { +; CHECK-LABEL: callstruct65: +; CHECK: .seh_proc callstruct65 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #96 +; CHECK-NEXT: .seh_stackalloc 96 +; CHECK-NEXT: str x30, [sp, #80] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 80 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstruct65 +; CHECK-NEXT: ldrb w10, [x0, #64] +; CHECK-NEXT: ldp q0, q1, [x0, #32] +; CHECK-NEXT: adrp x12, __os_arm64x_check_icall +; CHECK-NEXT: strb w10, [sp, #64] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m65$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m65$i8) +; CHECK-NEXT: ldp q3, q2, [x0] +; CHECK-NEXT: stp q0, q1, [sp, #32] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct65] +; CHECK-NEXT: stp q3, q2, [sp] +; CHECK-NEXT: ldr x9, [x12, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #80] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 80 +; CHECK-NEXT: add sp, sp, #96 +; CHECK-NEXT: .seh_stackalloc 96 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s65, align 1 + %0 = load ptr, ptr @pfnstruct65, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 65, i1 false) + call arm64ec_argsize(65) void %0(ptr sret(%struct.s65) align 1 %agg.result, ptr arm64ec_argsize(65) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(128) void @callstruct128(ptr sret(%struct.s128) align 1 %agg.result, ptr arm64ec_argsize(128) %x) { +; CHECK-LABEL: callstruct128: +; CHECK: .seh_proc callstruct128 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #144 +; CHECK-NEXT: .seh_stackalloc 144 +; CHECK-NEXT: str x30, [sp, #128] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 128 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: ldp q0, q1, [x0, #64] +; CHECK-NEXT: adrp x9, pfnstruct128 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q2, q3, [x0, #96] +; CHECK-NEXT: stp q0, q1, [sp, #64] +; CHECK-NEXT: ldp q0, q4, [x0] +; CHECK-NEXT: stp q2, q3, [sp, #96] +; CHECK-NEXT: ldp q1, q2, [x0, #32] +; CHECK-NEXT: stp q0, q4, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct128] +; CHECK-NEXT: stp q1, q2, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m128$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m128$i8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #128] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 128 +; CHECK-NEXT: add sp, sp, #144 +; CHECK-NEXT: .seh_stackalloc 144 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s128, align 1 + %0 = load ptr, ptr @pfnstruct128, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 128, i1 false) + call arm64ec_argsize(128) void %0(ptr sret(%struct.s128) align 1 %agg.result, ptr arm64ec_argsize(128) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(133) void @callstruct133(ptr sret(%struct.s133) align 1 %agg.result, ptr arm64ec_argsize(133) %x) { +; CHECK-LABEL: callstruct133: +; CHECK: .seh_proc callstruct133 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #160 +; CHECK-NEXT: .seh_stackalloc 160 +; CHECK-NEXT: str x30, [sp, #144] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 144 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: ldp q0, q1, [x0, #96] +; CHECK-NEXT: adrp x9, pfnstruct133 +; CHECK-NEXT: adrp x12, __os_arm64x_check_icall +; CHECK-NEXT: ldp q2, q3, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp, #96] +; CHECK-NEXT: ldur x10, [x0, #125] +; CHECK-NEXT: stp q2, q3, [sp, #32] +; CHECK-NEXT: ldp q1, q0, [x0, #64] +; CHECK-NEXT: stur x10, [sp, #125] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m133$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m133$i8) +; CHECK-NEXT: ldp q3, q2, [x0] +; CHECK-NEXT: stp q1, q0, [sp, #64] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct133] +; CHECK-NEXT: stp q3, q2, [sp] +; CHECK-NEXT: ldr x9, [x12, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #144] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 144 +; CHECK-NEXT: add sp, sp, #160 +; CHECK-NEXT: .seh_stackalloc 160 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s133, align 1 + %0 = load ptr, ptr @pfnstruct133, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 133, i1 false) + call arm64ec_argsize(133) void %0(ptr sret(%struct.s133) align 1 %agg.result, ptr arm64ec_argsize(133) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(192) void @callstruct192(ptr sret(%struct.s192) align 1 %agg.result, ptr arm64ec_argsize(192) %x) { +; CHECK-LABEL: callstruct192: +; CHECK: .seh_proc callstruct192 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #208 +; CHECK-NEXT: .seh_stackalloc 208 +; CHECK-NEXT: str x30, [sp, #192] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 192 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: ldp q0, q1, [x0, #128] +; CHECK-NEXT: adrp x9, pfnstruct192 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q2, q3, [x0, #160] +; CHECK-NEXT: stp q0, q1, [sp, #128] +; CHECK-NEXT: ldp q0, q1, [x0, #64] +; CHECK-NEXT: stp q2, q3, [sp, #160] +; CHECK-NEXT: ldp q2, q3, [x0, #96] +; CHECK-NEXT: stp q0, q1, [sp, #64] +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: stp q2, q3, [sp, #96] +; CHECK-NEXT: ldp q4, q2, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct192] +; CHECK-NEXT: stp q4, q2, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m192$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m192$i8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #192] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 192 +; CHECK-NEXT: add sp, sp, #208 +; CHECK-NEXT: .seh_stackalloc 208 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s192, align 1 + %0 = load ptr, ptr @pfnstruct192, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 192, i1 false) + call arm64ec_argsize(192) void %0(ptr sret(%struct.s192) align 1 %agg.result, ptr arm64ec_argsize(192) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(223) void @callstruct223(ptr sret(%struct.s223) align 1 %agg.result, ptr arm64ec_argsize(223) %x) { +; CHECK-LABEL: callstruct223: +; CHECK: .seh_proc callstruct223 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #240 +; CHECK-NEXT: .seh_stackalloc 240 +; CHECK-NEXT: str x30, [sp, #224] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 224 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: ldp q0, q1, [x0, #160] +; CHECK-NEXT: adrp x9, pfnstruct223 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: stp q0, q1, [sp, #160] +; CHECK-NEXT: ldr q2, [x0, #192] +; CHECK-NEXT: ldp q0, q1, [x0, #96] +; CHECK-NEXT: str q2, [sp, #192] +; CHECK-NEXT: ldur q3, [x0, #207] +; CHECK-NEXT: stp q0, q1, [sp, #96] +; CHECK-NEXT: ldp q0, q1, [x0, #32] +; CHECK-NEXT: stur q3, [sp, #207] +; CHECK-NEXT: ldp q2, q3, [x0, #128] +; CHECK-NEXT: stp q0, q1, [sp, #32] +; CHECK-NEXT: stp q2, q3, [sp, #128] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct223] +; CHECK-NEXT: ldp q2, q3, [x0, #64] +; CHECK-NEXT: ldp q4, q0, [x0] +; CHECK-NEXT: stp q2, q3, [sp, #64] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m223$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m223$i8) +; CHECK-NEXT: stp q4, q0, [sp] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #224] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 224 +; CHECK-NEXT: add sp, sp, #240 +; CHECK-NEXT: .seh_stackalloc 240 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s223, align 1 + %0 = load ptr, ptr @pfnstruct223, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 223, i1 false) + call arm64ec_argsize(223) void %0(ptr sret(%struct.s223) align 1 %agg.result, ptr arm64ec_argsize(223) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(256) void @callstruct256(ptr sret(%struct.s256) align 1 %agg.result, ptr arm64ec_argsize(256) %x) { +; CHECK-LABEL: callstruct256: +; CHECK: .seh_proc callstruct256 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #272 +; CHECK-NEXT: .seh_stackalloc 272 +; CHECK-NEXT: stp x29, x30, [sp, #256] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 256 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: ldp q0, q1, [x0, #192] +; CHECK-NEXT: adrp x9, pfnstruct256 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldp q2, q3, [x0, #224] +; CHECK-NEXT: stp q0, q1, [sp, #192] +; CHECK-NEXT: ldp q0, q1, [x0, #128] +; CHECK-NEXT: stp q2, q3, [sp, #224] +; CHECK-NEXT: ldp q2, q3, [x0, #160] +; CHECK-NEXT: stp q0, q1, [sp, #128] +; CHECK-NEXT: ldp q0, q1, [x0, #64] +; CHECK-NEXT: stp q2, q3, [sp, #160] +; CHECK-NEXT: ldp q2, q3, [x0, #96] +; CHECK-NEXT: stp q0, q1, [sp, #64] +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: stp q2, q3, [sp, #96] +; CHECK-NEXT: ldp q4, q2, [x0, #32] +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstruct256] +; CHECK-NEXT: stp q4, q2, [sp, #32] +; CHECK-NEXT: ldr x9, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m256$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m256$i8) +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldp x29, x30, [sp, #256] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 256 +; CHECK-NEXT: add sp, sp, #272 +; CHECK-NEXT: .seh_stackalloc 272 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s256, align 1 + %0 = load ptr, ptr @pfnstruct256, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 256, i1 false) + call arm64ec_argsize(256) void %0(ptr sret(%struct.s256) align 1 %agg.result, ptr arm64ec_argsize(256) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(257) void @callstruct257(ptr sret(%struct.s257) align 1 %agg.result, ptr arm64ec_argsize(257) %x) { +; CHECK-LABEL: callstruct257: +; CHECK: .seh_proc callstruct257 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #304 +; CHECK-NEXT: .seh_stackalloc 304 +; CHECK-NEXT: stp x19, x20, [sp, #272] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_regp x19, 272 +; CHECK-NEXT: stp x29, x30, [sp, #288] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 288 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov x19, x8 +; CHECK-NEXT: adrp x8, pfnstruct257 +; CHECK-NEXT: mov x1, x0 +; CHECK-NEXT: add x0, sp, #8 +; CHECK-NEXT: mov w2, #257 +; CHECK-NEXT: ldr x20, [x8, :lo12:pfnstruct257] +; CHECK-NEXT: bl "#memcpy" +; CHECK-NEXT: adrp x8, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$m257$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$m257$i8) +; CHECK-NEXT: mov x11, x20 +; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: add x0, sp, #8 +; CHECK-NEXT: mov x8, x19 +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldp x29, x30, [sp, #288] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 288 +; CHECK-NEXT: ldp x19, x20, [sp, #272] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_regp x19, 272 +; CHECK-NEXT: add sp, sp, #304 +; CHECK-NEXT: .seh_stackalloc 304 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.s257, align 1 + %0 = load ptr, ptr @pfnstruct257, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 257, i1 false) + call arm64ec_argsize(257) void %0(ptr sret(%struct.s257) align 1 %agg.result, ptr arm64ec_argsize(257) %agg.tmp) + ret void +} + + + +define dso_local arm64ec_argsize(8) %struct.f2 @callstructf2([2 x float] arm64ec_argsize(8) %x.coerce) { +; CHECK-LABEL: callstructf2: +; CHECK: .seh_proc callstructf2 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstructf2 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$F8$F8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$F8$F8) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstructf2] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstructf2, align 8 + %call = tail call arm64ec_argsize(8) %struct.f2 %0([2 x float] arm64ec_argsize(8) %x.coerce) + %1 = extractvalue %struct.f2 %call, 0 + %.fca.0.extract = extractvalue [2 x float] %1, 0 + %.fca.1.extract = extractvalue [2 x float] %1, 1 + %.fca.0.0.insert = insertvalue %struct.f2 poison, float %.fca.0.extract, 0, 0 + %.fca.0.1.insert = insertvalue %struct.f2 %.fca.0.0.insert, float %.fca.1.extract, 0, 1 + ret %struct.f2 %.fca.0.1.insert +} + + +define dso_local arm64ec_argsize(12) %struct.f3 @callstructf3([3 x float] arm64ec_argsize(12) %x.coerce) { +; CHECK-LABEL: callstructf3: +; CHECK: .seh_proc callstructf3 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstructf3 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$F12$F12) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$F12$F12) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstructf3] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstructf3, align 8 + %call = tail call arm64ec_argsize(12) %struct.f3 %0([3 x float] arm64ec_argsize(12) %x.coerce) + %1 = extractvalue %struct.f3 %call, 0 + %.fca.0.extract = extractvalue [3 x float] %1, 0 + %.fca.1.extract = extractvalue [3 x float] %1, 1 + %.fca.2.extract = extractvalue [3 x float] %1, 2 + %.fca.0.0.insert = insertvalue %struct.f3 poison, float %.fca.0.extract, 0, 0 + %.fca.0.1.insert = insertvalue %struct.f3 %.fca.0.0.insert, float %.fca.1.extract, 0, 1 + %.fca.0.2.insert = insertvalue %struct.f3 %.fca.0.1.insert, float %.fca.2.extract, 0, 2 + ret %struct.f3 %.fca.0.2.insert +} + + +define dso_local arm64ec_argsize(16) %struct.f4 @callstructf4([4 x float] arm64ec_argsize(16) %x.coerce) { +; CHECK-LABEL: callstructf4: +; CHECK: .seh_proc callstructf4 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstructf4 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$F16$F16) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$F16$F16) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstructf4] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstructf4, align 8 + %call = tail call arm64ec_argsize(16) %struct.f4 %0([4 x float] arm64ec_argsize(16) %x.coerce) + %1 = extractvalue %struct.f4 %call, 0 + %.fca.0.extract = extractvalue [4 x float] %1, 0 + %.fca.1.extract = extractvalue [4 x float] %1, 1 + %.fca.2.extract = extractvalue [4 x float] %1, 2 + %.fca.3.extract = extractvalue [4 x float] %1, 3 + %.fca.0.0.insert = insertvalue %struct.f4 poison, float %.fca.0.extract, 0, 0 + %.fca.0.1.insert = insertvalue %struct.f4 %.fca.0.0.insert, float %.fca.1.extract, 0, 1 + %.fca.0.2.insert = insertvalue %struct.f4 %.fca.0.1.insert, float %.fca.2.extract, 0, 2 + %.fca.0.3.insert = insertvalue %struct.f4 %.fca.0.2.insert, float %.fca.3.extract, 0, 3 + ret %struct.f4 %.fca.0.3.insert +} + + +define dso_local arm64ec_argsize(20) void @callstructf5(ptr sret(%struct.f5) align 1 %agg.result, ptr arm64ec_argsize(20) %x) { +; CHECK-LABEL: callstructf5: +; CHECK: .seh_proc callstructf5 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #48 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 32 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstructf5 +; CHECK-NEXT: adrp x10, __os_arm64x_check_icall +; CHECK-NEXT: ldr q0, [x0] +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstructf5] +; CHECK-NEXT: ldr w9, [x0, #16] +; CHECK-NEXT: str q0, [sp] +; CHECK-NEXT: ldr x12, [x10, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$F20$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$F20$i8) +; CHECK-NEXT: str w9, [sp, #16] +; CHECK-NEXT: blr x12 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 32 +; CHECK-NEXT: add sp, sp, #48 +; CHECK-NEXT: .seh_stackalloc 48 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.f5, align 1 + %0 = load ptr, ptr @pfnstructf5, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 20, i1 false) + call arm64ec_argsize(20) void %0(ptr sret(%struct.f5) align 1 %agg.result, ptr arm64ec_argsize(20) %agg.tmp) + ret void +} + + +define dso_local arm64ec_argsize(16) %struct.d2 @callstructd2([2 x double] arm64ec_argsize(16) %x.coerce) { +; CHECK-LABEL: callstructd2: +; CHECK: .seh_proc callstructd2 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstructd2 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$D16$D16) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$D16$D16) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstructd2] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstructd2, align 8 + %call = tail call arm64ec_argsize(16) %struct.d2 %0([2 x double] arm64ec_argsize(16) %x.coerce) + %1 = extractvalue %struct.d2 %call, 0 + %.fca.0.extract = extractvalue [2 x double] %1, 0 + %.fca.1.extract = extractvalue [2 x double] %1, 1 + %.fca.0.0.insert = insertvalue %struct.d2 poison, double %.fca.0.extract, 0, 0 + %.fca.0.1.insert = insertvalue %struct.d2 %.fca.0.0.insert, double %.fca.1.extract, 0, 1 + ret %struct.d2 %.fca.0.1.insert +} + + +define dso_local arm64ec_argsize(24) %struct.d3 @callstructd3([3 x double] arm64ec_argsize(24) %x.coerce) { +; CHECK-LABEL: callstructd3: +; CHECK: .seh_proc callstructd3 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstructd3 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$D24$D24) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$D24$D24) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstructd3] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstructd3, align 8 + %call = tail call arm64ec_argsize(24) %struct.d3 %0([3 x double] arm64ec_argsize(24) %x.coerce) + %1 = extractvalue %struct.d3 %call, 0 + %.fca.0.extract = extractvalue [3 x double] %1, 0 + %.fca.1.extract = extractvalue [3 x double] %1, 1 + %.fca.2.extract = extractvalue [3 x double] %1, 2 + %.fca.0.0.insert = insertvalue %struct.d3 poison, double %.fca.0.extract, 0, 0 + %.fca.0.1.insert = insertvalue %struct.d3 %.fca.0.0.insert, double %.fca.1.extract, 0, 1 + %.fca.0.2.insert = insertvalue %struct.d3 %.fca.0.1.insert, double %.fca.2.extract, 0, 2 + ret %struct.d3 %.fca.0.2.insert +} + + +define dso_local arm64ec_argsize(32) %struct.d4 @callstructd4([4 x double] arm64ec_argsize(32) %x.coerce) { +; CHECK-LABEL: callstructd4: +; CHECK: .seh_proc callstructd4 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x8, pfnstructd4 +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$D32$D32) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$D32$D32) +; CHECK-NEXT: ldr x11, [x8, :lo12:pfnstructd4] +; CHECK-NEXT: ldr x8, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: br x11 +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %0 = load ptr, ptr @pfnstructd4, align 8 + %call = tail call arm64ec_argsize(32) %struct.d4 %0([4 x double] arm64ec_argsize(32) %x.coerce) + %1 = extractvalue %struct.d4 %call, 0 + %.fca.0.extract = extractvalue [4 x double] %1, 0 + %.fca.1.extract = extractvalue [4 x double] %1, 1 + %.fca.2.extract = extractvalue [4 x double] %1, 2 + %.fca.3.extract = extractvalue [4 x double] %1, 3 + %.fca.0.0.insert = insertvalue %struct.d4 poison, double %.fca.0.extract, 0, 0 + %.fca.0.1.insert = insertvalue %struct.d4 %.fca.0.0.insert, double %.fca.1.extract, 0, 1 + %.fca.0.2.insert = insertvalue %struct.d4 %.fca.0.1.insert, double %.fca.2.extract, 0, 2 + %.fca.0.3.insert = insertvalue %struct.d4 %.fca.0.2.insert, double %.fca.3.extract, 0, 3 + ret %struct.d4 %.fca.0.3.insert +} + + +define dso_local arm64ec_argsize(40) void @callstructd5(ptr sret(%struct.d5) align 1 %agg.result, ptr arm64ec_argsize(40) %x) { +; CHECK-LABEL: callstructd5: +; CHECK: .seh_proc callstructd5 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: str x30, [sp, #48] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 48 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: adrp x9, pfnstructd5 +; CHECK-NEXT: ldr x10, [x0, #32] +; CHECK-NEXT: ldp q0, q1, [x0] +; CHECK-NEXT: str x10, [sp, #32] +; CHECK-NEXT: adrp x10, ($iexit_thunk$cdecl$D40$i8) +; CHECK-NEXT: add x10, x10, :lo12:($iexit_thunk$cdecl$D40$i8) +; CHECK-NEXT: ldr x11, [x9, :lo12:pfnstructd5] +; CHECK-NEXT: adrp x9, __os_arm64x_check_icall +; CHECK-NEXT: stp q0, q1, [sp] +; CHECK-NEXT: ldr x9, [x9, :lo12:__os_arm64x_check_icall] +; CHECK-NEXT: blr x9 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: blr x11 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 48 +; CHECK-NEXT: add sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %agg.tmp = alloca %struct.d5, align 1 + %0 = load ptr, ptr @pfnstructd5, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %agg.tmp, ptr align 1 %x, i64 40, i1 false) + call arm64ec_argsize(40) void %0(ptr sret(%struct.d5) align 1 %agg.result, ptr arm64ec_argsize(40) %agg.tmp) + ret void +}