Bits 'zero'
This commit is contained in:
parent
4fa1ba260a
commit
209aae6959
@ -2950,6 +2950,12 @@ const Converter = struct {
|
|||||||
@trap();
|
@trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ValueKeyword = enum {
|
||||||
|
@"_",
|
||||||
|
undefined,
|
||||||
|
zero,
|
||||||
|
};
|
||||||
|
|
||||||
fn parse_single_value(noalias converter: *Converter, noalias module: *Module, expected_type: ?*Type, value_kind: ValueKind) *Value {
|
fn parse_single_value(noalias converter: *Converter, noalias module: *Module, expected_type: ?*Type, value_kind: ValueKind) *Value {
|
||||||
converter.skip_space();
|
converter.skip_space();
|
||||||
|
|
||||||
@ -3121,45 +3127,68 @@ const Converter = struct {
|
|||||||
|
|
||||||
var llvm_value = bits.backing_type.llvm.handle.to_integer().get_constant(0, @intFromBool(false)).to_value();
|
var llvm_value = bits.backing_type.llvm.handle.to_integer().get_constant(0, @intFromBool(false)).to_value();
|
||||||
|
|
||||||
while (converter.consume_character_if_match('.')) : (field_count += 1) {
|
var zero = false;
|
||||||
|
while (true) : (field_count += 1) {
|
||||||
converter.skip_space();
|
converter.skip_space();
|
||||||
|
|
||||||
const field_name = converter.parse_identifier();
|
if (converter.consume_character_if_match(right_brace)) {
|
||||||
const field_index: u32 = for (bits.fields, 0..) |*field, field_index| {
|
break;
|
||||||
if (lib.string.equal(field.name, field_name)) {
|
} else if (converter.consume_character_if_match('.')) {
|
||||||
break @intCast(field_index);
|
const field_name = converter.parse_identifier();
|
||||||
|
const field_index: u32 = for (bits.fields, 0..) |*field, field_index| {
|
||||||
|
if (lib.string.equal(field.name, field_name)) {
|
||||||
|
break @intCast(field_index);
|
||||||
|
}
|
||||||
|
} else converter.report_error();
|
||||||
|
|
||||||
|
const field = bits.fields[field_index];
|
||||||
|
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
converter.expect_character('=');
|
||||||
|
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
const field_value = converter.parse_value(module, field.type, .value);
|
||||||
|
|
||||||
|
const extended_field_value = module.llvm.builder.create_zero_extend(field_value.llvm, bits.backing_type.llvm.handle);
|
||||||
|
const shifted_value = module.llvm.builder.create_shl(extended_field_value, bits.backing_type.llvm.handle.to_integer().get_constant(field.bit_offset, @intFromBool(false)).to_value());
|
||||||
|
const or_value = module.llvm.builder.create_or(llvm_value, shifted_value);
|
||||||
|
llvm_value = or_value;
|
||||||
|
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
_ = converter.consume_character_if_match(',');
|
||||||
|
|
||||||
|
converter.skip_space();
|
||||||
|
} else {
|
||||||
|
const identifier = converter.parse_identifier();
|
||||||
|
if (string_to_enum(ValueKeyword, identifier)) |value_keyword| switch (value_keyword) {
|
||||||
|
._ => converter.report_error(),
|
||||||
|
.undefined => @trap(),
|
||||||
|
.zero => {
|
||||||
|
zero = true;
|
||||||
|
converter.skip_space();
|
||||||
|
_ = converter.consume_character_if_match(',');
|
||||||
|
converter.skip_space();
|
||||||
|
converter.expect_character(right_brace);
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
} else {
|
||||||
|
converter.report_error();
|
||||||
}
|
}
|
||||||
} else converter.report_error();
|
}
|
||||||
|
|
||||||
const field = bits.fields[field_index];
|
|
||||||
|
|
||||||
converter.skip_space();
|
|
||||||
|
|
||||||
converter.expect_character('=');
|
|
||||||
|
|
||||||
converter.skip_space();
|
|
||||||
|
|
||||||
const field_value = converter.parse_value(module, field.type, .value);
|
|
||||||
|
|
||||||
const extended_field_value = module.llvm.builder.create_zero_extend(field_value.llvm, bits.backing_type.llvm.handle);
|
|
||||||
const shifted_value = module.llvm.builder.create_shl(extended_field_value, bits.backing_type.llvm.handle.to_integer().get_constant(field.bit_offset, @intFromBool(false)).to_value());
|
|
||||||
const or_value = module.llvm.builder.create_or(llvm_value, shifted_value);
|
|
||||||
llvm_value = or_value;
|
|
||||||
|
|
||||||
converter.skip_space();
|
|
||||||
|
|
||||||
_ = converter.consume_character_if_match(',');
|
|
||||||
|
|
||||||
converter.skip_space();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field_count != bits.fields.len) {
|
if (field_count != bits.fields.len) {
|
||||||
// expect: 'zero' keyword
|
// expect: 'zero' keyword
|
||||||
@trap();
|
if (zero) {
|
||||||
|
// TODO: should we do anything?
|
||||||
|
} else {
|
||||||
|
@trap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
converter.expect_character(right_brace);
|
|
||||||
|
|
||||||
const value = module.values.add();
|
const value = module.values.add();
|
||||||
value.* = .{
|
value.* = .{
|
||||||
.llvm = llvm_value,
|
.llvm = llvm_value,
|
||||||
@ -3293,20 +3322,37 @@ const Converter = struct {
|
|||||||
'a'...'z', 'A'...'Z', '_' => b: {
|
'a'...'z', 'A'...'Z', '_' => b: {
|
||||||
if (module.current_function) |current_function| {
|
if (module.current_function) |current_function| {
|
||||||
const identifier = converter.parse_identifier();
|
const identifier = converter.parse_identifier();
|
||||||
if (lib.string.equal(identifier, "_")) {
|
|
||||||
return module.get_infer_or_ignore_value();
|
if (string_to_enum(ValueKeyword, identifier)) |value_keyword| switch (value_keyword) {
|
||||||
} else if (lib.string.equal(identifier, "undefined")) {
|
._ => return module.get_infer_or_ignore_value(),
|
||||||
const expected_ty = expected_type orelse converter.report_error();
|
.undefined => {
|
||||||
// TODO: cache poison
|
const expected_ty = expected_type orelse converter.report_error();
|
||||||
const value = module.values.add();
|
// TODO: cache poison
|
||||||
value.* = .{
|
const value = module.values.add();
|
||||||
.llvm = expected_ty.llvm.handle.get_poison(),
|
value.* = .{
|
||||||
.type = expected_ty,
|
.llvm = expected_ty.llvm.handle.get_poison(),
|
||||||
.bb = .instruction, // TODO
|
.type = expected_ty,
|
||||||
.lvalue = false,
|
.bb = .instruction, // TODO
|
||||||
.dereference_to_assign = false,
|
.lvalue = false,
|
||||||
};
|
.dereference_to_assign = false,
|
||||||
return value;
|
};
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
.zero => {
|
||||||
|
const ty = expected_type orelse converter.report_error();
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = switch (ty.bb) {
|
||||||
|
.bits => |bits| .{
|
||||||
|
.llvm = bits.backing_type.llvm.handle.to_integer().get_constant(0, @intFromBool(false)).to_value(),
|
||||||
|
.lvalue = false,
|
||||||
|
.dereference_to_assign = false,
|
||||||
|
.type = ty,
|
||||||
|
.bb = .bits_initialization,
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
},
|
||||||
} else {
|
} else {
|
||||||
const variable = if (current_function.value.bb.function.locals.find(identifier)) |local| local else if (current_function.value.bb.function.arguments.find(identifier)) |argument| argument else if (module.globals.find(identifier)) |global| global else converter.report_error();
|
const variable = if (current_function.value.bb.function.locals.find(identifier)) |local| local else if (current_function.value.bb.function.arguments.find(identifier)) |argument| argument else if (module.globals.find(identifier)) |global| global else converter.report_error();
|
||||||
|
|
||||||
|
@ -384,3 +384,7 @@ test "basic_enum" {
|
|||||||
test "return_type_builtin" {
|
test "return_type_builtin" {
|
||||||
try invsrc(@src());
|
try invsrc(@src());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "bits_zero" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
35
tests/bits_zero.bbb
Normal file
35
tests/bits_zero.bbb
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
require = fn (ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
S = bits
|
||||||
|
{
|
||||||
|
a: u1,
|
||||||
|
b: u1,
|
||||||
|
c: u1,
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn () s32
|
||||||
|
{
|
||||||
|
>a: S = zero;
|
||||||
|
|
||||||
|
require(a.a == 0);
|
||||||
|
require(a.b == 0);
|
||||||
|
require(a.c == 0);
|
||||||
|
|
||||||
|
>b: S = {
|
||||||
|
.a = 1,
|
||||||
|
.b = 1,
|
||||||
|
zero,
|
||||||
|
};
|
||||||
|
|
||||||
|
require(b.a == 1);
|
||||||
|
require(b.b == 1);
|
||||||
|
require(b.c == 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user