Commit 4a957b9ea3

Andrew Kelley <superjoe30@gmail.com>
2017-02-16 19:45:14
move int and array types to central table
1 parent 1fc2082
src/all_types.hpp
@@ -1040,7 +1040,6 @@ struct TypeTableEntry {
     // use these fields to make sure we don't duplicate type table entries for the same type
     TypeTableEntry *pointer_parent[2][2]; // [0 - mut, 1 - const][0 - normal, 1 - volatile]
     TypeTableEntry *slice_parent[2]; // [0 - mut, 1 - const]
-    HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
     TypeTableEntry *maybe_parent;
     TypeTableEntry *error_parent;
     // If we generate a constant name value for this type, we memoize it here.
@@ -1195,13 +1194,29 @@ enum PanicMsgId {
 uint32_t fn_eval_hash(Scope*);
 bool fn_eval_eql(Scope *a, Scope *b);
 
-struct IntTypeId {
-    bool is_signed;
-    uint8_t bit_count;
+struct TypeId {
+    TypeTableEntryId id;
+
+    union {
+        struct {
+            TypeTableEntry *child_type;
+            bool is_const;
+            bool is_volatile;
+            uint8_t bit_offset;
+        } pointer;
+        struct {
+            TypeTableEntry *child_type;
+            uint64_t size;
+        } array;
+        struct {
+            bool is_signed;
+            uint8_t bit_count;
+        } integer;
+    } data;
 };
 
-uint32_t int_type_id_hash(IntTypeId);
-bool int_type_id_eql(IntTypeId a, IntTypeId b);
+uint32_t type_id_hash(TypeId);
+bool type_id_eql(TypeId a, TypeId b);
 
 struct CodeGen {
     LLVMModuleRef module;
@@ -1218,7 +1233,7 @@ struct CodeGen {
     HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
     HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
     HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
-    HashMap<IntTypeId, TypeTableEntry *, int_type_id_hash, int_type_id_eql> int_type_table;
+    HashMap<TypeId, TypeTableEntry *, type_id_hash, type_id_eql> type_table;
     HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
     HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
     HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
src/analyze.cpp
@@ -50,7 +50,6 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m
 
 TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
     TypeTableEntry *entry = allocate<TypeTableEntry>(1);
-    entry->arrays_by_size.init(2);
     entry->id = id;
     return entry;
 }
@@ -489,34 +488,38 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
 }
 
 TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size) {
-    auto existing_entry = child_type->arrays_by_size.maybe_get(array_size);
+    TypeId type_id;
+    type_id.id = TypeTableEntryIdArray;
+    type_id.data.array.child_type = child_type;
+    type_id.data.array.size = array_size;
+    auto existing_entry = g->type_table.maybe_get(type_id);
     if (existing_entry) {
         TypeTableEntry *entry = existing_entry->value;
         return entry;
-    } else {
-        ensure_complete_type(g, child_type);
+    }
 
-        TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
-        entry->zero_bits = (array_size == 0) || child_type->zero_bits;
+    ensure_complete_type(g, child_type);
 
-        buf_resize(&entry->name, 0);
-        buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name));
+    TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
+    entry->zero_bits = (array_size == 0) || child_type->zero_bits;
 
-        if (!entry->zero_bits) {
-            entry->type_ref = child_type->type_ref ? LLVMArrayType(child_type->type_ref, array_size) : nullptr;
+    buf_resize(&entry->name, 0);
+    buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name));
 
-            uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
-            uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
+    if (!entry->zero_bits) {
+        entry->type_ref = child_type->type_ref ? LLVMArrayType(child_type->type_ref, array_size) : nullptr;
 
-            entry->di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits,
-                    debug_align_in_bits, child_type->di_type, array_size);
-        }
-        entry->data.array.child_type = child_type;
-        entry->data.array.len = array_size;
+        uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
+        uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
 
-        child_type->arrays_by_size.put(array_size, entry);
-        return entry;
+        entry->di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits,
+                debug_align_in_bits, child_type->di_type, array_size);
     }
+    entry->data.array.child_type = child_type;
+    entry->data.array.len = array_size;
+
+    g->type_table.put(type_id, entry);
+    return entry;
 }
 
 static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,
@@ -2822,14 +2825,19 @@ TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint8_t size_in_bits) {
     if (common_entry)
         return *common_entry;
 
+    TypeId type_id;
+    type_id.id = TypeTableEntryIdInt;
+    type_id.data.integer.is_signed = is_signed;
+    type_id.data.integer.bit_count = size_in_bits;
+
     {
-        auto entry = g->int_type_table.maybe_get({is_signed, size_in_bits});
+        auto entry = g->type_table.maybe_get(type_id);
         if (entry)
             return entry->value;
     }
 
     TypeTableEntry *new_entry = make_int_type(g, is_signed, size_in_bits);
-    g->int_type_table.put({is_signed, size_in_bits}, new_entry);
+    g->type_table.put(type_id, new_entry);
     return new_entry;
 }
 
