14c0c4fbd1b8 — Leonard Ritter 15 days ago
* ABI: fixed returning multiple values of reference type; this rarely triggers before we auto-dereference stack references.
M src/platform_abi.cpp +5 -3
@@ 6,6 6,7 @@ 
 
 #include "platform_abi.hpp"
 #include "types.hpp"
+#include "type.hpp"
 #include "utils.hpp"
 #include "dyn_cast.inc"
 

          
@@ 116,7 117,7 @@ static size_t classify_tuple_like(size_t
     }
     ABIClass subclasses[MAX_ABI_CLASSES];
     for (size_t i = 0; i < count; ++i) {
-        auto ET = strip_qualifiers(fields[i]);
+        auto ET = qualified_storage_type(fields[i]).assert_ok();
         if (!packed)
             offset = align(offset, align_of(ET).assert_ok());
         size_t num = classify (ET, subclasses, offset % 8);

          
@@ 172,7 173,7 @@ static size_t classify_array_like(size_t
         classes[0] = ABI_CLASS_NO_CLASS;
         return 1;
     }
-    auto ET = element_type;
+    auto ET = qualified_storage_type(element_type).assert_ok();
     ABIClass subclasses[MAX_ABI_CLASSES];
     size_t alignment = align_of(ET).assert_ok();
     size_t esize = size_of(ET).assert_ok();

          
@@ 296,7 297,7 @@ static size_t classify(const Type *T, AB
 #endif // SCOPES_WIN32
 
 size_t abi_classify(const Type *T, ABIClass *classes) {
-    T = strip_qualifiers(T);
+    //const Type *ST = strip_qualifiers(T);
     if (T->kind() == TK_Arguments) {
         if (T == empty_arguments_type()) {
             classes[0] = ABI_CLASS_NO_CLASS;

          
@@ 304,6 305,7 @@ size_t abi_classify(const Type *T, ABICl
         }
         T = cast<ArgumentsType>(T)->to_tuple_type();
     }
+    T = qualified_storage_type(T).assert_ok();
 #ifdef SCOPES_WIN32
     classes[0] = ABI_CLASS_NO_CLASS;
     if (is_opaque(T))

          
M src/type.cpp +32 -0
@@ 367,6 367,38 @@ bool types_compatible(const Type *paramT
 }
 
 //------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+SCOPES_RESULT(const Type *) storage_type(const Type *T) {
+    SCOPES_RESULT_TYPE(const Type *);
+    T = strip_qualifiers(T);
+    switch(T->kind()) {
+    case TK_Typename: {
+        const TypenameType *tt = cast<TypenameType>(T);
+        if (!tt->is_complete()) {
+            SCOPES_ERROR(TypenameIncomplete, T);
+        }
+        if (tt->is_opaque()) {
+            SCOPES_ERROR(OpaqueType, T);
+        }
+        return tt->storage();
+    } break;
+    default: return T;
+    }
+}
+
+SCOPES_RESULT(const Type *) qualified_storage_type(const Type *T) {
+    //SCOPES_RESULT_TYPE(const Type *);
+    auto rq = try_qualifier<ReferQualifier>(T);
+    if (rq) {
+        T = strip_qualifiers(T);
+        return pointer_type(T, rq->flags, rq->storage_class);
+    } else {
+        return storage_type(T);
+    }
+}
+
+//------------------------------------------------------------------------------
 // TYPE CHECK PREDICATES
 //------------------------------------------------------------------------------
 

          
M src/type.hpp +5 -0
@@ 195,6 195,11 @@ bool all_plain(const Types &types);
 bool is_plain(const Type *T);
 
 //------------------------------------------------------------------------------
+
+SCOPES_RESULT(const Type *) storage_type(const Type *T);
+SCOPES_RESULT(const Type *) qualified_storage_type(const Type *T);
+
+//------------------------------------------------------------------------------
 // TYPE CHECK PREDICATES
 //------------------------------------------------------------------------------
 

          
M src/type/arguments_type.cpp +5 -1
@@ 66,7 66,11 @@ void ArgumentsType::stream_name(StyledSt
 
 const TupleType *ArgumentsType::to_tuple_type() const {
     assert(!values.empty());
-    return cast<TupleType>(tuple_type(values).assert_ok());
+    Types storage_types;
+    for (auto &&value : values) {
+        storage_types.push_back(qualified_storage_type(value).assert_ok());
+    }
+    return cast<TupleType>(tuple_type(storage_types).assert_ok());
 }
 
 ArgumentsType::ArgumentsType(const Types &_values) :

          
M src/type/typename_type.cpp +2 -18
@@ 10,6 10,8 @@ 
 #include "pointer_type.hpp"
 #include "arguments_type.hpp"
 #include "qualify_type.hpp"
+#include "../qualifiers.hpp"
+#include "../qualifier.inc"
 #include "../dyn_cast.inc"
 
 namespace scopes {

          
@@ 111,23 113,5 @@ SCOPES_RESULT(const TypenameType *) uniq
     return TT;
 }
 
-SCOPES_RESULT(const Type *) storage_type(const Type *T) {
-    SCOPES_RESULT_TYPE(const Type *);
-    T = strip_qualifiers(T);
-    switch(T->kind()) {
-    case TK_Typename: {
-        const TypenameType *tt = cast<TypenameType>(T);
-        if (!tt->is_complete()) {
-            SCOPES_ERROR(TypenameIncomplete, T);
-        }
-        if (tt->is_opaque()) {
-            SCOPES_ERROR(OpaqueType, T);
-        }
-        return tt->storage();
-    } break;
-    default: return T;
-    }
-}
-
 
 } // namespace scopes

          
M src/type/typename_type.hpp +0 -2
@@ 57,8 57,6 @@ const TypenameType *opaque_typename_type
 SCOPES_RESULT(const TypenameType *) plain_typename_type(const String *name, const Type *supertype, const Type *storage_type);
 SCOPES_RESULT(const TypenameType *) unique_typename_type(const String *name, const Type *supertype, const Type *storage_type);
 
-SCOPES_RESULT(const Type *) storage_type(const Type *T);
-
 } // namespace scopes
 
 #endif // SCOPES_TYPENAME_HPP
  No newline at end of file

          
M testing/test_abi.sc +38 -0
@@ 122,3 122,41 @@ do
     test (s.vertexCount == s2.vertexCount)
     test (s.triangleCount == s2.triangleCount)
     test (s.vertices == s2.vertices)
+
+do
+    let AB =
+        do
+            using import struct
+
+            struct AB plain
+                a : i32
+                b : i32
+                c : i32
+
+    fn mrv1 ()
+        let sptr = (malloc AB)
+        sptr.a = 1
+        sptr.b = 2
+        sptr.c = 3
+        # wrong ABI when references are being returned, produces crash
+        _ sptr.a sptr.b sptr.c
+
+    fn mrv2 ()
+        let sptr = (malloc-array i32 3)
+        sptr @ 0 = 1
+        sptr @ 1 = 2
+        sptr @ 2 = 3
+        # wrong ABI when references are being returned, produces crash
+        _ (sptr @ 0) (sptr @ 1) (sptr @ 2)
+
+    #compile
+        static-typify mrv1
+        'dump-function
+
+    let a b c = (mrv1)
+    print a b c
+
+    let a b c = (mrv2)
+    print a b c
+
+