This is a basic linear-probing hash map It works out to the following implementation enum used { empty, full, previously_full } struct element { used used; KeyType k; ValueType v; } struct Map { uint32_t ref_count; arena* arena; uint64_t count; uint64_t capacity; element* elements; } In order to l
()
| 73 | // If we end up with lots of insertions/deletions, this will prevent linear search |
| 74 | |
| 75 | func (c *C) defineMapTypes() { |
| 76 | // impls is a map of type mangled name to the public MapInfo structure. |
| 77 | // This is used to deduplicate maps that have the same underlying key and |
| 78 | // value LLVM types when lowered. |
| 79 | impls := map[string]*MapInfo{} |
| 80 | |
| 81 | for _, api := range c.APIs { |
| 82 | for _, t := range api.Maps { |
| 83 | mi := &MapInfo{ |
| 84 | Key: c.T.Target(t.KeyType), |
| 85 | Val: c.T.Target(t.ValueType), |
| 86 | Type: c.T.target[t].(codegen.Pointer).Element.(*codegen.Struct), |
| 87 | } |
| 88 | |
| 89 | mi.Elements = c.T.Struct(fmt.Sprintf("%v…%v", mi.Key.TypeName(), mi.Val.TypeName()), |
| 90 | // Used: 0 == empty, 1 == has a key, 2 == doesn't have a key, but |
| 91 | // can't assume your searched key doesn't exist |
| 92 | codegen.Field{Name: "used", Type: c.T.Target(semantic.Uint64Type)}, |
| 93 | codegen.Field{Name: "k", Type: mi.Key}, |
| 94 | codegen.Field{Name: "v", Type: mi.Val}, |
| 95 | ) |
| 96 | |
| 97 | mi.Type.SetBody(false, |
| 98 | codegen.Field{Name: MapRefCount, Type: c.T.Uint32}, |
| 99 | codegen.Field{Name: MapArena, Type: c.T.ArenaPtr}, |
| 100 | codegen.Field{Name: MapCount, Type: c.T.Uint64}, |
| 101 | codegen.Field{Name: MapCapacity, Type: c.T.Uint64}, |
| 102 | codegen.Field{Name: MapElements, Type: c.T.Pointer(mi.Elements)}, |
| 103 | ) |
| 104 | |
| 105 | valPtrTy := c.T.Pointer(mi.Val) |
| 106 | |
| 107 | name := fmt.Sprintf("%v_%v", api.Name(), t.Name()) |
| 108 | mi.MapMethods = MapMethods{ |
| 109 | Contains: c.M.Function(c.T.Bool, name+"_contains", c.T.Pointer(mi.Type), mi.Key).LinkPrivate().Inline(), |
| 110 | Index: c.M.Function(valPtrTy, name+"_index", c.T.Pointer(mi.Type), mi.Key, c.T.Bool).LinkPrivate().Inline(), |
| 111 | Remove: c.M.Function(c.T.Void, name+"_remove", c.T.Pointer(mi.Type), mi.Key).LinkPrivate().Inline(), |
| 112 | Clear: c.M.Function(c.T.Void, name+"_clear", c.T.Pointer(mi.Type)).LinkPrivate().Inline(), |
| 113 | ClearKeep: c.M.Function(c.T.Void, name+"_clear_keep", c.T.Pointer(mi.Type)).LinkPrivate().Inline(), |
| 114 | } |
| 115 | |
| 116 | // Use the mangled name of the map to determine whether the map has |
| 117 | // already been declared for the lowered map type. |
| 118 | mangled := c.Mangler(c.Mangle(mi.Type)) |
| 119 | impl, seen := impls[mangled] |
| 120 | |
| 121 | if !seen { |
| 122 | // First instance of this lowered map type. Define it. |
| 123 | copy := *mi |
| 124 | impl = © |
| 125 | impls[mangled] = impl |
| 126 | impl.MapMethods = MapMethods{ |
| 127 | Contains: c.Method(true, mi.Type, c.T.Bool, "contains", mi.Key).LinkOnceODR(), |
| 128 | Index: c.Method(false, mi.Type, valPtrTy, "index", mi.Key, c.T.Bool).LinkOnceODR(), |
| 129 | Remove: c.Method(false, mi.Type, c.T.Void, "remove", mi.Key).LinkOnceODR(), |
| 130 | Clear: c.Method(false, mi.Type, c.T.Void, "clear").LinkOnceODR(), |
| 131 | ClearKeep: c.Method(false, mi.Type, c.T.Void, "clear_keep").LinkOnceODR(), |
| 132 | } |
no test coverage detected