diff --git a/bootstrap/Compilation.zig b/bootstrap/Compilation.zig index 0d6e8ae..1668e94 100644 --- a/bootstrap/Compilation.zig +++ b/bootstrap/Compilation.zig @@ -19,7 +19,7 @@ const PinnedArray = library.PinnedArray; const UnpinnedArray = library.UnpinnedArray; const BlockList = library.BlockList; const MyAllocator = library.MyAllocator; -const MyHashMap = library.MyHashMap; +const PinnedHashMap = library.PinnedHashMap; const span = library.span; const format_int = library.format_int; const my_hash = library.my_hash; @@ -130,6 +130,24 @@ pub fn compileBuildExecutable(context: *const Context, arguments: []const []cons .node_buffer = try PinnedArray(Node).init_with_default_granularity(), .node_lists = try PinnedArray([]const Node.Index).init_with_default_granularity(), .data_to_emit = try PinnedArray(*Debug.Declaration.Global).init_with_default_granularity(), + .file_token_offsets = try PinnedHashMap(Token.Range, Debug.File.Index).init(std.mem.page_size), + .file_map = try PinnedHashMap([]const u8, Debug.File.Index).init(std.mem.page_size), + .identifiers = try PinnedHashMap(u32, []const u8).init(std.mem.page_size), + .string_literal_values = try PinnedHashMap(u32, [:0]const u8).init(std.mem.page_size), + .string_literal_globals = try PinnedHashMap(u32, *Debug.Declaration.Global).init(std.mem.page_size), + .optionals = try PinnedHashMap(Type.Index, Type.Index).init(std.mem.page_size), + .pointers = try PinnedHashMap(Type.Pointer, Type.Index).init(std.mem.page_size), + .slices = try PinnedHashMap(Type.Slice, Type.Index).init(std.mem.page_size), + .arrays = try PinnedHashMap(Type.Array, Type.Index).init(std.mem.page_size), + .integers = try PinnedHashMap(Type.Integer, Type.Index).init(std.mem.page_size), + .error_unions = try PinnedHashMap(Type.Error.Union.Descriptor, Type.Index).init(std.mem.page_size), + .two_structs = try PinnedHashMap([2]Type.Index, Type.Index).init(std.mem.page_size), + .fields_array = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .name_functions = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .external_functions = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .type_declarations = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .test_functions = try PinnedHashMap(*Debug.Declaration.Global, *Debug.Declaration.Global).init(std.mem.page_size), + .code_to_emit = try PinnedHashMap(Function.Definition.Index, *Debug.Declaration.Global).init(std.mem.page_size), }; try unit.compile(context); @@ -2941,7 +2959,7 @@ pub fn buildExecutable(context: *const Context, arguments: []const []const u8, o if (i + 1 != arguments.len) { i += 1; - c_source_files.appendSliceAssumeCapacity( arguments[i..]); + c_source_files.appendSliceAssumeCapacity(arguments[i..]); i = arguments.len; } else { reportUnterminatedArgumentError(current_argument); @@ -3026,6 +3044,24 @@ pub fn buildExecutable(context: *const Context, arguments: []const []const u8, o .node_buffer = try PinnedArray(Node).init_with_default_granularity(), .node_lists = try PinnedArray([]const Node.Index).init_with_default_granularity(), .data_to_emit = try PinnedArray(*Debug.Declaration.Global).init_with_default_granularity(), + .file_token_offsets = try PinnedHashMap(Token.Range, Debug.File.Index).init(std.mem.page_size), + .file_map = try PinnedHashMap([]const u8, Debug.File.Index).init(std.mem.page_size), + .identifiers = try PinnedHashMap(u32, []const u8).init(std.mem.page_size), + .string_literal_values = try PinnedHashMap(u32, [:0]const u8).init(std.mem.page_size), + .string_literal_globals = try PinnedHashMap(u32, *Debug.Declaration.Global).init(std.mem.page_size), + .optionals = try PinnedHashMap(Type.Index, Type.Index).init(std.mem.page_size), + .pointers = try PinnedHashMap(Type.Pointer, Type.Index).init(std.mem.page_size), + .slices = try PinnedHashMap(Type.Slice, Type.Index).init(std.mem.page_size), + .arrays = try PinnedHashMap(Type.Array, Type.Index).init(std.mem.page_size), + .integers = try PinnedHashMap(Type.Integer, Type.Index).init(std.mem.page_size), + .error_unions = try PinnedHashMap(Type.Error.Union.Descriptor, Type.Index).init(std.mem.page_size), + .two_structs = try PinnedHashMap([2]Type.Index, Type.Index).init(std.mem.page_size), + .fields_array = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .name_functions = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .external_functions = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .type_declarations = try PinnedHashMap(Type.Index, *Debug.Declaration.Global).init(std.mem.page_size), + .test_functions = try PinnedHashMap(*Debug.Declaration.Global, *Debug.Declaration.Global).init(std.mem.page_size), + .code_to_emit = try PinnedHashMap(Function.Definition.Index, *Debug.Declaration.Global).init(std.mem.page_size), }; try unit.compile(context); @@ -3052,10 +3088,10 @@ pub const Package = struct { directory: Directory, /// Relative to the package main directory source_path: []const u8, - dependencies: MyHashMap([]const u8, *Package) = .{}, + dependencies: PinnedHashMap([]const u8, *Package), - fn addDependency(package: *Package, allocator: *MyAllocator, package_name: []const u8, new_dependency: *Package) !void { - try package.dependencies.put_no_clobber(allocator, package_name, new_dependency); + fn addDependency(package: *Package, package_name: []const u8, new_dependency: *Package) !void { + try package.dependencies.put_no_clobber(package_name, new_dependency); } }; @@ -3298,6 +3334,7 @@ const _usize: Type.Index = .u64; const _ssize: Type.Index = .s64; fn serialize_comptime_parameters(unit: *Unit, context: *const Context, original_declaration: *Debug.Declaration, parameters: []const V.Comptime) !u32 { + _ = context; // autofix var name = BoundedArray(u8, 4096){}; const original_name = unit.getIdentifier(original_declaration.name); name.appendSliceAssumeCapacity(original_name); @@ -3339,7 +3376,7 @@ fn serialize_comptime_parameters(unit: *Unit, context: *const Context, original_ const hash = my_hash(name.slice()); // Don't allocate memory if not necessary if (unit.identifiers.get(hash) == null) { - try unit.identifiers.put_no_clobber(context.my_allocator, hash, name.slice()); + try unit.identifiers.put_no_clobber(hash, name.slice()); } return hash; @@ -3364,7 +3401,7 @@ pub const Type = union(enum) { pub const Polymorphic = struct { parameters: []const Token.Index, - instantiations: MyHashMap(u32, *Debug.Declaration.Global) = .{}, + instantiations: PinnedHashMap(u32, *Debug.Declaration.Global), node: Node.Index, pub fn get_instantiation(polymorphic: *Polymorphic, types: []const V.Comptime) ?*Debug.Declaration.Global { @@ -3395,7 +3432,7 @@ pub const Type = union(enum) { const new_declaration = unit.global_declarations.get(new_declaration_index); const parameter_hash = hash(parameters); - try polymorphic.instantiations.put_no_clobber(context.my_allocator, parameter_hash, new_declaration); + try polymorphic.instantiations.put_no_clobber(parameter_hash, new_declaration); } fn hash(types: []const V.Comptime) u32 { @@ -3735,7 +3772,7 @@ pub const Instruction = union(enum) { pub const max_value_count = 32; - const Value = struct{ + const Value = struct { value: V, basic_block: BasicBlock.Index, }; @@ -4111,7 +4148,7 @@ pub fn joinPath(context: *const Context, a: []const u8, b: []const u8) ![]const pub const PolymorphicFunction = struct { parameters: []const ComptimeParameterDeclaration, - instantiations: MyHashMap(u32, *Debug.Declaration.Global) = .{}, + instantiations: PinnedHashMap(u32, *Debug.Declaration.Global), node: Node.Index, is_member_call: bool, @@ -4150,7 +4187,7 @@ pub const PolymorphicFunction = struct { const new_declaration = unit.global_declarations.get(new_declaration_index); const parameter_hash = hash(parameters); - try polymorphic_function.instantiations.put_no_clobber(context.my_allocator, parameter_hash, new_declaration); + try polymorphic_function.instantiations.put_no_clobber(parameter_hash, new_declaration); return new_declaration; } @@ -4298,7 +4335,7 @@ pub const Debug = struct { }; pub const Scope = struct { - declarations: MyHashMap(u32, *Declaration) = .{}, + declarations: PinnedHashMap(u32, *Declaration), parent: ?*Scope = null, file: File.Index, line: u32, @@ -4314,7 +4351,7 @@ pub const Debug = struct { pub const Local = struct { scope: Scope, - local_declaration_map: MyHashMap(*Debug.Declaration.Local, Instruction.Index) = .{}, + local_declaration_map: PinnedHashMap(*Debug.Declaration.Local, Instruction.Index), }; pub const Global = struct { @@ -4324,8 +4361,8 @@ pub const Debug = struct { pub const Function = struct { scope: Scope, - argument_map: MyHashMap(*Debug.Declaration.Argument, Instruction.Index) = .{}, - // comptime_parameters: MyHashMap(*Debug.Declaration.Argument, + argument_map: PinnedHashMap(*Debug.Declaration.Argument, Instruction.Index), + // comptime_parameters: PinnedArray(*Debug.Declaration.Argument, }; fn lookupDeclaration(s: *Scope, name: u32, look_in_parent_scopes: bool) ?Lookup { @@ -4565,7 +4602,7 @@ pub const Builder = struct { const error_union_type_index = try unit.types.append(context.my_allocator, .{ .@"struct" = error_union_struct_index, }); - try unit.error_unions.put_no_clobber(context.my_allocator, error_union, error_union_type_index); + try unit.error_unions.put_no_clobber(error_union, error_union_type_index); return error_union_type_index; } @@ -4597,7 +4634,7 @@ pub const Builder = struct { } else { const string_name = try join_name(context, "__anon_str_", possible_id, 10); const identifier = try unit.processIdentifier(context, string_name); - try unit.string_literal_values.put_no_clobber(context.my_allocator, hash, string); + try unit.string_literal_values.put_no_clobber(hash, string); const string_global_index = try unit.global_declarations.append(context.my_allocator, .{ .declaration = .{ @@ -4637,7 +4674,7 @@ pub const Builder = struct { const string_global = unit.global_declarations.get(string_global_index); - try unit.string_literal_globals.put_no_clobber(context.my_allocator, hash, string_global); + try unit.string_literal_globals.put_no_clobber(hash, string_global); _ = unit.data_to_emit.append(string_global); @@ -4825,7 +4862,7 @@ pub const Builder = struct { .destination = destination, .source = v, }, - }); + }); try builder.appendInstruction(unit, context, store); const load = try unit.instructions.append(context.my_allocator, .{ @@ -4833,7 +4870,7 @@ pub const Builder = struct { .value = destination, .type = type_index, }, - }); + }); try builder.appendInstruction(unit, context, load); return V{ @@ -5177,7 +5214,9 @@ pub const Builder = struct { .kind = .function, .local = true, .level = builder.current_scope.level + 1, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, + .argument_map = try PinnedHashMap(*Debug.Declaration.Argument, Instruction.Index).init(std.mem.page_size), }, .type = function_type_index, .body = .null, @@ -5212,7 +5251,7 @@ pub const Builder = struct { comptime assert(@TypeOf(argument_declaration_index) == Debug.Declaration.Argument.Index); const argument = unit.argument_declarations.get(argument_declaration_index); - try builder.current_scope.declarations.put_no_clobber(context.my_allocator, argument_name_hash, &argument.declaration); + try builder.current_scope.declarations.put_no_clobber(argument_name_hash, &argument.declaration); const entry_block = try builder.newBasicBlock(unit, context); const exit_block = try builder.newBasicBlock(unit, context); @@ -5327,8 +5366,8 @@ pub const Builder = struct { const global = unit.global_declarations.get(global_index); - try unit.code_to_emit.put_no_clobber(context.my_allocator, function_definition_index, global); - try unit.name_functions.put_no_clobber(context.my_allocator, type_index, global); + try unit.code_to_emit.put_no_clobber(function_definition_index, global); + try unit.name_functions.put_no_clobber(type_index, global); return global; } @@ -5383,7 +5422,7 @@ pub const Builder = struct { const global_declaration = unit.global_declarations.get(global_declaration_index); _ = unit.data_to_emit.append(global_declaration); - try unit.fields_array.put_no_clobber(context.my_allocator, container_type_index, global_declaration); + try unit.fields_array.put_no_clobber(container_type_index, global_declaration); return global_declaration; }, @@ -5807,13 +5846,13 @@ pub const Builder = struct { const function_definition_global = polymorphic_function.instantiations.values()[0]; assert(function_definition_global.initial_value == .function_definition); - try unit.code_to_emit.put_no_clobber(context.my_allocator, function_definition_global.initial_value.function_definition, function_definition_global); + try unit.code_to_emit.put_no_clobber(function_definition_global.initial_value.function_definition, function_definition_global); return function_definition_global; }, .function_definition => |function_definition_index| { switch (unit.getNode(declaration_node_index).id) { - .function_definition => try unit.code_to_emit.put_no_clobber(context.my_allocator, function_definition_index, global_declaration), + .function_definition => try unit.code_to_emit.put_no_clobber(function_definition_index, global_declaration), else => { const actual_function_declaration = unit.code_to_emit.get(function_definition_index).?; global_declaration.initial_value = .{ @@ -5824,7 +5863,7 @@ pub const Builder = struct { }, .function_declaration => |function_type| { switch (unit.getNode(declaration_node_index).id) { - .function_prototype => try unit.external_functions.put_no_clobber(context.my_allocator, function_type, global_declaration), + .function_prototype => try unit.external_functions.put_no_clobber(function_type, global_declaration), else => { const actual_function_declaration = unit.external_functions.get(function_type).?; global_declaration.initial_value = .{ @@ -5841,7 +5880,7 @@ pub const Builder = struct { unreachable; } }, - else => unit.type_declarations.put(context.my_allocator, type_index, global_declaration) catch { + else => unit.type_declarations.put(type_index, global_declaration) catch { assert(unit.type_declarations.get(type_index).? == global_declaration); }, } @@ -5856,7 +5895,7 @@ pub const Builder = struct { .polymorphic_function => |*polymorphic_function| { const instantiation_value = try builder.resolveComptimeValue(unit, context, Type.Expect.none, global_declaration.attributes, polymorphic_function.node, global_declaration, .right, new_parameters, maybe_member_value, polymorphic_argument_nodes); const instantiation_global = instantiation_value.global; - try unit.code_to_emit.put(context.my_allocator, instantiation_global.initial_value.function_definition, instantiation_global); + try unit.code_to_emit.put(instantiation_global.initial_value.function_definition, instantiation_global); return instantiation_global; }, @@ -7274,6 +7313,7 @@ pub const Builder = struct { .local = false, .level = builder.current_scope.level + 1, .parent = &unit.scope.scope, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, }, .id = std.math.maxInt(u32), @@ -7482,7 +7522,7 @@ pub const Builder = struct { }); const comptime_parameter = unit.global_declarations.get(comptime_parameter_index); - try builder.current_scope.declarations.put_no_clobber(context.my_allocator, name_hash, &comptime_parameter.declaration); + try builder.current_scope.declarations.put_no_clobber(name_hash, &comptime_parameter.declaration); }, else => |t| @panic(@tagName(t)), }, @@ -7591,7 +7631,7 @@ pub const Builder = struct { comptime assert(@TypeOf(argument_declaration_index) == Debug.Declaration.Argument.Index); const argument = unit.argument_declarations.get(argument_declaration_index); - try builder.current_scope.declarations.put_no_clobber(context.my_allocator, argument_name_hash, &argument.declaration); + try builder.current_scope.declarations.put_no_clobber(argument_name_hash, &argument.declaration); } fn classify_argument_type_aarch64(builder: *Builder, unit: *Unit, context: *const Context, type_index: Type.Index) Function.AbiInfo { @@ -7928,7 +7968,7 @@ pub const Builder = struct { function_prototype.abi.return_type_abi = return_abi; const abi_infos = try context.arena.new_array(Function.AbiInfo, parameter_types_abi.len); @memcpy(abi_infos, parameter_types_abi.slice()); - function_prototype.abi.parameter_types_abi = abi_infos; + function_prototype.abi.parameter_types_abi = abi_infos; } const Class_SystemVx86_64 = enum { @@ -8482,6 +8522,7 @@ pub const Builder = struct { .level = builder.current_scope.level + 1, .local = false, .file = builder.current_file, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, }, .options = .{}, @@ -8572,7 +8613,7 @@ pub const Builder = struct { .attributes = .{}, }); const global_declaration = unit.global_declarations.get(global_declaration_index); - try struct_type.kind.@"struct".scope.scope.declarations.put_no_clobber(context.my_allocator, hash, &global_declaration.declaration); + try struct_type.kind.@"struct".scope.scope.declarations.put_no_clobber(hash, &global_declaration.declaration); } const polymorphic_type_index = switch (parameter_types.len > 0) { @@ -8585,6 +8626,7 @@ pub const Builder = struct { break :param heap_parameter_types; }, .node = container_node_index, + .instantiations = try PinnedHashMap(u32, *Debug.Declaration.Global).init(std.mem.page_size), }, }); const polymorphic_type = &unit.types.get(polymorphic_type_index).polymorphic; @@ -8648,6 +8690,7 @@ pub const Builder = struct { .level = builder.current_scope.level + 1, .local = false, .file = builder.current_file, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, }, }, @@ -8694,6 +8737,7 @@ pub const Builder = struct { .level = builder.current_scope.level + 1, .local = false, .file = builder.current_file, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, }, }, @@ -8853,7 +8897,7 @@ pub const Builder = struct { }); const global_declaration = unit.global_declarations.get(global_declaration_index); - try builder.current_scope.declarations.put_no_clobber(context.my_allocator, identifier_hash, &global_declaration.declaration); + try builder.current_scope.declarations.put_no_clobber(identifier_hash, &global_declaration.declaration); }, else => unreachable, } @@ -9078,15 +9122,15 @@ pub const Builder = struct { const test_global = unit.global_declarations.get(test_global_index); - try scope.scope.declarations.put_no_clobber(context.my_allocator, name_hash, &test_global.declaration); + try scope.scope.declarations.put_no_clobber(name_hash, &test_global.declaration); - try unit.test_functions.put_no_clobber(context.my_allocator, test_name_global, test_global); + try unit.test_functions.put_no_clobber(test_name_global, test_global); - try unit.code_to_emit.put_no_clobber(context.my_allocator, comptime_value.function_definition, test_global); + try unit.code_to_emit.put_no_clobber(comptime_value.function_definition, test_global); } } - for (builder.current_scope.declarations.values()) |declaration|{ + for (builder.current_scope.declarations.values()) |declaration| { const global_declaration: *Debug.Declaration.Global = @fieldParentPtr("declaration", declaration); if (global_declaration.attributes.contains(.@"export")) { const result = try builder.referenceGlobalDeclaration(unit, context, &scope.scope, declaration, .{}, &.{}, null, &.{}); @@ -9175,7 +9219,9 @@ pub const Builder = struct { .local = true, .level = builder.current_scope.level + 1, .file = builder.current_file, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, + .argument_map = try PinnedHashMap(*Debug.Declaration.Argument, Instruction.Index).init(std.mem.page_size), }, .has_debug_info = true, }); @@ -9498,7 +9544,7 @@ pub const Builder = struct { // else => |t| @panic(@tagName(t)), }; - try function.scope.argument_map.put_no_clobber(context.my_allocator, argument_declaration, stack); + try function.scope.argument_map.put_no_clobber(argument_declaration, stack); const debug_declare_argument = try unit.instructions.append(context.my_allocator, .{ .debug_declare_argument = .{ @@ -9672,6 +9718,7 @@ pub const Builder = struct { .node = function_node_index, .parameters = comptime_parameter_declarations, .is_member_call = is_member_call, + .instantiations = try PinnedHashMap(u32, *Debug.Declaration.Global).init(std.mem.page_size), }; _ = try polymorphic_function.add_instantiation(unit, context, comptime_parameter_instantiations, maybe_global orelse unreachable, current_function); return V.Comptime{ @@ -9909,6 +9956,7 @@ pub const Builder = struct { .local = false, .level = builder.current_scope.level + 1, .parent = builder.current_scope, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, }, .fields = try DynamicBoundedArray(Type.Error.Field.Index).init(context.arena, @intCast(nodes.len)), @@ -10868,7 +10916,7 @@ pub const Builder = struct { .expression = expression_to_slice, .index = 0, }, - }); + }); try builder.appendInstruction(unit, context, extract_pointer); const gep = try unit.instructions.append(context.my_allocator, .{ @@ -10879,7 +10927,7 @@ pub const Builder = struct { .name = try unit.processIdentifier(context, "slice_comptime_expression_slice"), .is_struct = false, }, - }); + }); try builder.appendInstruction(unit, context, gep); break :slice V{ @@ -10950,7 +10998,7 @@ pub const Builder = struct { .value = expression_to_slice, .type = pointer.type, }, - }); + }); try builder.appendInstruction(unit, context, load); const gep = try unit.instructions.append(context.my_allocator, .{ .get_element_pointer = .{ @@ -10989,7 +11037,7 @@ pub const Builder = struct { .insert_value = .{ .expression = .{ .value = .{ - .@"comptime" = .@"undefined", + .@"comptime" = .undefined, }, .type = destination_type_index, }, @@ -11667,7 +11715,7 @@ pub const Builder = struct { .@"comptime" = .{ .string_literal = hash, }, - }, + }, .type = ty, }; }, @@ -14225,14 +14273,14 @@ pub const Builder = struct { const local_declaration = unit.local_declarations.get(declaration_index); assert(builder.current_scope.kind == .block); - try builder.current_scope.declarations.put_no_clobber(context.my_allocator, identifier_hash, &local_declaration.declaration); + try builder.current_scope.declarations.put_no_clobber(identifier_hash, &local_declaration.declaration); if (emit) { const stack = try builder.createStackVariable(unit, context, declaration_type, null); assert(builder.current_scope.kind == .block); const local_scope: *Debug.Scope.Local = @fieldParentPtr("scope", builder.current_scope); - try local_scope.local_declaration_map.put_no_clobber(context.my_allocator, local_declaration, stack); + try local_scope.local_declaration_map.put_no_clobber(local_declaration, stack); const debug_declare_local = try unit.instructions.append(context.my_allocator, .{ .debug_declare_local_variable = .{ @@ -14276,7 +14324,9 @@ pub const Builder = struct { .level = builder.current_scope.level + 1, .local = builder.current_scope.local, .file = builder.current_file, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), }, + .local_declaration_map = try PinnedHashMap(*Debug.Declaration.Local, Instruction.Index).init(std.mem.page_size), }, }); @@ -16323,7 +16373,7 @@ pub const Builder = struct { .value = result, .type = ti, }, - }); + }); try builder.appendInstruction(unit, context, zero_extend); return .{ @@ -16933,28 +16983,27 @@ pub const Unit = struct { constant_arrays: V.Comptime.ConstantArray.List = .{}, constant_slices: V.Comptime.ConstantSlice.List = .{}, error_fields: Type.Error.Field.List = .{}, - file_token_offsets: MyHashMap(Token.Range, Debug.File.Index) = .{}, - file_map: MyHashMap([]const u8, Debug.File.Index) = .{}, - identifiers: MyHashMap(u32, []const u8) = .{}, - string_literal_values: MyHashMap(u32, [:0]const u8) = .{}, - string_literal_globals: MyHashMap(u32, *Debug.Declaration.Global) = .{}, + file_token_offsets: PinnedHashMap(Token.Range, Debug.File.Index), + file_map: PinnedHashMap([]const u8, Debug.File.Index), + identifiers: PinnedHashMap(u32, []const u8), + string_literal_values: PinnedHashMap(u32, [:0]const u8), + string_literal_globals: PinnedHashMap(u32, *Debug.Declaration.Global), - optionals: MyHashMap(Type.Index, Type.Index) = .{}, - pointers: MyHashMap(Type.Pointer, Type.Index) = .{}, - slices: MyHashMap(Type.Slice, Type.Index) = .{}, - arrays: MyHashMap(Type.Array, Type.Index) = .{}, - integers: MyHashMap(Type.Integer, Type.Index) = .{}, - error_unions: MyHashMap(Type.Error.Union.Descriptor, Type.Index) = .{}, - two_structs: MyHashMap([2]Type.Index, Type.Index) = .{}, - fields_array: MyHashMap(Type.Index, *Debug.Declaration.Global) = .{}, - name_functions: MyHashMap(Type.Index, *Debug.Declaration.Global) = .{}, - error_count: u32 = 0, + optionals: PinnedHashMap(Type.Index, Type.Index), + pointers: PinnedHashMap(Type.Pointer, Type.Index), + slices: PinnedHashMap(Type.Slice, Type.Index), + arrays: PinnedHashMap(Type.Array, Type.Index), + integers: PinnedHashMap(Type.Integer, Type.Index), + error_unions: PinnedHashMap(Type.Error.Union.Descriptor, Type.Index), + two_structs: PinnedHashMap([2]Type.Index, Type.Index), + fields_array: PinnedHashMap(Type.Index, *Debug.Declaration.Global), + name_functions: PinnedHashMap(Type.Index, *Debug.Declaration.Global), - code_to_emit: MyHashMap(Function.Definition.Index, *Debug.Declaration.Global) = .{}, + external_functions: PinnedHashMap(Type.Index, *Debug.Declaration.Global), + type_declarations: PinnedHashMap(Type.Index, *Debug.Declaration.Global), + test_functions: PinnedHashMap(*Debug.Declaration.Global, *Debug.Declaration.Global), + code_to_emit: PinnedHashMap(Function.Definition.Index, *Debug.Declaration.Global), data_to_emit: PinnedArray(*Debug.Declaration.Global), - external_functions: MyHashMap(Type.Index, *Debug.Declaration.Global) = .{}, - type_declarations: MyHashMap(Type.Index, *Debug.Declaration.Global) = .{}, - test_functions: MyHashMap(*Debug.Declaration.Global, *Debug.Declaration.Global) = .{}, scope: Debug.Scope.Global = .{ .scope = .{ .file = .null, @@ -16963,6 +17012,13 @@ pub const Unit = struct { .column = 0, .level = 0, .local = false, + .declarations = .{ + .key_pointer = undefined, + .value_pointer = undefined, + .length = 0, + .granularity = 0, + .committed = 0, + }, }, }, root_package: *Package = undefined, @@ -16975,6 +17031,7 @@ pub const Unit = struct { discard_identifiers: usize = 0, anon_i: usize = 0, anon_arr: usize = 0, + error_count: u32 = 0, fn dumpInstruction(instruction_index: Instruction.Index) !void { try write(.ir, "%"); @@ -17309,7 +17366,7 @@ pub const Unit = struct { .@"struct" = optional_struct_index, }); - try unit.optionals.put_no_clobber(context.my_allocator, element_type, optional_type_index); + try unit.optionals.put_no_clobber(element_type, optional_type_index); return optional_type_index; } @@ -17322,7 +17379,7 @@ pub const Unit = struct { const type_index = try unit.types.append(context.my_allocator, .{ .pointer = pointer, }); - try unit.pointers.put_no_clobber(context.my_allocator, pointer, type_index); + try unit.pointers.put_no_clobber(pointer, type_index); return type_index; } @@ -17335,7 +17392,7 @@ pub const Unit = struct { const type_index = try unit.types.append(context.my_allocator, .{ .slice = slice, }); - try unit.slices.put_no_clobber(context.my_allocator, slice, type_index); + try unit.slices.put_no_clobber(slice, type_index); return type_index; } @@ -17349,7 +17406,7 @@ pub const Unit = struct { const array_type = try unit.types.append(context.my_allocator, .{ .array = array, }); - try unit.arrays.put_no_clobber(context.my_allocator, array, array_type); + try unit.arrays.put_no_clobber(array, array_type); return array_type; } @@ -17381,7 +17438,7 @@ pub const Unit = struct { const type_index = try unit.types.append(context.my_allocator, .{ .integer = integer, }); - try unit.integers.put_no_clobber(context.my_allocator, integer, type_index); + try unit.integers.put_no_clobber(integer, type_index); return type_index; } }, @@ -17391,9 +17448,10 @@ pub const Unit = struct { } fn processIdentifier(unit: *Unit, context: *const Context, string: []const u8) !u32 { + _ = context; // autofix const hash = my_hash(string); if (unit.identifiers.get_pointer(hash) == null) { - try unit.identifiers.put_no_clobber(context.my_allocator, hash, string); + try unit.identifiers.put_no_clobber(hash, string); } return hash; } @@ -17434,7 +17492,7 @@ pub const Unit = struct { fixed_string.len += 1; fixed_string[zero_index] = 0; - const string = fixed_string[0 .. zero_index :0]; + const string = fixed_string[0..zero_index :0]; return string; } @@ -17508,7 +17566,7 @@ pub const Unit = struct { file.lexer = try lexer.analyze(file.source_code, &unit.token_buffer); assert(file.status == .loaded_into_memory); file.status = .lexed; - try unit.file_token_offsets.put_no_clobber(context.my_allocator, .{ + try unit.file_token_offsets.put_no_clobber(.{ .start = file.lexer.offset, .count = file.lexer.count, }, file_index); @@ -17582,18 +17640,21 @@ pub const Unit = struct { const file_index = try unit.files.append(context.my_allocator, Debug.File{ .relative_path = relative_path, .package = package, - .scope = .{ .scope = .{ - .file = .null, - .kind = .file, - .line = 0, - .column = 0, - .local = false, - .level = 1, - } }, + .scope = .{ + .scope = .{ + .file = .null, + .kind = .file, + .line = 0, + .column = 0, + .local = false, + .level = 1, + .declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size), + }, + }, }); // logln(.compilation, .new_file, "Adding file #{}: {s}\n", .{ file_index, full_path }); - try unit.file_map.put_no_clobber(context.my_allocator, full_path, file_index); + try unit.file_map.put_no_clobber(full_path, file_index); return .{ .index = file_index, @@ -17642,6 +17703,7 @@ pub const Unit = struct { .path = main_package_absolute_directory_path, }, .source_path = try context.my_allocator.duplicate_bytes(std.fs.path.basename(unit.descriptor.main_package_path)), + .dependencies = try PinnedHashMap([]const u8, *Package).init(std.mem.page_size), }; break :blk result; }; @@ -17655,6 +17717,7 @@ pub const Unit = struct { .path = directory_path, }, .source_path = "test_runner.nat", + .dependencies = try PinnedHashMap([]const u8, *Package).init(std.mem.page_size), }; unit.main_package = main_package; @@ -17689,9 +17752,10 @@ pub const Unit = struct { .handle = try std.fs.openDirAbsolute(package_descriptor.directory_path, .{}), }, .source_path = try std.mem.concat(context.allocator, u8, &.{ package_descriptor.name, ".nat" }), + .dependencies = try PinnedHashMap([]const u8, *Package).init(std.mem.page_size), }; - try unit.root_package.addDependency(context.my_allocator, package_descriptor.name, package); + try unit.root_package.addDependency(package_descriptor.name, package); package_ptr.* = package; } @@ -17763,7 +17827,7 @@ pub const Unit = struct { .@"struct" = two_struct, }); - try unit.two_structs.put_no_clobber(context.my_allocator, types, type_index); + try unit.two_structs.put_no_clobber(types, type_index); return type_index; } @@ -17838,11 +17902,11 @@ pub const Token = struct { length: u32, id: Token.Id, - pub const Buffer = struct{ + pub const Buffer = struct { line_offsets: PinnedArray(u32) = .{}, tokens: PinnedArray(Token) = .{}, }; - + pub const Id = enum { keyword_unsigned_integer, keyword_signed_integer, diff --git a/bootstrap/backend/llvm.zig b/bootstrap/backend/llvm.zig index f0960c7..220eb91 100644 --- a/bootstrap/backend/llvm.zig +++ b/bootstrap/backend/llvm.zig @@ -6,10 +6,11 @@ const write = Compilation.write; // const log = Compilation.log; // const logln = Compilation.logln; const Module = Compilation.Module; -const data_structures = @import("../library.zig"); -const BoundedArray = data_structures.BoundedArray; -const MyHashMap = data_structures.MyHashMap; -const PinnedArray = data_structures.PinnedArray; +const library = @import("../library.zig"); +const BoundedArray = library.BoundedArray; +const PinnedHashMap = library.PinnedHashMap; +const PinnedArray = library.PinnedArray; +const format_int = library.format_int; pub const bindings = @import("llvm_bindings.zig"); @@ -28,23 +29,23 @@ pub const LLVM = struct { module: *LLVM.Module, builder: *LLVM.Builder, debug_info_builder: *LLVM.DebugInfo.Builder, - debug_info_file_map: MyHashMap(Compilation.Debug.File.Index, *LLVM.DebugInfo.File) = .{}, - debug_type_map: MyHashMap(Compilation.Type.Index, *LLVM.DebugInfo.Type) = .{}, - type_name_map: MyHashMap(Compilation.Type.Index, []const u8) = .{}, - type_map: MyHashMap(Compilation.Type.Index, *LLVM.Type) = .{}, - function_declaration_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{}, - function_definition_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{}, - llvm_instruction_map: MyHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{}, - llvm_value_map: MyHashMap(Compilation.V, *LLVM.Value) = .{}, - llvm_block_map: MyHashMap(Compilation.BasicBlock.Index, *LLVM.Value.BasicBlock) = .{}, - llvm_external_functions: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{}, - global_variable_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.GlobalVariable) = .{}, - scope_map: MyHashMap(*Compilation.Debug.Scope, *LLVM.DebugInfo.Scope) = .{}, + debug_info_file_map: PinnedHashMap(Compilation.Debug.File.Index, *LLVM.DebugInfo.File), + debug_type_map: PinnedHashMap(Compilation.Type.Index, *LLVM.DebugInfo.Type), + type_name_map: PinnedHashMap(Compilation.Type.Index, []const u8), + type_map: PinnedHashMap(Compilation.Type.Index, *LLVM.Type), + function_declaration_map: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function), + function_definition_map: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function), + llvm_instruction_map: PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value), + llvm_value_map: PinnedHashMap(Compilation.V, *LLVM.Value), + llvm_block_map: PinnedHashMap(Compilation.BasicBlock.Index, *LLVM.Value.BasicBlock), + llvm_external_functions: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function), + global_variable_map: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.GlobalVariable), + scope_map: PinnedHashMap(*Compilation.Debug.Scope, *LLVM.DebugInfo.Scope), + argument_allocas: PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value), pointer_type: ?*LLVM.Type.Pointer = null, function: *LLVM.Value.Constant.Function = undefined, exit_block: *LLVM.Value.BasicBlock = undefined, sema_function: *Compilation.Debug.Declaration.Global = undefined, - argument_allocas: MyHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{}, return_phi_node: ?*LLVM.Value.Instruction.PhiNode = null, scope: *LLVM.DebugInfo.Scope = undefined, file: *LLVM.DebugInfo.File = undefined, @@ -1333,7 +1334,7 @@ pub const LLVM = struct { else => |t| @panic(@tagName(t)), }; - try llvm.type_map.put_no_clobber(context.my_allocator, type_index, llvm_type); + try llvm.type_map.put_no_clobber(type_index, llvm_type); return llvm_type; } @@ -1349,7 +1350,7 @@ pub const LLVM = struct { const filename = std.fs.path.basename(full_path); const directory = full_path[0 .. full_path.len - filename.len]; const debug_file = llvm.debug_info_builder.createFile(filename.ptr, filename.len, directory.ptr, directory.len) orelse unreachable; - try llvm.debug_info_file_map.put_no_clobber(context.my_allocator, sema_file_index, debug_file); + try llvm.debug_info_file_map.put_no_clobber(sema_file_index, debug_file); return debug_file; } } @@ -1360,7 +1361,7 @@ pub const LLVM = struct { } else { if (unit.type_declarations.get(sema_type_index)) |global_declaration| { const result = unit.getIdentifier(global_declaration.declaration.name); - try llvm.type_name_map.put_no_clobber(context.my_allocator, sema_type_index, result); + try llvm.type_name_map.put_no_clobber(sema_type_index, result); return result; } else { const sema_type = unit.types.get(sema_type_index); @@ -1369,7 +1370,7 @@ pub const LLVM = struct { .integer => |integer| switch (integer.kind) { .materialized_int => b: { var buffer: [65]u8 = undefined; - const format = data_structures.format_int(&buffer, integer.bit_count, 10, false); + const format = format_int(&buffer, integer.bit_count, 10, false); const slice_ptr = format.ptr - 1; const slice = slice_ptr[0 .. format.len + 1]; slice[0] = switch (integer.signedness) { @@ -1410,7 +1411,7 @@ pub const LLVM = struct { .array => |array| b: { name.appendAssumeCapacity('['); var buffer: [65]u8 = undefined; - const array_count = data_structures.format_int(&buffer, array.count, 10, false); + const array_count = format_int(&buffer, array.count, 10, false); name.appendSliceAssumeCapacity(array_count); name.appendAssumeCapacity(']'); const element_type_name = try llvm.renderTypeName(unit, context, array.type); @@ -1424,8 +1425,7 @@ pub const LLVM = struct { else => |t| @panic(@tagName(t)), }; - - try llvm.type_name_map.put(context.my_allocator, sema_type_index, if (name.len > 0) b: { + try llvm.type_name_map.put(sema_type_index, if (name.len > 0) b: { const new_name = try context.arena.new_array(u8, name.len); @memcpy(new_name, result); break :b new_name; @@ -1533,7 +1533,7 @@ pub const LLVM = struct { .forward_declaration = null, }); - try llvm.debug_type_map.put_no_clobber(context.my_allocator, sema_type_index, struct_type.toType()); + try llvm.debug_type_map.put_no_clobber(sema_type_index, struct_type.toType()); var field_types = BoundedArray(*LLVM.DebugInfo.Type, 512){}; bit_size = 0; @@ -1842,7 +1842,7 @@ pub const LLVM = struct { else => |t| @panic(@tagName(t)), }; - try llvm.debug_type_map.put(context.my_allocator, sema_type_index, result); + try llvm.debug_type_map.put(sema_type_index, result); assert(@intFromPtr(result) != 0xaaaa_aaaa_aaaa_aaaa); return result; @@ -1863,7 +1863,7 @@ pub const LLVM = struct { if (gep.is_struct and gep.index.type != .u32) unreachable; const gep_name = unit.getIdentifier(gep.name); const get_element_pointer = llvm.builder.createGEP(base_type, pointer, indices.ptr, indices.len, gep_name.ptr, gep_name.len, in_bounds) orelse unreachable; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, get_element_pointer); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, get_element_pointer); return get_element_pointer; } @@ -2047,7 +2047,7 @@ pub const LLVM = struct { basic_block_node.* = .{ .data = basic_block_index, }; - try llvm.llvm_block_map.put_no_clobber(context.my_allocator, basic_block_index, basic_block); + try llvm.llvm_block_map.put_no_clobber(basic_block_index, basic_block); return basic_block_node; } @@ -2287,8 +2287,8 @@ pub const LLVM = struct { }); switch (declaration.initial_value) { - .function_declaration => try llvm.function_declaration_map.put_no_clobber(context.my_allocator, declaration, function), - .function_definition => try llvm.function_definition_map.put_no_clobber(context.my_allocator, declaration, function), + .function_declaration => try llvm.function_declaration_map.put_no_clobber(declaration, function), + .function_definition => try llvm.function_definition_map.put_no_clobber(declaration, function), else => unreachable, } @@ -2360,7 +2360,7 @@ pub const LLVM = struct { const function_definition = unit.function_definitions.get(function_definition_index); const scope = subprogram.toLocalScope().toScope(); - try llvm.scope_map.put_no_clobber(context.my_allocator, &function_definition.scope.scope, scope); + try llvm.scope_map.put_no_clobber(&function_definition.scope.scope, scope); }, .function_declaration => {}, else => |t| @panic(@tagName(t)), @@ -2368,7 +2368,7 @@ pub const LLVM = struct { } switch (declaration.initial_value) { - .function_declaration => try llvm.llvm_external_functions.put_no_clobber(context.my_allocator, declaration, function), + .function_declaration => try llvm.llvm_external_functions.put_no_clobber(declaration, function), .function_definition => {}, else => |t| @panic(@tagName(t)), } @@ -2419,6 +2419,19 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo .inreg = llvm_context.getAttributeFromEnum(.InReg, 0), .@"noalias" = llvm_context.getAttributeFromEnum(.NoAlias, 0), }, + .debug_info_file_map = try PinnedHashMap(Compilation.Debug.File.Index, *LLVM.DebugInfo.File).init(std.mem.page_size), + .debug_type_map = try PinnedHashMap(Compilation.Type.Index, *LLVM.DebugInfo.Type).init(std.mem.page_size), + .type_name_map = try PinnedHashMap(Compilation.Type.Index, []const u8).init(std.mem.page_size), + .type_map = try PinnedHashMap(Compilation.Type.Index, *LLVM.Type).init(std.mem.page_size), + .function_declaration_map = try PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function).init(std.mem.page_size), + .function_definition_map = try PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function).init(std.mem.page_size), + .llvm_instruction_map = try PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value).init(std.mem.page_size), + .llvm_value_map = try PinnedHashMap(Compilation.V, *LLVM.Value).init(std.mem.page_size), + .llvm_block_map = try PinnedHashMap(Compilation.BasicBlock.Index, *LLVM.Value.BasicBlock).init(std.mem.page_size), + .llvm_external_functions = try PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function).init(std.mem.page_size), + .global_variable_map = try PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.GlobalVariable).init(std.mem.page_size), + .scope_map = try PinnedHashMap(*Compilation.Debug.Scope, *LLVM.DebugInfo.Scope).init(std.mem.page_size), + .argument_allocas = try PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value).init(std.mem.page_size), }; if (unit.descriptor.generate_debug_information) { @@ -2442,7 +2455,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const compile_unit = llvm.debug_info_builder.createCompileUnit(LLVM.DebugInfo.Language.c, debug_info_file, producer, producer.len, is_optimized, flags, flags.len, runtime_version, splitname, splitname.len, debug_info_kind, DWOId, split_debug_inlining, debug_info_for_profiling, name_table_kind, ranges_base_address, sysroot, sysroot.len, sdk, sdk.len) orelse unreachable; llvm.scope = compile_unit.toScope(); - try llvm.scope_map.put_no_clobber(context.my_allocator, &unit.scope.scope, llvm.scope); + try llvm.scope_map.put_no_clobber(&unit.scope.scope, llvm.scope); } for (unit.external_functions.values()) |external_function_declaration| { @@ -2469,7 +2482,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo .string_literal => |hash| { const string_literal = unit.string_literal_values.get(hash).?; const global_variable = llvm.builder.createGlobalString(string_literal.ptr, string_literal.len, name.ptr, name.len, address_space, llvm.module) orelse unreachable; - try llvm.global_variable_map.put_no_clobber(context.my_allocator, global_declaration, global_variable); + try llvm.global_variable_map.put_no_clobber(global_declaration, global_variable); }, else => { const global_type = try llvm.getType(unit, context, global_declaration.declaration.type); @@ -2485,7 +2498,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const thread_local_mode = LLVM.ThreadLocalMode.not_thread_local; const externally_initialized = false; const global_variable = llvm.module.addGlobalVariable(global_type, constant, linkage, initializer, name.ptr, name.len, null, thread_local_mode, address_space, externally_initialized) orelse return LLVM.Value.Error.constant_int; - try llvm.global_variable_map.put_no_clobber(context.my_allocator, global_declaration, global_variable); + try llvm.global_variable_map.put_no_clobber(global_declaration, global_variable); }, } @@ -2513,7 +2526,11 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo global_variable.setInitializer(constant_initializer); } + var phis = try PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value.Instruction.PhiNode).init(0x1000); + for (llvm.function_definition_map.keys(), llvm.function_definition_map.values()) |function_declaration, function| { + phis.clear(); + const function_definition_index = function_declaration.getFunctionDefinitionIndex(); const function_definition = unit.function_definitions.get(function_definition_index); llvm.function = function; @@ -2528,15 +2545,13 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo llvm.scope = subprogram.toLocalScope().toScope(); } - var alloca_map = MyHashMap(Compilation.Instruction.Index, *LLVM.Value){}; + var alloca_map = try PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value).init(std.mem.page_size); var block_command_list = BasicBlockList{}; const entry_block_node = try llvm.createBasicBlock(context, function_definition.basic_blocks.pointer[0], "fn_entry"); block_command_list.append(entry_block_node); - var phis = MyHashMap(Compilation.Instruction.Index, *LLVM.Value.Instruction.PhiNode){}; - while (block_command_list.len != 0) { const block_node = block_command_list.first orelse unreachable; const basic_block_index = block_node.data; @@ -2557,7 +2572,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo assert(@intFromEnum(push_scope.old.kind) >= @intFromEnum(Compilation.Debug.Scope.Kind.function)); const lexical_block = llvm.debug_info_builder.createLexicalBlock(old_scope, llvm.file, push_scope.new.line + 1, push_scope.new.column + 1) orelse unreachable; - try llvm.scope_map.put_no_clobber(context.my_allocator, push_scope.new, lexical_block.toScope()); + try llvm.scope_map.put_no_clobber(push_scope.new, lexical_block.toScope()); llvm.scope = lexical_block.toScope(); } }, @@ -2616,7 +2631,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo }, .number_literal => |literal| { var buffer: [65]u8 = undefined; - const number_literal = data_structures.format_int(&buffer, literal, 16, false); + const number_literal = format_int(&buffer, literal, 16, false); const slice_ptr = number_literal.ptr - 4; const literal_slice = slice_ptr[0 .. number_literal.len + 4]; literal_slice[0] = '$'; @@ -2632,7 +2647,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo } else { const value = try llvm.emitLeftValue(unit, context, sema_value); var buffer: [65]u8 = undefined; - const operand_number = data_structures.format_int(&buffer, operand_values.len, 16, false); + const operand_number = format_int(&buffer, operand_values.len, 16, false); const slice_ptr = operand_number.ptr - 2; const operand_slice = slice_ptr[0 .. operand_number.len + 2]; operand_slice[0] = '$'; @@ -2676,7 +2691,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const inline_assembly = LLVM.Value.InlineAssembly.get(function_type, &assembly_statements.buffer, assembly_statements.len, &constraints.buffer, constraints.len, has_side_effects, is_align_stack, dialect, can_throw) orelse return LLVM.Value.Error.inline_assembly; const call = llvm.builder.createCall(function_type, inline_assembly.toValue(), &operand_values.buffer, operand_values.len, "", "".len, null) orelse return LLVM.Value.Instruction.Error.call; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, call.toValue()); }, .stack_slot => |stack_slot| { // const stack_slot_type = unit.types.get(stack_slot.type); @@ -2685,8 +2700,8 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const type_alignment = unit.types.get(stack_slot.type).getAbiAlignment(unit); const alloca_array_size = null; const declaration_alloca = llvm.builder.createAlloca(declaration_type, address_space, alloca_array_size, "", "".len, type_alignment) orelse return LLVM.Value.Instruction.Error.alloca; - try alloca_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue()); - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue()); + try alloca_map.put_no_clobber(instruction_index, declaration_alloca.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, declaration_alloca.toValue()); }, .store => |store| { const right = try llvm.emitRightValue(unit, context, store.source); @@ -2706,7 +2721,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const cast_type = LLVM.Value.Instruction.Cast.Type.int_to_pointer; const cast_name = @tagName(cast_type); const cast_instruction = llvm.builder.createCast(cast_type, value, value.getType(), cast_name.ptr, cast_name.len) orelse return LLVM.Value.Instruction.Error.cast; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, cast_instruction); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, cast_instruction); }, .array_bitcast_to_integer => unreachable, // TODO: Poke metadata @@ -2724,27 +2739,27 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo .pointer_source_type_to_destination_type, .pointer_none_terminated_to_zero, => { - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, value); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, value); }, .sign_extend => { const sign_extend = llvm.builder.createCast(.sign_extend, value, dest_type, "sign_extend", "sign_extend".len) orelse return LLVM.Value.Instruction.Error.cast; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, sign_extend); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, sign_extend); }, .zero_extend => { const zero_extend = llvm.builder.createCast(.zero_extend, value, dest_type, "zero_extend", "zero_extend".len) orelse return LLVM.Value.Instruction.Error.cast; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, zero_extend); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, zero_extend); }, .bitcast => { const bitcast = llvm.builder.createCast(.bitcast, value, dest_type, "bitcast", "bitcast".len) orelse return LLVM.Value.Instruction.Error.cast; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, bitcast); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, bitcast); }, .pointer_to_int => { const pointer_to_int = llvm.builder.createCast(.pointer_to_int, value, dest_type, "pointer_to_int", "pointer_to_int".len) orelse return LLVM.Value.Instruction.Error.cast; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, pointer_to_int); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, pointer_to_int); }, .truncate => { const truncate = llvm.builder.createCast(.truncate, value, dest_type, "truncate", "truncate".len) orelse return LLVM.Value.Instruction.Error.cast; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, truncate); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, truncate); }, .error_union_type_int_to_pointer, .error_union_type_upcast, .error_union_type_downcast => unreachable, } @@ -2761,7 +2776,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo }, else => |t| @panic(@tagName(t)), }; - try llvm.llvm_value_map.put_no_clobber(context.my_allocator, load.value, value); + try llvm.llvm_value_map.put_no_clobber(load.value, value); break :blk value; }; @@ -2771,7 +2786,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const value_type = try llvm.getType(unit, context, load.type); const is_volatile = false; const load_i = llvm.builder.createLoad(value_type, value, is_volatile, "", "".len, alignment) orelse return LLVM.Value.Instruction.Error.load; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, load_i.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, load_i.toValue()); }, .integer_binary_operation => |binary_operation| { assert(binary_operation.left.type == binary_operation.right.type); @@ -2810,7 +2825,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo }, else => unreachable, }; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, instruction); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, instruction); }, .call => |sema_call| { var argument_buffer: [32]*LLVM.Value = undefined; @@ -2861,7 +2876,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo else => |t| @panic(@tagName(t)), }; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, call.toValue()); try llvm.setCallOrFunctionAttributes(unit, context, function_prototype, .{ .call = call, @@ -2918,14 +2933,14 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo }; const call_to_asm = llvm.builder.createCall(function_type, inline_asm.toValue(), syscall_arguments.ptr, syscall_arguments.len, "syscall", "syscall".len, null) orelse return LLVM.Value.Instruction.Error.call; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call_to_asm.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, call_to_asm.toValue()); }, .@"unreachable" => { _ = llvm.builder.createUnreachable() orelse return LLVM.Value.Instruction.Error.@"unreachable"; }, .abi_argument => |argument_index| { const argument = llvm.function.getArgument(argument_index) orelse unreachable; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, argument.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, argument.toValue()); }, .debug_declare_argument => |debug_declare| { if (generate_debug_information) { @@ -3024,7 +3039,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const value = try llvm.emitRightValue(unit, context, insert_value.new_value); const indices = [1]c_uint{insert_value.index}; const instruction = llvm.builder.createInsertValue(aggregate, value, &indices, indices.len, "", "".len) orelse unreachable; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, instruction); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, instruction); }, .extract_value => |extract_value| { switch (unit.types.get(extract_value.expression.type).*) { @@ -3037,7 +3052,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo assert(!aggregate.getType().isPointer()); const indices = [1]c_uint{extract_value.index}; const instruction = llvm.builder.createExtractValue(aggregate, &indices, indices.len, "", "".len) orelse unreachable; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, instruction); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, instruction); }, .integer_compare => |integer_compare| { assert(integer_compare.left.type == integer_compare.right.type); @@ -3057,7 +3072,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo .signed_greater_equal => .sge, }; const icmp = llvm.builder.createICmp(comparison_id, left, right, "", "".len) orelse unreachable; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, icmp); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, icmp); }, .jump => |jump| { const target_block = if (llvm.llvm_block_map.get(jump.to)) |target_block| target_block else blk: { @@ -3070,7 +3085,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo }; const br = llvm.builder.createBranch(target_block) orelse unreachable; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, br.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, br.toValue()); }, .branch => |branch| { const taken_node = try llvm.createBasicBlock(context, branch.taken, "taken_block"); @@ -3087,7 +3102,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const branch_weights = null; const unpredictable = null; const br = llvm.builder.createConditionalBranch(condition, taken_block, not_taken_block, branch_weights, unpredictable) orelse unreachable; - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, br.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, br.toValue()); }, .phi => |phi| { const phi_type = try llvm.getType(unit, context, phi.type); @@ -3095,9 +3110,9 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const phi_name = "phi"; const phi_node = llvm.builder.createPhi(phi_type, reserved_value_count, phi_name, phi_name.len) orelse unreachable; - try phis.put_no_clobber(context.my_allocator, instruction_index, phi_node); + try phis.put_no_clobber(instruction_index, phi_node); - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, phi_node.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, phi_node.toValue()); }, .umin => |umin| { const intrinsic_type = try llvm.getType(unit, context, umin.type); @@ -3106,7 +3121,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const right = try llvm.emitRightValue(unit, context, umin.right); const arguments = [_]*LLVM.Value{ left, right }; const intrinsic_call = try llvm.callIntrinsic("llvm.umin", ¶meter_types, &arguments); - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, intrinsic_call); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, intrinsic_call); }, .get_element_pointer => { _ = try llvm.createGEP(unit, context, instruction_index); @@ -3115,7 +3130,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const parameter_types: []const *LLVM.Type = &.{}; const parameter_values: []const *LLVM.Value = &.{}; const intrinsic_call = try llvm.callIntrinsic("llvm.trap", parameter_types, parameter_values); - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, intrinsic_call); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, intrinsic_call); }, .add_overflow => |add_overflow| { const intrinsic_type = try llvm.getType(unit, context, add_overflow.type); @@ -3124,7 +3139,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const right = try llvm.emitRightValue(unit, context, add_overflow.right); const arguments = [_]*LLVM.Value{ left, right }; const intrinsic_call = try llvm.callIntrinsic("llvm.sadd.with.overflow", ¶meter_types, &arguments); - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, intrinsic_call); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, intrinsic_call); }, .trailing_zeroes => |v| { const intrinsic_type = try llvm.getType(unit, context, v.type); @@ -3133,7 +3148,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const is_poison = llvm.context.getConstantInt(1, 0, false) orelse unreachable; const arguments = [_]*LLVM.Value{ value, is_poison.toValue() }; const intrinsic_call = try llvm.callIntrinsic("llvm.cttz", ¶meter_types, &arguments); - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, intrinsic_call); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, intrinsic_call); }, .@"switch" => |switch_expression| { const condition = try llvm.emitRightValue(unit, context, switch_expression.condition); @@ -3165,7 +3180,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo const branch_weights = null; const unpredictable = null; const switch_instruction = llvm.builder.createSwitch(condition, else_block, &condition_array.buffer, &basic_block_array.buffer, condition_array.len, branch_weights, unpredictable); - try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, switch_instruction.toValue()); + try llvm.llvm_instruction_map.put_no_clobber(instruction_index, switch_instruction.toValue()); }, .memcpy => |memcpy| { const destination = try llvm.emitLeftValue(unit, context, memcpy.destination); diff --git a/bootstrap/library.zig b/bootstrap/library.zig index 993cb04..3a623a6 100644 --- a/bootstrap/library.zig +++ b/bootstrap/library.zig @@ -11,13 +11,13 @@ pub fn assert(ok: bool) void { pub const Allocator = std.mem.Allocator; pub const BoundedArray = std.BoundedArray; -pub const Arena = struct{ +pub const Arena = struct { position: u64, commit_position: u64, alignment: u64, size: u64, - pub const Temporary = struct{ + pub const Temporary = struct { arena: *Arena, position: u64, }; @@ -71,7 +71,7 @@ pub const Arena = struct{ } } - pub inline fn new(arena: *Arena, comptime T: type) !*T{ + pub inline fn new(arena: *Arena, comptime T: type) !*T { const result: *T = @ptrCast(@alignCast(try arena.allocate(@sizeOf(T)))); return result; } @@ -83,7 +83,7 @@ pub const Arena = struct{ }; pub fn DynamicBoundedArray(comptime T: type) type { - return struct{ + return struct { pointer: [*]T = @constCast((&[_]T{}).ptr), length: u32 = 0, capacity: u32 = 0, @@ -114,7 +114,7 @@ pub fn DynamicBoundedArray(comptime T: type) type { array.length += count; } - pub fn slice(array: *Array) []T{ + pub fn slice(array: *Array) []T { return array.pointer[0..array.length]; } }; @@ -123,24 +123,26 @@ pub fn DynamicBoundedArray(comptime T: type) type { const pinned_array_page_size = 2 * 1024 * 1024; const pinned_array_max_size = std.math.maxInt(u32) - pinned_array_page_size; const pinned_array_default_granularity = pinned_array_page_size; -/// This must be used with big arrays + +// This must be used with big arrays, which are not resizeable (can't be cleared) pub fn PinnedArray(comptime T: type) type { - return struct{ + return struct { pointer: [*]T = @constCast((&[_]T{}).ptr), length: u32 = 0, granularity: u32 = 0, - pub const Index = enum(u32){ + pub const Index = enum(u32) { null = 0xffff_ffff, _, }; const Array = @This(); - pub fn const_slice(array: *const Array) []const T{ + pub fn const_slice(array: *const Array) []const T { return array.pointer[0..array.length]; } - pub fn slice(array: *Array) []T{ + + pub fn slice(array: *Array) []T { return array.pointer[0..array.length]; } @@ -155,14 +157,15 @@ pub fn PinnedArray(comptime T: type) type { return array.get_unchecked(i); } - pub fn get_index(array: *Array, item: *T) Index{ + pub fn get_index(array: *Array, item: *T) Index { const many_item: [*]T = @ptrCast(item); const result = @intFromPtr(many_item) - @intFromPtr(array.pointer); assert(result < pinned_array_max_size); return @enumFromInt(@divExact(result, @sizeOf(T))); } - pub fn init(granularity: u32) !Array{ + pub fn init(granularity: u32) !Array { + assert(granularity & 0xfff == 0); const raw_ptr = try reserve(pinned_array_max_size); try commit(raw_ptr, granularity); return Array{ @@ -172,30 +175,30 @@ pub fn PinnedArray(comptime T: type) type { }; } - pub fn init_with_default_granularity() !Array{ + pub fn init_with_default_granularity() !Array { return try Array.init(pinned_array_default_granularity); } - pub fn append(array: *Array, item: T) *T { - if (((array.length + 1) * @sizeOf(T)) & (array.granularity - 1) == 0) { - const length: u64 = array.length; - assert((length + 1) * @sizeOf(T) <= pinned_array_max_size); + pub fn ensure_capacity(array: *Array, additional: u32) void { + const length = array.length; + const size = length * @sizeOf(T); + const granularity_aligned_size = align_forward(size, array.granularity); + const new_size = size + additional * @sizeOf(T); + if (granularity_aligned_size < new_size) { + assert((length + additional) * @sizeOf(T) <= pinned_array_max_size); + const new_granularity_aligned_size = align_forward(new_size, array.granularity); const ptr: [*]u8 = @ptrCast(array.pointer); - commit(ptr + ((length + 1) * @sizeOf(T)), array.granularity) catch unreachable; + commit(ptr + granularity_aligned_size, new_granularity_aligned_size - granularity_aligned_size) catch unreachable; } + } + pub fn append(array: *Array, item: T) *T { + array.ensure_capacity(1); return array.append_with_capacity(item); } pub fn append_slice(array: *Array, items: []const T) void { - const count: u32 = @intCast(items.len); - if (((array.length + count) * @sizeOf(T)) & (array.granularity - 1) == 0) { - const length: u64 = array.length; - assert((length + count) * @sizeOf(T) <= pinned_array_max_size); - const ptr: [*]u8 = @ptrCast(array.pointer); - commit(ptr + ((length + count) * @sizeOf(T)), array.granularity) catch unreachable; - } - + array.ensure_capacity(@intCast(items.len)); array.append_slice_with_capacity(items); } @@ -218,7 +221,7 @@ pub fn PinnedArray(comptime T: type) type { }; } -pub fn reserve(size: u64) ![*]u8{ +pub fn reserve(size: u64) ![*]u8 { return switch (os) { .linux, .macos => (try std.posix.mmap(null, size, std.posix.PROT.NONE, .{ .ANONYMOUS = true, @@ -229,7 +232,7 @@ pub fn reserve(size: u64) ![*]u8{ }; } -pub fn commit(bytes: [*]u8, size: u64) !void{ +pub fn commit(bytes: [*]u8, size: u64) !void { const slice = bytes[0..size]; return switch (os) { .linux, .macos => try std.posix.mprotect(@alignCast(slice), std.posix.PROT.WRITE | std.posix.PROT.READ), @@ -445,41 +448,37 @@ const MapResult = struct { capacity: IndexType, }; -fn ensure_capacity_hashmap(allocator: *MyAllocator, current_capacity: IndexType, desired_capacity: IndexType, key_pointer: [*]u8, value_pointer: [*]u8, length: IndexType, key_size: IndexType, key_alignment: u16, value_size: IndexType, value_alignment: u16) !MapResult { - var new_capacity = @max(current_capacity, initial_item_count); - while (new_capacity < desired_capacity) { - new_capacity *= factor; - } +const pinned_hash_map_page_size = 2 * 1024 * 1024; +const pinned_hash_map_max_size = std.math.maxInt(u32) - pinned_hash_map_page_size; +const pinned_hash_map_default_granularity = pinned_hash_map_page_size; - if (new_capacity > current_capacity) { - const old_key_slice = key_pointer[0 .. length * key_size]; - const old_value_slice = value_pointer[0 .. length * value_size]; - const new_key_slice = try allocator.reallocate(old_key_slice, new_capacity * key_size, key_alignment); - const new_value_slice = try allocator.reallocate(old_value_slice, new_capacity * value_size, value_alignment); - - return .{ - .key_pointer = new_key_slice.ptr, - .value_pointer = new_value_slice.ptr, - .capacity = new_capacity, - }; - } else { - return .{ - .capacity = current_capacity, - .key_pointer = key_pointer, - .value_pointer = value_pointer, - }; - } -} - -pub fn MyHashMap(comptime K: type, comptime V: type) type { - // const K = []const u8; +pub fn PinnedHashMap(comptime K: type, comptime V: type) type { return struct { - key_pointer: [*]K = undefined, - value_pointer: [*]V = undefined, - length: IndexType = 0, - capacity: IndexType = 0, + key_pointer: [*]K, + value_pointer: [*]V, + length: u32, + granularity: u32, + committed: u32, - pub fn get_pointer(map: *@This(), key: K) ?*V { + const Map = @This(); + + pub fn init(granularity: u32) !Map { + assert(granularity & 0xfff == 0); + const key_raw_pointer = try reserve(pinned_hash_map_max_size); + try commit(key_raw_pointer, granularity); + const value_raw_pointer = try reserve(pinned_hash_map_max_size); + try commit(value_raw_pointer, granularity); + + return Map{ + .key_pointer = @alignCast(@ptrCast(key_raw_pointer)), + .value_pointer = @alignCast(@ptrCast(value_raw_pointer)), + .length = 0, + .granularity = granularity, + .committed = 1, + }; + } + + pub fn get_pointer(map: *Map, key: K) ?*V { for (map.keys(), 0..) |k, i| { const is_equal = switch (@typeInfo(K)) { .Pointer => |pointer| switch (pointer.size) { @@ -506,20 +505,20 @@ pub fn MyHashMap(comptime K: type, comptime V: type) type { } } - pub fn put(map: *@This(), allocator: *MyAllocator, key: K, value: V) !void { - if (map.get_pointer(key)) |value_ptr| { - value_ptr.* = value; + pub fn put(map: *@This(), key: K, value: V) !void { + if (map.get_pointer(key)) |value_pointer| { + value_pointer.* = value; } else { const len = map.length; - try map.ensure_capacity(allocator, len + 1); + map.ensure_capacity(len + 1); map.put_at_with_capacity(len, key, value); } } - pub fn put_no_clobber(map: *@This(), allocator: *MyAllocator, key: K, value: V) !void { + pub fn put_no_clobber(map: *@This(), key: K, value: V) !void { assert(map.get_pointer(key) == null); const len = map.length; - try map.ensure_capacity(allocator, len + 1); + map.ensure_capacity(len + 1); map.put_at_with_capacity(len, key, value); } @@ -530,11 +529,33 @@ pub fn MyHashMap(comptime K: type, comptime V: type) type { map.value_pointer[index] = value; } - pub fn ensure_capacity(map: *@This(), allocator: *MyAllocator, desired_capacity: IndexType) !void { - const result = try ensure_capacity_hashmap(allocator, map.capacity, desired_capacity, @ptrCast(map.key_pointer), @ptrCast(map.value_pointer), map.length, @sizeOf(K), @alignOf(K), @sizeOf(V), @alignOf(V)); - map.capacity = result.capacity; - map.key_pointer = @ptrCast(@alignCast(result.key_pointer)); - map.value_pointer = @ptrCast(@alignCast(result.value_pointer)); + fn ensure_capacity(map: *Map, additional: u32) void { + const length = map.length; + assert((length + additional) * @sizeOf(K) <= pinned_array_max_size); + + { + const key_size = length * @sizeOf(K); + const key_granularity_aligned_size = align_forward(key_size, map.granularity); + const key_new_size = key_size + additional * @sizeOf(K); + + if (key_granularity_aligned_size < key_new_size) { + const new_key_granularity_aligned_size = align_forward(key_new_size, map.granularity); + const key_pointer: [*]u8 = @ptrCast(map.key_pointer); + commit(key_pointer + key_granularity_aligned_size, new_key_granularity_aligned_size - key_granularity_aligned_size) catch unreachable; + } + } + + { + const value_size = length * @sizeOf(V); + const value_granularity_aligned_size = align_forward(value_size, map.granularity); + const value_new_size = value_size + additional * @sizeOf(K); + + if (value_granularity_aligned_size < value_new_size) { + const new_value_granularity_aligned_size = align_forward(value_new_size, map.granularity); + const value_pointer: [*]u8 = @ptrCast(map.value_pointer); + commit(value_pointer + value_granularity_aligned_size, new_value_granularity_aligned_size - value_granularity_aligned_size) catch unreachable; + } + } } pub fn keys(map: *@This()) []K { @@ -544,6 +565,10 @@ pub fn MyHashMap(comptime K: type, comptime V: type) type { pub fn values(map: *@This()) []V { return map.value_pointer[0..map.length]; } + + pub fn clear(map: *Map) void { + map.length = 0; + } }; }