More self-hosted work

This commit is contained in:
David Gonzalez Martin 2024-04-23 18:11:57 -06:00
parent eb31e4b663
commit b88f3bbba0
3 changed files with 251 additions and 66 deletions

View File

@ -3431,6 +3431,7 @@ pub const Type = union(enum) {
type: Type.Index,
termination: Termination,
},
cast: Type.Index,
};
const Error = struct {
@ -4605,7 +4606,7 @@ pub const Builder = struct {
}
}
fn resolveIntrinsic(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, node_index: Node.Index) anyerror!V {
fn resolveIntrinsic(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, node_index: Node.Index, side: Side) anyerror!V {
const node = unit.getNode(node_index);
const intrinsic_id: IntrinsicId = @enumFromInt(Node.unwrap(node.right));
const argument_node_list = unit.getNodeList(node.left);
@ -4702,12 +4703,18 @@ pub const Builder = struct {
.cast => {
assert(argument_node_list.len == 1);
const argument_node_index = argument_node_list[0];
const cast_type_expect = Type.Expect{
.cast = switch (type_expect) {
.type => |type_index| type_index,
else => |t| @panic(@tagName(t)),
},
};
// TODO: depends? .right is not always the right choice
const v = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, argument_node_index, .right);
const v = try builder.resolveRuntimeValue(unit, context, cast_type_expect, argument_node_index, side);
switch (type_expect) {
.type => |type_index| {
const cast_id = try builder.resolveCast(unit, context, type_index, v);
const cast_id = try builder.resolveCast(unit, context, type_index, v, side);
switch (cast_id) {
.array_bitcast_to_integer => switch (v.value) {
.@"comptime" => |ct| switch (ct) {
@ -4734,8 +4741,61 @@ pub const Builder = struct {
else => unreachable,
}
},
.string_literal => |hash| {
const string_literal = unit.getIdentifier(hash);
var value: u64 = 0;
for (string_literal, 0..) |byte, i| {
value |= @as(u64, byte) << @as(u6, @intCast(i * 8));
}
return V{
.value = .{
.@"comptime" = .{
.constant_int = .{
.value = value,
},
},
},
.type = switch (unit.types.get(type_index).*) {
.pointer => |pointer| pointer.type,
else => |t| @panic(@tagName(t)),
},
};
},
else => |t| @panic(@tagName(t)),
},
.runtime => {
const stack = try builder.createStackVariable(unit, context, type_index, null);
const destination = V{
.value = .{ .runtime = stack },
.type = try unit.getPointerType(context, .{
.type = type_index,
.many = false,
.termination = .none,
.mutability = .@"var",
.nullable = false,
}),
};
const store = try unit.instructions.append(context.my_allocator, .{
.store = .{
.destination = destination,
.source = v,
},
});
try builder.appendInstruction(unit, context, store);
const load = try unit.instructions.append(context.my_allocator, .{
.load = .{
.value = destination,
.type = type_index,
},
});
try builder.appendInstruction(unit, context, load);
return V{
.value = .{ .runtime = load },
.type = type_index,
};
},
else => |t| @panic(@tagName(t)),
},
else => {
@ -5287,7 +5347,7 @@ pub const Builder = struct {
}
}
fn resolveCast(builder: *Builder, unit: *Unit, context: *const Context, type_index: Type.Index, value: V) !Instruction.Cast.Id {
fn resolveCast(builder: *Builder, unit: *Unit, context: *const Context, type_index: Type.Index, value: V, side: Side) !Instruction.Cast.Id {
_ = builder; // autofix
_ = context; // autofix
assert(type_index != value.type);
@ -5329,6 +5389,20 @@ pub const Builder = struct {
return .pointer_source_type_to_destination_type;
}
},
.array => |array| {
const array_size = array.count * unit.types.get(array.type).getAbiSize(unit);
switch (side) {
.right => {
const destination_type_size = unit.types.get(destination_pointer.type).getAbiSize(unit);
if (array_size == destination_type_size) {
return .array_bitcast_to_integer;
} else {
unreachable;
}
},
.left => unreachable,
}
},
else => |t| @panic(@tagName(t)),
}
},
@ -6630,6 +6704,7 @@ pub const Builder = struct {
else => |t| @panic(@tagName(t)),
}
},
.cast => return v,
else => |t| @panic(@tagName(t)),
}
} else {
@ -9887,7 +9962,7 @@ pub const Builder = struct {
const result = try builder.resolveIdentifier(unit, context, type_expect, identifier, .{}, side, &.{});
break :block result;
},
.intrinsic => try builder.resolveIntrinsic(unit, context, type_expect, node_index),
.intrinsic => try builder.resolveIntrinsic(unit, context, type_expect, node_index, side),
.pointer_dereference => block: {
// TODO:
const pointer_type_expect = switch (type_expect) {
@ -9905,6 +9980,7 @@ pub const Builder = struct {
};
break :b result;
},
.cast => Type.Expect.none,
else => unreachable,
};
@ -9948,7 +10024,7 @@ pub const Builder = struct {
.right => switch (unit.types.get(pointer_like_value.type).*) {
.pointer => |pointer| right: {
const load_type = switch (type_expect) {
.none => b: {
.none, .cast => b: {
const pointer_element_type = pointer.type;
break :b pointer_element_type;
},
@ -9971,6 +10047,10 @@ pub const Builder = struct {
.type = load_type,
};
},
.integer => switch (type_expect) {
.type => |type_index| if (type_index == pointer_like_value.type) pointer_like_value else unreachable,
else => |t| @panic(@tagName(t)),
},
else => |t| @panic(@tagName(t)),
},
};
@ -10157,7 +10237,7 @@ pub const Builder = struct {
.integer => |int| switch (int.kind) {
.materialized_int, .comptime_int, .bool => {
const right_expect_type: Type.Expect = switch (type_expect) {
.none => switch (left_value.type) {
.none, .cast => switch (left_value.type) {
.comptime_int => type_expect,
else => Type.Expect{
.type = left_value.type,
@ -10281,7 +10361,7 @@ pub const Builder = struct {
assert(left_value.type == right_value.type);
const type_index = switch (type_expect) {
.none => switch (binary_operation_id) {
.none, .cast => switch (binary_operation_id) {
.bit_and,
.bit_or,
.bit_xor,
@ -10727,6 +10807,43 @@ pub const Builder = struct {
switch (len_expression.value) {
.@"comptime" => {
const pointer_value = switch (unit.types.get(expression_to_slice.type).*) {
.slice => |slice| slice: {
const extract_pointer = try unit.instructions.append(context.my_allocator, .{
.extract_value = .{
.expression = expression_to_slice,
.index = 0,
},
});
try builder.appendInstruction(unit, context, extract_pointer);
const gep = try unit.instructions.append(context.my_allocator, .{
.get_element_pointer = .{
.pointer = extract_pointer,
.index = range_start,
.base_type = slice.child_type,
.name = try unit.processIdentifier(context, "slice_comptime_expression_slice"),
.is_struct = false,
},
});
try builder.appendInstruction(unit, context, gep);
break :slice V{
.value = .{
.runtime = gep,
},
.type = try unit.getPointerType(context, .{
.type = try unit.getArrayType(context, .{
.type = slice.child_type,
.count = len_expression.value.@"comptime".constant_int.value,
.termination = slice.termination,
}),
.termination = .none,
.mutability = slice.mutability,
.many = true,
.nullable = false,
}),
};
},
.pointer => |pointer| switch (pointer.many) {
true => unreachable,
false => switch (unit.types.get(pointer.type).*) {
@ -10852,6 +10969,7 @@ pub const Builder = struct {
},
else => |t| @panic(@tagName(t)),
},
.none => break :block pointer_value,
else => |t| @panic(@tagName(t)),
}
},
@ -11458,6 +11576,46 @@ pub const Builder = struct {
},
else => |t| @panic(@tagName(t)),
},
.cast => |type_index| switch (unit.types.get(type_index).*) {
.pointer => switch (side) {
.left => unreachable,
.right => blk: {
const string_literal = try unit.fixupStringLiteral(context, node.token);
const hash = try unit.processIdentifier(context, string_literal);
const ty = try unit.getArrayType(context, .{
.type = .u8,
.count = string_literal.len,
.termination = .none,
});
break :blk V{
.value = .{
.@"comptime" = .{
.string_literal = hash,
},
},
.type = ty,
};
},
},
else => |t| @panic(@tagName(t)),
},
.none => none: {
const string_literal = try unit.fixupStringLiteral(context, node.token);
const hash = try unit.processIdentifier(context, string_literal);
const ty = try unit.getArrayType(context, .{
.type = .u8,
.count = string_literal.len,
.termination = .none,
});
break :none V{
.value = .{
.@"comptime" = .{
.string_literal = hash,
},
},
.type = ty,
};
},
else => |t| @panic(@tagName(t)),
},
.if_else => try builder.resolveIfElse(unit, context, type_expect, node_index),
@ -12450,7 +12608,7 @@ pub const Builder = struct {
.@"struct" => |struct_index| switch (unit.structs.get(struct_index).kind) {
.error_union => |error_union| {
switch (type_expect) {
.none => {},
.none, .cast => {},
.type => |type_index| {
switch (try builder.typecheck(unit, context, type_index, error_union.type)) {
.success => {},
@ -14081,7 +14239,7 @@ pub const Builder = struct {
.intrinsic => {
_ = try builder.resolveIntrinsic(unit, context, Type.Expect{
.type = .void,
}, statement_node_index);
}, statement_node_index, .right);
},
.constant_symbol_declaration,
.variable_symbol_declaration,
@ -15448,6 +15606,25 @@ pub const Builder = struct {
} else unreachable,
else => |t| @panic(@tagName(t)),
},
.string_literal => |hash| if (byte_equal(identifier, length_field_name)) switch (type_expect) {
.type => |type_index| switch (unit.types.get(type_index).*) {
.integer => |*integer| switch (integer.kind) {
.materialized_int => V{
.value = .{
.@"comptime" = .{
.constant_int = .{
.value = unit.getIdentifier(hash).len,
},
},
},
.type = type_index,
},
else => |t| @panic(@tagName(t)),
},
else => |t| @panic(@tagName(t)),
},
else => |t| @panic(@tagName(t)),
} else unreachable,
else => |t| @panic(@tagName(t)),
},
.runtime => |_| b: {
@ -15817,6 +15994,7 @@ pub const Builder = struct {
switch (type_expect) {
.none => return result,
.cast => return result,
.type => |ti| {
const typecheck_result = try builder.typecheck(unit, context, ti, result.type);
switch (typecheck_result) {

View File

@ -1597,7 +1597,7 @@ pub const LLVM = struct {
},
.bool => b: {
const flags = LLVM.DebugInfo.Node.Flags{
.visibility = .none,
.visibility = .private,
.forward_declaration = false,
.apple_block = false,
.block_by_ref_struct = false,
@ -1616,7 +1616,7 @@ pub const LLVM = struct {
.introduced_virtual = false,
.bit_field = false,
.no_return = false,
.type_pass_by_value = false,
.type_pass_by_value = true,
.type_pass_by_reference = false,
.enum_class = false,
.thunk = false,
@ -1625,7 +1625,7 @@ pub const LLVM = struct {
.little_endian = false,
.all_calls_described = false,
};
const boolean_type = llvm.debug_info_builder.createBasicType("bool", "bool".len, 1, .boolean, flags) orelse unreachable;
const boolean_type = llvm.debug_info_builder.createBasicType("bool", "bool".len, 8, .boolean, flags) orelse unreachable;
break :b boolean_type;
},
.@"enum" => |*enum_type| b: {

View File

@ -19,7 +19,7 @@ const Parser = struct{
const pointer = parser.text;
while (parser.index < length) {
const ch = pointer[parser.index];
const new_line = ch == '\r';
const new_line = ch == '\n';
const is_space = ch == ' ' or ch == '\t' or new_line or ch == '\r';
if (new_line) {
parser.current_line += 1;
@ -46,60 +46,67 @@ const parse = fn (arena: &Arena, bytes: []const u8) *!void {
.length = length,
};
//var index: u32 = 0;
//while (index < length) {
// parser.skip_whitespace();
while (parser.index < length) {
parser.skip_whitespace();
// if (index == length) {
// break;
// }
const current_index = parser.index;
if (current_index == length) {
break;
}
// const slice_8 = bytes[index..][0..8];
// const slice_4 = bytes[index..][0..4];
// const chunk_8: u64 = #cast(slice_8.@);
// const chunk_4: u64 = #cast(slice_4.@);
// const comptime_mask: u64 = #cast("comptime".@);
// const test_mask: u32 = #cast("test").@;
// const const_mask: u32 = #cast("const").@;
// const var_mask: u32 = #cast("var ").@;
// const is_comptime = chunk_8 == comptime_mask;
// const is_test = chunk_4 == test_mask;
// const is_const = chunk_4 == const_mask;
// const is_var = (chunk_4 & 0xffffff) == (var_mask & 0xffffff);
// const is_valid = is_comptime or is_test or is_const or is_var;
// if (is_valid) {
// exit(0);
// } else {
// exit(1);
// }
//}
//var index: u32 = 0;
//while (index + 64 < length) {
// var i = index;
// const top = index + max_initial_keyword_len + 1;
// var space: u32 = 0;
// while (i < top) {
// const is_space = bytes[i] == ' ';
// const is_space_int: u32 = #cast(is_space);
// const space_mask = 0 -% is_space_int;
// space |= (1 << i) & space_mask;
// i += 1;
// }
// if (space == 0) {
// unreachable;
// }
// const word_byte_count = #trailing_zeroes(space);
// const word = bytes[index..][0..word_byte_count];
// break;
//}
const slice = bytes[current_index..];
const is_const = byte_equal(slice[0.."const".length], "const");
const is_var = byte_equal(slice[0.."var".length], "var");
const is_test = byte_equal(slice[0.."test".length], "test");
const is_comptime = byte_equal(slice[0.."comptime".length], "comptime");
if (is_const) {
const space_index: u32 = "const".length;
const ch = slice[space_index];
const next_ch = slice[space_index + 1];
const is_normal_space = (ch == ' ' or ch == '\n') or (ch == '\t' or ch == '\r');
const is_comment = ch == '/' and next_ch == '/';
const is_space = is_normal_space or is_comment;
if (!is_space) {
exit(1);
}
exit(0);
} else if (is_var) {
const space_index: u32 = "var".length;
const ch = slice[space_index];
const next_ch = slice[space_index + 1];
const is_normal_space = (ch == ' ' or ch == '\n') or (ch == '\t' or ch == '\r');
const is_comment = ch == '/' and next_ch == '/';
const is_space = is_normal_space or is_comment;
if (!is_space) {
exit(1);
}
exit(0);
} else if (is_test) {
const space_index: u32 = "test".length;
const ch = slice[space_index];
const next_ch = slice[space_index + 1];
const is_normal_space = (ch == ' ' or ch == '\n') or (ch == '\t' or ch == '\r');
const is_comment = ch == '/' and next_ch == '/';
const is_space = is_normal_space or is_comment;
if (!is_space) {
exit(1);
}
exit(0);
} else if (is_comptime) {
const space_index: u32 = "comptime".length;
const ch = slice[space_index];
const next_ch = slice[space_index + 1];
const is_normal_space = (ch == ' ' or ch == '\n') or (ch == '\t' or ch == '\r');
const is_comment = ch == '/' and next_ch == '/';
const is_space = is_normal_space or is_comment;
if (!is_space) {
exit(1);
}
exit(0);
} else {
exit(1);
}
}
}
const FileStartToken = enum{