Pass 'bits'
This commit is contained in:
parent
a99423417d
commit
25849592b3
216
src/compiler.bbb
216
src/compiler.bbb
@ -1392,6 +1392,14 @@ TypeStruct = struct
|
||||
next: &Type,
|
||||
}
|
||||
|
||||
TypeBits = struct
|
||||
{
|
||||
fields: []Field,
|
||||
backing_type: &Type,
|
||||
line: u32,
|
||||
is_implicit_backing_type: u1,
|
||||
}
|
||||
|
||||
TypeContent = union
|
||||
{
|
||||
integer: TypeInteger,
|
||||
@ -1401,6 +1409,7 @@ TypeContent = union
|
||||
enum_array: TypeEnumArray,
|
||||
enum: TypeEnum,
|
||||
struct: TypeStruct,
|
||||
bits: TypeBits,
|
||||
}
|
||||
|
||||
TypeLLVM = struct
|
||||
@ -1926,6 +1935,22 @@ ValueVaArg = struct
|
||||
type: &Type,
|
||||
}
|
||||
|
||||
AggregateInitializationElement = struct
|
||||
{
|
||||
name: []u8,
|
||||
value: &Value,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
ValueAggregateInitialization = struct
|
||||
{
|
||||
elements: []AggregateInitializationElement,
|
||||
scope: &Scope,
|
||||
is_constant: u1,
|
||||
is_zero: u1,
|
||||
}
|
||||
|
||||
ValueContent = union
|
||||
{
|
||||
constant_integer: ValueConstantInteger,
|
||||
@ -1942,6 +1967,7 @@ ValueContent = union
|
||||
field_access: ValueFieldAccess,
|
||||
string_literal: []u8,
|
||||
va_arg: ValueVaArg,
|
||||
aggregate_initialization: ValueAggregateInitialization,
|
||||
}
|
||||
|
||||
ValueKind = enum
|
||||
@ -4769,6 +4795,94 @@ reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: [
|
||||
}
|
||||
}
|
||||
|
||||
parse_aggregate_initialization = fn (module: &Module, scope: &Scope, builder: ValueBuilder, end_ch: u8) &Value
|
||||
{
|
||||
skip_space(module);
|
||||
|
||||
>element_buffer: [64]AggregateInitializationElement = undefined;
|
||||
>field_count: u64 = 0;
|
||||
>is_zero: u1 = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
skip_space(module);
|
||||
|
||||
if (consume_character_if_match(module, end_ch))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
>field_index = field_count;
|
||||
>checkpoint = get_checkpoint(module);
|
||||
|
||||
if (consume_character_if_match(module, '.'))
|
||||
{
|
||||
>name = parse_identifier(module);
|
||||
skip_space(module);
|
||||
expect_character(module, '=');
|
||||
skip_space(module);
|
||||
|
||||
>line = get_line(module);
|
||||
>column = get_column(module);
|
||||
|
||||
>value = parse_value(module, scope, zero);
|
||||
skip_space(module);
|
||||
consume_character_if_match(module, ',');
|
||||
|
||||
element_buffer[field_index] = {
|
||||
.name = name,
|
||||
.value = value,
|
||||
.line = line,
|
||||
.column = column,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
>token = tokenize(module);
|
||||
is_zero = token.id == .value_keyword and token.content.value_keyword == .zero;
|
||||
|
||||
if (is_zero)
|
||||
{
|
||||
skip_space(module);
|
||||
|
||||
if (consume_character_if_match(module, ','))
|
||||
{
|
||||
skip_space(module);
|
||||
}
|
||||
|
||||
expect_character(module, right_brace);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
}
|
||||
|
||||
field_count += 1;
|
||||
}
|
||||
|
||||
>elements = arena_allocate_slice[AggregateInitializationElement](module.arena, field_count);
|
||||
memcpy(#pointer_cast(elements.pointer), #pointer_cast(&element_buffer), field_count * #byte_size(AggregateInitializationElement));
|
||||
|
||||
>result = new_value(module);
|
||||
result.& = {
|
||||
.content = {
|
||||
.aggregate_initialization = {
|
||||
.elements = elements,
|
||||
.scope = scope,
|
||||
.is_constant = 0,
|
||||
.is_zero = is_zero,
|
||||
},
|
||||
},
|
||||
.id = .aggregate_initialization,
|
||||
.kind = builder.kind,
|
||||
zero,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
{
|
||||
>token = builder.token;
|
||||
@ -5090,7 +5204,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
},
|
||||
.left_brace =>
|
||||
{
|
||||
#trap();
|
||||
result = parse_aggregate_initialization(module, scope, builder, right_brace);
|
||||
},
|
||||
.value_keyword =>
|
||||
{
|
||||
@ -5994,7 +6108,100 @@ parse = fn (module: &Module) void
|
||||
{
|
||||
.bits =>
|
||||
{
|
||||
#trap();
|
||||
>is_implicit_type = module.content[module.offset] == left_brace;
|
||||
|
||||
>backing_type: &Type = zero;
|
||||
|
||||
if (!is_implicit_type)
|
||||
{
|
||||
backing_type = parse_type(module, scope);
|
||||
}
|
||||
|
||||
skip_space(module);
|
||||
expect_character(module, left_brace);
|
||||
|
||||
>field_buffer: [64]Field = undefined;
|
||||
>field_bit_offset: u64 = 0;
|
||||
>field_count: u64 = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
skip_space(module);
|
||||
|
||||
if (consume_character_if_match(module, right_brace))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
>field_line = get_line(module);
|
||||
>field_name = parse_identifier(module);
|
||||
|
||||
skip_space(module);
|
||||
expect_character(module, ':');
|
||||
skip_space(module);
|
||||
|
||||
>field_type = parse_type(module, scope);
|
||||
|
||||
>field_bit_count = get_bit_size(field_type);
|
||||
|
||||
skip_space(module);
|
||||
|
||||
consume_character_if_match(module, ',');
|
||||
|
||||
field_buffer[field_count] = {
|
||||
.name = field_name,
|
||||
.type = field_type,
|
||||
.offset = field_bit_offset,
|
||||
.line = field_line,
|
||||
};
|
||||
|
||||
field_bit_offset += field_bit_count;
|
||||
field_count += 1;
|
||||
}
|
||||
|
||||
consume_character_if_match(module, ';');
|
||||
|
||||
>fields = arena_allocate_slice[Field](module.arena, field_count);
|
||||
memcpy(#pointer_cast(fields.pointer), #pointer_cast(&field_buffer), field_count * #byte_size(Field));
|
||||
|
||||
>needed_bit_count = #max(next_power_of_two(field_bit_offset), 8);
|
||||
if (needed_bit_count > #integer_max(u32))
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
>bit_count = needed_bit_count;
|
||||
|
||||
if (!backing_type)
|
||||
{
|
||||
backing_type = integer_type(module, { .bit_count = bit_count, .signed = 0 });
|
||||
}
|
||||
|
||||
if (backing_type.id != .integer)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
>backing_type_bit_size = get_bit_size(backing_type);
|
||||
if (backing_type_bit_size > 64)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
new_type(module, {
|
||||
.content = {
|
||||
.bits = {
|
||||
.fields = fields,
|
||||
.backing_type = backing_type,
|
||||
.line = global_line,
|
||||
.is_implicit_backing_type = is_implicit_type,
|
||||
},
|
||||
},
|
||||
.id = .bits,
|
||||
.name = global_name,
|
||||
.scope = &module.scope,
|
||||
zero,
|
||||
});
|
||||
},
|
||||
.enum =>
|
||||
{
|
||||
@ -8494,6 +8701,10 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
|
||||
value_type = value.content.va_arg.type;
|
||||
typecheck(module, expected_type, value_type);
|
||||
},
|
||||
.aggregate_initialization =>
|
||||
{
|
||||
#trap();
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -11869,6 +12080,7 @@ names: [_][]u8 = [
|
||||
"argv",
|
||||
"assignment_operators",
|
||||
"not_pointer",
|
||||
"bits",
|
||||
];
|
||||
|
||||
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32
|
||||
|
@ -3365,7 +3365,8 @@ void parse(Module* module)
|
||||
{
|
||||
skip_space(module);
|
||||
|
||||
if (consume_character_if_match(module, right_brace)) {
|
||||
if (consume_character_if_match(module, right_brace))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user