aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_expr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm_backend_expr.cpp')
-rw-r--r--src/llvm_backend_expr.cpp186
1 files changed, 124 insertions, 62 deletions
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index edda3a267..133df4d41 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -508,7 +508,7 @@ bool lb_is_matrix_simdable(Type *t) {
case TargetArch_arm64:
// TODO(bill): determine when this is fine
return true;
- case TargetArch_386:
+ case TargetArch_i386:
case TargetArch_wasm32:
case TargetArch_wasm64:
return false;
@@ -580,6 +580,27 @@ LLVMValueRef lb_matrix_to_trimmed_vector(lbProcedure *p, lbValue m) {
lbValue lb_emit_matrix_tranpose(lbProcedure *p, lbValue m, Type *type) {
if (is_type_array(m.type)) {
+ i32 rank = type_math_rank(m.type);
+ if (rank == 2) {
+ lbAddr addr = lb_add_local_generated(p, type, false);
+ lbValue dst = addr.addr;
+ lbValue src = m;
+ i32 n = cast(i32)get_array_type_count(m.type);
+ i32 m = cast(i32)get_array_type_count(type);
+ // m.type == [n][m]T
+ // type == [m][n]T
+
+ for (i32 j = 0; j < m; j++) {
+ lbValue dst_col = lb_emit_struct_ep(p, dst, j);
+ for (i32 i = 0; i < n; i++) {
+ lbValue dst_row = lb_emit_struct_ep(p, dst_col, i);
+ lbValue src_col = lb_emit_struct_ev(p, src, i);
+ lbValue src_row = lb_emit_struct_ev(p, src_col, j);
+ lb_emit_store(p, dst_row, src_row);
+ }
+ }
+ return lb_addr_load(p, addr);
+ }
// no-op
m.type = type;
return m;
@@ -1655,26 +1676,10 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
return res;
}
- if (is_type_float(src) && is_type_complex(dst)) {
- Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, false);
- lbValue gp = lb_addr_get_ptr(p, gen);
- lbValue real = lb_emit_conv(p, value, ft);
- lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real);
- return lb_addr_load(p, gen);
- }
- if (is_type_float(src) && is_type_quaternion(dst)) {
- Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, false);
- lbValue gp = lb_addr_get_ptr(p, gen);
- lbValue real = lb_emit_conv(p, value, ft);
- lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real);
- return lb_addr_load(p, gen);
- }
if (is_type_complex(src) && is_type_complex(dst)) {
Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, false);
+ lbAddr gen = lb_add_local_generated(p, t, false);
lbValue gp = lb_addr_get_ptr(p, gen);
lbValue real = lb_emit_conv(p, lb_emit_struct_ev(p, value, 0), ft);
lbValue imag = lb_emit_conv(p, lb_emit_struct_ev(p, value, 1), ft);
@@ -1686,7 +1691,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
if (is_type_quaternion(src) && is_type_quaternion(dst)) {
// @QuaternionLayout
Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, false);
+ lbAddr gen = lb_add_local_generated(p, t, false);
lbValue gp = lb_addr_get_ptr(p, gen);
lbValue q0 = lb_emit_conv(p, lb_emit_struct_ev(p, value, 0), ft);
lbValue q1 = lb_emit_conv(p, lb_emit_struct_ev(p, value, 1), ft);
@@ -1701,7 +1706,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
if (is_type_integer(src) && is_type_complex(dst)) {
Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, true);
+ lbAddr gen = lb_add_local_generated(p, t, true);
lbValue gp = lb_addr_get_ptr(p, gen);
lbValue real = lb_emit_conv(p, value, ft);
lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real);
@@ -1709,7 +1714,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
}
if (is_type_float(src) && is_type_complex(dst)) {
Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, true);
+ lbAddr gen = lb_add_local_generated(p, t, true);
lbValue gp = lb_addr_get_ptr(p, gen);
lbValue real = lb_emit_conv(p, value, ft);
lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real);
@@ -1719,7 +1724,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
if (is_type_integer(src) && is_type_quaternion(dst)) {
Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, true);
+ lbAddr gen = lb_add_local_generated(p, t, true);
lbValue gp = lb_addr_get_ptr(p, gen);
lbValue real = lb_emit_conv(p, value, ft);
// @QuaternionLayout
@@ -1728,7 +1733,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
}
if (is_type_float(src) && is_type_quaternion(dst)) {
Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, true);
+ lbAddr gen = lb_add_local_generated(p, t, true);
lbValue gp = lb_addr_get_ptr(p, gen);
lbValue real = lb_emit_conv(p, value, ft);
// @QuaternionLayout
@@ -1737,7 +1742,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
}
if (is_type_complex(src) && is_type_quaternion(dst)) {
Type *ft = base_complex_elem_type(dst);
- lbAddr gen = lb_add_local_generated(p, dst, true);
+ lbAddr gen = lb_add_local_generated(p, t, true);
lbValue gp = lb_addr_get_ptr(p, gen);
lbValue real = lb_emit_conv(p, lb_emit_struct_ev(p, value, 0), ft);
lbValue imag = lb_emit_conv(p, lb_emit_struct_ev(p, value, 1), ft);
@@ -1850,6 +1855,15 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
return lb_addr_load(p, parent);
}
}
+ if (dst->Union.variants.count == 1) {
+ Type *vt = dst->Union.variants[0];
+ if (internal_check_is_assignable_to(src, vt)) {
+ value = lb_emit_conv(p, value, vt);
+ lbAddr parent = lb_add_local_generated(p, t, true);
+ lb_emit_store_union_variant(p, parent.addr, value, vt);
+ return lb_addr_load(p, parent);
+ }
+ }
}
// NOTE(bill): This has to be done before 'Pointer <-> Pointer' as it's
@@ -2188,6 +2202,21 @@ lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue ri
}
}
+ if (is_type_matrix(a) && (op_kind == Token_CmpEq || op_kind == Token_NotEq)) {
+ Type *tl = base_type(a);
+ lbValue lhs = lb_address_from_load_or_generate_local(p, left);
+ lbValue rhs = lb_address_from_load_or_generate_local(p, right);
+
+
+ // TODO(bill): Test to see if this is actually faster!!!!
+ auto args = array_make<lbValue>(permanent_allocator(), 3);
+ args[0] = lb_emit_conv(p, lhs, t_rawptr);
+ args[1] = lb_emit_conv(p, rhs, t_rawptr);
+ args[2] = lb_const_int(p->module, t_int, type_size_of(tl));
+ lbValue val = lb_emit_runtime_call(p, "memory_compare", args);
+ lbValue res = lb_emit_comp(p, op_kind, val, lb_const_nil(p->module, val.type));
+ return lb_emit_conv(p, res, t_bool);
+ }
if (is_type_array(a) || is_type_enumerated_array(a)) {
Type *tl = base_type(a);
lbValue lhs = lb_address_from_load_or_generate_local(p, left);
@@ -2784,27 +2813,38 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
Type *src_type = type_deref(v.type);
Type *dst_type = type;
- lbValue src_tag = {};
- lbValue dst_tag = {};
- if (is_type_union_maybe_pointer(src_type)) {
- src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v);
- dst_tag = lb_const_bool(p->module, t_bool, true);
- } else {
- src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v));
- dst_tag = lb_const_union_tag(p->module, src_type, dst_type);
- }
- lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag);
- auto args = array_make<lbValue>(permanent_allocator(), 6);
- args[0] = ok;
+ if ((p->state_flags & StateFlag_no_type_assert) == 0) {
+ lbValue src_tag = {};
+ lbValue dst_tag = {};
+ if (is_type_union_maybe_pointer(src_type)) {
+ src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v);
+ dst_tag = lb_const_bool(p->module, t_bool, true);
+ } else {
+ src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v));
+ dst_tag = lb_const_union_tag(p->module, src_type, dst_type);
+ }
+
- args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
- args[2] = lb_const_int(p->module, t_i32, pos.line);
- args[3] = lb_const_int(p->module, t_i32, pos.column);
+ isize arg_count = 6;
+ if (build_context.disallow_rtti) {
+ arg_count = 4;
+ }
+
+ lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag);
+ auto args = array_make<lbValue>(permanent_allocator(), arg_count);
+ args[0] = ok;
- args[4] = lb_typeid(p->module, src_type);
- args[5] = lb_typeid(p->module, dst_type);
- lb_emit_runtime_call(p, "type_assertion_check", args);
+ args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
+ args[2] = lb_const_int(p->module, t_i32, pos.line);
+ args[3] = lb_const_int(p->module, t_i32, pos.column);
+
+ if (!build_context.disallow_rtti) {
+ args[4] = lb_typeid(p->module, src_type);
+ args[5] = lb_typeid(p->module, dst_type);
+ }
+ lb_emit_runtime_call(p, "type_assertion_check", args);
+ }
lbValue data_ptr = v;
return lb_emit_conv(p, data_ptr, tv.type);
@@ -2813,23 +2853,25 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
if (is_type_pointer(v.type)) {
v = lb_emit_load(p, v);
}
-
lbValue data_ptr = lb_emit_struct_ev(p, v, 0);
- lbValue any_id = lb_emit_struct_ev(p, v, 1);
- lbValue id = lb_typeid(p->module, type);
+ if ((p->state_flags & StateFlag_no_type_assert) == 0) {
+ GB_ASSERT(!build_context.disallow_rtti);
+ lbValue any_id = lb_emit_struct_ev(p, v, 1);
- lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id);
- auto args = array_make<lbValue>(permanent_allocator(), 6);
- args[0] = ok;
+ lbValue id = lb_typeid(p->module, type);
+ lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id);
+ auto args = array_make<lbValue>(permanent_allocator(), 6);
+ args[0] = ok;
- args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
- args[2] = lb_const_int(p->module, t_i32, pos.line);
- args[3] = lb_const_int(p->module, t_i32, pos.column);
+ args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
+ args[2] = lb_const_int(p->module, t_i32, pos.line);
+ args[3] = lb_const_int(p->module, t_i32, pos.column);
- args[4] = any_id;
- args[5] = id;
- lb_emit_runtime_call(p, "type_assertion_check", args);
+ args[4] = any_id;
+ args[5] = id;
+ lb_emit_runtime_call(p, "type_assertion_check", args);
+ }
return lb_emit_conv(p, data_ptr, tv.type);
} else {
@@ -2859,6 +2901,14 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
out &= ~StateFlag_bounds_check;
}
+ if (in & StateFlag_type_assert) {
+ out |= StateFlag_type_assert;
+ out &= ~StateFlag_no_type_assert;
+ } else if (in & StateFlag_no_type_assert) {
+ out |= StateFlag_no_type_assert;
+ out &= ~StateFlag_type_assert;
+ }
+
p->state_flags = out;
}
@@ -2978,7 +3028,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
lbBlock *done = lb_create_block(p, "if.done"); // NOTE(bill): Append later
lbBlock *else_ = lb_create_block(p, "if.else");
- lbValue cond = lb_build_cond(p, te->cond, then, else_);
+ lb_build_cond(p, te->cond, then, else_);
lb_start_block(p, then);
Type *type = default_type(type_of_expr(expr));
@@ -3279,9 +3329,9 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
case_end;
case_ast_node(se, SelectorExpr, expr);
- Ast *sel = unparen_expr(se->selector);
- if (sel->kind == Ast_Ident) {
- String selector = sel->Ident.token.string;
+ Ast *sel_node = unparen_expr(se->selector);
+ if (sel_node->kind == Ast_Ident) {
+ String selector = sel_node->Ident.token.string;
TypeAndValue tav = type_and_value_of_expr(se->expr);
if (tav.mode == Addressing_Invalid) {
@@ -3296,7 +3346,12 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
Type *type = base_type(tav.type);
if (tav.mode == Addressing_Type) { // Addressing_Type
- GB_PANIC("Unreachable");
+ 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_PANIC("Unreachable %.*s", LIT(selector));
}
if (se->swizzle_count > 0) {
@@ -3323,6 +3378,11 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
Selection sel = lookup_field(type, selector, false);
GB_ASSERT(sel.entity != nullptr);
+ if (sel.pseudo_field) {
+ GB_ASSERT(sel.entity->kind == Entity_Procedure);
+ Entity *e = entity_of_node(sel_node);
+ return lb_addr(lb_find_value_from_entity(p->module, e));
+ }
{
lbAddr addr = lb_build_addr(p, se->expr);
@@ -3476,7 +3536,8 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
GB_ASSERT_MSG(is_type_indexable(t), "%s %s", type_to_string(t), expr_to_string(expr));
if (is_type_map(t)) {
- lbValue map_val = lb_build_addr_ptr(p, ie->expr);
+ lbAddr map_addr = lb_build_addr(p, ie->expr);
+ lbValue map_val = lb_addr_load(p, map_addr);
if (deref) {
map_val = lb_emit_load(p, map_val);
}
@@ -3485,7 +3546,8 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
key = lb_emit_conv(p, key, t->Map.key);
Type *result_type = type_of_expr(expr);
- return lb_addr_map(map_val, key, t, result_type);
+ lbValue map_ptr = lb_address_from_load_or_generate_local(p, map_val);
+ return lb_addr_map(map_ptr, key, t, result_type);
}
switch (t->kind) {
@@ -4584,7 +4646,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
lbBlock *done = lb_create_block(p, "if.done"); // NOTE(bill): Append later
lbBlock *else_ = lb_create_block(p, "if.else");
- lbValue cond = lb_build_cond(p, te->cond, then, else_);
+ lb_build_cond(p, te->cond, then, else_);
lb_start_block(p, then);
Type *ptr_type = alloc_type_pointer(default_type(type_of_expr(expr)));