Merge pull request #7396 from kalsprite/union_const_backend

peel union constant to its variant
This commit is contained in:
Jeroen van Rijn
2026-08-20 01:51:05 +02:00
committed by GitHub
4 changed files with 88 additions and 22 deletions

View File

@@ -3439,7 +3439,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
cc.link_section = e->Variable.link_section;
ExactValue v = tav.value;
lbValue init = lb_const_value(m, e->type, v, tav.type, cc);
lbValue init = lb_const_value(m, e->type, v, lb_build_expr_original_const_type(decl->init_expr), cc);
LLVMDeleteGlobal(g.value);

View File

@@ -620,6 +620,10 @@ gb_internal LLVMValueRef lb_fill_fixed_capacity_dynamic_array(lbModule *m, i64 e
return llvm_const_named_struct(m, original_type, svalues, svalue_count);
}
// Defined in llvm_backend_expr.cpp. `U(3)` records the union as the expression's type, so a constant
// built from one has to be peeled back to the variant the checker resolved it to
gb_internal Type *lb_build_expr_original_const_type(Ast *expr);
gb_internal lbValue lb_const_value_bit_field(lbModule *m, Type *type, Ast *value_compound) {
ast_node(cl, CompoundLit, value_compound);
@@ -1411,7 +1415,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
}
if (lo == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
for (i64 k = lo; k < hi; k++) {
aos_values[value_index++] = val;
}
@@ -1426,7 +1430,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
i64 index = exact_value_to_i64(index_tav.value);
if (index == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
aos_values[value_index++] = val;
found = true;
break;
@@ -1481,7 +1485,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
for (isize i = 0; i < elem_count; i++) {
TypeAndValue tav = cl->elems[i]->tav;
GB_ASSERT(tav.mode != Addressing_Invalid);
aos_values[i] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
aos_values[i] = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(cl->elems[i]), cc).value;
}
for (isize i = elem_count; i < type->Struct.soa_count; i++) {
aos_values[i] = nullptr;
@@ -1560,7 +1564,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
}
if (lo == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
for (i64 k = lo; k < hi; k++) {
values[value_index++] = val;
}
@@ -1575,7 +1579,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
i64 index = exact_value_to_i64(index_tav.value);
if (index == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
values[value_index++] = val;
found = true;
break;
@@ -1603,7 +1607,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
if (is_type_tuple(tav.type)) {
elem_index += tav.type->Tuple.variables.count;
} else {
values[elem_index++] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
values[elem_index++] = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(cl->elems[i]), cc).value;
}
}
for (isize i = 0; i < type->Array.count; i++) {
@@ -1652,7 +1656,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
}
if (lo == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
for (i64 k = lo; k < hi; k++) {
values[value_index++] = val;
}
@@ -1667,7 +1671,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
i64 index = exact_value_to_i64(index_tav.value);
if (index == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
values[value_index++] = val;
found = true;
break;
@@ -1695,7 +1699,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
if (is_type_tuple(tav.type)) {
elem_index += tav.type->Tuple.variables.count;
} else {
values[elem_index++] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
values[elem_index++] = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(cl->elems[i]), cc).value;
}
}
for (isize i = 0; i < type->EnumeratedArray.count; i++) {
@@ -1744,7 +1748,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
if (lo == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
for (i64 k = lo; k < hi; k++) {
values[value_index++] = val;
}
@@ -1762,7 +1766,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
if (index == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
values[value_index++] = val;
found = true;
break;
@@ -1804,7 +1808,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
if (is_type_tuple(tav.type)) {
elem_index += tav.type->Tuple.variables.count;
} else {
values[elem_index++] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
values[elem_index++] = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(cl->elems[i]), cc).value;
}
}
for (isize i = 0; i < capacity; i++) {
@@ -1852,7 +1856,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
}
if (lo == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
for (i64 k = lo; k < hi; k++) {
values[value_index++] = val;
}
@@ -1867,7 +1871,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
i64 index = exact_value_to_i64(index_tav.value);
if (index == i) {
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
values[value_index++] = val;
found = true;
break;
@@ -1886,7 +1890,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
for (isize i = 0; i < elem_count; i++) {
TypeAndValue tav = cl->elems[i]->tav;
GB_ASSERT(tav.mode != Addressing_Invalid);
values[i] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
values[i] = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(cl->elems[i]), cc).value;
}
LLVMTypeRef et = lb_type(m, elem_type);
@@ -1971,7 +1975,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
i32 index = field_remapping[f->Variable.field_index];
if (elem_type_can_be_constant(f->type)) {
if (sel.index.count == 1) {
lbValue value = lb_const_value(m, f->type, tav.value, tav.type, cc);
lbValue value = lb_const_value(m, f->type, tav.value, lb_build_expr_original_const_type(fv->value), cc);
LLVMTypeRef value_type = LLVMTypeOf(value.value);
GB_ASSERT_MSG(lb_sizeof(value_type) == type_size_of(f->type), "%s vs %s", LLVMPrintTypeToString(value_type), type_to_string(f->type));
values[index] = value.value;
@@ -2081,7 +2085,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
if (elem_type_can_be_constant(f->type)) {
lbValue value = lb_const_value(m, f->type, tav.value, tav.type, cc);
lbValue value = lb_const_value(m, f->type, tav.value, lb_build_expr_original_const_type(cl->elems[i]), cc);
LLVMTypeRef value_type = LLVMTypeOf(value.value);
isize lb_sizeof_value_type = lb_sizeof(value_type);
isize type_size_of_f_type = type_size_of(f->type);
@@ -2222,7 +2226,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
for (i64 k = lo; k < hi; k++) {
i64 offset = matrix_row_major_index_to_offset(type, k);
GB_ASSERT(values[offset] == nullptr);
@@ -2234,7 +2238,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
i64 index = exact_value_to_i64(index_tav.value);
GB_ASSERT(index < max_count);
TypeAndValue tav = fv->value->tav;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
LLVMValueRef val = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(fv->value), cc).value;
i64 offset = matrix_row_major_index_to_offset(type, index);
GB_ASSERT(values[offset] == nullptr);
values[offset] = val;
@@ -2258,7 +2262,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Ty
GB_ASSERT(tav.mode != Addressing_Invalid);
i64 offset = 0;
offset = matrix_row_major_index_to_offset(type, i);
values[offset] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value;
values[offset] = lb_const_value(m, elem_type, tav.value, lb_build_expr_original_const_type(cl->elems[i]), cc).value;
}
for (isize i = 0; i < total_count; i++) {
if (values[i] == nullptr) {

View File

@@ -4471,6 +4471,14 @@ gb_internal Type *lb_build_expr_original_const_type(Ast *expr) {
Type *res = lb_build_expr_original_const_type(expr->CallExpr.args[0]);
return res;
}
} else if (expr->kind == Ast_Ident || expr->kind == Ast_SelectorExpr) {
// a named constant carries the union as its type, so follow it to the declaration the
// checker resolved: `C :: U(3)` is the variant `int`, not `U`
Entity *e = entity_of_node(expr);
if (e != nullptr && e->kind == Entity_Constant &&
e->decl_info != nullptr && e->decl_info->init_expr != nullptr) {
return lb_build_expr_original_const_type(e->decl_info->init_expr);
}
}
}
return type_of_expr(expr);
@@ -4850,7 +4858,7 @@ gb_internal lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *exp
GB_ASSERT(e != nullptr);
if (e->kind == Entity_Constant) {
Type *t = default_type(type_of_expr(expr));
lbValue v = lb_const_value(p->module, t, e->Constant.value, e->type, LB_CONST_CONTEXT_DEFAULT_NO_LOCAL);
lbValue v = lb_const_value(p->module, t, e->Constant.value, lb_build_expr_original_const_type(expr), LB_CONST_CONTEXT_DEFAULT_NO_LOCAL);
if (LLVMIsConstant(v.value)) {
lbAddr g = lb_add_global_generated_from_procedure(p, t, v);
return g;