Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2015-01-31 01:46:38 +0300
committerMiguel de Icaza <miguel@gnome.org>2015-02-28 17:43:07 +0300
commitc70a6a93d9364e943890715493e00bf2fc22582d (patch)
tree33b068fc413c442c0fc35da72186dbabebf288cc
parentc26de2695dd0a02d0f031af32f4a987fa94643c3 (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.c14
-rw-r--r--mono/mini/mini-llvm.c22
-rwxr-xr-xmono/mini/mini.h4
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 {