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>2017-02-22 23:06:08 +0300
committerZoltan Varga <vargaz@gmail.com>2017-02-22 23:08:41 +0300
commitcb947b7a56c09febb89b02b89599c003874b23f3 (patch)
tree6a7094f236a149c0165aec66984194e23a5cf72a
parent25a554dc6bd0b4e68a8ff5ca2b4980efd593d790 (diff)
[arm] Fix the passing of structs with 8 byte alignment with llvm on armeabi, they need to be passed as an int64 array to let llvm know that it might need to insert a dummy argument so they are passed in a even register pair. Fixes #52548.
-rw-r--r--mono/mini/mini-arm.c12
-rw-r--r--mono/mini/mini-arm.h2
-rw-r--r--mono/mini/mini-llvm.c10
-rw-r--r--mono/mini/mini.h2
4 files changed, 21 insertions, 5 deletions
diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c
index 42715480b00..f85644d42ca 100644
--- a/mono/mini/mini-arm.c
+++ b/mono/mini/mini-arm.c
@@ -1515,6 +1515,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
nwords = (align_size + sizeof (gpointer) -1 ) / sizeof (gpointer);
ainfo->storage = RegTypeStructByVal;
ainfo->struct_size = size;
+ ainfo->align = align;
/* FIXME: align stack_size if needed */
if (eabi_supported) {
if (align >= 8 && (gr & 1))
@@ -2166,7 +2167,16 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
break;
case RegTypeStructByVal:
lainfo->storage = LLVMArgAsIArgs;
- lainfo->nslots = ainfo->struct_size / sizeof (gpointer);
+ if (eabi_supported && ainfo->align == 8) {
+ /* LLVM models this by passing an int64 array */
+ lainfo->nslots = ALIGN_TO (ainfo->struct_size, 8) / 8;
+ lainfo->esize = 8;
+ } else {
+ lainfo->nslots = ainfo->struct_size / sizeof (gpointer);
+ lainfo->esize = 4;
+ }
+
+ printf ("D: %d\n", ainfo->align);
break;
case RegTypeStructByAddr:
case RegTypeStructByAddrOnStack:
diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h
index 28678638b6c..31194f2e60d 100644
--- a/mono/mini/mini-arm.h
+++ b/mono/mini/mini-arm.h
@@ -208,7 +208,7 @@ typedef struct {
guint8 reg;
ArgStorage storage;
/* RegTypeStructByVal */
- gint32 struct_size;
+ gint32 struct_size, align;
guint8 size : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal */
} ArgInfo;
diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c
index 563607f8c0f..745c29f13e4 100644
--- a/mono/mini/mini-llvm.c
+++ b/mono/mini/mini-llvm.c
@@ -1431,7 +1431,10 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
pindex ++;
break;
case LLVMArgAsIArgs:
- param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
+ if (ainfo->esize == 8)
+ param_types [pindex] = LLVMArrayType (LLVMInt64Type (), ainfo->nslots);
+ else
+ param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
pindex ++;
break;
case LLVMArgVtypeByRef:
@@ -3490,7 +3493,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
}
case LLVMArgAsIArgs:
g_assert (addresses [reg]);
- args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
+ if (ainfo->esize == 8)
+ args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (LLVMInt64Type (), ainfo->nslots), 0)), "");
+ else
+ args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
break;
case LLVMArgVtypeAsScalar:
g_assert_not_reached ();
diff --git a/mono/mini/mini.h b/mono/mini/mini.h
index 25316da3245..d8e9f9ca547 100644
--- a/mono/mini/mini.h
+++ b/mono/mini/mini.h
@@ -826,7 +826,7 @@ typedef struct {
* in the structure.
*/
int nslots;
- /* Only if storage == LLVMArgAsFpArgs/LLVMArgFpStruct (4/8) */
+ /* Only if storage == LLVMArgAsIArgs/LLVMArgAsFpArgs/LLVMArgFpStruct (4/8) */
int esize;
/* Parameter index in the LLVM signature */
int pindex;