diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index d9e8d2a1b..6b136765c 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -279,6 +279,7 @@ std::string TypeSystem::get_runtime_type(const TypeSpec& ts) { */ DerefInfo TypeSystem::get_deref_info(const TypeSpec& ts) const { DerefInfo info; + info.is_struct = true; if (!ts.has_single_arg()) { // not enough info. @@ -296,26 +297,23 @@ DerefInfo TypeSystem::get_deref_info(const TypeSpec& ts) const { if (ts.base_type() == "inline-array") { auto result_type = lookup_type(ts.get_single_arg()); - auto result_structure_type = dynamic_cast(result_type); - if (!result_structure_type || result_structure_type->is_dynamic()) { + if (auto result_structure_type = dynamic_cast(result_type); + result_structure_type && result_structure_type->is_dynamic()) { info.can_deref = false; return info; } - // it's an inline array of structures. We can "dereference". But really we don't do a memory + // it's an inline array of something. We can "dereference". But really we don't do a memory // dereference, we just add stride*idx to the pointer. info.can_deref = true; // deref operators should work... info.mem_deref = false; // but don't actually dereference a pointer info.result_type = ts.get_single_arg(); // what we're an inline-array of - info.sign_extend = false; // not applicable anyway + info.sign_extend = + result_type->get_load_signed(); // should the load be sign extended? false for refs. + info.is_struct = result_type->is_reference(); // is the underlying type a value or a reference? - if (result_type->is_reference()) { - info.stride = align(result_type->get_size_in_memory(), - result_type->get_inline_array_stride_alignment()); - } else { - // can't have an inline array of value types! - ASSERT(false); - } + info.stride = + align(result_type->get_size_in_memory(), result_type->get_inline_array_stride_alignment()); } else if (ts.base_type() == "pointer") { info.can_deref = true; info.result_type = ts.get_single_arg(); diff --git a/common/type_system/TypeSystem.h b/common/type_system/TypeSystem.h index 054a06548..beb3e0ced 100644 --- a/common/type_system/TypeSystem.h +++ b/common/type_system/TypeSystem.h @@ -48,6 +48,7 @@ struct DerefInfo { bool can_deref = false; bool mem_deref = false; bool sign_extend = false; + bool is_struct; RegClass reg = RegClass::INVALID; int stride = -1; int load_size = -1; diff --git a/goalc/compiler/compilation/Static.cpp b/goalc/compiler/compilation/Static.cpp index 019567c72..9e415d17d 100644 --- a/goalc/compiler/compilation/Static.cpp +++ b/goalc/compiler/compilation/Static.cpp @@ -1060,9 +1060,11 @@ StaticResult Compiler::fill_static_inline_array(const goos::Object& form, auto inline_array_type = m_ts.make_inline_array_typespec(content_type); auto deref_info = m_ts.get_deref_info(inline_array_type); - if (!deref_info.can_deref || deref_info.mem_deref) { + if (!deref_info.is_struct) { throw_compiler_error(form, "new static inline array of value types is currently not supported"); } + ASSERT(deref_info.can_deref); + ASSERT(!deref_info.mem_deref); auto obj = std::make_unique(seg); obj->set_offset(is_basic(content_type) ? 4 : 0); obj->data.resize(length * deref_info.stride); diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index 30b438a04..54cb10dee 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -1003,9 +1003,14 @@ Val* Compiler::compile_heap_new(const goos::Object& form, args.push_back(array_size); } - auto array = compile_real_function_call(form, malloc_func, args, env); - array->set_type(ts); - return array; + auto new_array = compile_real_function_call(form, malloc_func, args, env); + if (info.is_struct) { + new_array->set_type(ts); + } else { + // allocs of value types are exactly the same as a pointer deref + new_array->set_type(TypeSpec("pointer", {ts.get_single_arg()})); + } + return new_array; } else { bool got_content_type = false; // for boxed array std::string content_type; // for boxed array.