Delete old hashmap implementation

This commit is contained in:
David Gonzalez Martin 2024-04-25 18:43:26 -06:00
parent 0a50781ba4
commit 5539f1e904
3 changed files with 331 additions and 227 deletions

View File

@ -19,7 +19,7 @@ const PinnedArray = library.PinnedArray;
const UnpinnedArray = library.UnpinnedArray; const UnpinnedArray = library.UnpinnedArray;
const BlockList = library.BlockList; const BlockList = library.BlockList;
const MyAllocator = library.MyAllocator; const MyAllocator = library.MyAllocator;
const MyHashMap = library.MyHashMap; const PinnedHashMap = library.PinnedHashMap;
const span = library.span; const span = library.span;
const format_int = library.format_int; const format_int = library.format_int;
const my_hash = library.my_hash; 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_buffer = try PinnedArray(Node).init_with_default_granularity(),
.node_lists = try PinnedArray([]const Node.Index).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(), .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); try unit.compile(context);
@ -2941,7 +2959,7 @@ pub fn buildExecutable(context: *const Context, arguments: []const []const u8, o
if (i + 1 != arguments.len) { if (i + 1 != arguments.len) {
i += 1; i += 1;
c_source_files.appendSliceAssumeCapacity( arguments[i..]); c_source_files.appendSliceAssumeCapacity(arguments[i..]);
i = arguments.len; i = arguments.len;
} else { } else {
reportUnterminatedArgumentError(current_argument); 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_buffer = try PinnedArray(Node).init_with_default_granularity(),
.node_lists = try PinnedArray([]const Node.Index).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(), .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); try unit.compile(context);
@ -3052,10 +3088,10 @@ pub const Package = struct {
directory: Directory, directory: Directory,
/// Relative to the package main directory /// Relative to the package main directory
source_path: []const u8, 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 { fn addDependency(package: *Package, package_name: []const u8, new_dependency: *Package) !void {
try package.dependencies.put_no_clobber(allocator, package_name, new_dependency); try package.dependencies.put_no_clobber(package_name, new_dependency);
} }
}; };
@ -3298,6 +3334,7 @@ const _usize: Type.Index = .u64;
const _ssize: Type.Index = .s64; const _ssize: Type.Index = .s64;
fn serialize_comptime_parameters(unit: *Unit, context: *const Context, original_declaration: *Debug.Declaration, parameters: []const V.Comptime) !u32 { 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){}; var name = BoundedArray(u8, 4096){};
const original_name = unit.getIdentifier(original_declaration.name); const original_name = unit.getIdentifier(original_declaration.name);
name.appendSliceAssumeCapacity(original_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()); const hash = my_hash(name.slice());
// Don't allocate memory if not necessary // Don't allocate memory if not necessary
if (unit.identifiers.get(hash) == null) { 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; return hash;
@ -3364,7 +3401,7 @@ pub const Type = union(enum) {
pub const Polymorphic = struct { pub const Polymorphic = struct {
parameters: []const Token.Index, parameters: []const Token.Index,
instantiations: MyHashMap(u32, *Debug.Declaration.Global) = .{}, instantiations: PinnedHashMap(u32, *Debug.Declaration.Global),
node: Node.Index, node: Node.Index,
pub fn get_instantiation(polymorphic: *Polymorphic, types: []const V.Comptime) ?*Debug.Declaration.Global { 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 new_declaration = unit.global_declarations.get(new_declaration_index);
const parameter_hash = hash(parameters); 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 { fn hash(types: []const V.Comptime) u32 {
@ -3735,7 +3772,7 @@ pub const Instruction = union(enum) {
pub const max_value_count = 32; pub const max_value_count = 32;
const Value = struct{ const Value = struct {
value: V, value: V,
basic_block: BasicBlock.Index, 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 { pub const PolymorphicFunction = struct {
parameters: []const ComptimeParameterDeclaration, parameters: []const ComptimeParameterDeclaration,
instantiations: MyHashMap(u32, *Debug.Declaration.Global) = .{}, instantiations: PinnedHashMap(u32, *Debug.Declaration.Global),
node: Node.Index, node: Node.Index,
is_member_call: bool, is_member_call: bool,
@ -4150,7 +4187,7 @@ pub const PolymorphicFunction = struct {
const new_declaration = unit.global_declarations.get(new_declaration_index); const new_declaration = unit.global_declarations.get(new_declaration_index);
const parameter_hash = hash(parameters); 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; return new_declaration;
} }
@ -4298,7 +4335,7 @@ pub const Debug = struct {
}; };
pub const Scope = struct { pub const Scope = struct {
declarations: MyHashMap(u32, *Declaration) = .{}, declarations: PinnedHashMap(u32, *Declaration),
parent: ?*Scope = null, parent: ?*Scope = null,
file: File.Index, file: File.Index,
line: u32, line: u32,
@ -4314,7 +4351,7 @@ pub const Debug = struct {
pub const Local = struct { pub const Local = struct {
scope: Scope, scope: Scope,
local_declaration_map: MyHashMap(*Debug.Declaration.Local, Instruction.Index) = .{}, local_declaration_map: PinnedHashMap(*Debug.Declaration.Local, Instruction.Index),
}; };
pub const Global = struct { pub const Global = struct {
@ -4324,8 +4361,8 @@ pub const Debug = struct {
pub const Function = struct { pub const Function = struct {
scope: Scope, scope: Scope,
argument_map: MyHashMap(*Debug.Declaration.Argument, Instruction.Index) = .{}, argument_map: PinnedHashMap(*Debug.Declaration.Argument, Instruction.Index),
// comptime_parameters: MyHashMap(*Debug.Declaration.Argument, // comptime_parameters: PinnedArray(*Debug.Declaration.Argument,
}; };
fn lookupDeclaration(s: *Scope, name: u32, look_in_parent_scopes: bool) ?Lookup { 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, .{ const error_union_type_index = try unit.types.append(context.my_allocator, .{
.@"struct" = error_union_struct_index, .@"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; return error_union_type_index;
} }
@ -4597,7 +4634,7 @@ pub const Builder = struct {
} else { } else {
const string_name = try join_name(context, "__anon_str_", possible_id, 10); const string_name = try join_name(context, "__anon_str_", possible_id, 10);
const identifier = try unit.processIdentifier(context, string_name); 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, .{ const string_global_index = try unit.global_declarations.append(context.my_allocator, .{
.declaration = .{ .declaration = .{
@ -4637,7 +4674,7 @@ pub const Builder = struct {
const string_global = unit.global_declarations.get(string_global_index); 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); _ = unit.data_to_emit.append(string_global);
@ -4825,7 +4862,7 @@ pub const Builder = struct {
.destination = destination, .destination = destination,
.source = v, .source = v,
}, },
}); });
try builder.appendInstruction(unit, context, store); try builder.appendInstruction(unit, context, store);
const load = try unit.instructions.append(context.my_allocator, .{ const load = try unit.instructions.append(context.my_allocator, .{
@ -4833,7 +4870,7 @@ pub const Builder = struct {
.value = destination, .value = destination,
.type = type_index, .type = type_index,
}, },
}); });
try builder.appendInstruction(unit, context, load); try builder.appendInstruction(unit, context, load);
return V{ return V{
@ -5177,7 +5214,9 @@ pub const Builder = struct {
.kind = .function, .kind = .function,
.local = true, .local = true,
.level = builder.current_scope.level + 1, .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, .type = function_type_index,
.body = .null, .body = .null,
@ -5212,7 +5251,7 @@ pub const Builder = struct {
comptime assert(@TypeOf(argument_declaration_index) == Debug.Declaration.Argument.Index); comptime assert(@TypeOf(argument_declaration_index) == Debug.Declaration.Argument.Index);
const argument = unit.argument_declarations.get(argument_declaration_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 entry_block = try builder.newBasicBlock(unit, context);
const exit_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); 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.code_to_emit.put_no_clobber(function_definition_index, global);
try unit.name_functions.put_no_clobber(context.my_allocator, type_index, global); try unit.name_functions.put_no_clobber(type_index, global);
return global; return global;
} }
@ -5383,7 +5422,7 @@ pub const Builder = struct {
const global_declaration = unit.global_declarations.get(global_declaration_index); const global_declaration = unit.global_declarations.get(global_declaration_index);
_ = unit.data_to_emit.append(global_declaration); _ = 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; return global_declaration;
}, },
@ -5807,13 +5846,13 @@ pub const Builder = struct {
const function_definition_global = polymorphic_function.instantiations.values()[0]; const function_definition_global = polymorphic_function.instantiations.values()[0];
assert(function_definition_global.initial_value == .function_definition); 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; return function_definition_global;
}, },
.function_definition => |function_definition_index| { .function_definition => |function_definition_index| {
switch (unit.getNode(declaration_node_index).id) { 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 => { else => {
const actual_function_declaration = unit.code_to_emit.get(function_definition_index).?; const actual_function_declaration = unit.code_to_emit.get(function_definition_index).?;
global_declaration.initial_value = .{ global_declaration.initial_value = .{
@ -5824,7 +5863,7 @@ pub const Builder = struct {
}, },
.function_declaration => |function_type| { .function_declaration => |function_type| {
switch (unit.getNode(declaration_node_index).id) { 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 => { else => {
const actual_function_declaration = unit.external_functions.get(function_type).?; const actual_function_declaration = unit.external_functions.get(function_type).?;
global_declaration.initial_value = .{ global_declaration.initial_value = .{
@ -5841,7 +5880,7 @@ pub const Builder = struct {
unreachable; 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); assert(unit.type_declarations.get(type_index).? == global_declaration);
}, },
} }
@ -5856,7 +5895,7 @@ pub const Builder = struct {
.polymorphic_function => |*polymorphic_function| { .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_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; 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; return instantiation_global;
}, },
@ -7274,6 +7313,7 @@ pub const Builder = struct {
.local = false, .local = false,
.level = builder.current_scope.level + 1, .level = builder.current_scope.level + 1,
.parent = &unit.scope.scope, .parent = &unit.scope.scope,
.declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size),
}, },
}, },
.id = std.math.maxInt(u32), .id = std.math.maxInt(u32),
@ -7482,7 +7522,7 @@ pub const Builder = struct {
}); });
const comptime_parameter = unit.global_declarations.get(comptime_parameter_index); 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)), else => |t| @panic(@tagName(t)),
}, },
@ -7591,7 +7631,7 @@ pub const Builder = struct {
comptime assert(@TypeOf(argument_declaration_index) == Debug.Declaration.Argument.Index); comptime assert(@TypeOf(argument_declaration_index) == Debug.Declaration.Argument.Index);
const argument = unit.argument_declarations.get(argument_declaration_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 { fn classify_argument_type_aarch64(builder: *Builder, unit: *Unit, context: *const Context, type_index: Type.Index) Function.AbiInfo {
@ -8482,6 +8522,7 @@ pub const Builder = struct {
.level = builder.current_scope.level + 1, .level = builder.current_scope.level + 1,
.local = false, .local = false,
.file = builder.current_file, .file = builder.current_file,
.declarations = try PinnedHashMap(u32, *Debug.Declaration).init(std.mem.page_size),
}, },
}, },
.options = .{}, .options = .{},
@ -8572,7 +8613,7 @@ pub const Builder = struct {
.attributes = .{}, .attributes = .{},
}); });
const global_declaration = unit.global_declarations.get(global_declaration_index); 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) { const polymorphic_type_index = switch (parameter_types.len > 0) {
@ -8585,6 +8626,7 @@ pub const Builder = struct {
break :param heap_parameter_types; break :param heap_parameter_types;
}, },
.node = container_node_index, .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; const polymorphic_type = &unit.types.get(polymorphic_type_index).polymorphic;
@ -8648,6 +8690,7 @@ pub const Builder = struct {
.level = builder.current_scope.level + 1, .level = builder.current_scope.level + 1,
.local = false, .local = false,
.file = builder.current_file, .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, .level = builder.current_scope.level + 1,
.local = false, .local = false,
.file = builder.current_file, .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); 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, else => unreachable,
} }
@ -9078,15 +9122,15 @@ pub const Builder = struct {
const test_global = unit.global_declarations.get(test_global_index); 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); const global_declaration: *Debug.Declaration.Global = @fieldParentPtr("declaration", declaration);
if (global_declaration.attributes.contains(.@"export")) { if (global_declaration.attributes.contains(.@"export")) {
const result = try builder.referenceGlobalDeclaration(unit, context, &scope.scope, declaration, .{}, &.{}, null, &.{}); const result = try builder.referenceGlobalDeclaration(unit, context, &scope.scope, declaration, .{}, &.{}, null, &.{});
@ -9175,7 +9219,9 @@ pub const Builder = struct {
.local = true, .local = true,
.level = builder.current_scope.level + 1, .level = builder.current_scope.level + 1,
.file = builder.current_file, .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, .has_debug_info = true,
}); });
@ -9498,7 +9544,7 @@ pub const Builder = struct {
// else => |t| @panic(@tagName(t)), // 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, .{ const debug_declare_argument = try unit.instructions.append(context.my_allocator, .{
.debug_declare_argument = .{ .debug_declare_argument = .{
@ -9672,6 +9718,7 @@ pub const Builder = struct {
.node = function_node_index, .node = function_node_index,
.parameters = comptime_parameter_declarations, .parameters = comptime_parameter_declarations,
.is_member_call = is_member_call, .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); _ = try polymorphic_function.add_instantiation(unit, context, comptime_parameter_instantiations, maybe_global orelse unreachable, current_function);
return V.Comptime{ return V.Comptime{
@ -9909,6 +9956,7 @@ pub const Builder = struct {
.local = false, .local = false,
.level = builder.current_scope.level + 1, .level = builder.current_scope.level + 1,
.parent = builder.current_scope, .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)), .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, .expression = expression_to_slice,
.index = 0, .index = 0,
}, },
}); });
try builder.appendInstruction(unit, context, extract_pointer); try builder.appendInstruction(unit, context, extract_pointer);
const gep = try unit.instructions.append(context.my_allocator, .{ 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"), .name = try unit.processIdentifier(context, "slice_comptime_expression_slice"),
.is_struct = false, .is_struct = false,
}, },
}); });
try builder.appendInstruction(unit, context, gep); try builder.appendInstruction(unit, context, gep);
break :slice V{ break :slice V{
@ -10950,7 +10998,7 @@ pub const Builder = struct {
.value = expression_to_slice, .value = expression_to_slice,
.type = pointer.type, .type = pointer.type,
}, },
}); });
try builder.appendInstruction(unit, context, load); try builder.appendInstruction(unit, context, load);
const gep = try unit.instructions.append(context.my_allocator, .{ const gep = try unit.instructions.append(context.my_allocator, .{
.get_element_pointer = .{ .get_element_pointer = .{
@ -10989,7 +11037,7 @@ pub const Builder = struct {
.insert_value = .{ .insert_value = .{
.expression = .{ .expression = .{
.value = .{ .value = .{
.@"comptime" = .@"undefined", .@"comptime" = .undefined,
}, },
.type = destination_type_index, .type = destination_type_index,
}, },
@ -11667,7 +11715,7 @@ pub const Builder = struct {
.@"comptime" = .{ .@"comptime" = .{
.string_literal = hash, .string_literal = hash,
}, },
}, },
.type = ty, .type = ty,
}; };
}, },
@ -14225,14 +14273,14 @@ pub const Builder = struct {
const local_declaration = unit.local_declarations.get(declaration_index); const local_declaration = unit.local_declarations.get(declaration_index);
assert(builder.current_scope.kind == .block); 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) { if (emit) {
const stack = try builder.createStackVariable(unit, context, declaration_type, null); const stack = try builder.createStackVariable(unit, context, declaration_type, null);
assert(builder.current_scope.kind == .block); assert(builder.current_scope.kind == .block);
const local_scope: *Debug.Scope.Local = @fieldParentPtr("scope", builder.current_scope); 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, .{ const debug_declare_local = try unit.instructions.append(context.my_allocator, .{
.debug_declare_local_variable = .{ .debug_declare_local_variable = .{
@ -14276,7 +14324,9 @@ pub const Builder = struct {
.level = builder.current_scope.level + 1, .level = builder.current_scope.level + 1,
.local = builder.current_scope.local, .local = builder.current_scope.local,
.file = builder.current_file, .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, .value = result,
.type = ti, .type = ti,
}, },
}); });
try builder.appendInstruction(unit, context, zero_extend); try builder.appendInstruction(unit, context, zero_extend);
return .{ return .{
@ -16933,28 +16983,27 @@ pub const Unit = struct {
constant_arrays: V.Comptime.ConstantArray.List = .{}, constant_arrays: V.Comptime.ConstantArray.List = .{},
constant_slices: V.Comptime.ConstantSlice.List = .{}, constant_slices: V.Comptime.ConstantSlice.List = .{},
error_fields: Type.Error.Field.List = .{}, error_fields: Type.Error.Field.List = .{},
file_token_offsets: MyHashMap(Token.Range, Debug.File.Index) = .{}, file_token_offsets: PinnedHashMap(Token.Range, Debug.File.Index),
file_map: MyHashMap([]const u8, Debug.File.Index) = .{}, file_map: PinnedHashMap([]const u8, Debug.File.Index),
identifiers: MyHashMap(u32, []const u8) = .{}, identifiers: PinnedHashMap(u32, []const u8),
string_literal_values: MyHashMap(u32, [:0]const u8) = .{}, string_literal_values: PinnedHashMap(u32, [:0]const u8),
string_literal_globals: MyHashMap(u32, *Debug.Declaration.Global) = .{}, string_literal_globals: PinnedHashMap(u32, *Debug.Declaration.Global),
optionals: MyHashMap(Type.Index, Type.Index) = .{}, optionals: PinnedHashMap(Type.Index, Type.Index),
pointers: MyHashMap(Type.Pointer, Type.Index) = .{}, pointers: PinnedHashMap(Type.Pointer, Type.Index),
slices: MyHashMap(Type.Slice, Type.Index) = .{}, slices: PinnedHashMap(Type.Slice, Type.Index),
arrays: MyHashMap(Type.Array, Type.Index) = .{}, arrays: PinnedHashMap(Type.Array, Type.Index),
integers: MyHashMap(Type.Integer, Type.Index) = .{}, integers: PinnedHashMap(Type.Integer, Type.Index),
error_unions: MyHashMap(Type.Error.Union.Descriptor, Type.Index) = .{}, error_unions: PinnedHashMap(Type.Error.Union.Descriptor, Type.Index),
two_structs: MyHashMap([2]Type.Index, Type.Index) = .{}, two_structs: PinnedHashMap([2]Type.Index, Type.Index),
fields_array: MyHashMap(Type.Index, *Debug.Declaration.Global) = .{}, fields_array: PinnedHashMap(Type.Index, *Debug.Declaration.Global),
name_functions: MyHashMap(Type.Index, *Debug.Declaration.Global) = .{}, name_functions: PinnedHashMap(Type.Index, *Debug.Declaration.Global),
error_count: u32 = 0,
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), 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: Debug.Scope.Global = .{
.scope = .{ .scope = .{
.file = .null, .file = .null,
@ -16963,6 +17012,13 @@ pub const Unit = struct {
.column = 0, .column = 0,
.level = 0, .level = 0,
.local = false, .local = false,
.declarations = .{
.key_pointer = undefined,
.value_pointer = undefined,
.length = 0,
.granularity = 0,
.committed = 0,
},
}, },
}, },
root_package: *Package = undefined, root_package: *Package = undefined,
@ -16975,6 +17031,7 @@ pub const Unit = struct {
discard_identifiers: usize = 0, discard_identifiers: usize = 0,
anon_i: usize = 0, anon_i: usize = 0,
anon_arr: usize = 0, anon_arr: usize = 0,
error_count: u32 = 0,
fn dumpInstruction(instruction_index: Instruction.Index) !void { fn dumpInstruction(instruction_index: Instruction.Index) !void {
try write(.ir, "%"); try write(.ir, "%");
@ -17309,7 +17366,7 @@ pub const Unit = struct {
.@"struct" = optional_struct_index, .@"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; return optional_type_index;
} }
@ -17322,7 +17379,7 @@ pub const Unit = struct {
const type_index = try unit.types.append(context.my_allocator, .{ const type_index = try unit.types.append(context.my_allocator, .{
.pointer = pointer, .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; return type_index;
} }
@ -17335,7 +17392,7 @@ pub const Unit = struct {
const type_index = try unit.types.append(context.my_allocator, .{ const type_index = try unit.types.append(context.my_allocator, .{
.slice = slice, .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; return type_index;
} }
@ -17349,7 +17406,7 @@ pub const Unit = struct {
const array_type = try unit.types.append(context.my_allocator, .{ const array_type = try unit.types.append(context.my_allocator, .{
.array = array, .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; return array_type;
} }
@ -17381,7 +17438,7 @@ pub const Unit = struct {
const type_index = try unit.types.append(context.my_allocator, .{ const type_index = try unit.types.append(context.my_allocator, .{
.integer = integer, .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; return type_index;
} }
}, },
@ -17391,9 +17448,10 @@ pub const Unit = struct {
} }
fn processIdentifier(unit: *Unit, context: *const Context, string: []const u8) !u32 { fn processIdentifier(unit: *Unit, context: *const Context, string: []const u8) !u32 {
_ = context; // autofix
const hash = my_hash(string); const hash = my_hash(string);
if (unit.identifiers.get_pointer(hash) == null) { 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; return hash;
} }
@ -17434,7 +17492,7 @@ pub const Unit = struct {
fixed_string.len += 1; fixed_string.len += 1;
fixed_string[zero_index] = 0; fixed_string[zero_index] = 0;
const string = fixed_string[0 .. zero_index :0]; const string = fixed_string[0..zero_index :0];
return string; return string;
} }
@ -17508,7 +17566,7 @@ pub const Unit = struct {
file.lexer = try lexer.analyze(file.source_code, &unit.token_buffer); file.lexer = try lexer.analyze(file.source_code, &unit.token_buffer);
assert(file.status == .loaded_into_memory); assert(file.status == .loaded_into_memory);
file.status = .lexed; 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, .start = file.lexer.offset,
.count = file.lexer.count, .count = file.lexer.count,
}, file_index); }, file_index);
@ -17582,18 +17640,21 @@ pub const Unit = struct {
const file_index = try unit.files.append(context.my_allocator, Debug.File{ const file_index = try unit.files.append(context.my_allocator, Debug.File{
.relative_path = relative_path, .relative_path = relative_path,
.package = package, .package = package,
.scope = .{ .scope = .{ .scope = .{
.file = .null, .scope = .{
.kind = .file, .file = .null,
.line = 0, .kind = .file,
.column = 0, .line = 0,
.local = false, .column = 0,
.level = 1, .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 }); // 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 .{ return .{
.index = file_index, .index = file_index,
@ -17642,6 +17703,7 @@ pub const Unit = struct {
.path = main_package_absolute_directory_path, .path = main_package_absolute_directory_path,
}, },
.source_path = try context.my_allocator.duplicate_bytes(std.fs.path.basename(unit.descriptor.main_package_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; break :blk result;
}; };
@ -17655,6 +17717,7 @@ pub const Unit = struct {
.path = directory_path, .path = directory_path,
}, },
.source_path = "test_runner.nat", .source_path = "test_runner.nat",
.dependencies = try PinnedHashMap([]const u8, *Package).init(std.mem.page_size),
}; };
unit.main_package = main_package; unit.main_package = main_package;
@ -17689,9 +17752,10 @@ pub const Unit = struct {
.handle = try std.fs.openDirAbsolute(package_descriptor.directory_path, .{}), .handle = try std.fs.openDirAbsolute(package_descriptor.directory_path, .{}),
}, },
.source_path = try std.mem.concat(context.allocator, u8, &.{ package_descriptor.name, ".nat" }), .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; package_ptr.* = package;
} }
@ -17763,7 +17827,7 @@ pub const Unit = struct {
.@"struct" = two_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; return type_index;
} }
@ -17838,7 +17902,7 @@ pub const Token = struct {
length: u32, length: u32,
id: Token.Id, id: Token.Id,
pub const Buffer = struct{ pub const Buffer = struct {
line_offsets: PinnedArray(u32) = .{}, line_offsets: PinnedArray(u32) = .{},
tokens: PinnedArray(Token) = .{}, tokens: PinnedArray(Token) = .{},
}; };

View File

@ -6,10 +6,11 @@ const write = Compilation.write;
// const log = Compilation.log; // const log = Compilation.log;
// const logln = Compilation.logln; // const logln = Compilation.logln;
const Module = Compilation.Module; const Module = Compilation.Module;
const data_structures = @import("../library.zig"); const library = @import("../library.zig");
const BoundedArray = data_structures.BoundedArray; const BoundedArray = library.BoundedArray;
const MyHashMap = data_structures.MyHashMap; const PinnedHashMap = library.PinnedHashMap;
const PinnedArray = data_structures.PinnedArray; const PinnedArray = library.PinnedArray;
const format_int = library.format_int;
pub const bindings = @import("llvm_bindings.zig"); pub const bindings = @import("llvm_bindings.zig");
@ -28,23 +29,23 @@ pub const LLVM = struct {
module: *LLVM.Module, module: *LLVM.Module,
builder: *LLVM.Builder, builder: *LLVM.Builder,
debug_info_builder: *LLVM.DebugInfo.Builder, debug_info_builder: *LLVM.DebugInfo.Builder,
debug_info_file_map: MyHashMap(Compilation.Debug.File.Index, *LLVM.DebugInfo.File) = .{}, debug_info_file_map: PinnedHashMap(Compilation.Debug.File.Index, *LLVM.DebugInfo.File),
debug_type_map: MyHashMap(Compilation.Type.Index, *LLVM.DebugInfo.Type) = .{}, debug_type_map: PinnedHashMap(Compilation.Type.Index, *LLVM.DebugInfo.Type),
type_name_map: MyHashMap(Compilation.Type.Index, []const u8) = .{}, type_name_map: PinnedHashMap(Compilation.Type.Index, []const u8),
type_map: MyHashMap(Compilation.Type.Index, *LLVM.Type) = .{}, type_map: PinnedHashMap(Compilation.Type.Index, *LLVM.Type),
function_declaration_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{}, function_declaration_map: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function),
function_definition_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{}, function_definition_map: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function),
llvm_instruction_map: MyHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{}, llvm_instruction_map: PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value),
llvm_value_map: MyHashMap(Compilation.V, *LLVM.Value) = .{}, llvm_value_map: PinnedHashMap(Compilation.V, *LLVM.Value),
llvm_block_map: MyHashMap(Compilation.BasicBlock.Index, *LLVM.Value.BasicBlock) = .{}, llvm_block_map: PinnedHashMap(Compilation.BasicBlock.Index, *LLVM.Value.BasicBlock),
llvm_external_functions: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{}, llvm_external_functions: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function),
global_variable_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.GlobalVariable) = .{}, global_variable_map: PinnedHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.GlobalVariable),
scope_map: MyHashMap(*Compilation.Debug.Scope, *LLVM.DebugInfo.Scope) = .{}, scope_map: PinnedHashMap(*Compilation.Debug.Scope, *LLVM.DebugInfo.Scope),
argument_allocas: PinnedHashMap(Compilation.Instruction.Index, *LLVM.Value),
pointer_type: ?*LLVM.Type.Pointer = null, pointer_type: ?*LLVM.Type.Pointer = null,
function: *LLVM.Value.Constant.Function = undefined, function: *LLVM.Value.Constant.Function = undefined,
exit_block: *LLVM.Value.BasicBlock = undefined, exit_block: *LLVM.Value.BasicBlock = undefined,
sema_function: *Compilation.Debug.Declaration.Global = undefined, sema_function: *Compilation.Debug.Declaration.Global = undefined,
argument_allocas: MyHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{},
return_phi_node: ?*LLVM.Value.Instruction.PhiNode = null, return_phi_node: ?*LLVM.Value.Instruction.PhiNode = null,
scope: *LLVM.DebugInfo.Scope = undefined, scope: *LLVM.DebugInfo.Scope = undefined,
file: *LLVM.DebugInfo.File = undefined, file: *LLVM.DebugInfo.File = undefined,
@ -1333,7 +1334,7 @@ pub const LLVM = struct {
else => |t| @panic(@tagName(t)), 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; return llvm_type;
} }
@ -1349,7 +1350,7 @@ pub const LLVM = struct {
const filename = std.fs.path.basename(full_path); const filename = std.fs.path.basename(full_path);
const directory = full_path[0 .. full_path.len - filename.len]; 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; 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; return debug_file;
} }
} }
@ -1360,7 +1361,7 @@ pub const LLVM = struct {
} else { } else {
if (unit.type_declarations.get(sema_type_index)) |global_declaration| { if (unit.type_declarations.get(sema_type_index)) |global_declaration| {
const result = unit.getIdentifier(global_declaration.declaration.name); 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; return result;
} else { } else {
const sema_type = unit.types.get(sema_type_index); const sema_type = unit.types.get(sema_type_index);
@ -1369,7 +1370,7 @@ pub const LLVM = struct {
.integer => |integer| switch (integer.kind) { .integer => |integer| switch (integer.kind) {
.materialized_int => b: { .materialized_int => b: {
var buffer: [65]u8 = undefined; 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_ptr = format.ptr - 1;
const slice = slice_ptr[0 .. format.len + 1]; const slice = slice_ptr[0 .. format.len + 1];
slice[0] = switch (integer.signedness) { slice[0] = switch (integer.signedness) {
@ -1410,7 +1411,7 @@ pub const LLVM = struct {
.array => |array| b: { .array => |array| b: {
name.appendAssumeCapacity('['); name.appendAssumeCapacity('[');
var buffer: [65]u8 = undefined; 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.appendSliceAssumeCapacity(array_count);
name.appendAssumeCapacity(']'); name.appendAssumeCapacity(']');
const element_type_name = try llvm.renderTypeName(unit, context, array.type); const element_type_name = try llvm.renderTypeName(unit, context, array.type);
@ -1424,8 +1425,7 @@ pub const LLVM = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}; };
try llvm.type_name_map.put(sema_type_index, if (name.len > 0) b: {
try llvm.type_name_map.put(context.my_allocator, sema_type_index, if (name.len > 0) b: {
const new_name = try context.arena.new_array(u8, name.len); const new_name = try context.arena.new_array(u8, name.len);
@memcpy(new_name, result); @memcpy(new_name, result);
break :b new_name; break :b new_name;
@ -1533,7 +1533,7 @@ pub const LLVM = struct {
.forward_declaration = null, .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){}; var field_types = BoundedArray(*LLVM.DebugInfo.Type, 512){};
bit_size = 0; bit_size = 0;
@ -1842,7 +1842,7 @@ pub const LLVM = struct {
else => |t| @panic(@tagName(t)), 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); assert(@intFromPtr(result) != 0xaaaa_aaaa_aaaa_aaaa);
return result; return result;
@ -1863,7 +1863,7 @@ pub const LLVM = struct {
if (gep.is_struct and gep.index.type != .u32) unreachable; if (gep.is_struct and gep.index.type != .u32) unreachable;
const gep_name = unit.getIdentifier(gep.name); 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; 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; return get_element_pointer;
} }
@ -2047,7 +2047,7 @@ pub const LLVM = struct {
basic_block_node.* = .{ basic_block_node.* = .{
.data = basic_block_index, .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; return basic_block_node;
} }
@ -2287,8 +2287,8 @@ pub const LLVM = struct {
}); });
switch (declaration.initial_value) { switch (declaration.initial_value) {
.function_declaration => try llvm.function_declaration_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(context.my_allocator, declaration, function), .function_definition => try llvm.function_definition_map.put_no_clobber(declaration, function),
else => unreachable, else => unreachable,
} }
@ -2360,7 +2360,7 @@ pub const LLVM = struct {
const function_definition = unit.function_definitions.get(function_definition_index); const function_definition = unit.function_definitions.get(function_definition_index);
const scope = subprogram.toLocalScope().toScope(); 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 => {}, .function_declaration => {},
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -2368,7 +2368,7 @@ pub const LLVM = struct {
} }
switch (declaration.initial_value) { 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 => {}, .function_definition => {},
else => |t| @panic(@tagName(t)), 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), .inreg = llvm_context.getAttributeFromEnum(.InReg, 0),
.@"noalias" = llvm_context.getAttributeFromEnum(.NoAlias, 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) { 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; 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(); 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| { 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| { .string_literal => |hash| {
const string_literal = unit.string_literal_values.get(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; 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 => { else => {
const global_type = try llvm.getType(unit, context, global_declaration.declaration.type); 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 thread_local_mode = LLVM.ThreadLocalMode.not_thread_local;
const externally_initialized = false; 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; 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); 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| { 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_index = function_declaration.getFunctionDefinitionIndex();
const function_definition = unit.function_definitions.get(function_definition_index); const function_definition = unit.function_definitions.get(function_definition_index);
llvm.function = function; llvm.function = function;
@ -2528,15 +2545,13 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
llvm.scope = subprogram.toLocalScope().toScope(); 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{}; var block_command_list = BasicBlockList{};
const entry_block_node = try llvm.createBasicBlock(context, function_definition.basic_blocks.pointer[0], "fn_entry"); const entry_block_node = try llvm.createBasicBlock(context, function_definition.basic_blocks.pointer[0], "fn_entry");
block_command_list.append(entry_block_node); block_command_list.append(entry_block_node);
var phis = MyHashMap(Compilation.Instruction.Index, *LLVM.Value.Instruction.PhiNode){};
while (block_command_list.len != 0) { while (block_command_list.len != 0) {
const block_node = block_command_list.first orelse unreachable; const block_node = block_command_list.first orelse unreachable;
const basic_block_index = block_node.data; 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)); 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; 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(); llvm.scope = lexical_block.toScope();
} }
}, },
@ -2616,7 +2631,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
}, },
.number_literal => |literal| { .number_literal => |literal| {
var buffer: [65]u8 = undefined; 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 slice_ptr = number_literal.ptr - 4;
const literal_slice = slice_ptr[0 .. number_literal.len + 4]; const literal_slice = slice_ptr[0 .. number_literal.len + 4];
literal_slice[0] = '$'; literal_slice[0] = '$';
@ -2632,7 +2647,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
} else { } else {
const value = try llvm.emitLeftValue(unit, context, sema_value); const value = try llvm.emitLeftValue(unit, context, sema_value);
var buffer: [65]u8 = undefined; 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 slice_ptr = operand_number.ptr - 2;
const operand_slice = slice_ptr[0 .. operand_number.len + 2]; const operand_slice = slice_ptr[0 .. operand_number.len + 2];
operand_slice[0] = '$'; 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 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; 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| { .stack_slot => |stack_slot| {
// const stack_slot_type = unit.types.get(stack_slot.type); // 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 type_alignment = unit.types.get(stack_slot.type).getAbiAlignment(unit);
const alloca_array_size = null; 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; 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 alloca_map.put_no_clobber(instruction_index, declaration_alloca.toValue());
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue()); try llvm.llvm_instruction_map.put_no_clobber(instruction_index, declaration_alloca.toValue());
}, },
.store => |store| { .store => |store| {
const right = try llvm.emitRightValue(unit, context, store.source); 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_type = LLVM.Value.Instruction.Cast.Type.int_to_pointer;
const cast_name = @tagName(cast_type); 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; 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, .array_bitcast_to_integer => unreachable,
// TODO: Poke metadata // 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_source_type_to_destination_type,
.pointer_none_terminated_to_zero, .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 => { .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; 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 => { .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; 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 => { .bitcast => {
const bitcast = llvm.builder.createCast(.bitcast, value, dest_type, "bitcast", "bitcast".len) orelse return LLVM.Value.Instruction.Error.cast; 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 => { .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; 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 => { .truncate => {
const truncate = llvm.builder.createCast(.truncate, value, dest_type, "truncate", "truncate".len) orelse return LLVM.Value.Instruction.Error.cast; 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, .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)), 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; 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 value_type = try llvm.getType(unit, context, load.type);
const is_volatile = false; const is_volatile = false;
const load_i = llvm.builder.createLoad(value_type, value, is_volatile, "", "".len, alignment) orelse return LLVM.Value.Instruction.Error.load; 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| { .integer_binary_operation => |binary_operation| {
assert(binary_operation.left.type == binary_operation.right.type); 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, 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| { .call => |sema_call| {
var argument_buffer: [32]*LLVM.Value = undefined; 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)), 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, .{ try llvm.setCallOrFunctionAttributes(unit, context, function_prototype, .{
.call = call, .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; 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" => { .@"unreachable" => {
_ = llvm.builder.createUnreachable() orelse return LLVM.Value.Instruction.Error.@"unreachable"; _ = llvm.builder.createUnreachable() orelse return LLVM.Value.Instruction.Error.@"unreachable";
}, },
.abi_argument => |argument_index| { .abi_argument => |argument_index| {
const argument = llvm.function.getArgument(argument_index) orelse unreachable; 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| { .debug_declare_argument => |debug_declare| {
if (generate_debug_information) { 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 value = try llvm.emitRightValue(unit, context, insert_value.new_value);
const indices = [1]c_uint{insert_value.index}; const indices = [1]c_uint{insert_value.index};
const instruction = llvm.builder.createInsertValue(aggregate, value, &indices, indices.len, "", "".len) orelse unreachable; 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| { .extract_value => |extract_value| {
switch (unit.types.get(extract_value.expression.type).*) { 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()); assert(!aggregate.getType().isPointer());
const indices = [1]c_uint{extract_value.index}; const indices = [1]c_uint{extract_value.index};
const instruction = llvm.builder.createExtractValue(aggregate, &indices, indices.len, "", "".len) orelse unreachable; 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| { .integer_compare => |integer_compare| {
assert(integer_compare.left.type == integer_compare.right.type); 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, .signed_greater_equal => .sge,
}; };
const icmp = llvm.builder.createICmp(comparison_id, left, right, "", "".len) orelse unreachable; 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| { .jump => |jump| {
const target_block = if (llvm.llvm_block_map.get(jump.to)) |target_block| target_block else blk: { 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; 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| { .branch => |branch| {
const taken_node = try llvm.createBasicBlock(context, branch.taken, "taken_block"); 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 branch_weights = null;
const unpredictable = null; const unpredictable = null;
const br = llvm.builder.createConditionalBranch(condition, taken_block, not_taken_block, branch_weights, unpredictable) orelse unreachable; 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| { .phi => |phi| {
const phi_type = try llvm.getType(unit, context, phi.type); 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_name = "phi";
const phi_node = llvm.builder.createPhi(phi_type, reserved_value_count, phi_name, phi_name.len) orelse unreachable; 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| { .umin => |umin| {
const intrinsic_type = try llvm.getType(unit, context, umin.type); 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 right = try llvm.emitRightValue(unit, context, umin.right);
const arguments = [_]*LLVM.Value{ left, right }; const arguments = [_]*LLVM.Value{ left, right };
const intrinsic_call = try llvm.callIntrinsic("llvm.umin", &parameter_types, &arguments); const intrinsic_call = try llvm.callIntrinsic("llvm.umin", &parameter_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 => { .get_element_pointer => {
_ = try llvm.createGEP(unit, context, instruction_index); _ = 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_types: []const *LLVM.Type = &.{};
const parameter_values: []const *LLVM.Value = &.{}; const parameter_values: []const *LLVM.Value = &.{};
const intrinsic_call = try llvm.callIntrinsic("llvm.trap", parameter_types, parameter_values); 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| { .add_overflow => |add_overflow| {
const intrinsic_type = try llvm.getType(unit, context, add_overflow.type); 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 right = try llvm.emitRightValue(unit, context, add_overflow.right);
const arguments = [_]*LLVM.Value{ left, right }; const arguments = [_]*LLVM.Value{ left, right };
const intrinsic_call = try llvm.callIntrinsic("llvm.sadd.with.overflow", &parameter_types, &arguments); const intrinsic_call = try llvm.callIntrinsic("llvm.sadd.with.overflow", &parameter_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| { .trailing_zeroes => |v| {
const intrinsic_type = try llvm.getType(unit, context, v.type); 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 is_poison = llvm.context.getConstantInt(1, 0, false) orelse unreachable;
const arguments = [_]*LLVM.Value{ value, is_poison.toValue() }; const arguments = [_]*LLVM.Value{ value, is_poison.toValue() };
const intrinsic_call = try llvm.callIntrinsic("llvm.cttz", &parameter_types, &arguments); const intrinsic_call = try llvm.callIntrinsic("llvm.cttz", &parameter_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| { .@"switch" => |switch_expression| {
const condition = try llvm.emitRightValue(unit, context, switch_expression.condition); 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 branch_weights = null;
const unpredictable = 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); 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| { .memcpy => |memcpy| {
const destination = try llvm.emitLeftValue(unit, context, memcpy.destination); const destination = try llvm.emitLeftValue(unit, context, memcpy.destination);

View File

@ -11,13 +11,13 @@ pub fn assert(ok: bool) void {
pub const Allocator = std.mem.Allocator; pub const Allocator = std.mem.Allocator;
pub const BoundedArray = std.BoundedArray; pub const BoundedArray = std.BoundedArray;
pub const Arena = struct{ pub const Arena = struct {
position: u64, position: u64,
commit_position: u64, commit_position: u64,
alignment: u64, alignment: u64,
size: u64, size: u64,
pub const Temporary = struct{ pub const Temporary = struct {
arena: *Arena, arena: *Arena,
position: u64, 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)))); const result: *T = @ptrCast(@alignCast(try arena.allocate(@sizeOf(T))));
return result; return result;
} }
@ -83,7 +83,7 @@ pub const Arena = struct{
}; };
pub fn DynamicBoundedArray(comptime T: type) type { pub fn DynamicBoundedArray(comptime T: type) type {
return struct{ return struct {
pointer: [*]T = @constCast((&[_]T{}).ptr), pointer: [*]T = @constCast((&[_]T{}).ptr),
length: u32 = 0, length: u32 = 0,
capacity: u32 = 0, capacity: u32 = 0,
@ -114,7 +114,7 @@ pub fn DynamicBoundedArray(comptime T: type) type {
array.length += count; array.length += count;
} }
pub fn slice(array: *Array) []T{ pub fn slice(array: *Array) []T {
return array.pointer[0..array.length]; 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_page_size = 2 * 1024 * 1024;
const pinned_array_max_size = std.math.maxInt(u32) - pinned_array_page_size; const pinned_array_max_size = std.math.maxInt(u32) - pinned_array_page_size;
const pinned_array_default_granularity = 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 { pub fn PinnedArray(comptime T: type) type {
return struct{ return struct {
pointer: [*]T = @constCast((&[_]T{}).ptr), pointer: [*]T = @constCast((&[_]T{}).ptr),
length: u32 = 0, length: u32 = 0,
granularity: u32 = 0, granularity: u32 = 0,
pub const Index = enum(u32){ pub const Index = enum(u32) {
null = 0xffff_ffff, null = 0xffff_ffff,
_, _,
}; };
const Array = @This(); 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]; return array.pointer[0..array.length];
} }
pub fn slice(array: *Array) []T{
pub fn slice(array: *Array) []T {
return array.pointer[0..array.length]; return array.pointer[0..array.length];
} }
@ -155,14 +157,15 @@ pub fn PinnedArray(comptime T: type) type {
return array.get_unchecked(i); 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 many_item: [*]T = @ptrCast(item);
const result = @intFromPtr(many_item) - @intFromPtr(array.pointer); const result = @intFromPtr(many_item) - @intFromPtr(array.pointer);
assert(result < pinned_array_max_size); assert(result < pinned_array_max_size);
return @enumFromInt(@divExact(result, @sizeOf(T))); 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); const raw_ptr = try reserve(pinned_array_max_size);
try commit(raw_ptr, granularity); try commit(raw_ptr, granularity);
return Array{ 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); return try Array.init(pinned_array_default_granularity);
} }
pub fn append(array: *Array, item: T) *T { pub fn ensure_capacity(array: *Array, additional: u32) void {
if (((array.length + 1) * @sizeOf(T)) & (array.granularity - 1) == 0) { const length = array.length;
const length: u64 = array.length; const size = length * @sizeOf(T);
assert((length + 1) * @sizeOf(T) <= pinned_array_max_size); 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); 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); return array.append_with_capacity(item);
} }
pub fn append_slice(array: *Array, items: []const T) void { pub fn append_slice(array: *Array, items: []const T) void {
const count: u32 = @intCast(items.len); array.ensure_capacity(@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.append_slice_with_capacity(items); 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) { return switch (os) {
.linux, .macos => (try std.posix.mmap(null, size, std.posix.PROT.NONE, .{ .linux, .macos => (try std.posix.mmap(null, size, std.posix.PROT.NONE, .{
.ANONYMOUS = true, .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]; const slice = bytes[0..size];
return switch (os) { return switch (os) {
.linux, .macos => try std.posix.mprotect(@alignCast(slice), std.posix.PROT.WRITE | std.posix.PROT.READ), .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, 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 { const pinned_hash_map_page_size = 2 * 1024 * 1024;
var new_capacity = @max(current_capacity, initial_item_count); const pinned_hash_map_max_size = std.math.maxInt(u32) - pinned_hash_map_page_size;
while (new_capacity < desired_capacity) { const pinned_hash_map_default_granularity = pinned_hash_map_page_size;
new_capacity *= factor;
}
if (new_capacity > current_capacity) { pub fn PinnedHashMap(comptime K: type, comptime V: type) type {
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;
return struct { return struct {
key_pointer: [*]K = undefined, key_pointer: [*]K,
value_pointer: [*]V = undefined, value_pointer: [*]V,
length: IndexType = 0, length: u32,
capacity: IndexType = 0, 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| { for (map.keys(), 0..) |k, i| {
const is_equal = switch (@typeInfo(K)) { const is_equal = switch (@typeInfo(K)) {
.Pointer => |pointer| switch (pointer.size) { .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 { pub fn put(map: *@This(), key: K, value: V) !void {
if (map.get_pointer(key)) |value_ptr| { if (map.get_pointer(key)) |value_pointer| {
value_ptr.* = value; value_pointer.* = value;
} else { } else {
const len = map.length; const len = map.length;
try map.ensure_capacity(allocator, len + 1); map.ensure_capacity(len + 1);
map.put_at_with_capacity(len, key, value); 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); assert(map.get_pointer(key) == null);
const len = map.length; const len = map.length;
try map.ensure_capacity(allocator, len + 1); map.ensure_capacity(len + 1);
map.put_at_with_capacity(len, key, value); 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; map.value_pointer[index] = value;
} }
pub fn ensure_capacity(map: *@This(), allocator: *MyAllocator, desired_capacity: IndexType) !void { fn ensure_capacity(map: *Map, additional: u32) 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)); const length = map.length;
map.capacity = result.capacity; assert((length + additional) * @sizeOf(K) <= pinned_array_max_size);
map.key_pointer = @ptrCast(@alignCast(result.key_pointer));
map.value_pointer = @ptrCast(@alignCast(result.value_pointer)); {
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 { 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 { pub fn values(map: *@This()) []V {
return map.value_pointer[0..map.length]; return map.value_pointer[0..map.length];
} }
pub fn clear(map: *Map) void {
map.length = 0;
}
}; };
} }