[goalc] add support for non-static inline arrays of values

This commit is contained in:
ManDude 2022-08-13 15:39:56 +01:00
parent 8a13da3b59
commit 70f608cefd
4 changed files with 21 additions and 15 deletions

View File

@ -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<StructureType*>(result_type);
if (!result_structure_type || result_structure_type->is_dynamic()) {
if (auto result_structure_type = dynamic_cast<StructureType*>(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();

View File

@ -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;

View File

@ -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<StaticStructure>(seg);
obj->set_offset(is_basic(content_type) ? 4 : 0);
obj->data.resize(length * deref_info.stride);

View File

@ -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.