diff options
Diffstat (limited to 'src/llvm_backend_const.cpp')
| -rw-r--r-- | src/llvm_backend_const.cpp | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 4cfcecdc3..413fb365b 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -523,14 +523,11 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc lbValue single_elem = lb_const_value(m, elem, value, allow_local); single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem)); - - i64 stride_bytes = matrix_type_stride(type); - i64 stride_elems = stride_bytes/type_size_of(elem); - + i64 total_elem_count = matrix_type_total_elems(type); LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)total_elem_count); for (i64 i = 0; i < row; i++) { - elems[i*stride_elems + i] = single_elem.value; + elems[matrix_index_to_offset(type, i)] = single_elem.value; } for (i64 i = 0; i < total_elem_count; i++) { if (elems[i] == nullptr) { @@ -984,6 +981,82 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc res.value = LLVMConstInt(lb_type(m, original_type), bits, false); return res; + } else if (is_type_matrix(type)) { + ast_node(cl, CompoundLit, value.value_compound); + Type *elem_type = type->Matrix.elem; + isize elem_count = cl->elems.count; + if (elem_count == 0 || !elem_type_can_be_constant(elem_type)) { + return lb_const_nil(m, original_type); + } + + i64 max_count = type->Matrix.row_count*type->Matrix.column_count; + i64 total_count = matrix_type_total_elems(type); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)total_count); + if (cl->elems[0]->kind == Ast_FieldValue) { + for_array(j, cl->elems) { + Ast *elem = cl->elems[j]; + ast_node(fv, FieldValue, elem); + if (is_ast_range(fv->field)) { + ast_node(ie, BinaryExpr, fv->field); + TypeAndValue lo_tav = ie->left->tav; + TypeAndValue hi_tav = ie->right->tav; + GB_ASSERT(lo_tav.mode == Addressing_Constant); + GB_ASSERT(hi_tav.mode == Addressing_Constant); + + TokenKind op = ie->op.kind; + i64 lo = exact_value_to_i64(lo_tav.value); + i64 hi = exact_value_to_i64(hi_tav.value); + if (op != Token_RangeHalf) { + hi += 1; + } + TypeAndValue tav = fv->value->tav; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, allow_local).value; + for (i64 k = lo; k < hi; k++) { + i64 offset = matrix_index_to_offset(type, k); + GB_ASSERT(values[offset] == nullptr); + values[offset] = val; + } + } else { + TypeAndValue index_tav = fv->field->tav; + GB_ASSERT(index_tav.mode == Addressing_Constant); + i64 index = exact_value_to_i64(index_tav.value); + TypeAndValue tav = fv->value->tav; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, allow_local).value; + i64 offset = matrix_index_to_offset(type, index); + GB_ASSERT(values[offset] == nullptr); + values[offset] = val; + } + } + + for (i64 i = 0; i < total_count; i++) { + if (values[i] == nullptr) { + values[i] = LLVMConstNull(lb_type(m, elem_type)); + } + } + + res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)total_count, values, allow_local); + return res; + } else { + GB_ASSERT_MSG(elem_count == max_count, "%td != %td", elem_count, max_count); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)total_count); + + for_array(i, cl->elems) { + TypeAndValue tav = cl->elems[i]->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + i64 offset = matrix_index_to_offset(type, i); + values[offset] = lb_const_value(m, elem_type, tav.value, allow_local).value; + } + for (isize i = 0; i < total_count; i++) { + if (values[i] == nullptr) { + values[i] = LLVMConstNull(lb_type(m, elem_type)); + } + } + + res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)total_count, values, allow_local); + return res; + } } else { return lb_const_nil(m, original_type); } |