Bits
All checks were successful
All checks were successful
This commit is contained in:
parent
30b0b2a259
commit
4338755dbd
@ -223,7 +223,7 @@ pub const Type = struct {
|
|||||||
integer: Type.Integer,
|
integer: Type.Integer,
|
||||||
enumerator: Enumerator,
|
enumerator: Enumerator,
|
||||||
float,
|
float,
|
||||||
bits,
|
bits: Type.Bits,
|
||||||
pointer: Type.Pointer,
|
pointer: Type.Pointer,
|
||||||
function: Type.Function,
|
function: Type.Function,
|
||||||
array: Type.Array,
|
array: Type.Array,
|
||||||
@ -260,6 +260,7 @@ pub const Type = struct {
|
|||||||
const struct_type = module.llvm.context.get_struct_type(llvm_types);
|
const struct_type = module.llvm.context.get_struct_type(llvm_types);
|
||||||
break :blk struct_type.to_type();
|
break :blk struct_type.to_type();
|
||||||
},
|
},
|
||||||
|
.bits => |bits| bits.backing_type.resolve(module).handle,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
ty.llvm.handle = llvm_type;
|
ty.llvm.handle = llvm_type;
|
||||||
@ -317,6 +318,16 @@ pub const Type = struct {
|
|||||||
forward_declared.replace_all_uses_with(debug_struct_type);
|
forward_declared.replace_all_uses_with(debug_struct_type);
|
||||||
break :blk debug_struct_type.to_type();
|
break :blk debug_struct_type.to_type();
|
||||||
},
|
},
|
||||||
|
.bits => |bits| blk: {
|
||||||
|
var llvm_debug_member_type_buffer: [64]*llvm.DI.Type.Derived = undefined;
|
||||||
|
const llvm_debug_member_types = llvm_debug_member_type_buffer[0..bits.fields.len];
|
||||||
|
for (bits.fields, llvm_debug_member_types) |field, *llvm_debug_member_type| {
|
||||||
|
llvm_debug_member_type.* = module.llvm.di_builder.create_bit_field_member_type(module.scope.llvm.?, field.name, module.llvm.file, field.line, field.type.get_bit_size(), field.bit_offset, 0, .{}, bits.backing_type.llvm.debug.?);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct_type = module.llvm.di_builder.create_struct_type(module.scope.llvm.?, ty.name, module.llvm.file, bits.line, ty.get_bit_size(), @intCast(ty.get_bit_alignment()), .{}, llvm_debug_member_types);
|
||||||
|
break :blk struct_type.to_type();
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
} else null;
|
} else null;
|
||||||
ty.llvm.debug = debug_type;
|
ty.llvm.debug = debug_type;
|
||||||
@ -328,6 +339,13 @@ pub const Type = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Bits = struct {
|
||||||
|
fields: []const Field,
|
||||||
|
backing_type: *Type,
|
||||||
|
line: u32,
|
||||||
|
implicit_backing_type: bool,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Integer = struct {
|
pub const Integer = struct {
|
||||||
bit_count: u32,
|
bit_count: u32,
|
||||||
signed: bool,
|
signed: bool,
|
||||||
@ -425,8 +443,7 @@ pub const Type = struct {
|
|||||||
8, 16, 32, 64, 128 => false,
|
8, 16, 32, 64, 128 => false,
|
||||||
else => true,
|
else => true,
|
||||||
},
|
},
|
||||||
.bits => @trap(),
|
.bits => |bits| bits.backing_type.is_arbitrary_bit_integer(),
|
||||||
// .bits => |bits| bits.backing_type.is_arbitrary_bit_integer(),
|
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -448,6 +465,7 @@ pub const Type = struct {
|
|||||||
.array => |array| array.element_type.get_byte_alignment(),
|
.array => |array| array.element_type.get_byte_alignment(),
|
||||||
.enumerator => |enumerator| enumerator.backing_type.get_byte_alignment(),
|
.enumerator => |enumerator| enumerator.backing_type.get_byte_alignment(),
|
||||||
.structure => |structure| structure.byte_alignment,
|
.structure => |structure| structure.byte_alignment,
|
||||||
|
.bits => |bits| bits.backing_type.get_byte_alignment(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
@ -457,6 +475,7 @@ pub const Type = struct {
|
|||||||
return switch (ty.bb) {
|
return switch (ty.bb) {
|
||||||
.integer => |integer| integer.bit_count, // TODO: is this correct?
|
.integer => |integer| integer.bit_count, // TODO: is this correct?
|
||||||
.pointer => 64,
|
.pointer => 64,
|
||||||
|
.bits => |bits| bits.backing_type.get_bit_alignment(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -474,6 +493,7 @@ pub const Type = struct {
|
|||||||
const bit_size: u64 = switch (ty.bb) {
|
const bit_size: u64 = switch (ty.bb) {
|
||||||
.integer => |integer| integer.bit_count,
|
.integer => |integer| integer.bit_count,
|
||||||
.pointer => 64,
|
.pointer => 64,
|
||||||
|
.bits => |bits| bits.backing_type.get_bit_size(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
return bit_size;
|
return bit_size;
|
||||||
@ -641,6 +661,8 @@ pub const Value = struct {
|
|||||||
enum_literal: []const u8,
|
enum_literal: []const u8,
|
||||||
field_access: FieldAccess,
|
field_access: FieldAccess,
|
||||||
string_literal: []const u8,
|
string_literal: []const u8,
|
||||||
|
aggregate_initialization: AggregateInitialization,
|
||||||
|
zero,
|
||||||
},
|
},
|
||||||
type: ?*Type = null,
|
type: ?*Type = null,
|
||||||
llvm: ?*llvm.Value = null,
|
llvm: ?*llvm.Value = null,
|
||||||
@ -656,6 +678,12 @@ pub const Value = struct {
|
|||||||
is_constant: bool,
|
is_constant: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const AggregateInitialization = struct {
|
||||||
|
names: []const []const u8,
|
||||||
|
values: []const *Value,
|
||||||
|
is_constant: bool,
|
||||||
|
zero: bool,
|
||||||
|
};
|
||||||
|
|
||||||
const Intrinsic = union(Id) {
|
const Intrinsic = union(Id) {
|
||||||
byte_size: *Type,
|
byte_size: *Type,
|
||||||
@ -1654,6 +1682,19 @@ pub const Module = struct {
|
|||||||
};
|
};
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
|
r[@intFromEnum(Token.Id.@"{")] = .{
|
||||||
|
.before = rule_before_brace,
|
||||||
|
.after = null, // TODO: is this correct?
|
||||||
|
.precedence = .none,
|
||||||
|
};
|
||||||
|
count += 1;
|
||||||
|
r[@intFromEnum(Token.Id.@"}")] = .{
|
||||||
|
.before = null,
|
||||||
|
.after = null,
|
||||||
|
.precedence = .none,
|
||||||
|
};
|
||||||
|
count += 1;
|
||||||
|
|
||||||
r[@intFromEnum(Token.Id.@",")] = .{
|
r[@intFromEnum(Token.Id.@",")] = .{
|
||||||
.before = null,
|
.before = null,
|
||||||
.after = null,
|
.after = null,
|
||||||
@ -1905,6 +1946,14 @@ pub const Module = struct {
|
|||||||
module.offset += 1;
|
module.offset += 1;
|
||||||
break :blk .@"]";
|
break :blk .@"]";
|
||||||
},
|
},
|
||||||
|
left_brace => blk: {
|
||||||
|
module.offset += 1;
|
||||||
|
break :blk .@"{";
|
||||||
|
},
|
||||||
|
right_brace => blk: {
|
||||||
|
module.offset += 1;
|
||||||
|
break :blk .@"}";
|
||||||
|
},
|
||||||
',' => blk: {
|
',' => blk: {
|
||||||
module.offset += 1;
|
module.offset += 1;
|
||||||
break :blk .@",";
|
break :blk .@",";
|
||||||
@ -1919,7 +1968,7 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const string_slice = module.content[string_literal_start..][0..(module.offset - 1) - string_literal_start];
|
const string_slice = module.content[string_literal_start..][0 .. (module.offset - 1) - string_literal_start];
|
||||||
|
|
||||||
break :blk .{
|
break :blk .{
|
||||||
.string_literal = string_slice,
|
.string_literal = string_slice,
|
||||||
@ -2123,7 +2172,7 @@ pub const Module = struct {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
.@"while" => {
|
.@"while" => {
|
||||||
module.skip_space();
|
module.skip_space();
|
||||||
|
|
||||||
module.expect_character(left_parenthesis);
|
module.expect_character(left_parenthesis);
|
||||||
module.skip_space();
|
module.skip_space();
|
||||||
@ -2348,7 +2397,7 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.kind = if (variable.type) |t| switch (t.bb) {
|
.kind = if (variable.type) |t| switch (t.bb) {
|
||||||
.array, .function, .structure => .left,
|
.array, .function, .structure => .left,
|
||||||
.integer, .pointer, .enumerator => value_builder.kind,
|
.integer, .pointer, .enumerator, .bits => value_builder.kind,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
} else value_builder.kind,
|
} else value_builder.kind,
|
||||||
// if (variable.type != null and variable.type.?.bb == .function) .left else value_builder.kind,
|
// if (variable.type != null and variable.type.?.bb == .function) .left else value_builder.kind,
|
||||||
@ -2357,9 +2406,15 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn rule_before_value_keyword(noalias module: *Module, value_builder: Value.Builder) *Value {
|
fn rule_before_value_keyword(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
_ = value_builder;
|
const value = module.values.add();
|
||||||
_ = module;
|
const new_value: Value = switch (value_builder.token.value_keyword) {
|
||||||
@trap();
|
.zero => .{
|
||||||
|
.bb = .zero,
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
value.* = new_value;
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rule_before_value_intrinsic(noalias module: *Module, value_builder: Value.Builder) *Value {
|
fn rule_before_value_intrinsic(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
@ -2603,6 +2658,84 @@ pub const Module = struct {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rule_before_brace(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
|
assert(value_builder.left == null);
|
||||||
|
|
||||||
|
var name_buffer: [64][]const u8 = undefined;
|
||||||
|
var value_buffer: [64]*Value = undefined;
|
||||||
|
var field_count: u32 = 0;
|
||||||
|
var zero = false;
|
||||||
|
|
||||||
|
while (true) : (field_count += 1) {
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
if (module.consume_character_if_match(right_brace)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module.consume_character_if_match('.')) {
|
||||||
|
const name = module.parse_identifier();
|
||||||
|
name_buffer[field_count] = name;
|
||||||
|
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
module.expect_character('=');
|
||||||
|
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
const value = module.parse_value(.{});
|
||||||
|
value_buffer[field_count] = value;
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
_ = module.consume_character_if_match(',');
|
||||||
|
} else {
|
||||||
|
const token = module.tokenize();
|
||||||
|
switch (token) {
|
||||||
|
.value_keyword => |vkw| switch (vkw) {
|
||||||
|
.zero => {
|
||||||
|
zero = true;
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
if (module.consume_character_if_match(',')) {
|
||||||
|
module.skip_space();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.expect_character(right_brace);
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
else => module.report_error(),
|
||||||
|
},
|
||||||
|
else => module.report_error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = module.arena.allocate_bytes(field_count * @sizeOf([]const u8) + field_count * @sizeOf(*Value), @max(@alignOf([]const u8), @alignOf(*Value)));
|
||||||
|
const names = @as([*][]const u8, @alignCast(@ptrCast(blob)))[0..field_count];
|
||||||
|
@memcpy(names, name_buffer[0..field_count]);
|
||||||
|
const values = @as([*]*Value, @alignCast(@ptrCast(blob + (@sizeOf([]const u8) * field_count))))[0..field_count];
|
||||||
|
@memcpy(values, value_buffer[0..field_count]);
|
||||||
|
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.bb = .{
|
||||||
|
.aggregate_initialization = .{
|
||||||
|
.names = names,
|
||||||
|
.values = values,
|
||||||
|
.is_constant = false,
|
||||||
|
.zero = zero,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rule_after_brace(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
|
_ = module;
|
||||||
|
_ = value_builder;
|
||||||
|
@trap();
|
||||||
|
}
|
||||||
|
|
||||||
// Array initialization
|
// Array initialization
|
||||||
fn rule_before_bracket(noalias module: *Module, value_builder: Value.Builder) *Value {
|
fn rule_before_bracket(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
assert(value_builder.left == null);
|
assert(value_builder.left == null);
|
||||||
@ -2713,10 +2846,10 @@ pub const Module = struct {
|
|||||||
_ = struct_type;
|
_ = struct_type;
|
||||||
@trap();
|
@trap();
|
||||||
} else blk: {
|
} else blk: {
|
||||||
const byte_alignment = @max(pair[0].get_byte_alignment(), pair[1].get_byte_alignment());
|
const byte_alignment = @max(pair[0].get_byte_alignment(), pair[1].get_byte_alignment());
|
||||||
const byte_size = lib.align_forward_u64(pair[0].get_byte_size() + pair[1].get_byte_size(), byte_alignment);
|
const byte_size = lib.align_forward_u64(pair[0].get_byte_size() + pair[1].get_byte_size(), byte_alignment);
|
||||||
|
|
||||||
const fields = module.arena.allocate(Field, 2);
|
const fields = module.arena.allocate(Field, 2);
|
||||||
fields[0] = .{
|
fields[0] = .{
|
||||||
.bit_offset = 0,
|
.bit_offset = 0,
|
||||||
.byte_offset = 0,
|
.byte_offset = 0,
|
||||||
@ -3077,6 +3210,88 @@ pub const Module = struct {
|
|||||||
.name = global_name,
|
.name = global_name,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
.bits => {
|
||||||
|
const is_implicit_type = module.content[module.offset] == left_brace;
|
||||||
|
const maybe_backing_type: ?*Type = switch (is_implicit_type) {
|
||||||
|
true => null,
|
||||||
|
false => module.parse_type(),
|
||||||
|
};
|
||||||
|
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
module.expect_character(left_brace);
|
||||||
|
|
||||||
|
var field_buffer: [128]Field = undefined;
|
||||||
|
var field_line_buffer: [128]u32 = undefined;
|
||||||
|
var field_count: u64 = 0;
|
||||||
|
|
||||||
|
var field_bit_offset: u64 = 0;
|
||||||
|
|
||||||
|
while (true) : (field_count += 1) {
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
if (module.consume_character_if_match(right_brace)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const field_line = module.get_line();
|
||||||
|
field_line_buffer[field_count] = field_line;
|
||||||
|
|
||||||
|
const field_name = module.parse_identifier();
|
||||||
|
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
module.expect_character(':');
|
||||||
|
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
const field_type = module.parse_type();
|
||||||
|
|
||||||
|
field_buffer[field_count] = .{
|
||||||
|
.name = field_name,
|
||||||
|
.type = field_type,
|
||||||
|
.bit_offset = field_bit_offset,
|
||||||
|
.byte_offset = 0,
|
||||||
|
.line = field_line,
|
||||||
|
};
|
||||||
|
|
||||||
|
const field_bit_size = field_type.get_bit_size();
|
||||||
|
|
||||||
|
field_bit_offset += field_bit_size;
|
||||||
|
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
_ = module.consume_character_if_match(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = module.consume_character_if_match(';');
|
||||||
|
|
||||||
|
const fields = module.arena.allocate(Field, field_count);
|
||||||
|
@memcpy(fields, field_buffer[0..field_count]);
|
||||||
|
|
||||||
|
// const field_lines = field_line_buffer[0..field_count];
|
||||||
|
|
||||||
|
const backing_type = if (maybe_backing_type) |bt| bt else module.integer_type(@intCast(@max(8, lib.next_power_of_two(field_bit_offset))), false);
|
||||||
|
if (backing_type.bb != .integer) {
|
||||||
|
module.report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backing_type.get_bit_size() > 64) {
|
||||||
|
module.report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = module.types.append(.{
|
||||||
|
.name = global_name,
|
||||||
|
.bb = .{
|
||||||
|
.bits = .{
|
||||||
|
.fields = fields,
|
||||||
|
.backing_type = backing_type,
|
||||||
|
.line = global_line,
|
||||||
|
.implicit_backing_type = is_implicit_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -3780,11 +3995,11 @@ pub const Module = struct {
|
|||||||
.is_slice = false,
|
.is_slice = false,
|
||||||
.line = 0,
|
.line = 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const element_count = 1;
|
const element_count = 1;
|
||||||
const element_type = result;
|
const element_type = result;
|
||||||
const ty = module.types.append(.{
|
const ty = module.types.append(.{
|
||||||
.name = array_type_name(module.arena, element_type, element_count),
|
.name = array_type_name(module.arena, element_type, element_count),
|
||||||
.bb = .{
|
.bb = .{
|
||||||
@ -4065,6 +4280,76 @@ pub const Module = struct {
|
|||||||
// module.report_error();
|
// module.report_error();
|
||||||
// };
|
// };
|
||||||
},
|
},
|
||||||
|
.aggregate_initialization => |*aggregate_initialization| {
|
||||||
|
switch (expected_type.bb) {
|
||||||
|
.bits => |bits| {
|
||||||
|
var is_ordered = true;
|
||||||
|
var is_constant = true;
|
||||||
|
for (aggregate_initialization.names, aggregate_initialization.values, 0..) |field_name, field_value, initialization_index| {
|
||||||
|
const declaration_index = for (bits.fields, 0..) |field, declaration_index| {
|
||||||
|
if (lib.string.equal(field.name, field_name)) {
|
||||||
|
break declaration_index;
|
||||||
|
}
|
||||||
|
} else module.report_error();
|
||||||
|
is_ordered = is_ordered and declaration_index == initialization_index;
|
||||||
|
const field = &bits.fields[declaration_index];
|
||||||
|
const declaration_type = field.type;
|
||||||
|
module.analyze_value_type(function, field_value, .{ .type = declaration_type });
|
||||||
|
is_constant = is_constant and field_value.is_constant();
|
||||||
|
}
|
||||||
|
|
||||||
|
aggregate_initialization.is_constant = is_constant;
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.field_access => |field_access| {
|
||||||
|
module.analyze_value_type(function, field_access.aggregate, .{});
|
||||||
|
const field_name = field_access.field;
|
||||||
|
switch (field_access.aggregate.kind) {
|
||||||
|
.left => switch (field_access.aggregate.type.?.bb) {
|
||||||
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
|
.structure => |structure| {
|
||||||
|
const field_type = for (structure.fields) |*field| {
|
||||||
|
if (lib.string.equal(field_name, field.name)) {
|
||||||
|
break field.type;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
module.report_error();
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = field_type;
|
||||||
|
@trap();
|
||||||
|
// break :blk switch (value.kind) {
|
||||||
|
// .left => @trap(),
|
||||||
|
// .right => field_type,
|
||||||
|
// };
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
else => module.report_error(),
|
||||||
|
},
|
||||||
|
.right => switch (field_access.aggregate.type.?.bb) {
|
||||||
|
.bits => |bits| {
|
||||||
|
const field_type = for (bits.fields) |*field| {
|
||||||
|
if (lib.string.equal(field_name, field.name)) {
|
||||||
|
break field.type;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
module.report_error();
|
||||||
|
};
|
||||||
|
switch (value.kind) {
|
||||||
|
.left => module.report_error(),
|
||||||
|
.right => if (field_type != expected_type) {
|
||||||
|
module.report_error();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.zero => {},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4214,28 +4499,45 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.field_access => |field_access| blk: {
|
.field_access => |field_access| blk: {
|
||||||
assert(field_access.aggregate.kind == .left);
|
|
||||||
module.analyze_value_type(function, field_access.aggregate, .{});
|
module.analyze_value_type(function, field_access.aggregate, .{});
|
||||||
const field_name = field_access.field;
|
const field_name = field_access.field;
|
||||||
switch (field_access.aggregate.type.?.bb) {
|
switch (field_access.aggregate.kind) {
|
||||||
.pointer => |pointer| switch (pointer.type.bb) {
|
.left => switch (field_access.aggregate.type.?.bb) {
|
||||||
.structure => |structure| {
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
const field_type = for (structure.fields) |*field| {
|
.structure => |structure| {
|
||||||
|
const field_type = for (structure.fields) |*field| {
|
||||||
|
if (lib.string.equal(field_name, field.name)) {
|
||||||
|
break field.type;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
module.report_error();
|
||||||
|
};
|
||||||
|
|
||||||
|
break :blk switch (value.kind) {
|
||||||
|
.left => @trap(),
|
||||||
|
.right => field_type,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
else => module.report_error(),
|
||||||
|
},
|
||||||
|
.right => switch (field_access.aggregate.type.?.bb) {
|
||||||
|
.bits => |bits| {
|
||||||
|
const field_type = for (bits.fields) |*field| {
|
||||||
if (lib.string.equal(field_name, field.name)) {
|
if (lib.string.equal(field_name, field.name)) {
|
||||||
break field.type;
|
break field.type;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
module.report_error();
|
module.report_error();
|
||||||
};
|
};
|
||||||
|
|
||||||
break :blk switch (value.kind) {
|
break :blk switch (value.kind) {
|
||||||
.left => @trap(),
|
.left => module.report_error(),
|
||||||
.right => field_type,
|
.right => field_type,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
else => module.report_error(),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.string_literal => module.get_slice_type(.{ .type = module.integer_type(8, false) }),
|
.string_literal => module.get_slice_type(.{ .type = module.integer_type(8, false) }),
|
||||||
@ -4969,12 +5271,15 @@ pub const Module = struct {
|
|||||||
const gep = module.llvm.builder.create_gep(.{
|
const gep = module.llvm.builder.create_gep(.{
|
||||||
.type = element_type.llvm.handle.?,
|
.type = element_type.llvm.handle.?,
|
||||||
.aggregate = pointer_load,
|
.aggregate = pointer_load,
|
||||||
.indices = &.{ array_expression.index.llvm.? },
|
.indices = &.{array_expression.index.llvm.?},
|
||||||
});
|
});
|
||||||
|
|
||||||
break :blk switch (value.kind) {
|
break :blk switch (value.kind) {
|
||||||
.left => gep,
|
.left => gep,
|
||||||
.right => module.create_load(.{ .type = element_type, .value = gep, }),
|
.right => module.create_load(.{
|
||||||
|
.type = element_type,
|
||||||
|
.value = gep,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
@ -5032,29 +5337,76 @@ pub const Module = struct {
|
|||||||
.field_access => |field_access| blk: {
|
.field_access => |field_access| blk: {
|
||||||
module.emit_value(function, field_access.aggregate);
|
module.emit_value(function, field_access.aggregate);
|
||||||
const field_name = field_access.field;
|
const field_name = field_access.field;
|
||||||
switch (field_access.aggregate.type.?.bb) {
|
switch (field_access.aggregate.kind) {
|
||||||
.pointer => |pointer| switch (pointer.type.bb) {
|
.left => switch (field_access.aggregate.type.?.bb) {
|
||||||
.structure => |structure| {
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
const field_index: u32 = for (structure.fields, 0..) |field, field_index| {
|
.structure => |structure| {
|
||||||
|
const field_index: u32 = for (structure.fields, 0..) |field, field_index| {
|
||||||
|
if (lib.string.equal(field_name, field.name)) {
|
||||||
|
break @intCast(field_index);
|
||||||
|
}
|
||||||
|
} else module.report_error();
|
||||||
|
|
||||||
|
const gep = module.llvm.builder.create_struct_gep(pointer.type.resolve(module).handle.to_struct(), field_access.aggregate.llvm.?, field_index);
|
||||||
|
break :blk switch (value.kind) {
|
||||||
|
.left => gep,
|
||||||
|
.right => module.create_load(.{
|
||||||
|
.type = structure.fields[field_index].type,
|
||||||
|
.value = gep,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
.right => switch (field_access.aggregate.type.?.bb) {
|
||||||
|
.bits => |bits| {
|
||||||
|
const field_index: u32 = for (bits.fields, 0..) |field, field_index| {
|
||||||
if (lib.string.equal(field_name, field.name)) {
|
if (lib.string.equal(field_name, field.name)) {
|
||||||
break @intCast(field_index);
|
break @intCast(field_index);
|
||||||
}
|
}
|
||||||
} else module.report_error();
|
} else module.report_error();
|
||||||
|
const field = bits.fields[field_index];
|
||||||
|
|
||||||
const gep = module.llvm.builder.create_struct_gep(pointer.type.resolve(module).handle.to_struct(), field_access.aggregate.llvm.?, field_index);
|
const shift = module.llvm.builder.create_lshr(field_access.aggregate.llvm.?, bits.backing_type.llvm.handle.?.to_integer().get_constant(field.bit_offset, 0).to_value());
|
||||||
break :blk switch (value.kind) {
|
const trunc = module.llvm.builder.create_truncate(shift, field.type.resolve(module).handle);
|
||||||
.left => gep,
|
break :blk trunc;
|
||||||
.right => module.create_load(.{
|
|
||||||
.type = structure.fields[field_index].type,
|
|
||||||
.value = gep,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
else => @trap(),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.aggregate_initialization => |aggregate_initialization| switch (value_type.bb) {
|
||||||
|
.bits => |bits| switch (aggregate_initialization.is_constant) {
|
||||||
|
true => blk: {
|
||||||
|
var bits_value: u64 = 0;
|
||||||
|
for (aggregate_initialization.names, aggregate_initialization.values) |field_name, field_value| {
|
||||||
|
const declaration_index = for (bits.fields, 0..) |field, declaration_index| {
|
||||||
|
if (lib.string.equal(field_name, field.name)) {
|
||||||
|
break declaration_index;
|
||||||
|
}
|
||||||
|
} else unreachable;
|
||||||
|
const field = &bits.fields[declaration_index];
|
||||||
|
_ = field.bit_offset;
|
||||||
|
|
||||||
|
const fv = switch (field_value.bb) {
|
||||||
|
.constant_integer => |ci| ci.value,
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
bits_value |= fv << @intCast(field.bit_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm_value = bits.backing_type.resolve(module).handle.to_integer().get_constant(bits_value, @intFromBool(false));
|
||||||
|
break :blk llvm_value.to_value();
|
||||||
|
},
|
||||||
|
false => {
|
||||||
|
@trap();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
.zero => value_type.resolve(module).handle.get_zero().to_value(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5446,7 +5798,7 @@ pub const Module = struct {
|
|||||||
const u8_type = module.integer_type(8, false);
|
const u8_type = module.integer_type(8, false);
|
||||||
const global_variable = module.llvm.module.create_global_variable(.{
|
const global_variable = module.llvm.module.create_global_variable(.{
|
||||||
.linkage = .InternalLinkage,
|
.linkage = .InternalLinkage,
|
||||||
.name = module.arena.join_string(&.{ "conststring" }),
|
.name = module.arena.join_string(&.{"conststring"}),
|
||||||
.initial_value = constant_string,
|
.initial_value = constant_string,
|
||||||
.type = u8_type.llvm.handle.?.get_array_type(string_literal.len + @intFromBool(null_terminate)).to_type(),
|
.type = u8_type.llvm.handle.?.get_array_type(string_literal.len + @intFromBool(null_terminate)).to_type(),
|
||||||
});
|
});
|
||||||
@ -5718,6 +6070,9 @@ const Token = union(Id) {
|
|||||||
// Bracket
|
// Bracket
|
||||||
@"[",
|
@"[",
|
||||||
@"]",
|
@"]",
|
||||||
|
// Brace
|
||||||
|
@"{",
|
||||||
|
@"}",
|
||||||
|
|
||||||
@",",
|
@",",
|
||||||
@".",
|
@".",
|
||||||
@ -5779,6 +6134,9 @@ const Token = union(Id) {
|
|||||||
// Bracket
|
// Bracket
|
||||||
@"[",
|
@"[",
|
||||||
@"]",
|
@"]",
|
||||||
|
// Brace
|
||||||
|
@"{",
|
||||||
|
@"}",
|
||||||
|
|
||||||
@",",
|
@",",
|
||||||
@".",
|
@".",
|
||||||
|
@ -213,4 +213,8 @@ const names = &[_][]const u8{
|
|||||||
"basic_varargs",
|
"basic_varargs",
|
||||||
"basic_while",
|
"basic_while",
|
||||||
"not_pointer",
|
"not_pointer",
|
||||||
|
"bits",
|
||||||
|
"bits_no_backing_type",
|
||||||
|
"bits_return_u1",
|
||||||
|
"bits_zero",
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user