From 6c8c430c2a5af0a04a70cb4e9bf79c22f6554ab9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 18 Oct 2017 22:26:04 +0100 Subject: Fix enum iteration (issue #126) --- src/ir.cpp | 67 +++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 31 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 9e67cd952..853960d08 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1346,19 +1346,20 @@ irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr, bool zero_ini return instr; } -irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *name, bool zero_initialized) { - Entity *e = entity_of_ident(proc->module->info, name); +irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *ident, bool zero_initialized) { + Entity *e = entity_of_ident(proc->module->info, ident); if (e != nullptr) { - ir_emit_comment(proc, e->token.string); + String name = e->token.string; + ir_emit_comment(proc, name); if (e->kind == Entity_Variable && e->Variable.is_foreign) { - HashKey key = hash_string(e->token.string); + HashKey key = hash_string(name); irValue **prev_value = map_get(&proc->module->members, key); if (prev_value == nullptr) { // NOTE(bill): Don't do mutliple declarations in the IR irValue *g = ir_value_global(proc->module->allocator, e, nullptr); - g->Global.name = e->token.string; + g->Global.name = name; g->Global.is_foreign = true; ir_module_add_value(proc->module, e, g); map_set(&proc->module->members, key, g); @@ -1367,12 +1368,12 @@ irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *name, bool zero return *prev_value; } } - return ir_add_local(proc, e, name, zero_initialized); + return ir_add_local(proc, e, ident, zero_initialized); } return nullptr; } -irValue *ir_add_local_generated(irProcedure *proc, Type *type) { +irValue *ir_add_local_generated(irProcedure *proc, Type *type, bool zero_initialized = true) { GB_ASSERT(type != nullptr); Scope *scope = nullptr; @@ -1383,7 +1384,7 @@ irValue *ir_add_local_generated(irProcedure *proc, Type *type) { scope, empty_token, type, false); - return ir_add_local(proc, e, nullptr, true); + return ir_add_local(proc, e, nullptr, zero_initialized); } @@ -3267,7 +3268,7 @@ irValue *ir_emit_transmute(irProcedure *proc, irValue *value, Type *t) { -irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, TokenPos pos) { +irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, TokenPos pos, bool do_conversion_check=true) { gbAllocator a = proc->module->allocator; Type *src_type = ir_type(value); @@ -3286,7 +3287,7 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token value = ir_emit_load(proc, value); } Type *src = base_type(type_deref(src_type)); - GB_ASSERT(is_type_union(src)); + GB_ASSERT_MSG(is_type_union(src), "%s", type_to_string(src_type)); Type *dst = tuple->Tuple.variables[0]->type; @@ -3312,20 +3313,22 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token ir_start_block(proc, end_block); if (!is_tuple) { - // NOTE(bill): Panic on invalid conversion - Type *dst_type = tuple->Tuple.variables[0]->type; + if (do_conversion_check) { + // NOTE(bill): Panic on invalid conversion + Type *dst_type = tuple->Tuple.variables[0]->type; - irValue *ok = ir_emit_load(proc, ir_emit_struct_ep(proc, v, 1)); - irValue **args = gb_alloc_array(a, irValue *, 6); - args[0] = ok; + irValue *ok = ir_emit_load(proc, ir_emit_struct_ep(proc, v, 1)); + irValue **args = gb_alloc_array(a, irValue *, 6); + args[0] = ok; - args[1] = ir_find_or_add_entity_string(proc->module, pos.file); - args[2] = ir_const_int(a, pos.line); - args[3] = ir_const_int(a, pos.column); + args[1] = ir_find_or_add_entity_string(proc->module, pos.file); + args[2] = ir_const_int(a, pos.line); + args[3] = ir_const_int(a, pos.column); - args[4] = ir_type_info(proc, src_type); - args[5] = ir_type_info(proc, dst_type); - ir_emit_global_call(proc, "__type_assertion_check", args, 6); + args[4] = ir_type_info(proc, src_type); + args[5] = ir_type_info(proc, dst_type); + ir_emit_global_call(proc, "__type_assertion_check", args, 6); + } return ir_emit_load(proc, ir_emit_struct_ep(proc, v, 0)); } @@ -5556,7 +5559,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { ir_emit_comment(proc, str_lit("CompoundLit")); Type *type = type_of_expr(proc->module->info, expr); Type *bt = base_type(type); - irValue *v = ir_add_local_generated(proc, type); + + irValue *v = ir_add_local_generated(proc, type, true); Type *et = nullptr; switch (bt->kind) { @@ -5594,10 +5598,11 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { } case Type_Struct: { - // TODO(bill): "constant" unions are not initialized constantly at the moment. + + // 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 - bool is_union = is_type_union(bt); - GB_ASSERT(is_type_struct(bt) || is_type_union(bt)); + bool is_raw_union = is_type_raw_union(bt); + GB_ASSERT(is_type_struct(bt) || is_raw_union); TypeStruct *st = &bt->Struct; if (cl->elems.count > 0) { ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr))); @@ -5623,8 +5628,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { field = st->fields[index]; Type *ft = field->type; - if (!is_union && !is_type_union(ft) && - ir_is_elem_const(proc->module, elem, ft)) { + if (!is_raw_union && ir_is_elem_const(proc->module, elem, ft)) { continue; } @@ -6730,14 +6734,15 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { Type *enum_ptr = make_type_pointer(a, t); t = base_type(t); Type *core_elem = core_type(t); - i64 enum_count = t->Struct.fields.count; + i64 enum_count = t->Enum.field_count; irValue *max_count = ir_const_int(a, enum_count); - irValue *eti = ir_emit_union_cast(proc, ir_type_info(proc, t), t_type_info_enum_ptr, pos); - irValue *values = ir_emit_load(proc, ir_emit_struct_ep(proc, eti, 4)); + irValue *ti = ir_type_info(proc, t); + irValue *variant = ir_emit_struct_ep(proc, ti, 2); + irValue *eti_ptr = ir_emit_conv(proc, variant, t_type_info_enum_ptr); + irValue *values = ir_emit_load(proc, ir_emit_struct_ep(proc, eti_ptr, 2)); irValue *values_data = ir_slice_elem(proc, values); - irValue *offset_ = ir_add_local_generated(proc, t_int); ir_emit_store(proc, offset_, v_zero); -- cgit v1.2.3