Crash calling back into a C function on a Mac M1

Hi all,
I’m trying to call back into a C function from some code JITd by LLVM, and it’s crashing with EXC_BAD_ACCESS.
This is on a Mac M1. LLVM version is 15.0.7.

The C function being called:

static void testExternalFuncVec2(float* ret, float x)
{
	ret[0] = x;
	ret[1] = x*x;
}

And the disassembly of the C function: (from Xcode)

winter`Winter::testExternalFuncVec2:
    0x10010e474 <+0>:  sub    sp, sp, #0x10
    0x10010e478 <+4>:  str    x0, [sp, #0x8]
    0x10010e47c <+8>:  str    s0, [sp, #0x4]
    0x10010e480 <+12>: ldr    s0, [sp, #0x4]
    0x10010e484 <+16>: ldr    x8, [sp, #0x8]
->  0x10010e488 <+20>: str    s0, [x8]
    0x10010e48c <+24>: ldr    s0, [sp, #0x4]
    0x10010e490 <+28>: ldr    s1, [sp, #0x4]
    0x10010e494 <+32>: fmul   s0, s0, s1
    0x10010e498 <+36>: ldr    x8, [sp, #0x8]
    0x10010e49c <+40>: str    s0, [x8, #0x4]
    0x10010e4a0 <+44>: add    sp, sp, #0x10
    0x10010e4a4 <+48>: ret    

The disassembled LLVM JIT’d code, that calls the C function:

	.text
	.file	"WinterModule"
	.globl	main_float_
	.p2align	2
	.type	main_float_,@function
main_float_:
	sub	sp, sp, #48
	stp	d9, d8, [sp, #16]
	str	x30, [sp, #32]
	fmov	s8, s0
	add	x8, sp, #8
	bl	testExternalFuncVec2_float_
	ldr	s9, [sp, #8]
	add	x8, sp, #40
	fmov	s0, s8
	bl	testExternalFuncVec2_float_
	ldr	s0, [sp, #40]
	fadd	s0, s9, s0
	ldr	x30, [sp, #32]
	ldp	d9, d8, [sp, #16]
	add	sp, sp, #48
	ret
.Lfunc_end0:
	.size	main_float_, .Lfunc_end0-main_float_

	.section	".note.GNU-stack","",@progbits

And the corresponding LLVM IR:

; ModuleID = 'WinterModule'
source_filename = "WinterModule"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"

%vec2 = type { <2 x float> }

; Function Attrs: nounwind
declare void @testExternalFuncVec2_float_(ptr noalias sret(%vec2), float) local_unnamed_addr #0

; Function Attrs: nofree nosync nounwind readnone
define float @main_float_(float %x) local_unnamed_addr #1 {
entry:
  %res1 = alloca %vec2, align 8
  %res = alloca %vec2, align 8
  call void @testExternalFuncVec2_float_(ptr nonnull %res, float %x)
  %0 = load float, ptr %res, align 8
  call void @testExternalFuncVec2_float_(ptr nonnull %res1, float %x)
  %1 = load float, ptr %res1, align 8
  %2 = fadd nnan ninf nsz float %0, %1
  ret float %2
}

attributes #0 = { nounwind "warn-stack-size"="0" }
attributes #1 = { nofree nosync nounwind readnone "warn-stack-size"="0" }

Is this an issue of LLVM not using the correct calling convention on M1 Mac?
This code works fine on Windows, Linux and Mac x64.

Why have you marked it sret when the C function takes it as a normal pointer? As you can see here:

the ABI is to pass the sret (struct return) pointer via x8, not as if it were a normal argument, and this is true of both Apple’s and the standard Arm PCS.

Hi,
Removing SRET seems to solve the crash, thanks.
I was using it because conceptually the function result is returned via the first argument.

For that IR to be accurate you’d need to have C of the form:

struct { float f[2]; } testExternalFuncVec2(float x)
{
    ret[0] = x;
    ret[1] = x*x;
}

(or some kind of vector type)