diff options
author | Zoltan Varga <vargaz@gmail.com> | 2015-01-31 01:46:38 +0300 |
---|---|---|
committer | Miguel de Icaza <miguel@gnome.org> | 2015-02-28 17:43:07 +0300 |
commit | c70a6a93d9364e943890715493e00bf2fc22582d (patch) | |
tree | 33b068fc413c442c0fc35da72186dbabebf288cc | |
parent | c26de2695dd0a02d0f031af32f4a987fa94643c3 (diff) |
[arm] Enable llvm for methods with struct arguments larger than 2 words.monotouch-3.12.0-branch
-rw-r--r-- | mono/mini/mini-arm.c | 14 | ||||
-rw-r--r-- | mono/mini/mini-llvm.c | 22 | ||||
-rwxr-xr-x | mono/mini/mini.h | 4 |
3 files changed, 25 insertions, 15 deletions
diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 7e7c5937b97..fa62c77c70b 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -2242,18 +2242,8 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) linfo->args [i].storage = LLVMArgInIReg; break; case RegTypeStructByVal: - // FIXME: Passing entirely on the stack or split reg/stack - if (ainfo->vtsize == 0 && ainfo->size <= 2) { - linfo->args [i].storage = LLVMArgVtypeInReg; - linfo->args [i].pair_storage [0] = LLVMArgInIReg; - if (ainfo->size == 2) - linfo->args [i].pair_storage [1] = LLVMArgInIReg; - else - linfo->args [i].pair_storage [1] = LLVMArgNone; - } else { - cfg->exception_message = g_strdup_printf ("vtype-by-val on stack"); - cfg->disable_llvm = TRUE; - } + linfo->args [i].storage = LLVMArgAsIArgs; + linfo->args [i].nslots = ainfo->struct_size / sizeof (gpointer); break; default: cfg->exception_message = g_strdup_printf ("ainfo->storage (%d)", ainfo->storage); diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index 28e76665e16..3f0b9e49222 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -1153,12 +1153,14 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo * if (vretaddr && vret_arg_pindex == pindex) param_types [pindex ++] = IntPtrType (); for (i = 0; i < sig->param_count; ++i) { + LLVMArgInfo *ainfo = cinfo ? &cinfo->args [i + sig->hasthis] : NULL; + if (vretaddr && vret_arg_pindex == pindex) param_types [pindex ++] = IntPtrType (); pindexes [i] = pindex; - if (cinfo && cinfo->args [i + sig->hasthis].storage == LLVMArgVtypeInReg) { + if (ainfo && ainfo->storage == LLVMArgVtypeInReg) { for (j = 0; j < 2; ++j) { - switch (cinfo->args [i + sig->hasthis].pair_storage [j]) { + switch (ainfo->pair_storage [j]) { case LLVMArgInIReg: param_types [pindex ++] = LLVMIntType (sizeof (gpointer) * 8); break; @@ -1168,11 +1170,14 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo * g_assert_not_reached (); } } - } else if (cinfo && cinfo->args [i + sig->hasthis].storage == LLVMArgVtypeByVal) { + } else if (ainfo && ainfo->storage == LLVMArgVtypeByVal) { param_types [pindex] = type_to_llvm_arg_type (ctx, sig->params [i]); CHECK_FAILURE (ctx); param_types [pindex] = LLVMPointerType (param_types [pindex], 0); pindex ++; + } else if (ainfo && ainfo->storage == LLVMArgAsIArgs) { + param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots); + pindex ++; } else { param_types [pindex ++] = type_to_llvm_arg_type (ctx, sig->params [i]); } @@ -1823,6 +1828,13 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) /* Treat these as normal values */ ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], ""); } + } else if (ainfo->storage == LLVMArgAsIArgs) { + LLVMValueRef arg = LLVMGetParam (ctx->lmethod, ctx->pindexes [i]); + + ctx->addresses [reg] = build_alloca (ctx, sig->params [i]); + + /* 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))); } else { ctx->values [reg] = convert_full (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])), type_is_unsigned (ctx, sig->params [i])); } @@ -2125,6 +2137,9 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, } else if (ainfo->storage == LLVMArgVtypeByVal) { g_assert (addresses [reg]); args [pindex] = addresses [reg]; + } else if (ainfo->storage == LLVMArgAsIArgs) { + g_assert (addresses [reg]); + args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), ""); } else { g_assert (args [pindex]); if (i == 0 && sig->hasthis) @@ -4802,6 +4817,7 @@ mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call) } case LLVMArgVtypeByVal: case LLVMArgVtypeInReg: + case LLVMArgAsIArgs: MONO_INST_NEW (cfg, ins, OP_LLVM_OUTARG_VT); ins->dreg = mono_alloc_ireg (cfg); ins->sreg1 = in->dreg; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 71906332b88..61bdf896ad4 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -735,6 +735,8 @@ typedef enum { LLVMArgVtypeByVal, LLVMArgVtypeRetAddr, /* On on cinfo->ret */ LLVMArgGSharedVt, + /* Argument passed as a set of int args */ + LLVMArgAsIArgs } LLVMArgStorage; typedef struct { @@ -742,6 +744,8 @@ typedef struct { /* Only if storage == ArgValuetypeInReg */ LLVMArgStorage pair_storage [2]; + /* Only if storage == LLVMArgAsIArgs */ + int nslots; } LLVMArgInfo; typedef struct { |