aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_expr.cpp
diff options
context:
space:
mode:
authorRilleP <rikkypikki@hotmail.com>2024-04-10 19:10:33 +0200
committerGitHub <noreply@github.com>2024-04-10 19:10:33 +0200
commit95a38d5a96322cd9adbb03bd5b7425b93469e62f (patch)
tree8cdc3b962506ddc4b7b1883f0e2ecb9dce54e2f9 /src/llvm_backend_expr.cpp
parent239d4e10762a12e96280bd91003acbf2170cadf2 (diff)
parent13e459980b0143b49762cdfd04dd5cf1bbf83daa (diff)
Merge branch 'master' into parsing-package-fixes
Diffstat (limited to 'src/llvm_backend_expr.cpp')
-rw-r--r--src/llvm_backend_expr.cpp243
1 files changed, 176 insertions, 67 deletions
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index 4675e203b..fcec59968 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -684,12 +684,6 @@ gb_internal lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type
Type *mt = base_type(m.type);
GB_ASSERT(mt->kind == Type_Matrix);
- // TODO(bill): Determine why this fails on Windows sometimes
- if (false && lb_is_matrix_simdable(mt)) {
- LLVMValueRef vector = lb_matrix_to_trimmed_vector(p, m);
- return lb_matrix_cast_vector_to_type(p, vector, type);
- }
-
lbAddr res = lb_add_local_generated(p, type, true);
i64 row_count = mt->Matrix.row_count;
@@ -763,6 +757,7 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs,
GB_ASSERT(is_type_matrix(yt));
GB_ASSERT(xt->Matrix.column_count == yt->Matrix.row_count);
GB_ASSERT(are_types_identical(xt->Matrix.elem, yt->Matrix.elem));
+ GB_ASSERT(xt->Matrix.is_row_major == yt->Matrix.is_row_major);
Type *elem = xt->Matrix.elem;
@@ -770,7 +765,7 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs,
unsigned inner = cast(unsigned)xt->Matrix.column_count;
unsigned outer_columns = cast(unsigned)yt->Matrix.column_count;
- if (lb_is_matrix_simdable(xt)) {
+ if (!xt->Matrix.is_row_major && lb_is_matrix_simdable(xt)) {
unsigned x_stride = cast(unsigned)matrix_type_stride_in_elems(xt);
unsigned y_stride = cast(unsigned)matrix_type_stride_in_elems(yt);
@@ -812,7 +807,7 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs,
return lb_addr_load(p, res);
}
- {
+ if (!xt->Matrix.is_row_major) {
lbAddr res = lb_add_local_generated(p, type, true);
auto inners = slice_make<lbValue[2]>(permanent_allocator(), inner);
@@ -836,6 +831,30 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs,
}
return lb_addr_load(p, res);
+ } else {
+ lbAddr res = lb_add_local_generated(p, type, true);
+
+ auto inners = slice_make<lbValue[2]>(permanent_allocator(), inner);
+
+ for (unsigned i = 0; i < outer_rows; i++) {
+ for (unsigned j = 0; j < outer_columns; j++) {
+ lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j);
+ for (unsigned k = 0; k < inner; k++) {
+ inners[k][0] = lb_emit_matrix_ev(p, lhs, i, k);
+ inners[k][1] = lb_emit_matrix_ev(p, rhs, k, j);
+ }
+
+ lbValue sum = lb_const_nil(p->module, elem);
+ for (unsigned k = 0; k < inner; k++) {
+ lbValue a = inners[k][0];
+ lbValue b = inners[k][1];
+ sum = lb_emit_mul_add(p, a, b, sum, elem);
+ }
+ lb_emit_store(p, dst, sum);
+ }
+ }
+
+ return lb_addr_load(p, res);
}
}
@@ -855,7 +874,7 @@ gb_internal lbValue lb_emit_matrix_mul_vector(lbProcedure *p, lbValue lhs, lbVal
Type *elem = mt->Matrix.elem;
- if (lb_is_matrix_simdable(mt)) {
+ if (!mt->Matrix.is_row_major && lb_is_matrix_simdable(mt)) {
unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt);
unsigned row_count = cast(unsigned)mt->Matrix.row_count;
@@ -924,7 +943,7 @@ gb_internal lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbVal
Type *elem = mt->Matrix.elem;
- if (lb_is_matrix_simdable(mt)) {
+ if (!mt->Matrix.is_row_major && lb_is_matrix_simdable(mt)) {
unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt);
unsigned row_count = cast(unsigned)mt->Matrix.row_count;
@@ -1354,6 +1373,57 @@ gb_internal bool lb_is_empty_string_constant(Ast *expr) {
return false;
}
+gb_internal lbValue lb_build_binary_in(lbProcedure *p, lbValue left, lbValue right, TokenKind op) {
+ Type *rt = base_type(right.type);
+ if (is_type_pointer(rt)) {
+ right = lb_emit_load(p, right);
+ rt = base_type(type_deref(rt));
+ }
+
+ switch (rt->kind) {
+ case Type_Map:
+ {
+ lbValue map_ptr = lb_address_from_load_or_generate_local(p, right);
+ lbValue key = left;
+ lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map_ptr, key);
+ if (op == Token_in) {
+ return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool);
+ } else {
+ return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_CmpEq, ptr), t_bool);
+ }
+ }
+ break;
+ case Type_BitSet:
+ {
+ Type *key_type = rt->BitSet.elem;
+ GB_ASSERT(are_types_identical(left.type, key_type));
+
+ Type *it = bit_set_to_int(rt);
+ left = lb_emit_conv(p, left, it);
+ if (is_type_different_to_arch_endianness(it)) {
+ left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it));
+ }
+
+ lbValue lower = lb_const_value(p->module, left.type, exact_value_i64(rt->BitSet.lower));
+ lbValue key = lb_emit_arith(p, Token_Sub, left, lower, left.type);
+ lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, left.type, 1), key, left.type);
+ bit = lb_emit_conv(p, bit, it);
+
+ lbValue old_value = lb_emit_transmute(p, right, it);
+ lbValue new_value = lb_emit_arith(p, Token_And, old_value, bit, it);
+
+ if (op == Token_in) {
+ return lb_emit_conv(p, lb_emit_comp(p, Token_NotEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool);
+ } else {
+ return lb_emit_conv(p, lb_emit_comp(p, Token_CmpEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool);
+ }
+ }
+ break;
+ }
+ GB_PANIC("Invalid 'in' type");
+ return {};
+}
+
gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
ast_node(be, BinaryExpr, expr);
@@ -1461,57 +1531,8 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
{
lbValue left = lb_build_expr(p, be->left);
lbValue right = lb_build_expr(p, be->right);
- Type *rt = base_type(right.type);
- if (is_type_pointer(rt)) {
- right = lb_emit_load(p, right);
- rt = base_type(type_deref(rt));
- }
-
- switch (rt->kind) {
- case Type_Map:
- {
- lbValue map_ptr = lb_address_from_load_or_generate_local(p, right);
- lbValue key = left;
- lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map_ptr, key);
- if (be->op.kind == Token_in) {
- return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool);
- } else {
- return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_CmpEq, ptr), t_bool);
- }
- }
- break;
- case Type_BitSet:
- {
- Type *key_type = rt->BitSet.elem;
- GB_ASSERT(are_types_identical(left.type, key_type));
-
- Type *it = bit_set_to_int(rt);
- left = lb_emit_conv(p, left, it);
- if (is_type_different_to_arch_endianness(it)) {
- left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it));
- }
-
- lbValue lower = lb_const_value(p->module, left.type, exact_value_i64(rt->BitSet.lower));
- lbValue key = lb_emit_arith(p, Token_Sub, left, lower, left.type);
- lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, left.type, 1), key, left.type);
- bit = lb_emit_conv(p, bit, it);
-
- lbValue old_value = lb_emit_transmute(p, right, it);
- lbValue new_value = lb_emit_arith(p, Token_And, old_value, bit, it);
-
- if (be->op.kind == Token_in) {
- return lb_emit_conv(p, lb_emit_comp(p, Token_NotEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool);
- } else {
- return lb_emit_conv(p, lb_emit_comp(p, Token_CmpEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool);
- }
- }
- break;
- default:
- GB_PANIC("Invalid 'in' type");
- }
- break;
+ return lb_build_binary_in(p, left, right, be->op.kind);
}
- break;
default:
GB_PANIC("Invalid binary expression");
break;
@@ -1946,6 +1967,24 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
}
}
+ // bit_field <-> backing type
+ if (is_type_bit_field(src)) {
+ if (are_types_identical(src->BitField.backing_type, dst)) {
+ lbValue res = {};
+ res.type = t;
+ res.value = value.value;
+ return res;
+ }
+ }
+ if (is_type_bit_field(dst)) {
+ if (are_types_identical(src, dst->BitField.backing_type)) {
+ lbValue res = {};
+ res.type = t;
+ res.value = value.value;
+ return res;
+ }
+ }
+
// Pointer <-> uintptr
if (is_type_pointer(src) && is_type_uintptr(dst)) {
@@ -3657,7 +3696,7 @@ gb_internal void lb_build_addr_compound_lit_populate(lbProcedure *p, Slice<Ast *
Ast *elem = elems[i];
if (elem->kind == Ast_FieldValue) {
ast_node(fv, FieldValue, elem);
- if (lb_is_elem_const(fv->value, et)) {
+ if (bt->kind != Type_DynamicArray && lb_is_elem_const(fv->value, et)) {
continue;
}
if (is_ast_range(fv->field)) {
@@ -3953,12 +3992,21 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) {
}
lbValue index = lb_build_expr(p, ie->index);
index = lb_emit_conv(p, index, t_int);
- lbValue elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index);
+
+ isize bounds_len = 0;
+ lbValue elem = {};
+ if (t->Matrix.is_row_major) {
+ bounds_len = t->Matrix.row_count;
+ elem = lb_emit_matrix_ep(p, matrix, index, lb_const_int(p->module, t_int, 0));
+ } else {
+ bounds_len = t->Matrix.column_count;
+ elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index);
+ }
elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr)));
auto index_tv = type_and_value_of_expr(ie->index);
if (index_tv.mode != Addressing_Constant) {
- lbValue len = lb_const_int(p->module, t_int, t->Matrix.column_count);
+ lbValue len = lb_const_int(p->module, t_int, bounds_len);
lb_emit_bounds_check(p, ast_token(ie->index), index, len);
}
return lb_addr(elem);
@@ -4217,6 +4265,38 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
switch (bt->kind) {
default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
+ case Type_BitField:
+ for (Ast *elem : cl->elems) {
+ ast_node(fv, FieldValue, elem);
+ String name = fv->field->Ident.token.string;
+ Selection sel = lookup_field(bt, name, false);
+ GB_ASSERT(sel.is_bit_field);
+ GB_ASSERT(!sel.indirect);
+ GB_ASSERT(sel.index.count == 1);
+ GB_ASSERT(sel.entity != nullptr);
+
+ i64 index = sel.index[0];
+ i64 bit_offset = 0;
+ i64 bit_size = -1;
+ for_array(i, bt->BitField.fields) {
+ Entity *f = bt->BitField.fields[i];
+ if (f == sel.entity) {
+ bit_offset = bt->BitField.bit_offsets[i];
+ bit_size = bt->BitField.bit_sizes[i];
+ break;
+ }
+ }
+ GB_ASSERT(bit_size > 0);
+
+ Type *field_type = sel.entity->type;
+ lbValue field_expr = lb_build_expr(p, fv->value);
+ field_expr = lb_emit_conv(p, field_expr, field_type);
+
+ lbAddr field_addr = lb_addr_bit_field(v.addr, field_type, index, bit_offset, bit_size);
+ lb_addr_store(p, field_addr, field_expr);
+ }
+ return v;
+
case Type_Struct: {
// TODO(bill): "constant" '#raw_union's are not initialized constantly at the moment.
// NOTE(bill): This is due to the layout of the unions when printed to LLVM-IR
@@ -4597,15 +4677,17 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
if (tav.mode == Addressing_Type) { // Addressing_Type
Selection sel = lookup_field(tav.type, selector, true);
if (sel.pseudo_field) {
- GB_ASSERT(sel.entity->kind == Entity_Procedure);
- return lb_addr(lb_find_value_from_entity(p->module, sel.entity));
+ GB_ASSERT(sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup);
+ Entity *e = entity_of_node(sel_node);
+ GB_ASSERT(e->kind == Entity_Procedure);
+ return lb_addr(lb_find_value_from_entity(p->module, e));
}
GB_PANIC("Unreachable %.*s", LIT(selector));
}
if (se->swizzle_count > 0) {
Type *array_type = base_type(type_deref(tav.type));
- GB_ASSERT(array_type->kind == Type_Array);
+ GB_ASSERT(array_type->kind == Type_Array || array_type->kind == Type_SimdVector);
u8 swizzle_count = se->swizzle_count;
u8 swizzle_indices_raw = se->swizzle_indices;
u8 swizzle_indices[4] = {};
@@ -4621,7 +4703,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
a = lb_addr_get_ptr(p, addr);
}
- GB_ASSERT(is_type_array(expr->tav.type));
+ GB_ASSERT(is_type_array(expr->tav.type) || is_type_simd_vector(expr->tav.type));
return lb_addr_swizzle(a, expr->tav.type, swizzle_count, swizzle_indices);
}
@@ -4634,6 +4716,33 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
return lb_addr(lb_find_value_from_entity(p->module, e));
}
+ if (sel.is_bit_field) {
+ lbAddr addr = lb_build_addr(p, se->expr);
+
+ Selection sub_sel = sel;
+ sub_sel.index.count -= 1;
+
+ lbValue ptr = lb_addr_get_ptr(p, addr);
+ if (sub_sel.index.count > 0) {
+ ptr = lb_emit_deep_field_gep(p, ptr, sub_sel);
+ }
+ if (is_type_pointer(type_deref(ptr.type))) {
+ ptr = lb_emit_load(p, ptr);
+ }
+
+ Type *bf_type = type_deref(ptr.type);
+ bf_type = base_type(bf_type);
+ GB_ASSERT(bf_type->kind == Type_BitField);
+
+ i32 index = sel.index[sel.index.count-1];
+
+ Entity *f = bf_type->BitField.fields[index];
+ u8 bit_size = bf_type->BitField.bit_sizes[index];
+ i64 bit_offset = bf_type->BitField.bit_offsets[index];
+
+ return lb_addr_bit_field(ptr, f->type, index, bit_offset, bit_size);
+ }
+
{
lbAddr addr = lb_build_addr(p, se->expr);
if (addr.kind == lbAddr_Map) {