authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-26 14:25:52-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-26 14:25:52-04:00
loga0ae575ff8aef87d2dc4134c625f3a479b484b0f
treed7442193c336b49eb5a84a477a521ab85ad7d57f
parent40feecb3e468ca9fc3b5bcbe4b0a4aa30d10f226

codegen for enums chooses best order of tag and union fields

closes #396

3 files changed, 36 insertions(+), 23 deletions(-)

src/all_types.hpp+3-3
......@@ -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
994997struct TypeTableEntryEnumTag {
......@@ -2626,9 +2629,6 @@ static const size_t slice_len_index = 1;
26262629static const size_t maybe_child_index = 0;
26272630static const size_t maybe_null_index = 1;
26282631
2629static const size_t enum_gen_tag_index = 0;
2630static const size_t enum_gen_union_index = 1;
2631
26322632static const size_t err_union_err_index = 0;
26332633static const size_t err_union_payload_index = 1;
26342634
src/analyze.cpp+21-12
......@@ -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+12-8
......@@ -2250,6 +2250,11 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
22502250static 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))
......@@ -2257,7 +2262,7 @@ static LLVMValueRef ir_render_enum_field_ptr(CodeGen *g, IrExecutable *executabl
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 }