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-10-18 20:29:02 +0300
committerLudovic Henry <luhenry@microsoft.com>2017-10-25 17:35:58 +0300
commite66d9abbb271c3d08589c09afce4afc80de2d3b6 (patch)
tree8ebb9bf18640624a8c2db85ff46b2e72a1e65f70
parent1f4613aa1acacbea90a8aa82daeea4a449cf4df7 (diff)
[llvm] Fix the returning of vtypes using a hidden argument in bitcode, in some cases, we forgot to generate the code to return the value, causing random data to be returned. Fixes #59956. (#5786)mono-5.4.1.72017-06
-rw-r--r--mono/mini/gshared.cs46
-rw-r--r--mono/mini/mini-llvm.c15
2 files changed, 61 insertions, 0 deletions
diff --git a/mono/mini/gshared.cs b/mono/mini/gshared.cs
index 61402f7a4ec..910a6df73f5 100644
--- a/mono/mini/gshared.cs
+++ b/mono/mini/gshared.cs
@@ -1996,6 +1996,23 @@ public class Tests
Console.WriteLine ("X: " + iface.is_ref<AStruct3<string, int, int>> ());
return 0;
}
+
+ interface IFace59956 {
+ int foo<T> ();
+ }
+
+ class Impl59956 : IFace59956 {
+ public int foo<T> () {
+ var builder = new SparseArrayBuilder<T>(true);
+
+ return builder.Markers._count;
+ }
+ }
+
+ public static int test_1_59956_regress () {
+ IFace59956 iface = new Impl59956 ();
+ return iface.foo<int> ();
+ }
}
// #13191
@@ -2013,6 +2030,35 @@ public class MobileServiceCollection<TTable, TCol>
}
}
+// #59956
+internal struct Marker
+{
+ public Marker(int count, int index) {
+ }
+}
+
+public struct ArrayBuilder<T>
+{
+ private T[] _array;
+ public int _count;
+
+ public ArrayBuilder(int capacity) {
+ _array = new T[capacity];
+ _count = 1;
+ }
+}
+
+internal struct SparseArrayBuilder<T>
+{
+ private ArrayBuilder<Marker> _markers;
+
+ public SparseArrayBuilder(bool initialize) : this () {
+ _markers = new ArrayBuilder<Marker> (10);
+ }
+
+ public ArrayBuilder<Marker> Markers => _markers;
+}
+
#if !__MOBILE__
public class GSharedTests : Tests {
}
diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c
index 694189a96ac..79b0c8585ae 100644
--- a/mono/mini/mini-llvm.c
+++ b/mono/mini/mini-llvm.c
@@ -7492,7 +7492,22 @@ mono_llvm_create_vars (MonoCompile *cfg)
sig = mono_method_signature (cfg->method);
if (cfg->gsharedvt && cfg->llvm_only) {
+ gboolean vretaddr = FALSE;
+
if (mini_is_gsharedvt_variable_signature (sig) && sig->ret->type != MONO_TYPE_VOID) {
+ vretaddr = TRUE;
+ } else {
+ MonoMethodSignature *sig = mono_method_signature (cfg->method);
+ LLVMCallInfo *linfo;
+
+ linfo = get_llvm_call_info (cfg, sig);
+ vretaddr = (linfo->ret.storage == LLVMArgVtypeRetAddr || linfo->ret.storage == LLVMArgVtypeByRef || linfo->ret.storage == LLVMArgGsharedvtFixed || linfo->ret.storage == LLVMArgGsharedvtVariable || linfo->ret.storage == LLVMArgGsharedvtFixedVtype);
+ }
+ if (vretaddr) {
+ /*
+ * Creating vret_addr forces CEE_SETRET to store the result into it,
+ * so we don't have to generate any code in our OP_SETRET case.
+ */
cfg->vret_addr = mono_compile_create_var (cfg, &mono_get_intptr_class ()->byval_arg, OP_ARG);
if (G_UNLIKELY (cfg->verbose_level > 1)) {
printf ("vret_addr = ");