From 1fc256dd9076e1c44f1c67fd530840daa120a334 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 21 Feb 2024 19:42:34 +0100 Subject: Fix divergent proc call in `defer` Fixes #3216 Fixes #2985 --- src/llvm_backend_stmt.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/llvm_backend_stmt.cpp') diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 002fef881..388b512b2 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1843,7 +1843,11 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) { lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); - LLVMBuildRetVoid(p->builder); + // Check for terminator in the defer stmts + LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block); + if (!lb_is_instr_terminating(instr)) { + LLVMBuildRetVoid(p->builder); + } } else { LLVMValueRef ret_val = res.value; LLVMTypeRef ret_type = p->abi_function_type->ret.type; @@ -1868,7 +1872,12 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) { } lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); - LLVMBuildRet(p->builder, ret_val); + + // Check for terminator in the defer stmts + LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block); + if (!lb_is_instr_terminating(instr)) { + LLVMBuildRet(p->builder, ret_val); + } } } gb_internal void lb_build_return_stmt(lbProcedure *p, Slice const &return_results) { @@ -1887,8 +1896,12 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice const &return // No return values lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); - - LLVMBuildRetVoid(p->builder); + + // Check for terminator in the defer stmts + LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block); + if (!lb_is_instr_terminating(instr)) { + LLVMBuildRetVoid(p->builder); + } return; } else if (return_count == 1) { Entity *e = tuple->variables[0]; -- cgit v1.2.3 From 5107bdc06b7c1c8d02caef3e270e904218d82911 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 27 Feb 2024 15:45:53 +0000 Subject: Make `lb_type_info` use a procedure to load the global value --- src/llvm_backend.cpp | 2 +- src/llvm_backend.hpp | 2 +- src/llvm_backend_proc.cpp | 2 +- src/llvm_backend_stmt.cpp | 2 +- src/llvm_backend_type.cpp | 13 +++++-------- 5 files changed, 9 insertions(+), 12 deletions(-) (limited to 'src/llvm_backend_stmt.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a8d2df181..efba19f23 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1164,7 +1164,7 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc lbValue data = lb_emit_struct_ep(p, var.var, 0); lbValue ti = lb_emit_struct_ep(p, var.var, 1); lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr)); - lb_emit_store(p, ti, lb_type_info(main_module, var_type)); + lb_emit_store(p, ti, lb_type_info(p, var_type)); } else { LLVMTypeRef vt = llvm_addr_type(p->module, var.var); lbValue src0 = lb_emit_conv(p, var.init, t); diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 48e1c87c6..741557efd 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -485,7 +485,7 @@ gb_internal lbValue lb_emit_mul_add(lbProcedure *p, lbValue a, lbValue b, lbValu gb_internal void lb_fill_slice(lbProcedure *p, lbAddr const &slice, lbValue base_elem, lbValue len); -gb_internal lbValue lb_type_info(lbModule *m, Type *type); +gb_internal lbValue lb_type_info(lbProcedure *p, Type *type); gb_internal lbValue lb_find_or_add_entity_string(lbModule *m, String const &str); gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent = nullptr); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 9419f9a3c..13b0171e4 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1755,7 +1755,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu TypeAndValue tav = type_and_value_of_expr(arg); if (tav.mode == Addressing_Type) { Type *t = default_type(type_of_expr(arg)); - return lb_type_info(p->module, t); + return lb_type_info(p, t); } GB_ASSERT(is_type_typeid(tav.type)); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 388b512b2..0de9c0bf9 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -748,7 +748,7 @@ gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_ i64 enum_count = t->Enum.fields.count; lbValue max_count = lb_const_int(m, t_int, enum_count); - lbValue ti = lb_type_info(m, t); + lbValue ti = lb_type_info(p, t); lbValue variant = lb_emit_struct_ep(p, ti, 4); lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr); lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2)); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 881ac3119..aec1fb201 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -111,22 +111,19 @@ gb_internal lbValue lb_typeid(lbModule *m, Type *type) { return res; } -gb_internal lbValue lb_type_info(lbModule *m, Type *type) { +gb_internal lbValue lb_type_info(lbProcedure *p, Type *type) { GB_ASSERT(!build_context.no_rtti); type = default_type(type); + lbModule *m = p->module; isize index = lb_type_info_index(m->info, type); GB_ASSERT(index >= 0); - LLVMValueRef global = lb_global_type_info_data_ptr(m).value; + lbValue global = lb_global_type_info_data_ptr(m); - LLVMValueRef global_array = LLVMGetInitializer(global); - LLVMValueRef index_value = LLVMConstInt(lb_type(m, t_int), index, false); - lbValue res = {}; - res.value = LLVMConstPointerCast(LLVMConstExtractElement(global_array, index_value), lb_type(m, t_type_info_ptr)); - res.type = t_type_info_ptr; - return res; + lbValue ptr = lb_emit_array_epi(p, global, index); + return lb_emit_load(p, ptr); } gb_internal LLVMTypeRef lb_get_procedure_raw_type(lbModule *m, Type *type) { -- cgit v1.2.3 From effc71ca439a393d6d7ceeb3c433e0fcdc910ff1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 18 Mar 2024 12:20:53 +0000 Subject: Fix `case:` bug with by-ref unions --- src/llvm_backend.hpp | 2 +- src/llvm_backend_stmt.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/llvm_backend_stmt.cpp') diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 741557efd..6000be32d 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -508,7 +508,7 @@ gb_internal lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_pt gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e); gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e); -gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value); +gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case); gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValue value); gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos); gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String const &procedure, TokenPos const &pos); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 0de9c0bf9..4ecf70ec4 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1454,7 +1454,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * lb_close_scope(p, lbDeferExit_Default, done); } -gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value) { +gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case) { Entity *e = implicit_entity_of_node(clause); GB_ASSERT(e != nullptr); if (e->flags & EntityFlag_Value) { @@ -1463,8 +1463,9 @@ gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValu lbAddr x = lb_add_local(p, e->type, e, false); lb_addr_store(p, x, value); } else { - // by reference - GB_ASSERT(are_types_identical(e->type, type_deref(value.type))); + if (!is_default_case) { + GB_ASSERT_MSG(are_types_identical(e->type, type_deref(value.type)), "%s %s", type_to_string(e->type), type_to_string(value.type)); + } lb_add_entity(p->module, e, value); } } @@ -1622,7 +1623,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss lb_open_scope(p, cc->scope); if (cc->list.count == 0) { lb_start_block(p, default_block); - lb_store_type_case_implicit(p, clause, parent_value); + lb_store_type_case_implicit(p, clause, parent_value, true); lb_type_case_body(p, ss->label, clause, p->curr_block, done); continue; } @@ -1688,7 +1689,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss lb_add_entity(p->module, case_entity, ptr); lb_add_debug_local_variable(p, ptr.value, case_entity->type, case_entity->token); } else { - lb_store_type_case_implicit(p, clause, parent_value); + lb_store_type_case_implicit(p, clause, parent_value, false); } lb_type_case_body(p, ss->label, clause, body, done); -- cgit v1.2.3 From b862691d7524d5dc05d6c43872daa7a488c2411a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Apr 2024 13:08:07 +0100 Subject: Support `for in` with `bit_set` --- src/check_stmt.cpp | 13 ++++++ src/llvm_backend_expr.cpp | 102 +++++++++++++++++++++++----------------------- src/llvm_backend_stmt.cpp | 94 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 152 insertions(+), 57 deletions(-) (limited to 'src/llvm_backend_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 1d7e7d4e9..b25df01a6 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1554,6 +1554,19 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) } break; + case Type_BitSet: + array_add(&vals, t->BitSet.elem); + if (rs->vals.count > 1) { + error(rs->vals[1], "Expected 1 name when iterating over a bit_set, got %td", rs->vals.count); + } + if (rs->vals.count == 1 && + rs->vals[0]->kind == Ast_UnaryExpr && + rs->vals[0]->UnaryExpr.op.kind == Token_And) { + error(rs->vals[0], "When iteraing across a bit_set, you cannot modify the value with '&' as that does not make much sense"); + } + add_type_info_type(ctx, operand.type); + break; + case Type_EnumeratedArray: if (is_ptr) use_by_reference_for_value = true; array_add(&vals, t->EnumeratedArray.elem); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 12949f0ab..f6f36e861 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1373,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); @@ -1480,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; diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 4ecf70ec4..24dd321f6 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -737,6 +737,22 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, lb_start_block(p, done); } +gb_internal lbValue lb_enum_values_slice(lbProcedure *p, Type *enum_type, i64 *enum_count_) { + Type *t = enum_type; + GB_ASSERT(is_type_enum(t)); + t = base_type(t); + GB_ASSERT(t->kind == Type_Enum); + i64 enum_count = t->Enum.fields.count; + + if (enum_count_) *enum_count_ = enum_count; + + lbValue ti = lb_type_info(p, t); + lbValue variant = lb_emit_struct_ep(p, ti, 4); + lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr); + lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2)); + return values; +} + gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_type, lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) { lbModule *m = p->module; @@ -744,15 +760,11 @@ gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_ GB_ASSERT(is_type_enum(t)); t = base_type(t); Type *core_elem = core_type(t); - GB_ASSERT(t->kind == Type_Enum); - i64 enum_count = t->Enum.fields.count; - lbValue max_count = lb_const_int(m, t_int, enum_count); + i64 enum_count = 0; - lbValue ti = lb_type_info(p, t); - lbValue variant = lb_emit_struct_ep(p, ti, 4); - lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr); - lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2)); + lbValue values = lb_enum_values_slice(p, enum_type, &enum_count); lbValue values_data = lb_slice_elem(p, values); + lbValue max_count = lb_const_int(m, t_int, enum_count); lbAddr offset_ = lb_add_local_generated(p, t_int, false); lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); @@ -1052,6 +1064,74 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc case Type_Tuple: lb_build_range_tuple(p, expr, val0_type, val1_type, &val, &key, &loop, &done); break; + + case Type_BitSet: { + lbModule *m = p->module; + + lbValue the_set = lb_build_expr(p, expr); + if (is_type_pointer(type_deref(the_set.type))) { + the_set = lb_emit_load(p, the_set); + } + + Type *elem = et->BitSet.elem; + if (is_type_enum(elem)) { + i64 enum_count = 0; + lbValue values = lb_enum_values_slice(p, elem, &enum_count); + lbValue values_data = lb_slice_elem(p, values); + lbValue max_count = lb_const_int(m, t_int, enum_count); + + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); + + loop = lb_create_block(p, "for.bit_set.enum.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbBlock *body_check = lb_create_block(p, "for.bit_set.enum.body-check"); + lbBlock *body = lb_create_block(p, "for.bit_set.enum.body"); + done = lb_create_block(p, "for.bit_set.enum.done"); + + lbValue offset = lb_addr_load(p, offset_); + lbValue cond = lb_emit_comp(p, Token_Lt, offset, max_count); + lb_emit_if(p, cond, body_check, done); + lb_start_block(p, body_check); + + lbValue val_ptr = lb_emit_ptr_offset(p, values_data, offset); + lb_emit_increment(p, offset_.addr); + val = lb_emit_load(p, val_ptr); + val = lb_emit_conv(p, val, elem); + + lbValue check = lb_build_binary_in(p, val, the_set, Token_in); + lb_emit_if(p, check, body, loop); + lb_start_block(p, body); + } else { + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, offset_, lb_const_int(m, t_int, et->BitSet.lower)); + + lbValue max_count = lb_const_int(m, t_int, et->BitSet.upper); + + loop = lb_create_block(p, "for.bit_set.range.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbBlock *body_check = lb_create_block(p, "for.bit_set.range.body-check"); + lbBlock *body = lb_create_block(p, "for.bit_set.range.body"); + done = lb_create_block(p, "for.bit_set.range.done"); + + lbValue offset = lb_addr_load(p, offset_); + lbValue cond = lb_emit_comp(p, Token_LtEq, offset, max_count); + lb_emit_if(p, cond, body_check, done); + lb_start_block(p, body_check); + + val = lb_emit_conv(p, offset, elem); + lb_emit_increment(p, offset_.addr); + + lbValue check = lb_build_binary_in(p, val, the_set, Token_in); + lb_emit_if(p, check, body, loop); + lb_start_block(p, body); + } + break; + } default: GB_PANIC("Cannot range over %s", type_to_string(expr_type)); break; -- cgit v1.2.3