[llvmonly] Fix a few issues passing and returning vtypes smaller than one machine...
authorZoltan Varga <vargaz@gmail.com>
Wed, 10 Feb 2016 05:46:57 +0000 (00:46 -0500)
committerZoltan Varga <vargaz@gmail.com>
Wed, 10 Feb 2016 05:46:57 +0000 (00:46 -0500)
mono/mini/mini-llvm.c

index 917abaa855535726df70d0f6449bdd6f7ae0fec6..3484ed3faecd954d4e87bd83f8e16699f43d47a8 100644 (file)
@@ -1259,11 +1259,18 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
        case LLVMArgVtypeByVal:
                /* Vtype returned normally by val */
                break;
-       case LLVMArgVtypeAsScalar:
+       case LLVMArgVtypeAsScalar: {
+               int size = mono_class_value_size (mono_class_from_mono_type (rtype), NULL);
                /* LLVM models this by returning an int */
-               g_assert (cinfo->ret.nslots == 1 || cinfo->ret.nslots == 2);
-               ret_type = LLVMIntType (cinfo->ret.nslots * sizeof (mgreg_t) * 8);
+               if (size < SIZEOF_VOID_P) {
+                       g_assert (cinfo->ret.nslots == 1);
+                       ret_type = LLVMIntType (size * 8);
+               } else {
+                       g_assert (cinfo->ret.nslots == 1 || cinfo->ret.nslots == 2);
+                       ret_type = LLVMIntType (cinfo->ret.nslots * sizeof (mgreg_t) * 8);
+               }
                break;
+       }
        case LLVMArgFpStruct: {
                /* Vtype returned as a fp struct */
                LLVMTypeRef members [16];
@@ -2906,11 +2913,20 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
                }
                case LLVMArgAsIArgs: {
                        LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
+                       int size;
 
+                       /* The argument is received as an array of ints, store it into the real argument */
                        ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
 
-                       /* The argument is received as an array of ints, store it into the real argument */
-                       LLVMBuildStore (ctx->builder, arg, convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMTypeOf (arg), 0)));
+                       size = mono_class_value_size (mono_class_from_mono_type (ainfo->type), NULL);
+                       if (size < SIZEOF_VOID_P) {
+                               /* The upper bits of the registers might not be valid */
+                               LLVMValueRef val = LLVMBuildExtractValue (builder, arg, 0, "");
+                               LLVMValueRef dest = convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMIntType (size * 8), 0));
+                               LLVMBuildStore (ctx->builder, LLVMBuildTrunc (builder, val, LLVMIntType (size * 8), ""), dest);
+                       } else {
+                               LLVMBuildStore (ctx->builder, arg, convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMTypeOf (arg), 0)));
+                       }
                        break;
                }
                case LLVMArgVtypeAsScalar: