mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-23 06:45:19 +00:00
Rudimentary support for some constant struct #raw_union
This commit is contained in:
@@ -9847,7 +9847,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
||||
if (t->Struct.is_raw_union) {
|
||||
if (cl->elems.count > 0) {
|
||||
// NOTE: unions cannot be constant
|
||||
is_constant = false;
|
||||
is_constant = elem_type_can_be_constant(t);
|
||||
|
||||
if (cl->elems[0]->kind != Ast_FieldValue) {
|
||||
gbString type_str = type_to_string(type);
|
||||
|
||||
@@ -1475,6 +1475,39 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
|
||||
}
|
||||
|
||||
if (is_type_raw_union(type)) {
|
||||
if (is_type_raw_union_constantable(type)) {
|
||||
GB_ASSERT(cl->elems.count == 1);
|
||||
GB_ASSERT(cl->elems[0]->kind == Ast_FieldValue);
|
||||
ast_node(fv, FieldValue, cl->elems[0]);
|
||||
Entity *f = entity_of_node(fv->field);
|
||||
|
||||
TypeAndValue tav = fv->value->tav;
|
||||
if (tav.value.kind != ExactValue_Invalid) {
|
||||
lbValue value = lb_const_value(m, f->type, tav.value, cc, f->type);
|
||||
|
||||
LLVMValueRef values[2];
|
||||
unsigned value_count = 0;
|
||||
|
||||
values[value_count++] = value.value;
|
||||
|
||||
i64 union_alignment = type_align_of(type);
|
||||
i64 value_alignment = type_align_of(f->type);
|
||||
i64 alignment = gb_max(gb_min(value_alignment, union_alignment), 1);
|
||||
|
||||
i64 union_size = type_size_of(type);
|
||||
i64 value_size = lb_sizeof(LLVMTypeOf(value.value));
|
||||
i64 padding = union_size-value_size;
|
||||
if (padding > 0) {
|
||||
LLVMTypeRef padding_type = lb_type_padding_filler(m, padding, alignment);
|
||||
values[value_count++] = LLVMConstNull(padding_type);
|
||||
}
|
||||
|
||||
LLVMValueRef res = LLVMConstStructInContext(m->ctx, values, value_count, true);
|
||||
|
||||
return {res, original_type};
|
||||
}
|
||||
|
||||
}
|
||||
return lb_const_nil(m, original_type);
|
||||
}
|
||||
|
||||
|
||||
@@ -2531,6 +2531,20 @@ gb_internal bool is_type_union_constantable(Type *type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
gb_internal bool is_type_raw_union_constantable(Type *type) {
|
||||
Type *bt = base_type(type);
|
||||
GB_ASSERT(bt->kind == Type_Struct);
|
||||
GB_ASSERT(bt->Struct.is_raw_union);
|
||||
|
||||
for (Entity *f : bt->Struct.fields) {
|
||||
if (!is_type_constant_type(f->type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
gb_internal bool elem_type_can_be_constant(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == t_invalid) {
|
||||
@@ -2540,7 +2554,7 @@ gb_internal bool elem_type_can_be_constant(Type *t) {
|
||||
return false;
|
||||
}
|
||||
if (is_type_raw_union(t)) {
|
||||
return false;
|
||||
return is_type_raw_union_constantable(t);
|
||||
}
|
||||
if (is_type_union(t)) {
|
||||
return is_type_union_constantable(t);
|
||||
@@ -2556,7 +2570,7 @@ gb_internal bool elem_cannot_be_constant(Type *t) {
|
||||
return !is_type_union_constantable(t);
|
||||
}
|
||||
if (is_type_raw_union(t)) {
|
||||
return true;
|
||||
return !is_type_raw_union_constantable(t);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user