Reduce usage of UnpinnedArray to just Compilation

This commit is contained in:
David Gonzalez Martin 2024-04-25 00:10:36 -06:00
parent 7bd4095cd7
commit 8ae3b0caa4
6 changed files with 253 additions and 252 deletions

View File

@ -7,8 +7,9 @@ const write = Compilation.write;
// const logln = Compilation.logln; // const logln = Compilation.logln;
const Module = Compilation.Module; const Module = Compilation.Module;
const data_structures = @import("../library.zig"); const data_structures = @import("../library.zig");
const BoundedArray = data_structures.BoundedArray;
const MyHashMap = data_structures.MyHashMap; const MyHashMap = data_structures.MyHashMap;
const UnpinnedArray = data_structures.UnpinnedArray; const PinnedArray = data_structures.PinnedArray;
pub const bindings = @import("llvm_bindings.zig"); pub const bindings = @import("llvm_bindings.zig");
@ -1221,19 +1222,20 @@ pub const LLVM = struct {
return llvm_type; return llvm_type;
} else { } else {
const sema_type = unit.types.get(type_index); const sema_type = unit.types.get(type_index);
var type_buffer = BoundedArray(*LLVM.Type, 512){};
const llvm_type: *LLVM.Type = switch (sema_type.*) { const llvm_type: *LLVM.Type = switch (sema_type.*) {
.function => |function_prototype_index| blk: { .function => |function_prototype_index| blk: {
const sema_function_prototype = unit.function_prototypes.get(function_prototype_index); const sema_function_prototype = unit.function_prototypes.get(function_prototype_index);
const llvm_return_type = try llvm.getType(unit, context, sema_function_prototype.abi.return_type); const llvm_return_type = try llvm.getType(unit, context, sema_function_prototype.abi.return_type);
var parameter_types = try UnpinnedArray(*LLVM.Type).initialize_with_capacity(context.my_allocator, @intCast(sema_function_prototype.abi.parameter_types.len)); var parameter_types = BoundedArray(*LLVM.Type, 512){};
for (sema_function_prototype.abi.parameter_types) |argument_type_index| { for (sema_function_prototype.abi.parameter_types) |argument_type_index| {
parameter_types.append_with_capacity(try llvm.getType(unit, context, argument_type_index)); parameter_types.appendAssumeCapacity(try llvm.getType(unit, context, argument_type_index));
} }
const is_var_args = false; const is_var_args = false;
const llvm_function_type = LLVM.Context.getFunctionType(llvm_return_type, parameter_types.pointer, parameter_types.length, is_var_args) orelse return Type.Error.function; const llvm_function_type = LLVM.Context.getFunctionType(llvm_return_type, &parameter_types.buffer, parameter_types.len, is_var_args) orelse return Type.Error.function;
break :blk llvm_function_type.toType(); break :blk llvm_function_type.toType();
}, },
.integer => |integer| switch (integer.kind) { .integer => |integer| switch (integer.kind) {
@ -1294,16 +1296,15 @@ pub const LLVM = struct {
break :blk struct_type.toType(); break :blk struct_type.toType();
}, },
.@"struct" => |*sema_struct_type| blk: { .@"struct" => |*sema_struct_type| blk: {
var field_type_list = try UnpinnedArray(*LLVM.Type).initialize_with_capacity(context.my_allocator, sema_struct_type.fields.length);
for (sema_struct_type.fields.slice()) |sema_field_index| { for (sema_struct_type.fields.slice()) |sema_field_index| {
const sema_field = unit.struct_fields.get(sema_field_index); const sema_field = unit.struct_fields.get(sema_field_index);
const llvm_type = try llvm.getType(unit, context, sema_field.type); const llvm_type = try llvm.getType(unit, context, sema_field.type);
field_type_list.append_with_capacity(llvm_type); type_buffer.appendAssumeCapacity(llvm_type);
} }
// TODO: // TODO:
const is_packed = false; const is_packed = false;
const struct_type = llvm.context.getStructType(field_type_list.pointer, field_type_list.length, is_packed) orelse return Type.Error.@"struct"; const struct_type = llvm.context.getStructType(&type_buffer.buffer, type_buffer.len, is_packed) orelse return Type.Error.@"struct";
break :blk struct_type.toType(); break :blk struct_type.toType();
}, },
@ -1363,6 +1364,7 @@ pub const LLVM = struct {
return result; return result;
} else { } else {
const sema_type = unit.types.get(sema_type_index); const sema_type = unit.types.get(sema_type_index);
var name = BoundedArray(u8, 4096){};
const result: []const u8 = switch (sema_type.*) { const result: []const u8 = switch (sema_type.*) {
.integer => |integer| switch (integer.kind) { .integer => |integer| switch (integer.kind) {
.materialized_int => b: { .materialized_int => b: {
@ -1382,14 +1384,13 @@ pub const LLVM = struct {
}, },
// .bool => "bool", // .bool => "bool",
.pointer => |pointer| b: { .pointer => |pointer| b: {
var name = UnpinnedArray(u8){}; name.appendAssumeCapacity('&');
try name.append(context.my_allocator, '&');
if (pointer.mutability == .@"const") { if (pointer.mutability == .@"const") {
try name.append_slice(context.my_allocator, "const"); name.appendSliceAssumeCapacity("const");
} }
try name.append(context.my_allocator, ' '); name.appendAssumeCapacity(' ');
const element_type_name = try llvm.renderTypeName(unit, context, pointer.type); const element_type_name = try llvm.renderTypeName(unit, context, pointer.type);
try name.append_slice(context.my_allocator, element_type_name); name.appendSliceAssumeCapacity(element_type_name);
break :b name.slice(); break :b name.slice();
}, },
.@"struct" => |struct_index| switch (unit.structs.get(struct_index).kind) { .@"struct" => |struct_index| switch (unit.structs.get(struct_index).kind) {
@ -1398,24 +1399,22 @@ pub const LLVM = struct {
}, },
// TODO: termination // TODO: termination
.slice => |slice| b: { .slice => |slice| b: {
var name = UnpinnedArray(u8){}; name.appendSliceAssumeCapacity("[] ");
try name.append_slice(context.my_allocator, "[] ");
if (slice.mutability == .@"const") { if (slice.mutability == .@"const") {
try name.append_slice(context.my_allocator, "const "); name.appendSliceAssumeCapacity("const ");
} }
const element_type_name = try llvm.renderTypeName(unit, context, slice.child_type); const element_type_name = try llvm.renderTypeName(unit, context, slice.child_type);
try name.append_slice(context.my_allocator, element_type_name); name.appendSliceAssumeCapacity(element_type_name);
break :b name.slice(); break :b name.slice();
}, },
.array => |array| b: { .array => |array| b: {
var name = UnpinnedArray(u8){}; name.appendAssumeCapacity('[');
try name.append(context.my_allocator, '[');
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 = data_structures.format_int(&buffer, array.count, 10, false);
try name.append_slice(context.my_allocator, array_count); name.appendSliceAssumeCapacity(array_count);
try name.append(context.my_allocator, ']'); name.appendAssumeCapacity(']');
const element_type_name = try llvm.renderTypeName(unit, context, array.type); const element_type_name = try llvm.renderTypeName(unit, context, array.type);
try name.append_slice(context.my_allocator, element_type_name); name.appendSliceAssumeCapacity(element_type_name);
break :b name.slice(); break :b name.slice();
}, },
@ -1425,7 +1424,12 @@ pub const LLVM = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}; };
try llvm.type_name_map.put(context.my_allocator, sema_type_index, result);
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);
@memcpy(new_name, result);
break :b new_name;
} else result);
return result; return result;
} }
@ -1530,7 +1534,7 @@ pub const LLVM = struct {
}); });
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(context.my_allocator, sema_type_index, struct_type.toType());
var field_types = try UnpinnedArray(*LLVM.DebugInfo.Type).initialize_with_capacity(context.my_allocator, @intCast(fields.len)); var field_types = BoundedArray(*LLVM.DebugInfo.Type, 512){};
bit_size = 0; bit_size = 0;
for (fields) |struct_field_index| { for (fields) |struct_field_index| {
@ -1541,11 +1545,11 @@ pub const LLVM = struct {
const field_name = unit.getIdentifier(struct_field.name); const field_name = unit.getIdentifier(struct_field.name);
const alignment = struct_field_bit_size; const alignment = struct_field_bit_size;
const member_type = llvm.debug_info_builder.createMemberType(null, field_name.ptr, field_name.len, file, 0, struct_field_bit_size, alignment, bit_size, flags, field_type).toType(); const member_type = llvm.debug_info_builder.createMemberType(null, field_name.ptr, field_name.len, file, 0, struct_field_bit_size, alignment, bit_size, flags, field_type).toType();
field_types.append_with_capacity(member_type); field_types.appendAssumeCapacity(member_type);
bit_size += struct_field_bit_size; bit_size += struct_field_bit_size;
} }
llvm.debug_info_builder.replaceCompositeTypes(struct_type, field_types.pointer, field_types.length); llvm.debug_info_builder.replaceCompositeTypes(struct_type, &field_types.buffer, field_types.len);
return struct_type.toType(); return struct_type.toType();
} }
@ -1629,14 +1633,17 @@ pub const LLVM = struct {
break :b boolean_type; break :b boolean_type;
}, },
.@"enum" => |*enum_type| b: { .@"enum" => |*enum_type| b: {
var enumerators = try UnpinnedArray(*LLVM.DebugInfo.Type.Enumerator).initialize_with_capacity(context.my_allocator, enum_type.fields.length); var enumerators = try context.arena.new_array(*LLVM.DebugInfo.Type.Enumerator, enum_type.fields.length);
enumerators.len = 0;
for (enum_type.fields.slice()) |enum_field_index| { for (enum_type.fields.slice()) |enum_field_index| {
const enum_field = unit.enum_fields.get(enum_field_index); const enum_field = unit.enum_fields.get(enum_field_index);
const enum_field_name = unit.getIdentifier(enum_field.name); const enum_field_name = unit.getIdentifier(enum_field.name);
const is_unsigned = true; const is_unsigned = true;
const enumerator = llvm.debug_info_builder.createEnumerator(enum_field_name.ptr, enum_field_name.len, enum_field.value, is_unsigned) orelse unreachable; const enumerator = llvm.debug_info_builder.createEnumerator(enum_field_name.ptr, enum_field_name.len, enum_field.value, is_unsigned) orelse unreachable;
enumerators.append_with_capacity(enumerator); const index = enumerators.len;
enumerators.len += 1;
enumerators[index] = enumerator;
} }
const type_declaration = unit.type_declarations.get(sema_type_index).?; const type_declaration = unit.type_declarations.get(sema_type_index).?;
@ -1651,18 +1658,21 @@ pub const LLVM = struct {
const alignment = 0; const alignment = 0;
const line = type_declaration.declaration.line + 1; const line = type_declaration.declaration.line + 1;
const scope = try llvm.getScope(unit, context, enum_type.scope.scope.parent.?); const scope = try llvm.getScope(unit, context, enum_type.scope.scope.parent.?);
const enumeration_type = llvm.debug_info_builder.createEnumerationType(scope, name.ptr, name.len, file, line, bit_size, alignment, enumerators.pointer, enumerators.length, backing_type) orelse unreachable; const enumeration_type = llvm.debug_info_builder.createEnumerationType(scope, name.ptr, name.len, file, line, bit_size, alignment, enumerators.ptr, enumerators.len, backing_type) orelse unreachable;
break :b enumeration_type.toType(); break :b enumeration_type.toType();
}, },
.@"error" => |*error_type| b: { .@"error" => |*error_type| b: {
var enumerators = try UnpinnedArray(*LLVM.DebugInfo.Type.Enumerator).initialize_with_capacity(context.my_allocator, error_type.fields.length); var enumerators = try context.arena.new_array(*LLVM.DebugInfo.Type.Enumerator, error_type.fields.length);
enumerators.len = 0;
for (error_type.fields.slice()) |error_field_index| { for (error_type.fields.slice()) |error_field_index| {
const error_field = unit.error_fields.get(error_field_index); const error_field = unit.error_fields.get(error_field_index);
const error_field_name = unit.getIdentifier(error_field.name); const error_field_name = unit.getIdentifier(error_field.name);
const is_unsigned = true; const is_unsigned = true;
const enumerator = llvm.debug_info_builder.createEnumerator(error_field_name.ptr, error_field_name.len, error_field.value, is_unsigned) orelse unreachable; const enumerator = llvm.debug_info_builder.createEnumerator(error_field_name.ptr, error_field_name.len, error_field.value, is_unsigned) orelse unreachable;
enumerators.append_with_capacity(enumerator); const index = enumerators.len;
enumerators.len += 1;
enumerators[index] = enumerator;
} }
const type_declaration = unit.type_declarations.get(sema_type_index).?; const type_declaration = unit.type_declarations.get(sema_type_index).?;
@ -1677,7 +1687,7 @@ pub const LLVM = struct {
const alignment = 0; const alignment = 0;
const line = type_declaration.declaration.line + 1; const line = type_declaration.declaration.line + 1;
const scope = try llvm.getScope(unit, context, error_type.scope.scope.parent.?); const scope = try llvm.getScope(unit, context, error_type.scope.scope.parent.?);
const enumeration_type = llvm.debug_info_builder.createEnumerationType(scope, name.ptr, name.len, file, line, bit_size, alignment, enumerators.pointer, enumerators.length, backing_type) orelse unreachable; const enumeration_type = llvm.debug_info_builder.createEnumerationType(scope, name.ptr, name.len, file, line, bit_size, alignment, enumerators.ptr, enumerators.len, backing_type) orelse unreachable;
break :b enumeration_type.toType(); break :b enumeration_type.toType();
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -1791,10 +1801,10 @@ pub const LLVM = struct {
}, },
.function => |function_prototype_index| b: { .function => |function_prototype_index| b: {
const function_prototype = unit.function_prototypes.get(function_prototype_index); const function_prototype = unit.function_prototypes.get(function_prototype_index);
var parameter_types = try UnpinnedArray(*LLVM.DebugInfo.Type).initialize_with_capacity(context.my_allocator, @intCast(function_prototype.argument_types.len)); var parameter_types = BoundedArray(*LLVM.DebugInfo.Type, 512){};
for (function_prototype.argument_types) |argument_type_index| { for (function_prototype.argument_types) |argument_type_index| {
const argument_type = try llvm.getDebugType(unit, context, argument_type_index); const argument_type = try llvm.getDebugType(unit, context, argument_type_index);
parameter_types.append_with_capacity(argument_type); parameter_types.appendAssumeCapacity(argument_type);
} }
const subroutine_type_flags = LLVM.DebugInfo.Node.Flags{ const subroutine_type_flags = LLVM.DebugInfo.Node.Flags{
.visibility = .none, .visibility = .none,
@ -1826,7 +1836,7 @@ pub const LLVM = struct {
.all_calls_described = false, .all_calls_described = false,
}; };
const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none; const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none;
const subroutine_type = llvm.debug_info_builder.createSubroutineType(parameter_types.pointer, parameter_types.length, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable; const subroutine_type = llvm.debug_info_builder.createSubroutineType(&parameter_types.buffer, parameter_types.len, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable;
break :b subroutine_type.toType(); break :b subroutine_type.toType();
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -2072,7 +2082,9 @@ pub const LLVM = struct {
const sema_array_type = unit.types.get(constant_array.type).array; const sema_array_type = unit.types.get(constant_array.type).array;
const constant_type = try llvm.getType(unit, context, constant_array.type); const constant_type = try llvm.getType(unit, context, constant_array.type);
const array_type = constant_type.toArray() orelse unreachable; const array_type = constant_type.toArray() orelse unreachable;
var list = try UnpinnedArray(*LLVM.Value.Constant).initialize_with_capacity(context.my_allocator, @intCast(constant_array.values.len));
var list = try context.arena.new_array(*LLVM.Value.Constant, constant_array.values.len);
list.len = 0;
for (constant_array.values) |sema_value| { for (constant_array.values) |sema_value| {
const value = switch (sema_value) { const value = switch (sema_value) {
.constant_int => |const_int| b: { .constant_int => |const_int| b: {
@ -2099,16 +2111,19 @@ pub const LLVM = struct {
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}; };
list.append_with_capacity(value);
const index = list.len;
list.len += 1;
list[index] = value;
} }
const result = array_type.getConstant(list.pointer, list.length) orelse unreachable; const result = array_type.getConstant(list.ptr, list.len) orelse unreachable;
return result; return result;
} }
fn getConstantStruct(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, constant_struct_index: Compilation.V.Comptime.ConstantStruct.Index) !*LLVM.Value.Constant { fn getConstantStruct(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, constant_struct_index: Compilation.V.Comptime.ConstantStruct.Index) !*LLVM.Value.Constant {
const constant_struct = unit.constant_structs.get(constant_struct_index); const constant_struct = unit.constant_structs.get(constant_struct_index);
var field_values = try UnpinnedArray(*LLVM.Value.Constant).initialize_with_capacity(context.my_allocator, @intCast(constant_struct.fields.len)); var field_values = BoundedArray(*LLVM.Value.Constant, 512){};
const sema_struct_index = unit.types.get(constant_struct.type).@"struct"; const sema_struct_index = unit.types.get(constant_struct.type).@"struct";
const sema_struct = unit.structs.get(sema_struct_index); const sema_struct = unit.structs.get(sema_struct_index);
const llvm_type = try llvm.getType(unit, context, constant_struct.type); const llvm_type = try llvm.getType(unit, context, constant_struct.type);
@ -2119,7 +2134,7 @@ pub const LLVM = struct {
for (constant_struct.fields, sema_struct_type.fields.slice()) |field_value, field_index| { for (constant_struct.fields, sema_struct_type.fields.slice()) |field_value, field_index| {
const field = unit.struct_fields.get(field_index); const field = unit.struct_fields.get(field_index);
const constant = try llvm.emitComptimeRightValue(unit, context, field_value, field.type); const constant = try llvm.emitComptimeRightValue(unit, context, field_value, field.type);
field_values.append_with_capacity(constant); field_values.appendAssumeCapacity(constant);
} }
}, },
.error_union => |error_union| { .error_union => |error_union| {
@ -2130,7 +2145,7 @@ pub const LLVM = struct {
const field_types = [2]Compilation.Type.Index{ err_union_base_type, .bool }; const field_types = [2]Compilation.Type.Index{ err_union_base_type, .bool };
for (field_types, constant_struct.fields) |field_type_index, field_value| { for (field_types, constant_struct.fields) |field_type_index, field_value| {
const constant = try llvm.emitComptimeRightValue(unit, context, field_value, field_type_index); const constant = try llvm.emitComptimeRightValue(unit, context, field_value, field_type_index);
field_values.append_with_capacity(constant); field_values.appendAssumeCapacity(constant);
} }
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -2141,7 +2156,7 @@ pub const LLVM = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
const const_struct = struct_type.getConstant(field_values.pointer, field_values.length) orelse unreachable; const const_struct = struct_type.getConstant(&field_values.buffer, field_values.len) orelse unreachable;
return const_struct; return const_struct;
} }
@ -2162,9 +2177,9 @@ pub const LLVM = struct {
} }
fn emitParameterAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, abi: Compilation.Function.AbiInfo, is_return: bool) !*const LLVM.Attribute.Set { fn emitParameterAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, abi: Compilation.Function.AbiInfo, is_return: bool) !*const LLVM.Attribute.Set {
var attributes = UnpinnedArray(*LLVM.Attribute){}; var attributes = BoundedArray(*LLVM.Attribute, 256){};
if (abi.attributes.by_reg) { if (abi.attributes.by_reg) {
try attributes.append(context.my_allocator, llvm.attributes.inreg); attributes.appendAssumeCapacity(llvm.attributes.inreg);
} }
switch (abi.kind) { switch (abi.kind) {
.ignore => { .ignore => {
@ -2175,39 +2190,39 @@ pub const LLVM = struct {
const indirect_type = try llvm.getType(unit, context, indirect.type); const indirect_type = try llvm.getType(unit, context, indirect.type);
if (is_return) { if (is_return) {
const sret = llvm.context.getAttributeFromType(.StructRet, indirect_type); const sret = llvm.context.getAttributeFromType(.StructRet, indirect_type);
try attributes.append(context.my_allocator, sret); attributes.appendAssumeCapacity(sret);
try attributes.append(context.my_allocator, llvm.attributes.@"noalias"); attributes.appendAssumeCapacity(llvm.attributes.@"noalias");
// TODO: alignment // TODO: alignment
} else { } else {
if (abi.attributes.by_value) { if (abi.attributes.by_value) {
const byval = llvm.context.getAttributeFromType(.ByVal, indirect_type); const byval = llvm.context.getAttributeFromType(.ByVal, indirect_type);
try attributes.append(context.my_allocator, byval); attributes.appendAssumeCapacity(byval);
} }
//TODO: alignment //TODO: alignment
} }
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
const attribute_set = llvm.context.getAttributeSet(attributes.pointer, attributes.length); const attribute_set = llvm.context.getAttributeSet(&attributes.buffer, attributes.len);
return attribute_set; return attribute_set;
} }
fn getFunctionAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, function_prototype: *Compilation.Function.Prototype) !*const LLVM.Attribute.Set { fn getFunctionAttributes(llvm: *LLVM, unit: *Compilation.Unit, function_prototype: *Compilation.Function.Prototype) *const LLVM.Attribute.Set {
var function_attributes = UnpinnedArray(*LLVM.Attribute){}; var function_attributes = BoundedArray(*LLVM.Attribute, 256){};
try function_attributes.append(context.my_allocator, llvm.attributes.nounwind); function_attributes.appendAssumeCapacity(llvm.attributes.nounwind);
switch (unit.types.get(function_prototype.return_type).*) { switch (unit.types.get(function_prototype.return_type).*) {
.noreturn => { .noreturn => {
try function_attributes.append(context.my_allocator, llvm.attributes.noreturn); function_attributes.appendAssumeCapacity(llvm.attributes.noreturn);
}, },
else => {}, else => {},
} }
if (function_prototype.attributes.naked) { if (function_prototype.attributes.naked) {
try function_attributes.append(context.my_allocator, llvm.attributes.naked); function_attributes.appendAssumeCapacity(llvm.attributes.naked);
} }
const function_attribute_set = llvm.context.getAttributeSet(function_attributes.pointer, function_attributes.length); const function_attribute_set = llvm.context.getAttributeSet(&function_attributes.buffer, function_attributes.len);
return function_attribute_set; return function_attribute_set;
} }
@ -2217,14 +2232,14 @@ pub const LLVM = struct {
}; };
fn setCallOrFunctionAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, function_prototype: *Compilation.Function.Prototype, call_or_function: CallOrFunction) !void { fn setCallOrFunctionAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, function_prototype: *Compilation.Function.Prototype, call_or_function: CallOrFunction) !void {
const function_attribute_set = try llvm.getFunctionAttributes(unit, context, function_prototype); const function_attribute_set = llvm.getFunctionAttributes(unit, function_prototype);
var parameter_attribute_sets = try UnpinnedArray(*const LLVM.Attribute.Set).initialize_with_capacity(context.my_allocator, @intCast(function_prototype.abi.parameter_types_abi.len + @intFromBool(function_prototype.abi.return_type_abi.kind == .indirect))); var parameter_attribute_sets = BoundedArray(*const LLVM.Attribute.Set, 512){};
const return_attribute_set = blk: { const return_attribute_set = blk: {
const attribute_set = try llvm.emitParameterAttributes(unit, context, function_prototype.abi.return_type_abi, true); const attribute_set = try llvm.emitParameterAttributes(unit, context, function_prototype.abi.return_type_abi, true);
break :blk switch (function_prototype.abi.return_type_abi.kind) { break :blk switch (function_prototype.abi.return_type_abi.kind) {
.indirect => b: { .indirect => b: {
parameter_attribute_sets.append_with_capacity(attribute_set); parameter_attribute_sets.appendAssumeCapacity(attribute_set);
break :b llvm.context.getAttributeSet(null, 0); break :b llvm.context.getAttributeSet(null, 0);
}, },
else => attribute_set, else => attribute_set,
@ -2233,18 +2248,18 @@ pub const LLVM = struct {
for (function_prototype.abi.parameter_types_abi) |parameter_type_abi| { for (function_prototype.abi.parameter_types_abi) |parameter_type_abi| {
const parameter_attribute_set = try llvm.emitParameterAttributes(unit, context, parameter_type_abi, false); const parameter_attribute_set = try llvm.emitParameterAttributes(unit, context, parameter_type_abi, false);
parameter_attribute_sets.append_with_capacity(parameter_attribute_set); parameter_attribute_sets.appendAssumeCapacity(parameter_attribute_set);
} }
const calling_convention = getCallingConvention(function_prototype.calling_convention); const calling_convention = getCallingConvention(function_prototype.calling_convention);
switch (call_or_function) { switch (call_or_function) {
.call => |call| { .call => |call| {
call.setAttributes(llvm.context, function_attribute_set, return_attribute_set, parameter_attribute_sets.pointer, parameter_attribute_sets.length); call.setAttributes(llvm.context, function_attribute_set, return_attribute_set, &parameter_attribute_sets.buffer, parameter_attribute_sets.len);
call.setCallingConvention(calling_convention); call.setCallingConvention(calling_convention);
}, },
.function => |function| { .function => |function| {
function.setAttributes(llvm.context, function_attribute_set, return_attribute_set, parameter_attribute_sets.pointer, parameter_attribute_sets.length); function.setAttributes(llvm.context, function_attribute_set, return_attribute_set, &parameter_attribute_sets.buffer, parameter_attribute_sets.len);
function.setCallingConvention(calling_convention); function.setCallingConvention(calling_convention);
}, },
} }
@ -2286,10 +2301,10 @@ pub const LLVM = struct {
if (generate_debug_information) { if (generate_debug_information) {
// if (data_structures.byte_equal(name, "nat_split_struct_ints")) @breakpoint(); // if (data_structures.byte_equal(name, "nat_split_struct_ints")) @breakpoint();
const debug_file = try llvm.getDebugInfoFile(unit, context, declaration.declaration.scope.file); const debug_file = try llvm.getDebugInfoFile(unit, context, declaration.declaration.scope.file);
var parameter_types = try UnpinnedArray(*LLVM.DebugInfo.Type).initialize_with_capacity(context.my_allocator, @intCast(function_prototype.argument_types.len)); var parameter_types = BoundedArray(*LLVM.DebugInfo.Type, 512){};
for (function_prototype.argument_types) |argument_type_index| { for (function_prototype.argument_types) |argument_type_index| {
const argument_type = try llvm.getDebugType(unit, context, argument_type_index); const argument_type = try llvm.getDebugType(unit, context, argument_type_index);
parameter_types.append_with_capacity(argument_type); parameter_types.appendAssumeCapacity(argument_type);
} }
const subroutine_type_flags = LLVM.DebugInfo.Node.Flags{ const subroutine_type_flags = LLVM.DebugInfo.Node.Flags{
@ -2322,7 +2337,7 @@ pub const LLVM = struct {
.all_calls_described = false, .all_calls_described = false,
}; };
const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none; const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none;
const subroutine_type = llvm.debug_info_builder.createSubroutineType(parameter_types.pointer, parameter_types.length, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable; const subroutine_type = llvm.debug_info_builder.createSubroutineType(&parameter_types.buffer, parameter_types.len, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable;
const subprogram_flags = LLVM.DebugInfo.Subprogram.Flags{ const subprogram_flags = LLVM.DebugInfo.Subprogram.Flags{
.virtuality = .none, .virtuality = .none,
.local_to_unit = !export_or_extern, .local_to_unit = !export_or_extern,
@ -2570,10 +2585,10 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
.inline_assembly => |inline_assembly_index| { .inline_assembly => |inline_assembly_index| {
const assembly_block = unit.inline_assembly.get(inline_assembly_index); const assembly_block = unit.inline_assembly.get(inline_assembly_index);
var assembly_statements = UnpinnedArray(u8){}; var assembly_statements = BoundedArray(u8, 4096){};
var constraints = UnpinnedArray(u8){}; var constraints = BoundedArray(u8, 4096){};
var operand_values = UnpinnedArray(*LLVM.Value){}; var operand_values = BoundedArray(*LLVM.Value, 256){};
var operand_types = UnpinnedArray(*LLVM.Type){}; var operand_types = BoundedArray(*LLVM.Type, 256){};
switch (unit.descriptor.arch) { switch (unit.descriptor.arch) {
.x86_64 => { .x86_64 => {
@ -2581,13 +2596,13 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
const instruction = unit.assembly_instructions.get(assembly_instruction_index); const instruction = unit.assembly_instructions.get(assembly_instruction_index);
const instruction_id: Compilation.InlineAssembly.x86_64.Instruction = @enumFromInt(instruction.id); const instruction_id: Compilation.InlineAssembly.x86_64.Instruction = @enumFromInt(instruction.id);
try assembly_statements.append_slice(context.my_allocator, switch (instruction_id) { assembly_statements.appendSliceAssumeCapacity(switch (instruction_id) {
.xor => "xorl", .xor => "xorl",
.mov => "movq", .mov => "movq",
.@"and" => "andq", .@"and" => "andq",
.call => "callq", .call => "callq",
}); });
try assembly_statements.append(context.my_allocator, ' '); assembly_statements.appendAssumeCapacity(' ');
if (instruction.operands.len > 0) { if (instruction.operands.len > 0) {
var reverse_operand_iterator = std.mem.reverseIterator(instruction.operands); var reverse_operand_iterator = std.mem.reverseIterator(instruction.operands);
@ -2596,8 +2611,8 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
switch (operand) { switch (operand) {
.register => |register_value| { .register => |register_value| {
const register: Compilation.InlineAssembly.x86_64.Register = @enumFromInt(register_value); const register: Compilation.InlineAssembly.x86_64.Register = @enumFromInt(register_value);
try assembly_statements.append(context.my_allocator, '%'); assembly_statements.appendAssumeCapacity('%');
try assembly_statements.append_slice(context.my_allocator, @tagName(register)); assembly_statements.appendSliceAssumeCapacity(@tagName(register));
}, },
.number_literal => |literal| { .number_literal => |literal| {
var buffer: [65]u8 = undefined; var buffer: [65]u8 = undefined;
@ -2608,7 +2623,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
literal_slice[1] = '$'; literal_slice[1] = '$';
literal_slice[2] = '0'; literal_slice[2] = '0';
literal_slice[3] = 'x'; literal_slice[3] = 'x';
try assembly_statements.append_slice(context.my_allocator, try context.my_allocator.duplicate_bytes(literal_slice)); assembly_statements.appendSliceAssumeCapacity(try context.my_allocator.duplicate_bytes(literal_slice));
}, },
.value => |sema_value| { .value => |sema_value| {
if (llvm.llvm_value_map.get(sema_value)) |v| { if (llvm.llvm_value_map.get(sema_value)) |v| {
@ -2617,7 +2632,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.length, 16, false); const operand_number = data_structures.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] = '$';
@ -2628,23 +2643,23 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
new_buffer[operand_slice.len + 1] = 'P'; new_buffer[operand_slice.len + 1] = 'P';
new_buffer[operand_slice.len + 2] = '}'; new_buffer[operand_slice.len + 2] = '}';
const new_slice = try context.my_allocator.duplicate_bytes(new_buffer[0 .. operand_slice.len + 3]); const new_slice = try context.my_allocator.duplicate_bytes(new_buffer[0 .. operand_slice.len + 3]);
try assembly_statements.append_slice(context.my_allocator, new_slice); assembly_statements.appendSliceAssumeCapacity(new_slice);
try operand_values.append(context.my_allocator, value); operand_values.appendAssumeCapacity(value);
const value_type = value.getType(); const value_type = value.getType();
try operand_types.append(context.my_allocator, value_type); operand_types.appendAssumeCapacity(value_type);
try constraints.append(context.my_allocator, 'X'); constraints.appendAssumeCapacity('X');
} }
}, },
} }
try assembly_statements.append_slice(context.my_allocator, ", "); assembly_statements.appendSliceAssumeCapacity(", ");
} }
_ = assembly_statements.pop(); _ = assembly_statements.pop();
_ = assembly_statements.pop(); _ = assembly_statements.pop();
} }
try assembly_statements.append_slice(context.my_allocator, "\n\t"); assembly_statements.appendSliceAssumeCapacity("\n\t");
} }
// try constraints.append_slice(context.allocator, ",~{dirflag},~{fpsr},~{flags}"); // try constraints.append_slice(context.allocator, ",~{dirflag},~{fpsr},~{flags}");
@ -2653,14 +2668,14 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
} }
const is_var_args = false; const is_var_args = false;
const function_type = LLVM.Context.getFunctionType(try llvm.getType(unit, context, Compilation.Type.Index.void), operand_types.pointer, operand_types.length, is_var_args) orelse unreachable; const function_type = LLVM.Context.getFunctionType(try llvm.getType(unit, context, Compilation.Type.Index.void), &operand_types.buffer, operand_types.len, is_var_args) orelse unreachable;
const has_side_effects = true; const has_side_effects = true;
const is_align_stack = true; const is_align_stack = true;
const dialect = LLVM.Value.InlineAssembly.Dialect.@"at&t"; const dialect = LLVM.Value.InlineAssembly.Dialect.@"at&t";
const can_throw = false; const can_throw = false;
const inline_assembly = LLVM.Value.InlineAssembly.get(function_type, assembly_statements.pointer, assembly_statements.length, constraints.pointer, constraints.length, 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.pointer, operand_values.length, "", "".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(context.my_allocator, instruction_index, call.toValue());
}, },
.stack_slot => |stack_slot| { .stack_slot => |stack_slot| {
@ -2876,27 +2891,27 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
const return_type = try llvm.getType(unit, context, Compilation.Type.usize); const return_type = try llvm.getType(unit, context, Compilation.Type.usize);
const is_var_args = false; const is_var_args = false;
const function_type = LLVM.Context.getFunctionType(return_type, syscall_argument_types.ptr, syscall_argument_types.len, is_var_args) orelse unreachable; const function_type = LLVM.Context.getFunctionType(return_type, syscall_argument_types.ptr, syscall_argument_types.len, is_var_args) orelse unreachable;
var constraints = UnpinnedArray(u8){}; var constraints = BoundedArray(u8, 4096){};
const inline_asm = switch (unit.descriptor.arch) { const inline_asm = switch (unit.descriptor.arch) {
.x86_64 => blk: { .x86_64 => blk: {
try constraints.append_slice(context.my_allocator, "={rax}"); constraints.appendSliceAssumeCapacity("={rax}");
const syscall_registers = [7][]const u8{ "rax", "rdi", "rsi", "rdx", "r10", "r8", "r9" }; const syscall_registers = [7][]const u8{ "rax", "rdi", "rsi", "rdx", "r10", "r8", "r9" };
for (syscall_registers[0..syscall_argument_count]) |syscall_register| { for (syscall_registers[0..syscall_argument_count]) |syscall_register| {
try constraints.append(context.my_allocator, ','); constraints.appendAssumeCapacity(',');
try constraints.append(context.my_allocator, '{'); constraints.appendAssumeCapacity('{');
try constraints.append_slice(context.my_allocator, syscall_register); constraints.appendSliceAssumeCapacity(syscall_register);
try constraints.append(context.my_allocator, '}'); constraints.appendAssumeCapacity('}');
} }
try constraints.append_slice(context.my_allocator, ",~{rcx},~{r11},~{memory}"); constraints.appendSliceAssumeCapacity(",~{rcx},~{r11},~{memory}");
const assembly = "syscall"; const assembly = "syscall";
const has_side_effects = true; const has_side_effects = true;
const is_align_stack = true; const is_align_stack = true;
const can_throw = false; const can_throw = false;
const inline_assembly = LLVM.Value.InlineAssembly.get(function_type, assembly, assembly.len, constraints.pointer, constraints.length, has_side_effects, is_align_stack, LLVM.Value.InlineAssembly.Dialect.@"at&t", can_throw) orelse return LLVM.Value.Error.inline_assembly; const inline_assembly = LLVM.Value.InlineAssembly.get(function_type, assembly, assembly.len, &constraints.buffer, constraints.len, has_side_effects, is_align_stack, LLVM.Value.InlineAssembly.Dialect.@"at&t", can_throw) orelse return LLVM.Value.Error.inline_assembly;
break :blk inline_assembly; break :blk inline_assembly;
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -3129,8 +3144,10 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
last_block = else_block_node; last_block = else_block_node;
break :b bb; break :b bb;
} else null; } else null;
var basic_block_array = try UnpinnedArray(*LLVM.Value.BasicBlock).initialize_with_capacity(context.my_allocator, switch_expression.cases.length);
var condition_array = try UnpinnedArray(*LLVM.Value.Constant.Int).initialize_with_capacity(context.my_allocator, switch_expression.cases.length); var basic_block_array = BoundedArray(*LLVM.Value.BasicBlock, 4096){};
var condition_array = BoundedArray(*LLVM.Value.Constant.Int, 4096){};
for (switch_expression.cases.pointer[0..switch_expression.cases.length]) |case| { for (switch_expression.cases.pointer[0..switch_expression.cases.length]) |case| {
const constant_value = try llvm.emitComptimeRightValue(unit, context, case.condition, switch_expression.condition.type); const constant_value = try llvm.emitComptimeRightValue(unit, context, case.condition, switch_expression.condition.type);
const constant_int = constant_value.toInt() orelse unreachable; const constant_int = constant_value.toInt() orelse unreachable;
@ -3141,13 +3158,13 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
const block = llvm.llvm_block_map.get(case.basic_block).?; const block = llvm.llvm_block_map.get(case.basic_block).?;
break :b block; break :b block;
}; };
condition_array.append_with_capacity(constant_int); condition_array.appendAssumeCapacity(constant_int);
basic_block_array.append_with_capacity(block); basic_block_array.appendAssumeCapacity(block);
} }
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.pointer, basic_block_array.pointer, condition_array.length, 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(context.my_allocator, instruction_index, switch_instruction.toValue());
}, },
.memcpy => |memcpy| { .memcpy => |memcpy| {
@ -3207,8 +3224,6 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
const result = llvm.function.verify(&message_ptr, &message_len); const result = llvm.function.verify(&message_ptr, &message_len);
if (!result) { if (!result) {
// std.debug.print("PANIC: Failed to verify function:\n{s}\n", .{error_message});
var module_len: usize = 0; var module_len: usize = 0;
const module_ptr = llvm.module.toString(&module_len); const module_ptr = llvm.module.toString(&module_len);
const module_dump = module_ptr[0..module_len]; const module_dump = module_ptr[0..module_len];
@ -3269,25 +3284,34 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
.windows => "x86_64-windows-gnu", .windows => "x86_64-windows-gnu",
}; };
const cpu = "generic"; const cpu = "generic";
const temp_use_native_features = true;
const features = if (temp_use_native_features) blk: {
var buffer = UnpinnedArray(u8){};
for (@import("builtin").cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
const is_enabled = @import("builtin").cpu.features.isEnabled(index);
if (feature.llvm_name) |llvm_name| { var features = PinnedArray(u8){
const plus_or_minus = "-+"[@intFromBool(is_enabled)]; .pointer = @constCast(@ptrCast("")),
try buffer.append(context.my_allocator, plus_or_minus); .length = 0,
try buffer.append_slice(context.my_allocator, llvm_name); .granularity = 0,
try buffer.append_slice(context.my_allocator, ","); };
const temp_use_native_features = true;
if (temp_use_native_features) {
const feature_list = @import("builtin").cpu.arch.allFeaturesList();
if (feature_list.len > 0) {
features = try PinnedArray(u8).init_with_default_granularity();
for (feature_list, 0..) |feature, index_usize| {
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
const is_enabled = @import("builtin").cpu.features.isEnabled(index);
if (feature.llvm_name) |llvm_name| {
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
_ = features.append(plus_or_minus);
features.append_slice(llvm_name);
features.append_slice(",");
}
} }
assert(std.mem.endsWith(u8, features.slice(), ","));
features.length -= 1;
} }
if (buffer.length == 0) break :blk ""; }
assert(std.mem.endsWith(u8, buffer.slice(), ","));
buffer.slice()[buffer.length - 1] = 0;
break :blk buffer.slice()[0 .. buffer.length - 1 :0];
} else "";
const target = blk: { const target = blk: {
var error_message: [*]const u8 = undefined; var error_message: [*]const u8 = undefined;
@ -3306,7 +3330,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
.optimize_for_speed, .optimize_for_size => .default, .optimize_for_speed, .optimize_for_size => .default,
.aggressively_optimize_for_speed, .aggressively_optimize_for_size => .aggressive, .aggressively_optimize_for_speed, .aggressively_optimize_for_size => .aggressive,
}; };
const target_machine = target.createTargetMachine(target_triple.ptr, target_triple.len, cpu, cpu.len, features.ptr, features.len, LLVM.RelocationModel.static, code_model, is_code_model_present, codegen_optimization_level, jit) orelse unreachable; const target_machine = target.createTargetMachine(target_triple.ptr, target_triple.len, cpu, cpu.len, features.pointer, features.length, LLVM.RelocationModel.static, code_model, is_code_model_present, codegen_optimization_level, jit) orelse unreachable;
llvm.module.setTargetMachineDataLayout(target_machine); llvm.module.setTargetMachineDataLayout(target_machine);
llvm.module.setTargetTriple(target_triple.ptr, target_triple.len); llvm.module.setTargetTriple(target_triple.ptr, target_triple.len);
const file_path = unit.descriptor.executable_path; const file_path = unit.descriptor.executable_path;

View File

@ -8,7 +8,6 @@ const byte_equal = library.byte_equal;
const enumFromString = library.enumFromString; const enumFromString = library.enumFromString;
const MyAllocator = library.MyAllocator; const MyAllocator = library.MyAllocator;
const PinnedArray = library.PinnedArray; const PinnedArray = library.PinnedArray;
const UnpinnedArray = library.UnpinnedArray;
const Compilation = @import("../Compilation.zig"); const Compilation = @import("../Compilation.zig");
const File = Compilation.File; const File = Compilation.File;

View File

@ -363,7 +363,7 @@ const Analyzer = struct {
} }
} else @panic(identifier_name); } else @panic(identifier_name);
try stack_list.append(attribute_node); stack_list.appendAssumeCapacity(attribute_node);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_assign => {}, .operator_assign => {},
@ -462,7 +462,7 @@ const Analyzer = struct {
} }
} else @panic(identifier_name); } else @panic(identifier_name);
try attribute_and_return_type_node_list.append(attribute_node); attribute_and_return_type_node_list.appendAssumeCapacity(attribute_node);
if (analyzer.peekToken() == .operator_comma) analyzer.consumeToken(); if (analyzer.peekToken() == .operator_comma) analyzer.consumeToken();
} }
@ -471,7 +471,7 @@ const Analyzer = struct {
const arguments = try analyzer.argumentList(.operator_left_parenthesis, .operator_right_parenthesis); const arguments = try analyzer.argumentList(.operator_left_parenthesis, .operator_right_parenthesis);
const return_type = try analyzer.typeExpression(); const return_type = try analyzer.typeExpression();
try attribute_and_return_type_node_list.append(return_type); attribute_and_return_type_node_list.appendAssumeCapacity(return_type);
const function_prototype = try analyzer.addNode(.{ const function_prototype = try analyzer.addNode(.{
.id = .function_prototype, .id = .function_prototype,
@ -510,7 +510,7 @@ const Analyzer = struct {
analyzer.consumeToken(); analyzer.consumeToken();
} }
try list.append(try analyzer.addNode(.{ list.appendAssumeCapacity(try analyzer.addNode(.{
.id = id, .id = id,
.token = identifier_token, .token = identifier_token,
.left = type_expression, .left = type_expression,
@ -552,7 +552,7 @@ const Analyzer = struct {
=> try analyzer.symbolDeclaration(), => try analyzer.symbolDeclaration(),
}; };
try list.append(statement_index); list.appendAssumeCapacity(statement_index);
} }
_ = try analyzer.expectToken(.operator_right_brace); _ = try analyzer.expectToken(.operator_right_brace);
@ -627,7 +627,7 @@ const Analyzer = struct {
else => left, else => left,
}; };
try array_list.append(switch_case_node); array_list.appendAssumeCapacity(switch_case_node);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_comma => analyzer.consumeToken(), .operator_comma => analyzer.consumeToken(),
@ -660,7 +660,7 @@ const Analyzer = struct {
.right = expr, .right = expr,
}); });
try list.append(node); list.appendAssumeCapacity(node);
} }
_ = try analyzer.expectToken(.operator_right_brace); _ = try analyzer.expectToken(.operator_right_brace);
@ -770,7 +770,7 @@ const Analyzer = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}; };
try for_expression_list.append(node_index); for_expression_list.appendAssumeCapacity(node_index);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_comma => analyzer.consumeToken(), .operator_comma => analyzer.consumeToken(),
@ -801,7 +801,7 @@ const Analyzer = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
try payload_nodes.append(try analyzer.addNode(.{ payload_nodes.appendAssumeCapacity(try analyzer.addNode(.{
.id = id, .id = id,
.token = payload_token, .token = payload_token,
.left = Node.Index.null, .left = Node.Index.null,
@ -992,7 +992,7 @@ const Analyzer = struct {
.operator_semicolon => {}, .operator_semicolon => {},
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
try operand_list.append(node); operand_list.appendAssumeCapacity(node);
} }
analyzer.consumeToken(); analyzer.consumeToken();
@ -1004,7 +1004,7 @@ const Analyzer = struct {
.right = try analyzer.nodeList(&operand_list), .right = try analyzer.nodeList(&operand_list),
}); });
try instruction_list.append(instruction); instruction_list.appendAssumeCapacity(instruction);
} }
_ = try analyzer.expectToken(.operator_backtick); _ = try analyzer.expectToken(.operator_backtick);
@ -1016,7 +1016,7 @@ const Analyzer = struct {
.left = try analyzer.nodeList(&instruction_list), .left = try analyzer.nodeList(&instruction_list),
.right = .null, .right = .null,
}); });
try list.append(assembly_block); list.appendAssumeCapacity(assembly_block);
const intrinsic = try analyzer.addNode(.{ const intrinsic = try analyzer.addNode(.{
.id = .intrinsic, .id = .intrinsic,
@ -1029,7 +1029,7 @@ const Analyzer = struct {
} else { } else {
while (analyzer.peekToken() != .operator_right_parenthesis) { while (analyzer.peekToken() != .operator_right_parenthesis) {
const parameter = try analyzer.expression(); const parameter = try analyzer.expression();
try list.append(parameter); list.appendAssumeCapacity(parameter);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_comma => analyzer.consumeToken(), .operator_comma => analyzer.consumeToken(),
@ -1465,7 +1465,7 @@ const Analyzer = struct {
break :blk .pointer_type; break :blk .pointer_type;
}, },
.many_pointer_type => blk: { .many_pointer_type => blk: {
try list.append(try analyzer.addNode(.{ list.appendAssumeCapacity(try analyzer.addNode(.{
.id = .many_pointer_expression, .id = .many_pointer_expression,
.token = analyzer.token_i, .token = analyzer.token_i,
.left = Node.Index.null, .left = Node.Index.null,
@ -1475,7 +1475,7 @@ const Analyzer = struct {
_ = try analyzer.expectToken(.operator_ampersand); _ = try analyzer.expectToken(.operator_ampersand);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_right_bracket => {}, .operator_right_bracket => {},
.operator_colon => try list.append(try analyzer.parseTermination()), .operator_colon => list.appendAssumeCapacity(try analyzer.parseTermination()),
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
_ = try analyzer.expectToken(.operator_right_bracket); _ = try analyzer.expectToken(.operator_right_bracket);
@ -1490,17 +1490,17 @@ const Analyzer = struct {
break :blk .slice_type; break :blk .slice_type;
}, },
.operator_colon => { .operator_colon => {
try list.append(try analyzer.parseTermination()); list.appendAssumeCapacity(try analyzer.parseTermination());
_ = try analyzer.expectToken(.operator_right_bracket); _ = try analyzer.expectToken(.operator_right_bracket);
break :blk .slice_type; break :blk .slice_type;
}, },
else => { else => {
const length_expression = try analyzer.expression(); const length_expression = try analyzer.expression();
try list.append(length_expression); list.appendAssumeCapacity(length_expression);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_right_bracket => {}, .operator_right_bracket => {},
.operator_colon => try list.append(try analyzer.parseTermination()), .operator_colon => list.appendAssumeCapacity(try analyzer.parseTermination()),
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
@ -1525,7 +1525,7 @@ const Analyzer = struct {
analyzer.consumeTokens(@intFromBool(analyzer.peekToken() == .fixed_keyword_const)); analyzer.consumeTokens(@intFromBool(analyzer.peekToken() == .fixed_keyword_const));
if (const_node != .null) { if (const_node != .null) {
try list.append(const_node); list.appendAssumeCapacity(const_node);
} }
} else { } else {
assert(list.len > 0); assert(list.len > 0);
@ -1533,7 +1533,7 @@ const Analyzer = struct {
const type_expression = try analyzer.typeExpression(); const type_expression = try analyzer.typeExpression();
assert(type_expression != .null); assert(type_expression != .null);
try list.append(type_expression); list.appendAssumeCapacity(type_expression);
const node_list = try analyzer.nodeList(&list); const node_list = try analyzer.nodeList(&list);
@ -1544,15 +1544,7 @@ const Analyzer = struct {
.right = Node.Index.null, .right = Node.Index.null,
}; };
// logln(.parser, .pointer_like_type_expression, "ARRAY START\n===========", .{});
// for (list.slice()) |ni| {
// const n = analyzer.nodes.get(ni);
// logln(.parser, .pointer_like_type_expression, "{s} node element: {s}", .{ @tagName(expression_type), @tagName(n.id) });
// }
// logln(.parser, .pointer_like_type_expression, "ARRAY END\n=========", .{});
const node_index = try analyzer.addNode(node); const node_index = try analyzer.addNode(node);
// logln(.parser, .pointer_like_type_expression, "Pointer end", .{});
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_comma, .operator_comma,
@ -1663,7 +1655,7 @@ const Analyzer = struct {
}); });
} }
try expression_list.append(parameter); expression_list.appendAssumeCapacity(parameter);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_right_parenthesis => {}, .operator_right_parenthesis => {},
@ -1726,7 +1718,7 @@ const Analyzer = struct {
.right = Node.Index.null, .right = Node.Index.null,
}); });
try list.append(field_initialization); list.appendAssumeCapacity(field_initialization);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_comma => analyzer.consumeToken(), .operator_comma => analyzer.consumeToken(),
else => {}, else => {},
@ -1737,7 +1729,7 @@ const Analyzer = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}, },
else => blk: { else => blk: {
try list.append(try analyzer.anonymousExpression()); list.appendAssumeCapacity(try analyzer.anonymousExpression());
_ = try analyzer.expectToken(.operator_comma); _ = try analyzer.expectToken(.operator_comma);
break :blk .anonymous; break :blk .anonymous;
}, },
@ -1754,7 +1746,7 @@ const Analyzer = struct {
else => {}, else => {},
} }
try list.append(field_expression_initializer); list.appendAssumeCapacity(field_expression_initializer);
break :blk .anonymous; break :blk .anonymous;
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -1837,7 +1829,7 @@ const Analyzer = struct {
var list = Node.StackList{}; var list = Node.StackList{};
while (analyzer.peekToken() != .operator_right_parenthesis) { while (analyzer.peekToken() != .operator_right_parenthesis) {
const parameter_node = try analyzer.expression(); const parameter_node = try analyzer.expression();
try list.append(parameter_node); list.appendAssumeCapacity(parameter_node);
switch (analyzer.peekToken()) { switch (analyzer.peekToken()) {
.operator_comma => analyzer.consumeToken(), .operator_comma => analyzer.consumeToken(),
else => {}, else => {},
@ -1935,7 +1927,7 @@ const Analyzer = struct {
// logln(.parser, .container_members, "Container member {s}", .{@tagName(member_node.id)}); // logln(.parser, .container_members, "Container member {s}", .{@tagName(member_node.id)});
assert(member_node.id != .identifier); assert(member_node.id != .identifier);
try list.append(member_node_index); list.appendAssumeCapacity(member_node_index);
} }
if (maybe_token_id) |_| _ = try analyzer.expectToken(.operator_right_brace); if (maybe_token_id) |_| _ = try analyzer.expectToken(.operator_right_brace);
@ -2169,7 +2161,7 @@ const Analyzer = struct {
.right = value_associated, .right = value_associated,
}); });
try list.append(error_field_node); list.appendAssumeCapacity(error_field_node);
} }
analyzer.consumeToken(); analyzer.consumeToken();

View File

@ -99,9 +99,16 @@ pub fn PinnedArray(comptime T: type) type {
const Array = @This(); const Array = @This();
pub fn const_slice(array: *const Array) []const T{
return array.pointer[0..array.length];
}
pub fn slice(array: *Array) []T{
return array.pointer[0..array.length];
}
pub fn get_unchecked(array: *Array, index: u32) *T { pub fn get_unchecked(array: *Array, index: u32) *T {
const slice = array.pointer[0..array.length]; const array_slice = array.slice();
return &slice[index]; return &array_slice[index];
} }
pub fn get(array: *Array, index: Index) *T { pub fn get(array: *Array, index: Index) *T {
@ -142,6 +149,18 @@ pub fn PinnedArray(comptime T: type) type {
return array.append_with_capacity(item); return array.append_with_capacity(item);
} }
pub fn append_slice(array: *Array, items: []const T) void {
const count: u32 = @intCast(items.len);
if (((array.length + count) * @sizeOf(T)) & (array.granularity - 1) == 0) {
const length: u64 = array.length;
assert((length + count) * @sizeOf(T) <= pinned_array_max_size);
const ptr: [*]u8 = @ptrCast(array.pointer);
commit(ptr + ((length + count) * @sizeOf(T)), array.granularity) catch unreachable;
}
array.append_slice_with_capacity(items);
}
pub fn append_with_capacity(array: *Array, item: T) *T { pub fn append_with_capacity(array: *Array, item: T) *T {
const index = array.length; const index = array.length;
assert(index * @sizeOf(T) < pinned_array_max_size); assert(index * @sizeOf(T) < pinned_array_max_size);
@ -150,6 +169,14 @@ pub fn PinnedArray(comptime T: type) type {
ptr.* = item; ptr.* = item;
return ptr; return ptr;
} }
pub fn append_slice_with_capacity(array: *Array, items: []const T) void {
const index = array.length;
const count: u32 = @intCast(items.len);
assert((index + count - 1) * @sizeOf(T) < pinned_array_max_size);
array.length += count;
@memcpy(array.pointer[index..][0..count], items);
}
}; };
} }
@ -711,41 +738,6 @@ fn copy_backwards(comptime T: type, destination: []T, source: []const T) void {
} }
} }
test {
var page_allocator = PageAllocator{};
const allocator = &page_allocator.allocator;
var foo = UnpinnedArray(u32){};
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
try foo.append(allocator, 1);
}
pub fn equal(a: anytype, b: @TypeOf(a)) bool { pub fn equal(a: anytype, b: @TypeOf(a)) bool {
const T = @TypeOf(a); const T = @TypeOf(a);

View File

@ -3,97 +3,97 @@ const assert = std.debug.assert;
const linker = @import("linker.zig"); const linker = @import("linker.zig");
const library = @import("../library.zig"); const library = @import("../library.zig");
const UnpinnedArray = library.UnpinnedArray; const PinnedArray = library.PinnedArray;
const Compilation = @import("../Compilation.zig"); const Compilation = @import("../Compilation.zig");
const write = Compilation.write; const write = Compilation.write;
pub fn link(context: *const Compilation.Context, options: linker.Options) !void { pub fn link(context: *const Compilation.Context, options: linker.Options) !void {
assert(options.backend == .lld); assert(options.backend == .lld);
var argv = UnpinnedArray([]const u8){}; var argv = try PinnedArray([]const u8).init_with_default_granularity();
const driver_program = switch (@import("builtin").os.tag) { const driver_program = switch (@import("builtin").os.tag) {
.windows => "lld-link", .windows => "lld-link",
.linux => "ld.lld", .linux => "ld.lld",
.macos => "ld64.lld", .macos => "ld64.lld",
else => @compileError("OS not supported"), else => @compileError("OS not supported"),
}; };
try argv.append(context.my_allocator, driver_program); _ = argv.append(driver_program);
try argv.append(context.my_allocator, "--error-limit=0"); _ = argv.append("--error-limit=0");
// const output_path = out_path orelse "a.out"; // const output_path = out_path orelse "a.out";
try argv.append(context.my_allocator, "-o"); _ = argv.append("-o");
try argv.append(context.my_allocator, options.output_file_path); _ = argv.append(options.output_file_path);
try argv.append_slice(context.my_allocator, options.extra_arguments); argv.append_slice(options.extra_arguments);
for (options.objects) |object| { for (options.objects) |object| {
try argv.append(context.my_allocator, object.path); _ = argv.append(object.path);
} }
const ci = @import("configuration").ci; const ci = @import("configuration").ci;
switch (@import("builtin").os.tag) { switch (@import("builtin").os.tag) {
.macos => { .macos => {
try argv.append(context.my_allocator, "-dynamic"); _ = argv.append("-dynamic");
try argv.append_slice(context.my_allocator, &.{ "-platform_version", "macos", "13.4.1", "13.3" }); argv.append_slice(context.my_allocator, &.{ "-platform_version", "macos", "13.4.1", "13.3" });
try argv.append(context.my_allocator, "-arch"); _ = argv.append("-arch");
try argv.append(context.my_allocator, switch (@import("builtin").cpu.arch) { _ = argv.append(switch (@import("builtin").cpu.arch) {
.aarch64 => "arm64", .aarch64 => "arm64",
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}); });
try argv.append_slice(context.my_allocator, &.{ "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" }); argv.append_slice(&.{ "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" });
if (!library.ends_with_slice(options.output_file_path, ".dylib")) { if (!library.ends_with_slice(options.output_file_path, ".dylib")) {
try argv.append_slice(context.my_allocator, &.{ "-e", "_main" }); argv.append_slice(&.{ "-e", "_main" });
} }
try argv.append(context.my_allocator, "-lSystem"); _ = argv.append("-lSystem");
if (options.link_libcpp) { if (options.link_libcpp) {
try argv.append(context.my_allocator, "-L/Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib"); _ = argv.append("-L/Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib");
try argv.append(context.my_allocator, "-lc++"); _ = argv.append("-lc++");
} }
}, },
.linux => { .linux => {
if (ci) { if (ci) {
if (options.link_libcpp) { if (options.link_libcpp) {
assert(options.link_libc); assert(options.link_libc);
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/libstdc++.so.6"); _ = argv.append("/lib/x86_64-linux-gnu/libstdc++.so.6");
} }
if (options.link_libc) { if (options.link_libc) {
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/crt1.o"); _ = argv.append("/lib/x86_64-linux-gnu/crt1.o");
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/crti.o"); _ = argv.append("/lib/x86_64-linux-gnu/crti.o");
try argv.append_slice(context.my_allocator, &.{ "-L", "/lib/x86_64-linux-gnu" }); argv.append_slice(&.{ "-L", "/lib/x86_64-linux-gnu" });
try argv.append_slice(context.my_allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" }); argv.append_slice(&.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
try argv.append(context.my_allocator, "--as-needed"); _ = argv.append("--as-needed");
try argv.append(context.my_allocator, "-lm"); _ = argv.append("-lm");
try argv.append(context.my_allocator, "-lpthread"); _ = argv.append("-lpthread");
try argv.append(context.my_allocator, "-lc"); _ = argv.append("-lc");
try argv.append(context.my_allocator, "-ldl"); _ = argv.append("-ldl");
try argv.append(context.my_allocator, "-lrt"); _ = argv.append("-lrt");
try argv.append(context.my_allocator, "-lutil"); _ = argv.append("-lutil");
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/crtn.o"); _ = argv.append("/lib/x86_64-linux-gnu/crtn.o");
} }
} else { } else {
if (options.link_libcpp) { if (options.link_libcpp) {
assert(options.link_libc); assert(options.link_libc);
try argv.append(context.my_allocator, "/usr/lib/libstdc++.so"); _ = argv.append("/usr/lib/libstdc++.so");
} }
if (options.link_libc) { if (options.link_libc) {
try argv.append(context.my_allocator, "/usr/lib/crt1.o"); _ = argv.append("/usr/lib/crt1.o");
try argv.append(context.my_allocator, "/usr/lib/crti.o"); _ = argv.append("/usr/lib/crti.o");
try argv.append_slice(context.my_allocator, &.{ "-L", "/usr/lib" }); argv.append_slice(&.{ "-L", "/usr/lib" });
try argv.append_slice(context.my_allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" }); argv.append_slice(&.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
try argv.append(context.my_allocator, "--as-needed"); _ = argv.append("--as-needed");
try argv.append(context.my_allocator, "-lm"); _ = argv.append("-lm");
try argv.append(context.my_allocator, "-lpthread"); _ = argv.append("-lpthread");
try argv.append(context.my_allocator, "-lc"); _ = argv.append("-lc");
try argv.append(context.my_allocator, "-ldl"); _ = argv.append("-ldl");
try argv.append(context.my_allocator, "-lrt"); _ = argv.append("-lrt");
try argv.append(context.my_allocator, "-lutil"); _ = argv.append("-lutil");
try argv.append(context.my_allocator, "/usr/lib/crtn.o"); _ = argv.append("/usr/lib/crtn.o");
} }
} }
}, },
@ -102,10 +102,10 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void
} }
for (options.libraries) |lib| { for (options.libraries) |lib| {
try argv.append(context.my_allocator, try std.mem.concat(context.allocator, u8, &.{ "-l", lib.path })); _ = argv.append(try std.mem.concat(context.allocator, u8, &.{ "-l", lib.path }));
} }
const argv_zero_terminated = try Compilation.argsCopyZ(context.allocator, argv.slice()); const argv_zero_terminated = try Compilation.argsCopyZ(context.allocator, argv.const_slice());
var stdout_ptr: [*]const u8 = undefined; var stdout_ptr: [*]const u8 = undefined;
var stdout_len: usize = 0; var stdout_len: usize = 0;
@ -121,7 +121,7 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void
if (!result) { if (!result) {
const stdout = stdout_ptr[0..stdout_len]; const stdout = stdout_ptr[0..stdout_len];
const stderr = stderr_ptr[0..stderr_len]; const stderr = stderr_ptr[0..stderr_len];
for (argv.slice()) |arg| { for (argv.const_slice()) |arg| {
try write(.panic, arg); try write(.panic, arg);
try write(.panic, " "); try write(.panic, " ");
} }

View File

@ -9,7 +9,6 @@ const library = @import("library.zig");
const byte_equal = library.byte_equal; const byte_equal = library.byte_equal;
const MyAllocator = library.MyAllocator; const MyAllocator = library.MyAllocator;
const PageAllocator = library.PageAllocator; const PageAllocator = library.PageAllocator;
const UnpinnedArray = library.UnpinnedArray;
const env_detecting_libc_paths = "NATIVITY_IS_DETECTING_LIBC_PATHS"; const env_detecting_libc_paths = "NATIVITY_IS_DETECTING_LIBC_PATHS";
@ -27,26 +26,21 @@ var my_allocator = PageAllocator{};
pub fn main() !void { pub fn main() !void {
var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator); var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const allocator = arena_allocator.allocator(); const allocator = arena_allocator.allocator();
var arg_it = try std.process.ArgIterator.initWithAllocator(allocator); const arguments: []const []const u8 = try std.process.argsAlloc(allocator);
var args = library.UnpinnedArray([]const u8){};
const context = try Compilation.createContext(allocator, &my_allocator.allocator); const context = try Compilation.createContext(allocator, &my_allocator.allocator);
while (arg_it.next()) |arg| { // const debug_args = false;
try args.append(context.my_allocator, arg); // if (debug_args and @import("builtin").os.tag != .windows) {
} // assert(arguments.len > 0);
const arguments = args.slice(); // const home_dir = std.posix.getenv("HOME") orelse unreachable;
const debug_args = false; // const timestamp = std.time.milliTimestamp();
if (debug_args and @import("builtin").os.tag != .windows) { // var argument_list = UnpinnedArray(u8){};
assert(arguments.len > 0); // for (arguments) |arg| {
const home_dir = std.posix.getenv("HOME") orelse unreachable; // argument_list.append_slice(context.my_allocator, arg) catch {};
const timestamp = std.time.milliTimestamp(); // argument_list.append(context.my_allocator, ' ') catch {};
var argument_list = UnpinnedArray(u8){}; // }
for (arguments) |arg| { // argument_list.append(context.my_allocator, '\n') catch {};
argument_list.append_slice(context.my_allocator, arg) catch {}; // std.fs.cwd().writeFile(std.fmt.allocPrint(std.heap.page_allocator, "{s}/dev/nativity/nat/invocation_log_{}", .{ home_dir, timestamp }) catch unreachable, argument_list.slice()) catch {};
argument_list.append(context.my_allocator, ' ') catch {}; // }
}
argument_list.append(context.my_allocator, '\n') catch {};
std.fs.cwd().writeFile(std.fmt.allocPrint(std.heap.page_allocator, "{s}/dev/nativity/nat/invocation_log_{}", .{ home_dir, timestamp }) catch unreachable, argument_list.slice()) catch {};
}
if (arguments.len <= 1) { if (arguments.len <= 1) {
return error.InvalidInput; return error.InvalidInput;