Commit 28dd9d478d

Andrew Kelley <andrew@ziglang.org>
2021-07-12 21:40:32
C backend: TypedefMap is now ArrayHashMap
The C backend depends on insertion order into this map so that type definitions will be declared before they are used.
1 parent 03156e5
Changed files (5)
src/codegen/c.zig
@@ -39,11 +39,11 @@ const BlockData = struct {
 };
 
 pub const CValueMap = std.AutoHashMap(*Inst, CValue);
-pub const TypedefMap = std.HashMap(
+pub const TypedefMap = std.ArrayHashMap(
     Type,
     struct { name: []const u8, rendered: []u8 },
-    Type.HashContext,
-    std.hash_map.default_max_load_percentage,
+    Type.HashContext32,
+    true,
 );
 
 fn formatTypeAsCIdentifier(
src/codegen/spirv.zig
@@ -18,7 +18,7 @@ const Inst = ir.Inst;
 pub const Word = u32;
 pub const ResultId = u32;
 
-pub const TypeMap = std.HashMap(Type, u32, Type.HashContext, std.hash_map.default_max_load_percentage);
+pub const TypeMap = std.HashMap(Type, u32, Type.HashContext64, std.hash_map.default_max_load_percentage);
 pub const InstMap = std.AutoHashMap(*Inst, ResultId);
 
 const IncomingBlock = struct {
src/link/C.zig
@@ -89,8 +89,7 @@ pub fn freeDecl(self: *C, decl: *Module.Decl) void {
 fn deinitDecl(gpa: *Allocator, decl: *Module.Decl) void {
     decl.link.c.code.deinit(gpa);
     decl.fn_link.c.fwd_decl.deinit(gpa);
-    var it = decl.fn_link.c.typedefs.valueIterator();
-    while (it.next()) |value| {
+    for (decl.fn_link.c.typedefs.values()) |value| {
         gpa.free(value.rendered);
     }
     decl.fn_link.c.typedefs.deinit(gpa);
@@ -108,8 +107,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
     const code = &decl.link.c.code;
     fwd_decl.shrinkRetainingCapacity(0);
     {
-        var it = typedefs.valueIterator();
-        while (it.next()) |value| {
+        for (typedefs.values()) |value| {
             module.gpa.free(value.rendered);
         }
     }
@@ -135,8 +133,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
         object.blocks.deinit(module.gpa);
         object.code.deinit();
         object.dg.fwd_decl.deinit();
-        var it = object.dg.typedefs.valueIterator();
-        while (it.next()) |value| {
+        for (object.dg.typedefs.values()) |value| {
             module.gpa.free(value.rendered);
         }
         object.dg.typedefs.deinit();
@@ -207,7 +204,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
     }
 
     var fn_count: usize = 0;
-    var typedefs = std.HashMap(Type, void, Type.HashContext, std.hash_map.default_max_load_percentage).init(comp.gpa);
+    var typedefs = std.HashMap(Type, void, Type.HashContext64, std.hash_map.default_max_load_percentage).init(comp.gpa);
     defer typedefs.deinit();
 
     // Typedefs, forward decls and non-functions first.
@@ -217,7 +214,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
         if (!decl.has_tv) continue;
         const buf = buf: {
             if (decl.val.castTag(.function)) |_| {
-                try typedefs.ensureUnusedCapacity(decl.fn_link.c.typedefs.count());
+                try typedefs.ensureUnusedCapacity(@intCast(u32, decl.fn_link.c.typedefs.count()));
                 var it = decl.fn_link.c.typedefs.iterator();
                 while (it.next()) |new| {
                     const gop = typedefs.getOrPutAssumeCapacity(new.key_ptr.*);
src/link.zig
@@ -168,7 +168,7 @@ pub const File = struct {
     };
 
     /// For DWARF .debug_info.
-    pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.HashContext, std.hash_map.default_max_load_percentage);
+    pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.HashContext64, std.hash_map.default_max_load_percentage);
 
     /// For DWARF .debug_info.
     pub const DbgInfoTypeReloc = struct {
src/type.zig
@@ -602,7 +602,7 @@ pub const Type = extern union {
         return hasher.final();
     }
 
-    pub const HashContext = struct {
+    pub const HashContext64 = struct {
         pub fn hash(self: @This(), t: Type) u64 {
             _ = self;
             return t.hash();
@@ -613,6 +613,17 @@ pub const Type = extern union {
         }
     };
 
+    pub const HashContext32 = struct {
+        pub fn hash(self: @This(), t: Type) u32 {
+            _ = self;
+            return @truncate(u32, t.hash());
+        }
+        pub fn eql(self: @This(), a: Type, b: Type) bool {
+            _ = self;
+            return a.eql(b);
+        }
+    };
+
     pub fn copy(self: Type, allocator: *Allocator) error{OutOfMemory}!Type {
         if (self.tag_if_small_enough < Tag.no_payload_count) {
             return Type{ .tag_if_small_enough = self.tag_if_small_enough };