@@ -3877,12 +3885,88 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits) {
     return entry;
 }
 
-uint32_t int_type_id_hash(IntTypeId x) {
-    uint32_t hash = x.is_signed ? 2652528194 : 163929201;
-    hash += ((uint32_t)x.bit_count) * 2998081557;
-    return hash;
+uint32_t type_id_hash(TypeId x) {
+    switch (x.id) {
+        case TypeTableEntryIdInvalid:
+        case TypeTableEntryIdVar:
+        case TypeTableEntryIdMetaType:
+        case TypeTableEntryIdVoid:
+        case TypeTableEntryIdBool:
+        case TypeTableEntryIdUnreachable:
+        case TypeTableEntryIdFloat:
+        case TypeTableEntryIdStruct:
+        case TypeTableEntryIdNumLitFloat:
+        case TypeTableEntryIdNumLitInt:
+        case TypeTableEntryIdUndefLit:
+        case TypeTableEntryIdNullLit:
+        case TypeTableEntryIdMaybe:
+        case TypeTableEntryIdErrorUnion:
+        case TypeTableEntryIdPureError:
+        case TypeTableEntryIdEnum:
+        case TypeTableEntryIdEnumTag:
+        case TypeTableEntryIdUnion:
+        case TypeTableEntryIdFn:
+        case TypeTableEntryIdTypeDecl:
+        case TypeTableEntryIdNamespace:
+        case TypeTableEntryIdBlock:
+        case TypeTableEntryIdBoundFn:
+        case TypeTableEntryIdArgTuple:
+            zig_unreachable();
+        case TypeTableEntryIdPointer:
+            return hash_ptr(x.data.pointer.child_type) +
+                (x.data.pointer.is_const ? 2749109194 : 4047371087) +
+                (x.data.pointer.is_volatile ? 536730450 : 1685612214) +
+                (((uint32_t)x.data.pointer.bit_offset) * 2639019452);
+        case TypeTableEntryIdArray:
+            return hash_ptr(x.data.array.child_type) +
+                (x.data.array.size * 2122979968);
+        case TypeTableEntryIdInt:
+            return (x.data.integer.is_signed ? 2652528194 : 163929201) +
+                    (((uint32_t)x.data.integer.bit_count) * 2998081557);
+    }
+    zig_unreachable();
 }
 
-bool int_type_id_eql(IntTypeId a, IntTypeId b) {
-    return (a.is_signed == b.is_signed && a.bit_count == b.bit_count);
+bool type_id_eql(TypeId a, TypeId b) {
+    if (a.id != b.id)
+        return false;
+    switch (a.id) {
+        case TypeTableEntryIdInvalid:
+        case TypeTableEntryIdVar:
+        case TypeTableEntryIdMetaType:
+        case TypeTableEntryIdVoid:
+        case TypeTableEntryIdBool:
+        case TypeTableEntryIdUnreachable:
+        case TypeTableEntryIdFloat:
+        case TypeTableEntryIdStruct:
+        case TypeTableEntryIdNumLitFloat:
+        case TypeTableEntryIdNumLitInt:
+        case TypeTableEntryIdUndefLit:
+        case TypeTableEntryIdNullLit:
+        case TypeTableEntryIdMaybe:
+        case TypeTableEntryIdErrorUnion:
+        case TypeTableEntryIdPureError:
+        case TypeTableEntryIdEnum:
+        case TypeTableEntryIdEnumTag:
+        case TypeTableEntryIdUnion:
+        case TypeTableEntryIdFn:
+        case TypeTableEntryIdTypeDecl:
+        case TypeTableEntryIdNamespace:
+        case TypeTableEntryIdBlock:
+        case TypeTableEntryIdBoundFn:
+        case TypeTableEntryIdArgTuple:
+            zig_unreachable();
+        case TypeTableEntryIdPointer:
+            return a.data.pointer.child_type == b.data.pointer.child_type &&
+                a.data.pointer.is_const == b.data.pointer.is_const &&
+                a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
+                a.data.pointer.bit_offset == b.data.pointer.bit_offset;
+        case TypeTableEntryIdArray:
+            return a.data.array.child_type == b.data.array.child_type &&
+                a.data.array.size == b.data.array.size;
+        case TypeTableEntryIdInt:
+            return a.data.integer.is_signed == b.data.integer.is_signed &&
+                a.data.integer.bit_count == b.data.integer.bit_count;
+    }
+    zig_unreachable();
 }
src/codegen.cpp
@@ -58,7 +58,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
     g->import_table.init(32);
     g->builtin_fn_table.init(32);
     g->primitive_type_table.init(32);
-    g->int_type_table.init(8);
+    g->type_table.init(32);
     g->fn_type_table.init(32);
     g->error_table.init(16);
     g->generic_table.init(16);