From b0dbee932a918d4e8a3ae02d08cf49fea6337e11 Mon Sep 17 00:00:00 2001 From: Jeremi Kurdek <59935235+jkurdek@users.noreply.github.com> Date: Wed, 14 Aug 2024 09:53:25 +0200 Subject: [PATCH] [Mono AOT] Fix error when returning zero sized struct (#106013) * Fix error when returning zero sized struct * Add test * Fix x64 errors --- src/mono/mono/mini/mini-llvm.c | 11 +++++-- .../JitBlue/Runtime_103628/Runtime_103628.cs | 29 +++++++++++++++++++ .../Runtime_103628/Runtime_103628.csproj | 8 +++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.csproj diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 4918e9abeb4ab..b85d6b562e837 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -1593,7 +1593,7 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo * ret_type = LLVMStructType (members, 1, FALSE); } else if (cinfo->ret.pair_storage [0] == LLVMArgNone && cinfo->ret.pair_storage [1] == LLVMArgNone) { /* Empty struct */ - ret_type = LLVMVoidType (); + ret_type = LLVMStructType (NULL, 0, FALSE); } else if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgInIReg) { LLVMTypeRef members [2]; @@ -1610,7 +1610,11 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo * case LLVMArgVtypeAsScalar: { int size = mono_class_value_size (mono_class_from_mono_type_internal (rtype), NULL); /* LLVM models this by returning an int */ - if (size < TARGET_SIZEOF_VOID_P) { + if (size == 0) { + /* Empty struct with LayoutKind attribute and without specified size */ + g_assert(cinfo->ret.nslots == 0); + ret_type = LLVMIntType (8); + } else if (size < TARGET_SIZEOF_VOID_P) { g_assert (cinfo->ret.nslots == 1); ret_type = LLVMIntType (size * 8); } else { @@ -4946,6 +4950,9 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, /* Empty struct */ break; + if (LLVMTypeOf (lcall) == LLVMStructType (NULL, 0, FALSE)) + break; + if (!addresses [ins->dreg]) addresses [ins->dreg] = build_alloca_address (ctx, sig->ret); diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.cs b/src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.cs new file mode 100644 index 0000000000000..ef904b9699168 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using Xunit; + +[StructLayout(LayoutKind.Sequential)] +public struct S1 +{ +} + +[StructLayout(LayoutKind.Auto)] +public struct S2 +{ +} + +public class Runtime_103628 +{ + public static S1 Get_S1() => new S1(); + + public static S2 Get_S2() => new S2(); + + [Fact] + public static void TestEntryPoint() + { + S1 s1 = Get_S1(); + S2 s2 = Get_S2(); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.csproj new file mode 100644 index 0000000000000..de6d5e08882e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_103628/Runtime_103628.csproj @@ -0,0 +1,8 @@ + + + True + + + + +