Ditch allocator for arena
This commit is contained in:
parent
387e073b4c
commit
46f070294c
@ -3165,8 +3165,10 @@ fn getTypeAbiAlignment(ty: *Type, unit: *Unit) u32 {
|
|||||||
// TODO: is this correct?
|
// TODO: is this correct?
|
||||||
.abi_compatible_error_union => |error_union| {
|
.abi_compatible_error_union => |error_union| {
|
||||||
const t = unit.types.get(error_union.type).getAbiAlignment(unit);
|
const t = unit.types.get(error_union.type).getAbiAlignment(unit);
|
||||||
|
if (error_union.padding != .null) {
|
||||||
const padding = unit.types.get(error_union.padding).getAbiAlignment(unit);
|
const padding = unit.types.get(error_union.padding).getAbiAlignment(unit);
|
||||||
return @max(t, padding);
|
return @max(t, padding);
|
||||||
|
} else return t;
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
@ -3226,10 +3228,14 @@ fn getTypeHomogeneousAggregate(ty: *Type, unit: *Unit) ?HomogeneousAggregate {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _usize: Type.Index = .u64;
|
||||||
|
const _ssize: Type.Index = .s64;
|
||||||
|
|
||||||
pub const Type = union(enum) {
|
pub const Type = union(enum) {
|
||||||
void,
|
void,
|
||||||
noreturn,
|
noreturn,
|
||||||
type,
|
type,
|
||||||
|
any,
|
||||||
@"struct": Struct.Index,
|
@"struct": Struct.Index,
|
||||||
function: Function.Prototype.Index,
|
function: Function.Prototype.Index,
|
||||||
integer: Type.Integer,
|
integer: Type.Integer,
|
||||||
@ -3238,6 +3244,9 @@ pub const Type = union(enum) {
|
|||||||
array: Type.Array,
|
array: Type.Array,
|
||||||
polymorphic: Type.Polymorphic,
|
polymorphic: Type.Polymorphic,
|
||||||
|
|
||||||
|
pub const @"usize" = _usize;
|
||||||
|
pub const @"ssize" = _ssize;
|
||||||
|
|
||||||
pub const Polymorphic = struct {
|
pub const Polymorphic = struct {
|
||||||
parameters: []const Token.Index,
|
parameters: []const Token.Index,
|
||||||
instantiations: MyHashMap(u32, *Debug.Declaration.Global) = .{},
|
instantiations: MyHashMap(u32, *Debug.Declaration.Global) = .{},
|
||||||
@ -3323,15 +3332,6 @@ pub const Type = union(enum) {
|
|||||||
return getTypeBitSize(ty, unit);
|
return getTypeBitSize(ty, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getByteSize(ty: *Type, unit: *Unit) u32 {
|
|
||||||
_ = unit; // autofix
|
|
||||||
return switch (ty.*) {
|
|
||||||
.integer => |integer| std.math.divCeil(u16, integer.bit_count, @bitSizeOf(u8)) catch unreachable,
|
|
||||||
.pointer => 8,
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getAbiSize(ty: *Type, unit: *Unit) u32 {
|
pub fn getAbiSize(ty: *Type, unit: *Unit) u32 {
|
||||||
return getTypeAbiSize(ty, unit);
|
return getTypeAbiSize(ty, unit);
|
||||||
}
|
}
|
||||||
@ -3481,6 +3481,7 @@ pub const Type = union(enum) {
|
|||||||
noreturn,
|
noreturn,
|
||||||
type,
|
type,
|
||||||
comptime_int,
|
comptime_int,
|
||||||
|
any,
|
||||||
bool,
|
bool,
|
||||||
u1,
|
u1,
|
||||||
u8,
|
u8,
|
||||||
@ -3491,8 +3492,8 @@ pub const Type = union(enum) {
|
|||||||
s16,
|
s16,
|
||||||
s32,
|
s32,
|
||||||
s64,
|
s64,
|
||||||
usize,
|
// usize,
|
||||||
ssize,
|
// ssize,
|
||||||
|
|
||||||
const bool_type = Type.u1;
|
const bool_type = Type.u1;
|
||||||
|
|
||||||
@ -3514,6 +3515,7 @@ pub const Type = union(enum) {
|
|||||||
.kind = .comptime_int,
|
.kind = .comptime_int,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.any = .any,
|
||||||
.u1 = .{
|
.u1 = .{
|
||||||
.integer = .{
|
.integer = .{
|
||||||
.bit_count = 1,
|
.bit_count = 1,
|
||||||
@ -3577,20 +3579,20 @@ pub const Type = union(enum) {
|
|||||||
.kind = .materialized_int,
|
.kind = .materialized_int,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.ssize = .{
|
// .ssize = .{
|
||||||
.integer = .{
|
// .integer = .{
|
||||||
.bit_count = 64,
|
// .bit_count = 64,
|
||||||
.signedness = .signed,
|
// .signedness = .signed,
|
||||||
.kind = .materialized_int,
|
// .kind = .materialized_int,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
.usize = .{
|
// .usize = .{
|
||||||
.integer = .{
|
// .integer = .{
|
||||||
.bit_count = 64,
|
// .bit_count = 64,
|
||||||
.signedness = .unsigned,
|
// .signedness = .unsigned,
|
||||||
.kind = .materialized_int,
|
// .kind = .materialized_int,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3788,6 +3790,7 @@ pub const Instruction = union(enum) {
|
|||||||
pointer_var_to_const,
|
pointer_var_to_const,
|
||||||
pointer_const_to_var,
|
pointer_const_to_var,
|
||||||
pointer_to_nullable,
|
pointer_to_nullable,
|
||||||
|
pointer_source_type_to_destination_type,
|
||||||
slice_var_to_const,
|
slice_var_to_const,
|
||||||
slice_to_nullable,
|
slice_to_nullable,
|
||||||
slice_to_not_null,
|
slice_to_not_null,
|
||||||
@ -4323,11 +4326,11 @@ pub const Builder = struct {
|
|||||||
if (padding_bit_count == 0 and t.* == .integer) {
|
if (padding_bit_count == 0 and t.* == .integer) {
|
||||||
error_union_for_error = abi_type_index;
|
error_union_for_error = abi_type_index;
|
||||||
} else {
|
} else {
|
||||||
const padding_type = try unit.getArrayType(context, .{
|
const padding_type = if (padding_bit_count != 0) try unit.getArrayType(context, .{
|
||||||
.count = padding_bit_count,
|
.count = padding_bit_count,
|
||||||
.type = .u1,
|
.type = .u1,
|
||||||
.termination = .none,
|
.termination = .none,
|
||||||
});
|
}) else .null;
|
||||||
|
|
||||||
const error_union_for_error_struct_index = try unit.structs.append(context.my_allocator, .{
|
const error_union_for_error_struct_index = try unit.structs.append(context.my_allocator, .{
|
||||||
.kind = .{
|
.kind = .{
|
||||||
@ -4630,7 +4633,7 @@ pub const Builder = struct {
|
|||||||
assert(argument_node_list.len == 1);
|
assert(argument_node_list.len == 1);
|
||||||
const argument_type_index = try builder.resolveType(unit, context, argument_node_list[0], &.{});
|
const argument_type_index = try builder.resolveType(unit, context, argument_node_list[0], &.{});
|
||||||
const argument_type = unit.types.get(argument_type_index);
|
const argument_type = unit.types.get(argument_type_index);
|
||||||
const argument_size = argument_type.getByteSize(unit);
|
const argument_size = argument_type.getAbiSize(unit);
|
||||||
|
|
||||||
const integer_value = argument_size;
|
const integer_value = argument_size;
|
||||||
const integer_type = switch (type_expect) {
|
const integer_type = switch (type_expect) {
|
||||||
@ -4641,7 +4644,7 @@ pub const Builder = struct {
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.none => .usize,
|
.none => Type.usize,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4662,7 +4665,7 @@ pub const Builder = struct {
|
|||||||
var instruction_list = try UnpinnedArray(V).initialize_with_capacity(context.my_allocator, @intCast(argument_node_list.len));
|
var instruction_list = try UnpinnedArray(V).initialize_with_capacity(context.my_allocator, @intCast(argument_node_list.len));
|
||||||
// TODO
|
// TODO
|
||||||
const arg_type_expect = Type.Expect{
|
const arg_type_expect = Type.Expect{
|
||||||
.type = Type.Index.usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (argument_node_list) |argument_node_index| {
|
for (argument_node_list) |argument_node_index| {
|
||||||
@ -4682,7 +4685,7 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = syscall,
|
.runtime = syscall,
|
||||||
},
|
},
|
||||||
.type = Type.Index.usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@panic("Syscall argument mismatch");
|
@panic("Syscall argument mismatch");
|
||||||
@ -4809,7 +4812,7 @@ pub const Builder = struct {
|
|||||||
return .pointer_const_to_var;
|
return .pointer_const_to_var;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
return .pointer_source_type_to_destination_type;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
@ -5409,23 +5412,13 @@ pub const Builder = struct {
|
|||||||
.integer => |source_integer| switch (source_integer.kind) {
|
.integer => |source_integer| switch (source_integer.kind) {
|
||||||
.materialized_int => {
|
.materialized_int => {
|
||||||
if (destination_integer.signedness == source_integer.signedness) {
|
if (destination_integer.signedness == source_integer.signedness) {
|
||||||
if (destination_integer.bit_count == source_integer.bit_count) {
|
if (destination_integer.bit_count > source_integer.bit_count) {
|
||||||
if (destination_type_index == .usize and source_type_index == .u64) {
|
|
||||||
return .success;
|
|
||||||
} else if (destination_type_index == .u64 and source_type_index == .usize) {
|
|
||||||
return .success;
|
|
||||||
} else if (destination_type_index == .ssize and source_type_index == .s64) {
|
|
||||||
return .success;
|
|
||||||
} else if (destination_type_index == .s64 and source_type_index == .ssize) {
|
|
||||||
return .success;
|
|
||||||
} else {
|
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
} else if (destination_integer.bit_count > source_integer.bit_count) {
|
|
||||||
return switch (destination_integer.signedness) {
|
return switch (destination_integer.signedness) {
|
||||||
.signed => .sign_extend,
|
.signed => .sign_extend,
|
||||||
.unsigned => .zero_extend,
|
.unsigned => .zero_extend,
|
||||||
};
|
};
|
||||||
|
} else if (destination_integer.bit_count == source_integer.bit_count) {
|
||||||
|
unreachable;
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
@ -5932,6 +5925,13 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
|
const has_padding = switch (unit.types.get(error_union.union_for_error).*) {
|
||||||
|
.@"struct" => |struct_index| switch (unit.structs.get(struct_index).kind) {
|
||||||
|
.abi_compatible_error_union => |eu| eu.padding != .null,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
const undef = V{
|
const undef = V{
|
||||||
.value = .{
|
.value = .{
|
||||||
.@"comptime" = .undefined,
|
.@"comptime" = .undefined,
|
||||||
@ -5956,7 +5956,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.type = error_union.union_for_error,
|
.type = error_union.union_for_error,
|
||||||
},
|
},
|
||||||
.index = 2,
|
.index = @as(u32, 1) + @intFromBool(has_padding),
|
||||||
.new_value = .{
|
.new_value = .{
|
||||||
.value = .{
|
.value = .{
|
||||||
.@"comptime" = .{
|
.@"comptime" = .{
|
||||||
@ -6250,8 +6250,13 @@ pub const Builder = struct {
|
|||||||
switch (node.id) {
|
switch (node.id) {
|
||||||
.assign, .add_assign, .sub_assign, .div_assign => {
|
.assign, .add_assign, .sub_assign, .div_assign => {
|
||||||
if (unit.getNode(node.left).id == .discard) {
|
if (unit.getNode(node.left).id == .discard) {
|
||||||
const r = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, node.right, .right);
|
_ = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, node.right, .right);
|
||||||
return r;
|
return .{
|
||||||
|
.value = .{
|
||||||
|
.@"comptime" = .void,
|
||||||
|
},
|
||||||
|
.type = .void,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
const left = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, node.left, .left);
|
const left = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, node.left, .left);
|
||||||
const expected_right_type = switch (left.value) {
|
const expected_right_type = switch (left.value) {
|
||||||
@ -6376,7 +6381,7 @@ pub const Builder = struct {
|
|||||||
var termination = Type.Termination.none;
|
var termination = Type.Termination.none;
|
||||||
const len_node = unit.getNode(attribute_node_list[0]);
|
const len_node = unit.getNode(attribute_node_list[0]);
|
||||||
const len = switch (len_node.id) {
|
const len = switch (len_node.id) {
|
||||||
else => switch (try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .usize }, .{}, attribute_node_list[0], null, .right, &.{})) {
|
else => switch (try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = Type.usize }, .{}, attribute_node_list[0], null, .right, &.{})) {
|
||||||
.comptime_int => |ct_int| ct_int.value,
|
.comptime_int => |ct_int| ct_int.value,
|
||||||
.constant_int => |constant_int| constant_int.value,
|
.constant_int => |constant_int| constant_int.value,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
@ -6413,14 +6418,14 @@ pub const Builder = struct {
|
|||||||
|
|
||||||
const result: Type.Index = switch (node.id) {
|
const result: Type.Index = switch (node.id) {
|
||||||
.keyword_noreturn => .noreturn,
|
.keyword_noreturn => .noreturn,
|
||||||
.usize_type => .usize,
|
.usize_type => Type.usize,
|
||||||
.void_type => .void,
|
.void_type => .void,
|
||||||
.identifier, .field_access => {
|
.identifier, .field_access => {
|
||||||
const resolved_type_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .type }, .{}, node_index, null, .right, new_parameters);
|
const resolved_type_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .type }, .{}, node_index, null, .right, new_parameters);
|
||||||
return resolved_type_value.type;
|
return resolved_type_value.type;
|
||||||
},
|
},
|
||||||
.bool_type => .bool,
|
.bool_type => .bool,
|
||||||
.ssize_type => .ssize,
|
.ssize_type => Type.ssize,
|
||||||
.signed_integer_type,
|
.signed_integer_type,
|
||||||
.unsigned_integer_type,
|
.unsigned_integer_type,
|
||||||
=> b: {
|
=> b: {
|
||||||
@ -6445,6 +6450,7 @@ pub const Builder = struct {
|
|||||||
.usize_type,
|
.usize_type,
|
||||||
.pointer_type,
|
.pointer_type,
|
||||||
.self,
|
.self,
|
||||||
|
.any,
|
||||||
=> {
|
=> {
|
||||||
if (element_type_index != .null) {
|
if (element_type_index != .null) {
|
||||||
unreachable;
|
unreachable;
|
||||||
@ -6638,6 +6644,7 @@ pub const Builder = struct {
|
|||||||
return type_index;
|
return type_index;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.any => .any,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -7121,12 +7128,10 @@ pub const Builder = struct {
|
|||||||
.u16,
|
.u16,
|
||||||
.u32,
|
.u32,
|
||||||
.u64,
|
.u64,
|
||||||
.usize,
|
|
||||||
.s8,
|
.s8,
|
||||||
.s16,
|
.s16,
|
||||||
.s32,
|
.s32,
|
||||||
.s64,
|
.s64,
|
||||||
.ssize,
|
|
||||||
.bool,
|
.bool,
|
||||||
=> result[current_index] = .integer,
|
=> result[current_index] = .integer,
|
||||||
else => switch (integer.kind) {
|
else => switch (integer.kind) {
|
||||||
@ -7310,7 +7315,7 @@ pub const Builder = struct {
|
|||||||
switch (ty.*) {
|
switch (ty.*) {
|
||||||
.pointer => return if (offset == 0) type_index else unreachable,
|
.pointer => return if (offset == 0) type_index else unreachable,
|
||||||
.integer => |integer| switch (type_index) {
|
.integer => |integer| switch (type_index) {
|
||||||
.u64, .s64, .usize, .ssize => return type_index,
|
.u64, .s64 => return type_index,
|
||||||
.bool, .u8, .u16, .u32, .s8, .s16, .s32 => {
|
.bool, .u8, .u16, .u32, .s8, .s16, .s32 => {
|
||||||
if (offset != 0) unreachable;
|
if (offset != 0) unreachable;
|
||||||
const start = source_offset + ty.getAbiSize(unit);
|
const start = source_offset + ty.getAbiSize(unit);
|
||||||
@ -8523,7 +8528,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
.name = try unit.processIdentifier(context, "direct_pair"),
|
.name = try unit.processIdentifier(context, "direct_pair"),
|
||||||
},
|
},
|
||||||
@ -8913,7 +8918,7 @@ pub const Builder = struct {
|
|||||||
.type = type_index,
|
.type = type_index,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.unsigned_integer_type => return .{
|
.unsigned_integer_type, .signed_integer_type => return .{
|
||||||
.type = try builder.resolveType(unit, context, node_index, new_parameters),
|
.type = try builder.resolveType(unit, context, node_index, new_parameters),
|
||||||
},
|
},
|
||||||
.@"switch" => return try builder.resolveComptimeSwitch(unit, context, type_expect, global_attributes, node_index, maybe_global),
|
.@"switch" => return try builder.resolveComptimeSwitch(unit, context, type_expect, global_attributes, node_index, maybe_global),
|
||||||
@ -8926,13 +8931,7 @@ pub const Builder = struct {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.signed_integer_type => {
|
.add, .mul => {
|
||||||
const result = try builder.resolveIntegerType(unit, context, node_index);
|
|
||||||
return .{
|
|
||||||
.type = result,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
.add => {
|
|
||||||
const left = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, node.left, null, .right, &.{});
|
const left = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, node.left, null, .right, &.{});
|
||||||
const left_type = left.getType(unit);
|
const left_type = left.getType(unit);
|
||||||
const right = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = left_type }, .{}, node.right, null, .right, &.{});
|
const right = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = left_type }, .{}, node.right, null, .right, &.{});
|
||||||
@ -8944,7 +8943,11 @@ pub const Builder = struct {
|
|||||||
.comptime_int => |right_ct_int| {
|
.comptime_int => |right_ct_int| {
|
||||||
assert(right_ct_int.signedness == .unsigned);
|
assert(right_ct_int.signedness == .unsigned);
|
||||||
const right_value = right_ct_int.value;
|
const right_value = right_ct_int.value;
|
||||||
const result = left_value + right_value;
|
const result = switch (node.id) {
|
||||||
|
.add => left_value + right_value,
|
||||||
|
.mul => left_value * right_value,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
return .{
|
return .{
|
||||||
.comptime_int = .{
|
.comptime_int = .{
|
||||||
.value = result,
|
.value = result,
|
||||||
@ -9139,7 +9142,7 @@ pub const Builder = struct {
|
|||||||
.pointer_dereference => block: {
|
.pointer_dereference => block: {
|
||||||
// TODO:
|
// TODO:
|
||||||
const pointer_type_expect = switch (type_expect) {
|
const pointer_type_expect = switch (type_expect) {
|
||||||
.none => unreachable, //type_expect,
|
.none => type_expect,
|
||||||
.type => |type_index| b: {
|
.type => |type_index| b: {
|
||||||
const pointer_type = try unit.getPointerType(context, .{
|
const pointer_type = try unit.getPointerType(context, .{
|
||||||
.type = type_index,
|
.type = type_index,
|
||||||
@ -9159,8 +9162,18 @@ pub const Builder = struct {
|
|||||||
// TODO: is this right? .right
|
// TODO: is this right? .right
|
||||||
const pointer_value = try builder.resolveRuntimeValue(unit, context, pointer_type_expect, node.left, .right);
|
const pointer_value = try builder.resolveRuntimeValue(unit, context, pointer_type_expect, node.left, .right);
|
||||||
|
|
||||||
|
break :block switch (side) {
|
||||||
|
.left => pointer_value,
|
||||||
|
.right => right: {
|
||||||
const load_type = switch (type_expect) {
|
const load_type = switch (type_expect) {
|
||||||
.none => unreachable,
|
.none => b: {
|
||||||
|
const pointer_type = unit.types.get(pointer_value.type);
|
||||||
|
const pointer_element_type = pointer_type.pointer.type;
|
||||||
|
switch (unit.types.get(pointer_element_type).*) {
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
break :b pointer_element_type;
|
||||||
|
},
|
||||||
.type => |type_index| type_index,
|
.type => |type_index| type_index,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
@ -9173,13 +9186,15 @@ pub const Builder = struct {
|
|||||||
});
|
});
|
||||||
try builder.appendInstruction(unit, context, load);
|
try builder.appendInstruction(unit, context, load);
|
||||||
|
|
||||||
break :block .{
|
break :right .{
|
||||||
.value = .{
|
.value = .{
|
||||||
.runtime = load,
|
.runtime = load,
|
||||||
},
|
},
|
||||||
.type = load_type,
|
.type = load_type,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
.compare_equal,
|
.compare_equal,
|
||||||
.compare_not_equal,
|
.compare_not_equal,
|
||||||
.compare_greater,
|
.compare_greater,
|
||||||
@ -9685,7 +9700,7 @@ pub const Builder = struct {
|
|||||||
|
|
||||||
const range_node = unit.getNode(node.right);
|
const range_node = unit.getNode(node.right);
|
||||||
assert(range_node.id == .range);
|
assert(range_node.id == .range);
|
||||||
const range_start: V = try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = .usize }, range_node.left, .right);
|
const range_start: V = try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = Type.usize }, range_node.left, .right);
|
||||||
const range_end: V = switch (range_node.right) {
|
const range_end: V = switch (range_node.right) {
|
||||||
.null => switch (unit.types.get(expression_to_slice.type).*) {
|
.null => switch (unit.types.get(expression_to_slice.type).*) {
|
||||||
.slice => b: {
|
.slice => b: {
|
||||||
@ -9701,7 +9716,7 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = extract_value,
|
.runtime = extract_value,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.pointer => |pointer| switch (pointer.many) {
|
.pointer => |pointer| switch (pointer.many) {
|
||||||
@ -9715,7 +9730,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
.slice => |slice| b: {
|
.slice => |slice| b: {
|
||||||
_ = slice; // autofix
|
_ = slice; // autofix
|
||||||
@ -9747,14 +9762,14 @@ pub const Builder = struct {
|
|||||||
.runtime = gep,
|
.runtime = gep,
|
||||||
},
|
},
|
||||||
.type = try unit.getPointerType(context, .{
|
.type = try unit.getPointerType(context, .{
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
.termination = .none,
|
.termination = .none,
|
||||||
.many = false,
|
.many = false,
|
||||||
.nullable = false,
|
.nullable = false,
|
||||||
.mutability = .@"const",
|
.mutability = .@"const",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
try builder.appendInstruction(unit, context, load);
|
try builder.appendInstruction(unit, context, load);
|
||||||
@ -9763,7 +9778,7 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = load,
|
.runtime = load,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.pointer => |child_pointer| b: {
|
.pointer => |child_pointer| b: {
|
||||||
@ -9778,7 +9793,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
@ -9790,7 +9805,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
else => try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = .usize }, range_node.right, .right),
|
else => try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = Type.usize }, range_node.right, .right),
|
||||||
};
|
};
|
||||||
|
|
||||||
const len_expression: V = b: {
|
const len_expression: V = b: {
|
||||||
@ -9812,7 +9827,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
const range_compute = try unit.instructions.append(context.my_allocator, .{
|
const range_compute = try unit.instructions.append(context.my_allocator, .{
|
||||||
@ -9830,7 +9845,7 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = range_compute,
|
.runtime = range_compute,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -10381,7 +10396,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -10527,7 +10542,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -10584,7 +10599,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -10649,7 +10664,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -10749,7 +10764,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
else => original_index_value,
|
else => original_index_value,
|
||||||
};
|
};
|
||||||
@ -11229,8 +11244,21 @@ pub const Builder = struct {
|
|||||||
.error_union => |return_error_union| {
|
.error_union => |return_error_union| {
|
||||||
switch (try builder.typecheck(unit, context, return_error_union.@"error", error_union.@"error")) {
|
switch (try builder.typecheck(unit, context, return_error_union.@"error", error_union.@"error")) {
|
||||||
.success => {
|
.success => {
|
||||||
const error_value = if (error_union.union_for_error == error_union.abi) {
|
const error_value = if (error_union.union_for_error == error_union.abi) blk: {
|
||||||
unreachable;
|
const extract_value = try unit.instructions.append(context.my_allocator, .{
|
||||||
|
.extract_value = .{
|
||||||
|
.expression = value,
|
||||||
|
.index = 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
try builder.appendInstruction(unit, context, extract_value);
|
||||||
|
|
||||||
|
break :blk V{
|
||||||
|
.type = error_union.abi,
|
||||||
|
.value = .{
|
||||||
|
.runtime = extract_value,
|
||||||
|
},
|
||||||
|
};
|
||||||
} else err: {
|
} else err: {
|
||||||
const try_alloca = try builder.createStackVariable(unit, context, value.type, null);
|
const try_alloca = try builder.createStackVariable(unit, context, value.type, null);
|
||||||
|
|
||||||
@ -11342,6 +11370,14 @@ pub const Builder = struct {
|
|||||||
.type = return_type_index,
|
.type = return_type_index,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
const has_padding = switch (unit.types.get(error_union.union_for_error).*) {
|
||||||
|
.@"struct" => |si| switch (unit.structs.get(si).kind) {
|
||||||
|
.abi_compatible_error_union => |eu| eu.padding != .null,
|
||||||
|
.raw_error_union => false,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
const v = V{
|
const v = V{
|
||||||
.value = .{
|
.value = .{
|
||||||
.@"comptime" = .undefined,
|
.@"comptime" = .undefined,
|
||||||
@ -11366,7 +11402,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.type = error_union.union_for_error,
|
.type = error_union.union_for_error,
|
||||||
},
|
},
|
||||||
.index = 2,
|
.index = @as(u32, 1) + @intFromBool(has_padding),
|
||||||
.new_value = .{
|
.new_value = .{
|
||||||
.value = .{
|
.value = .{
|
||||||
.@"comptime" = .{
|
.@"comptime" = .{
|
||||||
@ -11623,6 +11659,10 @@ pub const Builder = struct {
|
|||||||
.type = field.type,
|
.type = field.type,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
const identifier = unit.getIdentifier(field.name);
|
||||||
|
try write(.panic, "Missing field: ");
|
||||||
|
try write(.panic, identifier);
|
||||||
|
try write(.panic, "\n");
|
||||||
@panic("Missing field");
|
@panic("Missing field");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11957,6 +11997,8 @@ pub const Builder = struct {
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
try write(.panic, "Right identifier in field access like call expression: ");
|
||||||
|
try write(.panic, right_identifier);
|
||||||
@panic("Right identifier in field access like call expression");
|
@panic("Right identifier in field access like call expression");
|
||||||
//std.debug.panic("Right identifier in field-access-like call expression not found: '{s}'", .{right_identifier});
|
//std.debug.panic("Right identifier in field-access-like call expression not found: '{s}'", .{right_identifier});
|
||||||
}
|
}
|
||||||
@ -12372,7 +12414,10 @@ pub const Builder = struct {
|
|||||||
const argument_value = try builder.resolveRuntimeValue(unit, context, arg_type_expect, argument_node_index, .right);
|
const argument_value = try builder.resolveRuntimeValue(unit, context, arg_type_expect, argument_node_index, .right);
|
||||||
|
|
||||||
switch (argument_abi.kind) {
|
switch (argument_abi.kind) {
|
||||||
.direct => argument_list.append_with_capacity(argument_value),
|
.direct => {
|
||||||
|
assert(argument_value.type == argument_type_index);
|
||||||
|
argument_list.append_with_capacity(argument_value);
|
||||||
|
},
|
||||||
.direct_coerce => |coerced_type_index| if (coerced_type_index == argument_value.type) argument_list.append_with_capacity(argument_value) else {
|
.direct_coerce => |coerced_type_index| if (coerced_type_index == argument_value.type) argument_list.append_with_capacity(argument_value) else {
|
||||||
const stack = try builder.createStackVariable(unit, context, argument_value.type, null);
|
const stack = try builder.createStackVariable(unit, context, argument_value.type, null);
|
||||||
|
|
||||||
@ -12945,7 +12990,35 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
} else typecheck_enum_result.else_switch_case_group_index orelse unreachable;
|
} else typecheck_enum_result.else_switch_case_group_index orelse unreachable;
|
||||||
const true_switch_case_node = unit.getNode(case_nodes[group_index]);
|
const true_switch_case_node = unit.getNode(case_nodes[group_index]);
|
||||||
_ = try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = .void }, true_switch_case_node.right, .right);
|
const value = try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = .void }, true_switch_case_node.right, .right);
|
||||||
|
switch (value.type) {
|
||||||
|
.void, .noreturn => {},
|
||||||
|
else => @panic("Unexpected type"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.bool => |boolean| {
|
||||||
|
assert(case_nodes.len == 2);
|
||||||
|
|
||||||
|
for (case_nodes) |case_node_index| {
|
||||||
|
const case_node = unit.getNode(case_node_index);
|
||||||
|
assert(case_node.left != .null);
|
||||||
|
assert(case_node.right != .null);
|
||||||
|
const boolean_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .bool }, .{}, case_node.left, null, .right, &.{});
|
||||||
|
switch (boolean_value) {
|
||||||
|
.bool => |case_boolean| {
|
||||||
|
if (case_boolean == boolean) {
|
||||||
|
const v = try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = .void }, case_node.right, .right);
|
||||||
|
switch (v.type) {
|
||||||
|
.void, .noreturn => break,
|
||||||
|
else => @panic("Unexpected type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
@ -13038,9 +13111,9 @@ pub const Builder = struct {
|
|||||||
.range => blk: {
|
.range => blk: {
|
||||||
assert(last_element_node.left != .null);
|
assert(last_element_node.left != .null);
|
||||||
|
|
||||||
const range_start = try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = .usize }, last_element_node.left, .right);
|
const range_start = try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = Type.usize }, last_element_node.left, .right);
|
||||||
const emit = true;
|
const emit = true;
|
||||||
const stack_slot = try builder.emitLocalVariableDeclaration(unit, context, last_element_payload.token, .@"var", .usize, range_start, emit, null);
|
const stack_slot = try builder.emitLocalVariableDeclaration(unit, context, last_element_payload.token, .@"var", Type.usize, range_start, emit, null);
|
||||||
// This is put up here so that the length is constant throughout the loop and we dont have to load the variable unnecessarily
|
// This is put up here so that the length is constant throughout the loop and we dont have to load the variable unnecessarily
|
||||||
const range_end = switch (last_element_node.right) {
|
const range_end = switch (last_element_node.right) {
|
||||||
.null => switch (unit.types.get(slices.pointer[0].type).*) {
|
.null => switch (unit.types.get(slices.pointer[0].type).*) {
|
||||||
@ -13057,12 +13130,12 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = len_extract_instruction,
|
.runtime = len_extract_instruction,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
else => try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = .usize }, last_element_node.right, .right),
|
else => try builder.resolveRuntimeValue(unit, context, Type.Expect{ .type = Type.usize }, last_element_node.right, .right),
|
||||||
};
|
};
|
||||||
|
|
||||||
break :blk .{
|
break :blk .{
|
||||||
@ -13080,7 +13153,7 @@ pub const Builder = struct {
|
|||||||
const name = try join_name(context, "__anon_i_", unit.anon_i, 10);
|
const name = try join_name(context, "__anon_i_", unit.anon_i, 10);
|
||||||
unit.anon_i += 1;
|
unit.anon_i += 1;
|
||||||
const emit = true;
|
const emit = true;
|
||||||
const stack_slot = try builder.emitLocalVariableDeclaration(unit, context, last_element_payload.token, .@"var", .usize, .{
|
const stack_slot = try builder.emitLocalVariableDeclaration(unit, context, last_element_payload.token, .@"var", Type.usize, .{
|
||||||
.value = .{
|
.value = .{
|
||||||
.@"comptime" = .{
|
.@"comptime" = .{
|
||||||
.constant_int = .{
|
.constant_int = .{
|
||||||
@ -13088,7 +13161,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
}, emit, name);
|
}, emit, name);
|
||||||
|
|
||||||
const len_extract_value = try unit.instructions.append(context.my_allocator, .{
|
const len_extract_value = try unit.instructions.append(context.my_allocator, .{
|
||||||
@ -13105,7 +13178,7 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = len_extract_value,
|
.runtime = len_extract_value,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -13119,7 +13192,7 @@ pub const Builder = struct {
|
|||||||
builder.current_basic_block = loop_header;
|
builder.current_basic_block = loop_header;
|
||||||
|
|
||||||
const pointer_to_usize = try unit.getPointerType(context, .{
|
const pointer_to_usize = try unit.getPointerType(context, .{
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
.mutability = .@"const",
|
.mutability = .@"const",
|
||||||
.nullable = false,
|
.nullable = false,
|
||||||
.many = false,
|
.many = false,
|
||||||
@ -13134,7 +13207,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.type = pointer_to_usize,
|
.type = pointer_to_usize,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -13146,10 +13219,10 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = load,
|
.runtime = load,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
.right = loop_counter.end,
|
.right = loop_counter.end,
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
.id = .unsigned_less,
|
.id = .unsigned_less,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -13175,7 +13248,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.type = pointer_to_usize,
|
.type = pointer_to_usize,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
try builder.appendInstruction(unit, context, load_i);
|
try builder.appendInstruction(unit, context, load_i);
|
||||||
@ -13254,7 +13327,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.type = pointer_to_usize,
|
.type = pointer_to_usize,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -13266,7 +13339,7 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = load_iterator,
|
.runtime = load_iterator,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
.right = .{
|
.right = .{
|
||||||
.value = .{
|
.value = .{
|
||||||
@ -13276,7 +13349,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
.id = .add,
|
.id = .add,
|
||||||
.signedness = .unsigned,
|
.signedness = .unsigned,
|
||||||
@ -13291,13 +13364,13 @@ pub const Builder = struct {
|
|||||||
.value = .{
|
.value = .{
|
||||||
.runtime = loop_counter.stack_slot,
|
.runtime = loop_counter.stack_slot,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
.source = .{
|
.source = .{
|
||||||
.value = .{
|
.value = .{
|
||||||
.runtime = increment,
|
.runtime = increment,
|
||||||
},
|
},
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -14076,7 +14149,7 @@ pub const Builder = struct {
|
|||||||
} else unreachable;
|
} else unreachable;
|
||||||
const field_type = switch (slice_field) {
|
const field_type = switch (slice_field) {
|
||||||
.pointer => slice.child_pointer_type,
|
.pointer => slice.child_pointer_type,
|
||||||
.length => Type.Index.usize,
|
.length => Type.usize,
|
||||||
};
|
};
|
||||||
const field_index = @intFromEnum(slice_field);
|
const field_index = @intFromEnum(slice_field);
|
||||||
|
|
||||||
@ -14108,7 +14181,7 @@ pub const Builder = struct {
|
|||||||
.runtime = gep,
|
.runtime = gep,
|
||||||
},
|
},
|
||||||
.type = try unit.getPointerType(context, .{
|
.type = try unit.getPointerType(context, .{
|
||||||
.type = .usize,
|
.type = Type.usize,
|
||||||
.many = false,
|
.many = false,
|
||||||
.nullable = false,
|
.nullable = false,
|
||||||
.termination = .none,
|
.termination = .none,
|
||||||
@ -14535,6 +14608,13 @@ pub const Builder = struct {
|
|||||||
.type = ti,
|
.type = ti,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
const has_padding = switch (unit.types.get(error_union.union_for_error).*) {
|
||||||
|
.@"struct" => |si| switch (unit.structs.get(si).kind) {
|
||||||
|
.abi_compatible_error_union => |eu| eu.padding != .null,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
const v = V{
|
const v = V{
|
||||||
.value = .{
|
.value = .{
|
||||||
.@"comptime" = .undefined,
|
.@"comptime" = .undefined,
|
||||||
@ -14559,7 +14639,7 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.type = error_union.union_for_error,
|
.type = error_union.union_for_error,
|
||||||
},
|
},
|
||||||
.index = 2,
|
.index = @as(u32, 1) + @intFromBool(has_padding),
|
||||||
.new_value = .{
|
.new_value = .{
|
||||||
.value = .{
|
.value = .{
|
||||||
.@"comptime" = .{
|
.@"comptime" = .{
|
||||||
@ -15609,6 +15689,7 @@ pub const Unit = struct {
|
|||||||
if (unit.arrays.get(array)) |array_type| {
|
if (unit.arrays.get(array)) |array_type| {
|
||||||
return array_type;
|
return array_type;
|
||||||
} else {
|
} else {
|
||||||
|
assert(array.count != 0);
|
||||||
const array_type = try unit.types.append(context.my_allocator, .{
|
const array_type = try unit.types.append(context.my_allocator, .{
|
||||||
.array = array,
|
.array = array,
|
||||||
});
|
});
|
||||||
@ -16052,6 +16133,7 @@ pub const FixedKeyword = enum {
|
|||||||
@"or",
|
@"or",
|
||||||
bitfield,
|
bitfield,
|
||||||
Self,
|
Self,
|
||||||
|
any,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Descriptor = struct {
|
pub const Descriptor = struct {
|
||||||
@ -16264,6 +16346,7 @@ pub const Token = struct {
|
|||||||
fixed_keyword_or,
|
fixed_keyword_or,
|
||||||
fixed_keyword_bitfield,
|
fixed_keyword_bitfield,
|
||||||
fixed_keyword_Self,
|
fixed_keyword_Self,
|
||||||
|
fixed_keyword_any,
|
||||||
unused1,
|
unused1,
|
||||||
unused2,
|
unused2,
|
||||||
unused3,
|
unused3,
|
||||||
|
@ -1254,7 +1254,7 @@ pub const LLVM = struct {
|
|||||||
},
|
},
|
||||||
.slice => |slice| blk: {
|
.slice => |slice| blk: {
|
||||||
const llvm_pointer_type = try llvm.getType(unit, context, slice.child_pointer_type);
|
const llvm_pointer_type = try llvm.getType(unit, context, slice.child_pointer_type);
|
||||||
const llvm_usize_type = try llvm.getType(unit, context, .usize);
|
const llvm_usize_type = try llvm.getType(unit, context, Compilation.Type.usize);
|
||||||
const slice_types = [_]*Type{ llvm_pointer_type, llvm_usize_type };
|
const slice_types = [_]*Type{ llvm_pointer_type, llvm_usize_type };
|
||||||
const is_packed = false;
|
const is_packed = false;
|
||||||
const struct_type = llvm.context.getStructType(&slice_types, slice_types.len, is_packed) orelse return Type.Error.@"struct";
|
const struct_type = llvm.context.getStructType(&slice_types, slice_types.len, is_packed) orelse return Type.Error.@"struct";
|
||||||
@ -1272,11 +1272,19 @@ pub const LLVM = struct {
|
|||||||
},
|
},
|
||||||
.abi_compatible_error_union => |error_union| blk: {
|
.abi_compatible_error_union => |error_union| blk: {
|
||||||
const error_union_type = try llvm.getType(unit, context, error_union.type);
|
const error_union_type = try llvm.getType(unit, context, error_union.type);
|
||||||
const padding_type = try llvm.getType(unit, context, error_union.padding);
|
|
||||||
const boolean_type = try llvm.getType(unit, context, .bool);
|
const boolean_type = try llvm.getType(unit, context, .bool);
|
||||||
const types = [3]*LLVM.Type{ error_union_type, padding_type, boolean_type };
|
var three_types: [3]*LLVM.Type = undefined;
|
||||||
|
var two_types: [2]*LLVM.Type = undefined;
|
||||||
|
const types: []const *LLVM.Type = if (error_union.padding == .null) b: {
|
||||||
|
two_types = .{ error_union_type, boolean_type };
|
||||||
|
break :b &two_types;
|
||||||
|
} else b: {
|
||||||
|
const padding_type = try llvm.getType(unit, context, error_union.padding);
|
||||||
|
three_types = .{ error_union_type, padding_type, boolean_type };
|
||||||
|
break :b &three_types;
|
||||||
|
};
|
||||||
const is_packed = false;
|
const is_packed = false;
|
||||||
const struct_type = llvm.context.getStructType(&types, types.len, is_packed) orelse return Type.Error.@"struct";
|
const struct_type = llvm.context.getStructType(types.ptr, types.len, is_packed) orelse return Type.Error.@"struct";
|
||||||
break :blk struct_type.toType();
|
break :blk struct_type.toType();
|
||||||
},
|
},
|
||||||
.@"struct" => |*sema_struct_type| blk: {
|
.@"struct" => |*sema_struct_type| blk: {
|
||||||
@ -1406,6 +1414,7 @@ pub const LLVM = struct {
|
|||||||
},
|
},
|
||||||
// TODO
|
// TODO
|
||||||
.function => "fn_type",
|
.function => "fn_type",
|
||||||
|
.any => "any",
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1669,15 +1678,49 @@ pub const LLVM = struct {
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
.pointer => |pointer| b: {
|
.pointer => |pointer| b: {
|
||||||
|
if (pointer.type == .any) {
|
||||||
|
const flags = LLVM.DebugInfo.Node.Flags{
|
||||||
|
.visibility = .none,
|
||||||
|
.forward_declaration = false,
|
||||||
|
.apple_block = false,
|
||||||
|
.block_by_ref_struct = false,
|
||||||
|
.virtual = false,
|
||||||
|
.artificial = false,
|
||||||
|
.explicit = false,
|
||||||
|
.prototyped = false,
|
||||||
|
.objective_c_class_complete = false,
|
||||||
|
.object_pointer = false,
|
||||||
|
.vector = false,
|
||||||
|
.static_member = false,
|
||||||
|
.lvalue_reference = false,
|
||||||
|
.rvalue_reference = false,
|
||||||
|
.reserved = false,
|
||||||
|
.inheritance = .none,
|
||||||
|
.introduced_virtual = false,
|
||||||
|
.bit_field = false,
|
||||||
|
.no_return = false,
|
||||||
|
.type_pass_by_value = false,
|
||||||
|
.type_pass_by_reference = false,
|
||||||
|
.enum_class = false,
|
||||||
|
.thunk = false,
|
||||||
|
.non_trivial = false,
|
||||||
|
.big_endian = false,
|
||||||
|
.little_endian = false,
|
||||||
|
.all_calls_described = false,
|
||||||
|
};
|
||||||
|
const pointer_type = llvm.debug_info_builder.createBasicType(name.ptr, name.len, 64, .address, flags) orelse unreachable;
|
||||||
|
break :b pointer_type;
|
||||||
|
} else {
|
||||||
const element_type = try llvm.getDebugType(unit, context, pointer.type);
|
const element_type = try llvm.getDebugType(unit, context, pointer.type);
|
||||||
const pointer_width = @bitSizeOf(usize);
|
const pointer_width = @bitSizeOf(usize);
|
||||||
const alignment = 3;
|
const alignment = 3;
|
||||||
const pointer_type = llvm.debug_info_builder.createPointerType(element_type, pointer_width, alignment, name.ptr, name.len) orelse unreachable;
|
const pointer_type = llvm.debug_info_builder.createPointerType(element_type, pointer_width, alignment, name.ptr, name.len) orelse unreachable;
|
||||||
break :b pointer_type.toType();
|
break :b pointer_type.toType();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.slice => |slice| b: {
|
.slice => |slice| b: {
|
||||||
const pointer_type = try llvm.getDebugType(unit, context, slice.child_pointer_type);
|
const pointer_type = try llvm.getDebugType(unit, context, slice.child_pointer_type);
|
||||||
const len_type = try llvm.getDebugType(unit, context, .usize);
|
const len_type = try llvm.getDebugType(unit, context, Compilation.Type.usize);
|
||||||
const scope = null;
|
const scope = null;
|
||||||
const file = null;
|
const file = null;
|
||||||
const line = 1;
|
const line = 1;
|
||||||
@ -1733,6 +1776,7 @@ pub const LLVM = struct {
|
|||||||
const byte_size = 1; // array.count * unit.types.get(array.element_type).getSize();
|
const byte_size = 1; // array.count * unit.types.get(array.element_type).getSize();
|
||||||
const bit_size = byte_size * 8;
|
const bit_size = byte_size * 8;
|
||||||
const element_type = try llvm.getDebugType(unit, context, array.type);
|
const element_type = try llvm.getDebugType(unit, context, array.type);
|
||||||
|
assert(array.count != 0);
|
||||||
const array_type = llvm.debug_info_builder.createArrayType(bit_size, 1, element_type, array.count) orelse unreachable;
|
const array_type = llvm.debug_info_builder.createArrayType(bit_size, 1, element_type, array.count) orelse unreachable;
|
||||||
break :b array_type.toType();
|
break :b array_type.toType();
|
||||||
},
|
},
|
||||||
@ -2630,6 +2674,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.pointer_to_nullable,
|
.pointer_to_nullable,
|
||||||
.pointer_const_to_var,
|
.pointer_const_to_var,
|
||||||
.pointer_to_array_to_pointer_to_many,
|
.pointer_to_array_to_pointer_to_many,
|
||||||
|
.pointer_source_type_to_destination_type,
|
||||||
=> {
|
=> {
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, value);
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, value);
|
||||||
},
|
},
|
||||||
@ -2789,7 +2834,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
syscall_argument_type.* = syscall_argument.*.getType();
|
syscall_argument_type.* = syscall_argument.*.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
const return_type = try llvm.getType(unit, context, Compilation.Type.Index.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 = UnpinnedArray(u8){};
|
||||||
|
@ -198,6 +198,7 @@ pub const Node = struct {
|
|||||||
bitfield_type,
|
bitfield_type,
|
||||||
comptime_expression,
|
comptime_expression,
|
||||||
self,
|
self,
|
||||||
|
any,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1874,6 +1875,15 @@ const Analyzer = struct {
|
|||||||
const token = analyzer.peekToken();
|
const token = analyzer.peekToken();
|
||||||
|
|
||||||
return try switch (token) {
|
return try switch (token) {
|
||||||
|
.fixed_keyword_any => try analyzer.addNode(.{
|
||||||
|
.id = .any,
|
||||||
|
.token = b: {
|
||||||
|
analyzer.consumeToken();
|
||||||
|
break :b token_i;
|
||||||
|
},
|
||||||
|
.left = .null,
|
||||||
|
.right = .null,
|
||||||
|
}),
|
||||||
.fixed_keyword_Self => try analyzer.addNode(.{
|
.fixed_keyword_Self => try analyzer.addNode(.{
|
||||||
.id = .self,
|
.id = .self,
|
||||||
.token = b: {
|
.token = b: {
|
||||||
@ -2051,6 +2061,7 @@ const Analyzer = struct {
|
|||||||
.right = backing_type,
|
.right = backing_type,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
.operator_ampersand => try analyzer.pointerOrArrayTypeExpression(.single_pointer_type),
|
||||||
else => |t| switch (t) {
|
else => |t| switch (t) {
|
||||||
.identifier => @panic(analyzer.bytes(token_i)),
|
.identifier => @panic(analyzer.bytes(token_i)),
|
||||||
else => @panic(@tagName(t)),
|
else => @panic(@tagName(t)),
|
||||||
|
@ -441,8 +441,59 @@ const waitpid = fn(pid: Process.Id, flags: u32) WaitPidError!u32 {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reserve = fn (size: u64) *!&any {
|
||||||
|
switch (current) {
|
||||||
|
.linux, .macos => {
|
||||||
|
const syscall_result = system.mmap(null, size, .{
|
||||||
|
.read = false,
|
||||||
|
.write = false,
|
||||||
|
.execute = false,
|
||||||
|
}, .{
|
||||||
|
.anonymous = true,
|
||||||
|
.private = true,
|
||||||
|
.shared = false,
|
||||||
|
.fixed = false,
|
||||||
|
}, -1, 0);
|
||||||
|
|
||||||
|
switch (link_libc) {
|
||||||
|
true => {
|
||||||
|
if (syscall_result != system.MAP_FAILED) {
|
||||||
|
const result: &any = #cast(syscall_result);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false => {
|
||||||
|
const result = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
const pointer: &any = #cast(result);
|
||||||
|
return pointer;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
else => #error("OS not supported"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const commit = fn (reserved_memory: &any, size: u64) *!void {
|
||||||
|
switch (current) {
|
||||||
|
.linux, .macos => {
|
||||||
|
const syscall_result = system.mprotect(reserved_memory, size, .{
|
||||||
|
.read = true,
|
||||||
|
.write = true,
|
||||||
|
.execute = false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
else => #error("OS not supported"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MemFdCreateError = error{
|
const MemFdCreateError = error{
|
||||||
};
|
};
|
||||||
|
|
||||||
const memfd_create = fn(name: [&:0]const u8, flags: u32) MemFdCreateError!FileDescriptor{
|
const memfd_create = fn(name: [&:0]const u8, flags: u32) MemFdCreateError!FileDescriptor{
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => {
|
.linux => {
|
||||||
|
@ -872,6 +872,12 @@ const mmap = fn(address: ?[&]u8, length: usize, protection_flags: ProtectionFlag
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mprotect = fn(address: &any, length: usize, protection_flags: ProtectionFlags) usize {
|
||||||
|
const flat_protection_flags: u32 = #cast(protection_flags);
|
||||||
|
const result = #syscall(#cast(Syscall.mprotect), #cast(address), length, flat_protection_flags);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
const munmap = fn(bytes: []const u8) usize {
|
const munmap = fn(bytes: []const u8) usize {
|
||||||
const result = #syscall(#cast(Syscall.munmap), #cast(bytes.pointer), bytes.length);
|
const result = #syscall(#cast(Syscall.munmap), #cast(bytes.pointer), bytes.length);
|
||||||
return result;
|
return result;
|
||||||
|
103
lib/std/std.nat
103
lib/std/std.nat
@ -70,74 +70,55 @@ const print_u8 = fn(n: u8) void {
|
|||||||
print_usize(n);
|
print_usize(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Allocator = struct {
|
const kilobytes = fn (n: u64) u64 {
|
||||||
handler: &const fn(allocator: &Allocator, old_ptr: ?[&]const u8, old_size: usize, new_size: usize, alignment: u16) Allocator.Error![&]u8,
|
return n * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
const Error = error{
|
const megabytes = fn (n: u64) u64 {
|
||||||
out_of_memory,
|
return n * 1024 * 1024;
|
||||||
free_failed,
|
}
|
||||||
|
|
||||||
|
const gigabytes = fn (n: u64) u64 {
|
||||||
|
return n * 1024 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
const terabytes = fn (n: u64) u64 {
|
||||||
|
return n * 1024 * 1024 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Arena = struct{
|
||||||
|
position: u64,
|
||||||
|
commit_position: u64,
|
||||||
|
alignment: u64,
|
||||||
|
size: u64,
|
||||||
|
|
||||||
|
const Temporary = struct{
|
||||||
|
arena: &Arena,
|
||||||
|
position: u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
const allocate = fn (allocator: &Allocator, size: usize, alignment: u16) Allocator.Error![]u8 {
|
const commit_granularity = 2 * 1024 * 1024;
|
||||||
const pointer = try allocator.handler(allocator, old_ptr = null, old_size = 0, new_size = size, alignment);
|
|
||||||
return pointer[0..size];
|
|
||||||
}
|
|
||||||
|
|
||||||
const free = fn (allocator: &Allocator, bytes: []const u8) Allocator.Error!void {
|
const allocate = fn (requested_size: u64) *!&Arena {
|
||||||
_ = try allocator.handler(allocator, old_ptr = bytes.pointer, old_size = bytes.length, new_size = 0, alignment = 0);
|
var size = requested_size;
|
||||||
}
|
const size_roundup_granularity = megabytes(64);
|
||||||
|
size += size_roundup_granularity - 1;
|
||||||
|
size -= size % size_roundup_granularity;
|
||||||
|
const initial_commit_size = commit_granularity;
|
||||||
|
assert(initial_commit_size >= #size(Arena));
|
||||||
|
|
||||||
const duplicate_bytes = fn (allocator: &Allocator, bytes: []const u8) Allocator.Error![]u8 {
|
const reserved_memory = try os.reserve(size);
|
||||||
const result = try allocator.allocate(size = bytes.length, alignment = 0);
|
try os.commit(reserved_memory, initial_commit_size);
|
||||||
copy_bytes(destination = result, source = bytes);
|
|
||||||
return result;
|
const arena: &Arena = #cast(reserved_memory);
|
||||||
}
|
arena.@ = .{
|
||||||
|
.position = #size(Arena),
|
||||||
|
.commit_position = initial_commit_size,
|
||||||
|
.alignment = 8,
|
||||||
|
.size = size,
|
||||||
};
|
};
|
||||||
|
|
||||||
const PageAllocator = struct{
|
return arena;
|
||||||
allocator: Allocator = .{
|
|
||||||
.handler = handler.&,
|
|
||||||
},
|
|
||||||
|
|
||||||
const allocate = fn (a: &PageAllocator, size: usize, alignment: u16) Allocator.Error![]u8 {
|
|
||||||
const allocation_result = try a.allocator.allocate(size, alignment);
|
|
||||||
return allocation_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const free = fn (a: &PageAllocator, bytes: []const u8) Allocator.Error!void {
|
|
||||||
try a.allocator.free(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handler = fn (allocator: &Allocator, maybe_old_ptr: ?[&]const u8, old_size: usize, new_size: usize, alignment: u16) Allocator.Error![&]u8{
|
|
||||||
var maybe_new_ptr: [&]u8 = undefined;
|
|
||||||
if (new_size > 0) {
|
|
||||||
const general_protection_flags = os.ProtectionFlags{
|
|
||||||
.read = true,
|
|
||||||
.write = true,
|
|
||||||
.execute = false,
|
|
||||||
};
|
|
||||||
const general_map_flags = os.MapFlags{
|
|
||||||
.reserve = true,
|
|
||||||
.commit = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
maybe_new_ptr = os.allocate_virtual_memory(address = null, length = new_size, general_protection_flags, general_map_flags) catch return Allocator.Error.out_of_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maybe_old_ptr) |old_ptr| {
|
|
||||||
if (new_size > 0) {
|
|
||||||
unreachable;
|
|
||||||
} else {
|
|
||||||
os.free_virtual_memory(old_ptr[0..old_size]) catch return Allocator.Error.free_failed;
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return maybe_new_ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const get_allocator = fn(page_allocator: &PageAllocator) &Allocator {
|
|
||||||
return page_allocator.allocator.&;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
const Arena = std.Arena;
|
||||||
|
|
||||||
const main = fn() *!void {
|
const main = fn() *!void {
|
||||||
const size = 0x1000;
|
var arena = try Arena.allocate(2*1024*1024);
|
||||||
|
|
||||||
const result = try std.page_allocator.allocate(size, alignment = 12);
|
|
||||||
result[0] = 0;
|
|
||||||
try std.page_allocator.free(result);
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user