parent
b52bffcf8d
commit
cacba6f435
@ -1867,7 +1867,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
|
|||||||
uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
|
uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
|
||||||
|
|
||||||
TypeTableEntry *tag_type = union_type->data.unionation.tag_type;
|
TypeTableEntry *tag_type = union_type->data.unionation.tag_type;
|
||||||
if (tag_type == nullptr) {
|
if (tag_type == nullptr || tag_type->zero_bits) {
|
||||||
assert(most_aligned_union_member != nullptr);
|
assert(most_aligned_union_member != nullptr);
|
||||||
|
|
||||||
if (padding_in_bits > 0) {
|
if (padding_in_bits > 0) {
|
||||||
@ -2509,8 +2509,10 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
|
|||||||
|
|
||||||
if (create_enum_type) {
|
if (create_enum_type) {
|
||||||
ImportTableEntry *import = get_scope_import(scope);
|
ImportTableEntry *import = get_scope_import(scope);
|
||||||
uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref);
|
uint64_t tag_debug_size_in_bits = tag_type->zero_bits ? 0 :
|
||||||
uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref);
|
8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref);
|
||||||
|
uint64_t tag_debug_align_in_bits = tag_type->zero_bits ? 0 :
|
||||||
|
8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref);
|
||||||
// TODO get a more accurate debug scope
|
// TODO get a more accurate debug scope
|
||||||
ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
|
ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
|
||||||
ZigLLVMFileToScope(import->di_file), buf_ptr(&tag_type->name),
|
ZigLLVMFileToScope(import->di_file), buf_ptr(&tag_type->name),
|
||||||
@ -3451,7 +3453,6 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {
|
|||||||
TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) {
|
TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) {
|
||||||
assert(type_entry->id == TypeTableEntryIdUnion);
|
assert(type_entry->id == TypeTableEntryIdUnion);
|
||||||
assert(type_entry->data.unionation.zero_bits_known);
|
assert(type_entry->data.unionation.zero_bits_known);
|
||||||
assert(type_entry->data.unionation.gen_tag_index != SIZE_MAX);
|
|
||||||
for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
|
for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
|
||||||
TypeUnionField *field = &type_entry->data.unionation.fields[i];
|
TypeUnionField *field = &type_entry->data.unionation.fields[i];
|
||||||
if (bigint_cmp(&field->enum_field->value, tag) == CmpEQ) {
|
if (bigint_cmp(&field->enum_field->value, tag) == CmpEQ) {
|
||||||
|
21
src/ir.cpp
21
src/ir.cpp
@ -4769,7 +4769,8 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
|
static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
|
||||||
IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *target_value_ptr, IrInstruction *prong_value,
|
IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime,
|
||||||
|
IrInstruction *target_value_ptr, IrInstruction *prong_value,
|
||||||
ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
|
ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
|
||||||
{
|
{
|
||||||
assert(switch_node->type == NodeTypeSwitchExpr);
|
assert(switch_node->type == NodeTypeSwitchExpr);
|
||||||
@ -4786,7 +4787,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
|
|||||||
bool is_shadowable = false;
|
bool is_shadowable = false;
|
||||||
bool is_const = true;
|
bool is_const = true;
|
||||||
VariableTableEntry *var = ir_create_var(irb, var_symbol_node, scope,
|
VariableTableEntry *var = ir_create_var(irb, var_symbol_node, scope,
|
||||||
var_name, is_const, is_const, is_shadowable, is_comptime);
|
var_name, is_const, is_const, is_shadowable, var_is_comptime);
|
||||||
child_scope = var->child_scope;
|
child_scope = var->child_scope;
|
||||||
IrInstruction *var_value;
|
IrInstruction *var_value;
|
||||||
if (prong_value) {
|
if (prong_value) {
|
||||||
@ -4827,10 +4828,13 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
|||||||
ZigList<IrInstructionSwitchBrCase> cases = {0};
|
ZigList<IrInstructionSwitchBrCase> cases = {0};
|
||||||
|
|
||||||
IrInstruction *is_comptime;
|
IrInstruction *is_comptime;
|
||||||
|
IrInstruction *var_is_comptime;
|
||||||
if (ir_should_inline(irb->exec, scope)) {
|
if (ir_should_inline(irb->exec, scope)) {
|
||||||
is_comptime = ir_build_const_bool(irb, scope, node, true);
|
is_comptime = ir_build_const_bool(irb, scope, node, true);
|
||||||
|
var_is_comptime = is_comptime;
|
||||||
} else {
|
} else {
|
||||||
is_comptime = ir_build_test_comptime(irb, scope, node, target_value);
|
is_comptime = ir_build_test_comptime(irb, scope, node, target_value);
|
||||||
|
var_is_comptime = ir_build_test_comptime(irb, scope, node, target_value_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigList<IrInstruction *> incoming_values = {0};
|
ZigList<IrInstruction *> incoming_values = {0};
|
||||||
@ -4856,7 +4860,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
|||||||
IrBasicBlock *prev_block = irb->current_basic_block;
|
IrBasicBlock *prev_block = irb->current_basic_block;
|
||||||
ir_set_cursor_at_end_and_append_block(irb, else_block);
|
ir_set_cursor_at_end_and_append_block(irb, else_block);
|
||||||
if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
|
if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
|
||||||
is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
|
is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
|
||||||
{
|
{
|
||||||
return irb->codegen->invalid_instruction;
|
return irb->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
@ -4923,7 +4927,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
|||||||
|
|
||||||
ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
|
ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
|
||||||
if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
|
if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
|
||||||
is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
|
is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
|
||||||
{
|
{
|
||||||
return irb->codegen->invalid_instruction;
|
return irb->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
@ -4967,7 +4971,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
|||||||
IrBasicBlock *prev_block = irb->current_basic_block;
|
IrBasicBlock *prev_block = irb->current_basic_block;
|
||||||
ir_set_cursor_at_end_and_append_block(irb, prong_block);
|
ir_set_cursor_at_end_and_append_block(irb, prong_block);
|
||||||
if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
|
if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
|
||||||
is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))
|
is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))
|
||||||
{
|
{
|
||||||
return irb->codegen->invalid_instruction;
|
return irb->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
@ -12254,11 +12258,18 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
|||||||
}
|
}
|
||||||
TypeTableEntry *tag_type = target_type->data.unionation.tag_type;
|
TypeTableEntry *tag_type = target_type->data.unionation.tag_type;
|
||||||
assert(tag_type != nullptr);
|
assert(tag_type != nullptr);
|
||||||
|
assert(tag_type->id == TypeTableEntryIdEnum);
|
||||||
if (pointee_val) {
|
if (pointee_val) {
|
||||||
ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
|
ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
|
||||||
bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag);
|
bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag);
|
||||||
return tag_type;
|
return tag_type;
|
||||||
}
|
}
|
||||||
|
if (tag_type->data.enumeration.src_field_count == 1) {
|
||||||
|
ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
|
||||||
|
TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
|
||||||
|
bigint_init_bigint(&out_val->data.x_enum_tag, &only_field->value);
|
||||||
|
return tag_type;
|
||||||
|
}
|
||||||
|
|
||||||
IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
|
IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
|
||||||
switch_target_instruction->base.source_node, target_value_ptr);
|
switch_target_instruction->base.source_node, target_value_ptr);
|
||||||
|
@ -235,3 +235,30 @@ test "constant packed union" {
|
|||||||
fn testConstPackedUnion(expected_tokens: []const PackThis) {
|
fn testConstPackedUnion(expected_tokens: []const PackThis) {
|
||||||
assert(expected_tokens[0].StringLiteral == 1);
|
assert(expected_tokens[0].StringLiteral == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "switch on union with only 1 field" {
|
||||||
|
var r: PartialInst = undefined;
|
||||||
|
r = PartialInst.Compiled;
|
||||||
|
switch (r) {
|
||||||
|
PartialInst.Compiled => {
|
||||||
|
var z: PartialInstWithPayload = undefined;
|
||||||
|
z = PartialInstWithPayload { .Compiled = 1234 };
|
||||||
|
switch (z) {
|
||||||
|
PartialInstWithPayload.Compiled => |x| {
|
||||||
|
assert(x == 1234);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PartialInst = union(enum) {
|
||||||
|
Compiled,
|
||||||
|
};
|
||||||
|
|
||||||
|
const PartialInstWithPayload = union(enum) {
|
||||||
|
Compiled: i32,
|
||||||
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user