Skip to content

Commit a0ae575

Browse files
committed
codegen for enums chooses best order of tag and union fields
closes #396
1 parent 40feecb commit a0ae575

File tree

3 files changed

+36
-23
lines changed

3 files changed

+36
-23
lines changed

src/all_types.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,9 @@ struct TypeTableEntryEnum {
989989

990990
bool zero_bits_loop_flag;
991991
bool zero_bits_known;
992+
993+
size_t gen_union_index;
994+
size_t gen_tag_index;
992995
};
993996

994997
struct TypeTableEntryEnumTag {
@@ -2626,9 +2629,6 @@ static const size_t slice_len_index = 1;
26262629
static const size_t maybe_child_index = 0;
26272630
static const size_t maybe_null_index = 1;
26282631

2629-
static const size_t enum_gen_tag_index = 0;
2630-
static const size_t enum_gen_union_index = 1;
2631-
26322632
static const size_t err_union_err_index = 0;
26332633
static const size_t err_union_payload_index = 1;
26342634

src/analyze.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13061306
TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);
13071307
enum_type->data.enumeration.tag_type = tag_type_entry;
13081308

1309+
uint64_t align_of_tag_in_bits = 8*LLVMPreferredAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
1310+
13091311
if (most_aligned_union_member) {
13101312
// create llvm type for union
13111313
uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
@@ -1329,11 +1331,18 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13291331
assert(8*LLVMPreferredAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits);
13301332
assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);
13311333

1334+
if (align_of_tag_in_bits >= biggest_align_in_bits) {
1335+
enum_type->data.enumeration.gen_tag_index = 0;
1336+
enum_type->data.enumeration.gen_union_index = 1;
1337+
} else {
1338+
enum_type->data.enumeration.gen_union_index = 0;
1339+
enum_type->data.enumeration.gen_tag_index = 1;
1340+
}
1341+
13321342
// create llvm type for root struct
1333-
LLVMTypeRef root_struct_element_types[] = {
1334-
tag_type_entry->type_ref,
1335-
union_type_ref,
1336-
};
1343+
LLVMTypeRef root_struct_element_types[2];
1344+
root_struct_element_types[enum_type->data.enumeration.gen_tag_index] = tag_type_entry->type_ref;
1345+
root_struct_element_types[enum_type->data.enumeration.gen_union_index] = union_type_ref;
13371346
LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false);
13381347

13391348
// create debug type for tag
@@ -1353,7 +1362,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13531362
gen_field_count, 0, "");
13541363

13551364
// create debug types for members of root struct
1356-
uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, 0);
1365+
uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref,
1366+
enum_type->data.enumeration.gen_tag_index);
13571367
ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
13581368
ZigLLVMTypeToScope(enum_type->di_type), "tag_field",
13591369
import->di_file, (unsigned)(decl_node->line + 1),
@@ -1362,7 +1372,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13621372
tag_offset_in_bits,
13631373
0, tag_di_type);
13641374

1365-
uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, 1);
1375+
uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref,
1376+
enum_type->data.enumeration.gen_union_index);
13661377
ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
13671378
ZigLLVMTypeToScope(enum_type->di_type), "union_field",
13681379
import->di_file, (unsigned)(decl_node->line + 1),
@@ -1372,11 +1383,9 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13721383
0, union_di_type);
13731384

13741385
// create debug type for root struct
1375-
ZigLLVMDIType *di_root_members[] = {
1376-
tag_member_di_type,
1377-
union_member_di_type,
1378-
};
1379-
1386+
ZigLLVMDIType *di_root_members[2];
1387+
di_root_members[enum_type->data.enumeration.gen_tag_index] = tag_member_di_type;
1388+
di_root_members[enum_type->data.enumeration.gen_union_index] = union_member_di_type;
13801389

13811390
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, enum_type->type_ref);
13821391
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref);
@@ -1396,7 +1405,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13961405

13971406
// create debug type for tag
13981407
uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);
1399-
uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, tag_type_entry->type_ref);
1408+
uint64_t tag_debug_align_in_bits = 8*LLVMPreferredAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);
14001409
ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
14011410
ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name),
14021411
import->di_file, (unsigned)(decl_node->line + 1),

src/codegen.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,14 +2250,19 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
22502250
static LLVMValueRef ir_render_enum_field_ptr(CodeGen *g, IrExecutable *executable,
22512251
IrInstructionEnumFieldPtr *instruction)
22522252
{
2253+
TypeTableEntry *enum_ptr_type = instruction->enum_ptr->value.type;
2254+
assert(enum_ptr_type->id == TypeTableEntryIdPointer);
2255+
TypeTableEntry *enum_type = enum_ptr_type->data.pointer.child_type;
2256+
assert(enum_type->id == TypeTableEntryIdEnum);
2257+
22532258
TypeEnumField *field = instruction->field;
22542259

22552260
if (!type_has_bits(field->type_entry))
22562261
return nullptr;
22572262

22582263
LLVMValueRef enum_ptr = ir_llvm_value(g, instruction->enum_ptr);
22592264
LLVMTypeRef field_type_ref = LLVMPointerType(field->type_entry->type_ref, 0);
2260-
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, enum_ptr, enum_gen_union_index, "");
2265+
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, enum_ptr, enum_type->data.enumeration.gen_union_index, "");
22612266
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
22622267

22632268
return bitcasted_union_field_ptr;
@@ -3112,7 +3117,7 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI
31123117
if (enum_type->data.enumeration.gen_field_count == 0)
31133118
return enum_val;
31143119

3115-
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_gen_tag_index, "");
3120+
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_type->data.enumeration.gen_tag_index, "");
31163121
return get_handle_value(g, tag_field_ptr, tag_type, false);
31173122
}
31183123

@@ -3127,13 +3132,13 @@ static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, Ir
31273132

31283133
LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
31293134

3130-
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_gen_tag_index, "");
3135+
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_tag_index, "");
31313136
LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
31323137

31333138
TypeTableEntry *union_val_type = instruction->field->type_entry;
31343139
if (type_has_bits(union_val_type)) {
31353140
LLVMValueRef new_union_val = ir_llvm_value(g, instruction->init_value);
3136-
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_gen_union_index, "");
3141+
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_union_index, "");
31373142
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
31383143
LLVMPointerType(union_val_type->type_ref, 0), "");
31393144

@@ -3687,10 +3692,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
36873692
} else {
36883693
union_value = LLVMGetUndef(union_type_ref);
36893694
}
3690-
LLVMValueRef fields[] = {
3691-
tag_value,
3692-
union_value,
3693-
};
3695+
LLVMValueRef fields[2];
3696+
fields[type_entry->data.enumeration.gen_tag_index] = tag_value;
3697+
fields[type_entry->data.enumeration.gen_union_index] = union_value;
36943698
return LLVMConstStruct(fields, 2, false);
36953699
}
36963700
}

0 commit comments

Comments
 (0)