Pass 'basic_union'

This commit is contained in:
David Gonzalez Martin 2025-06-16 15:30:48 -06:00
parent 06395cc20e
commit a9b6bae43e

View File

@ -1407,6 +1407,22 @@ TypeAlias = struct
line: u32,
}
UnionField = struct
{
type: &Type,
name: []u8,
line: u32,
}
TypeUnion = struct
{
fields: []UnionField,
byte_size: u64,
biggest_field: u64,
byte_alignment: u32,
line: u32,
}
TypeContent = union
{
integer: TypeInteger,
@ -1418,6 +1434,7 @@ TypeContent = union
struct: TypeStruct,
bits: TypeBits,
alias: TypeAlias,
union: TypeUnion,
}
TypeLLVM = struct
@ -7115,7 +7132,88 @@ parse = fn (module: &Module) void
},
.union =>
{
#trap();
skip_space(module);
expect_character(module, left_brace);
>union_type: &Type = undefined;
if (type_forward_declaration)
{
union_type = type_forward_declaration;
}
else
{
union_type = new_type(module, {
.id = .forward_declaration,
.name = global_name,
.scope = &module.scope,
zero,
});
}
>field_count: u64 = 0;
>biggest_field: u64 = 0;
>alignment: u32 = 1;
>byte_size: u64 = 0;
>field_buffer: [64]UnionField = undefined;
while (1)
{
skip_space(module);
if (consume_character_if_match(module, right_brace))
{
break;
}
>field_index = field_count;
field_count += 1;
>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_alignment = get_byte_alignment(field_type);
>field_size = get_byte_size(field_type);
field_buffer[field_index] = {
.type = field_type,
.name = field_name,
.line = field_line,
};
biggest_field = #select(field_size > byte_size, field_index, biggest_field);
alignment = #max(alignment, field_alignment);
byte_size = #max(byte_size, field_size);
skip_space(module);
consume_character_if_match(module, ',');
}
skip_space(module);
consume_character_if_match(module, ';');
>fields = arena_allocate_slice[UnionField](module.arena, field_count);
memcpy(#pointer_cast(fields.pointer), #pointer_cast(&field_buffer), field_count * #byte_size(UnionField));
>biggest_size = get_byte_size(fields[biggest_field].type);
assert(biggest_size == byte_size);
union_type.content.union = {
.fields = fields,
.byte_size = byte_size,
.byte_alignment = alignment,
.line = global_line,
.biggest_field = biggest_field,
};
union_type.id = .union;
},
}
}
@ -15903,6 +16001,7 @@ names: [_][]u8 =
"integer_formats",
"for_each_int",
"bool_array",
"basic_union",
];
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32