Commit f12d36641f

Andrew Kelley <superjoe30@gmail.com>
2017-11-16 16:06:58
union secret field is the tag index instead of distinct type index
See #144
1 parent 018cbff
src/all_types.hpp
@@ -105,7 +105,8 @@ struct ConstStructValue {
 };
 
 struct ConstUnionValue {
-    ConstExprValue *value;
+    uint64_t tag;
+    ConstExprValue *payload;
     ConstParent parent;
 };
 
@@ -349,6 +350,7 @@ struct TypeEnumField {
 struct TypeUnionField {
     Buf *name;
     TypeTableEntry *type_entry;
+    uint32_t value;
     uint32_t gen_index;
 };
 
@@ -1067,8 +1069,6 @@ struct TypeTableEntryUnion {
 
     uint32_t union_size_bytes;
     TypeTableEntry *most_aligned_union_member;
-
-    HashMap<const TypeTableEntry *, uint32_t, type_ptr_hash, type_ptr_eql> distinct_types = {};
 };
 
 struct FnGenParamInfo {
src/analyze.cpp
@@ -1872,8 +1872,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
 
     bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
     ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
-    auto distinct_types = &union_type->data.unionation.distinct_types;
-    distinct_types->init(4);
 
     Scope *scope = &union_type->data.unionation.decls_scope->base;
     ImportTableEntry *import = get_scope_import(scope);
@@ -1895,10 +1893,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
         if (!type_has_bits(field_type))
             continue;
 
-        size_t distinct_type_index = distinct_types->size();
-        if (distinct_types->put_unique(field_type, distinct_type_index) == nullptr) {
-            di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(&field_type->name), distinct_type_index);
-        }
+        di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_union_field->name), i);
 
         uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
         uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref);
@@ -1954,7 +1949,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
 
     assert(most_aligned_union_member != nullptr);
 
-    bool want_safety = (distinct_types->size() > 1) && auto_layout;
+    bool want_safety = auto_layout && (field_count >= 2);
     uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
 
 
@@ -2007,7 +2002,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
     assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);
 
     // create llvm type for root struct
-    TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, distinct_types->size() - 1);
+    TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
     TypeTableEntry *tag_type_entry = tag_int_type;
     union_type->data.unionation.tag_type = tag_type_entry;
     uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
@@ -2034,7 +2029,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
     ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
             ZigLLVMTypeToScope(union_type->di_type), "AnonEnum",
             import->di_file, (unsigned)(decl_node->line + 1),
-            tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, distinct_types->size(),
+            tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count,
             tag_type_entry->di_type, "");
 
     // create debug type for union
@@ -2257,6 +2252,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
         type_union_field->name = field_node->data.struct_field.name;
         TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
         type_union_field->type_entry = field_type;
+        type_union_field->value = i;
 
         type_ensure_zero_bits_known(g, field_type);
         if (type_is_invalid(field_type)) {
@@ -2276,9 +2272,11 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
         }
     }
 
+    bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
+
     union_type->data.unionation.zero_bits_loop_flag = false;
     union_type->data.unionation.gen_field_count = gen_field_index;
-    union_type->zero_bits = (gen_field_index == 0);
+    union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !auto_layout));
     union_type->data.unionation.zero_bits_known = true;
 
     // also compute abi_alignment
src/codegen.cpp
@@ -3962,7 +3962,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
         case TypeTableEntryIdUnion:
             {
                 LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;
-                ConstExprValue *payload_value = const_val->data.x_union.value;
+                ConstExprValue *payload_value = const_val->data.x_union.payload;
                 assert(payload_value != nullptr);
 
                 if (!type_has_bits(payload_value->type)) {
@@ -3999,8 +3999,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
                     return union_value_ref;
                 }
 
-                size_t distinct_type_index = type_entry->data.unionation.distinct_types.get(const_val->data.x_union.value->type);
-                LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, distinct_type_index, false);
+                LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, const_val->data.x_union.tag, false);
 
                 LLVMValueRef fields[2];
                 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
src/ir.cpp
@@ -13158,7 +13158,8 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir
             return ira->codegen->builtin_types.entry_invalid;
 
         ConstExprValue *out_val = ir_build_const_from(ira, instruction);
-        out_val->data.x_union.value = field_val;
+        out_val->data.x_union.payload = field_val;
+        out_val->data.x_union.tag = type_field->value;
 
         ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
         if (parent != nullptr) {