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];
}
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: