authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-12 01:59:55-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-12 01:59:55-05:00
log76a849b1f2c1bb57de4baf8dfd49fe9f9e2340f3
tree60b863f9ce40d7514bbdf6888a7dcd01e5c1e644
parentef63bc9cca6370f03d76a2a19dd7cdd7e23270d4

IR: implement memberCount builtin


5 files changed, 71 insertions(+), 21 deletions(-)

src/all_types.hpp+7
...@@ -1418,6 +1418,7 @@ enum IrInstructionId {...@@ -1418,6 +1418,7 @@ enum IrInstructionId {
1418 IrInstructionIdMemset,1418 IrInstructionIdMemset,
1419 IrInstructionIdMemcpy,1419 IrInstructionIdMemcpy,
1420 IrInstructionIdSlice,1420 IrInstructionIdSlice,
1421 IrInstructionIdMemberCount,
1421};1422};
14221423
1423struct IrInstruction {1424struct IrInstruction {
...@@ -1953,6 +1954,12 @@ struct IrInstructionSlice {...@@ -1953,6 +1954,12 @@ struct IrInstructionSlice {
1953 LLVMValueRef tmp_ptr;1954 LLVMValueRef tmp_ptr;
1954};1955};
19551956
1957struct IrInstructionMemberCount {
1958 IrInstruction base;
1959
1960 IrInstruction *container;
1961};
1962
1956enum LValPurpose {1963enum LValPurpose {
1957 LValPurposeNone,1964 LValPurposeNone,
1958 LValPurposeAssign,1965 LValPurposeAssign,
src/analyze.cpp+2-2
...@@ -1648,10 +1648,10 @@ static void resolve_decl_container(CodeGen *g, TldContainer *tld_container) {...@@ -1648,10 +1648,10 @@ static void resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
1648 case TypeTableEntryIdStruct:1648 case TypeTableEntryIdStruct:
1649 resolve_struct_type(g, tld_container->type_entry);1649 resolve_struct_type(g, tld_container->type_entry);
1650 return;1650 return;
1651 case ContainerKindEnum:1651 case TypeTableEntryIdEnum:
1652 resolve_enum_type(g, tld_container->type_entry);1652 resolve_enum_type(g, tld_container->type_entry);
1653 return;1653 return;
1654 case ContainerKindUnion:1654 case TypeTableEntryIdUnion:
1655 resolve_union_type(g, tld_container->type_entry);1655 resolve_union_type(g, tld_container->type_entry);
1656 return;1656 return;
1657 default:1657 default:
src/codegen.cpp+1
...@@ -2094,6 +2094,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2094,6 +2094,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2094 case IrInstructionIdCUndef:2094 case IrInstructionIdCUndef:
2095 case IrInstructionIdEmbedFile:2095 case IrInstructionIdEmbedFile:
2096 case IrInstructionIdIntType:2096 case IrInstructionIdIntType:
2097 case IrInstructionIdMemberCount:
2097 zig_unreachable();2098 zig_unreachable();
2098 case IrInstructionIdReturn:2099 case IrInstructionIdReturn:
2099 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2100 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+52-19
...@@ -387,6 +387,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) {...@@ -387,6 +387,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) {
387 return IrInstructionIdSlice;387 return IrInstructionIdSlice;
388}388}
389389
390static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {
391 return IrInstructionIdMemberCount;
392}
393
390template<typename T>394template<typename T>
391static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {395static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
392 T *special_instruction = allocate<T>(1);396 T *special_instruction = allocate<T>(1);
...@@ -1596,6 +1600,15 @@ static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_ins...@@ -1596,6 +1600,15 @@ static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_ins
1596 return new_instruction;1600 return new_instruction;
1597}1601}
15981602
1603static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *container) {
1604 IrInstructionMemberCount *instruction = ir_build_instruction<IrInstructionMemberCount>(irb, scope, source_node);
1605 instruction->container = container;
1606
1607 ir_ref_instruction(container);
1608
1609 return &instruction->base;
1610}
1611
1599static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,1612static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
1600 bool gen_error_defers, bool gen_maybe_defers)1613 bool gen_error_defers, bool gen_maybe_defers)
1601{1614{
...@@ -2469,8 +2482,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -2469,8 +2482,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
24692482
2470 return ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value);2483 return ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value);
2471 }2484 }
2472 case BuiltinFnIdAlignof:
2473 case BuiltinFnIdMemberCount:2485 case BuiltinFnIdMemberCount:
2486 {
2487 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
2488 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
2489 if (arg0_value == irb->codegen->invalid_instruction)
2490 return arg0_value;
2491
2492 return ir_build_member_count(irb, scope, node, arg0_value);
2493 }
2494 case BuiltinFnIdAlignof:
2474 case BuiltinFnIdAddWithOverflow:2495 case BuiltinFnIdAddWithOverflow:
2475 case BuiltinFnIdSubWithOverflow:2496 case BuiltinFnIdSubWithOverflow:
2476 case BuiltinFnIdMulWithOverflow:2497 case BuiltinFnIdMulWithOverflow:
...@@ -8408,6 +8429,33 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -8408,6 +8429,33 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
8408 return return_type;8429 return return_type;
8409}8430}
84108431
8432static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) {
8433 IrInstruction *container = instruction->container->other;
8434 if (container->type_entry->id == TypeTableEntryIdInvalid)
8435 return ira->codegen->builtin_types.entry_invalid;
8436 TypeTableEntry *container_type = ir_resolve_type(ira, container);
8437 TypeTableEntry *canon_type = get_underlying_type(container_type);
8438
8439 uint64_t result;
8440 if (canon_type->id == TypeTableEntryIdInvalid) {
8441 return ira->codegen->builtin_types.entry_invalid;
8442 } else if (canon_type->id == TypeTableEntryIdEnum) {
8443 result = canon_type->data.enumeration.src_field_count;
8444 } else if (canon_type->id == TypeTableEntryIdStruct) {
8445 result = canon_type->data.structure.src_field_count;
8446 } else if (canon_type->id == TypeTableEntryIdUnion) {
8447 result = canon_type->data.unionation.src_field_count;
8448 } else {
8449 ir_add_error(ira, &instruction->base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name)));
8450 return ira->codegen->builtin_types.entry_invalid;
8451 }
8452
8453 bool depends_on_compile_var = container->static_value.depends_on_compile_var;
8454 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
8455 bignum_init_unsigned(&out_val->data.x_bignum, result);
8456 return ira->codegen->builtin_types.entry_num_lit_int;
8457}
8458
8411static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {8459static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
8412 switch (instruction->id) {8460 switch (instruction->id) {
8413 case IrInstructionIdInvalid:8461 case IrInstructionIdInvalid:
...@@ -8530,6 +8578,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -8530,6 +8578,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
8530 return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction);8578 return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction);
8531 case IrInstructionIdSlice:8579 case IrInstructionIdSlice:
8532 return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);8580 return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);
8581 case IrInstructionIdMemberCount:
8582 return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);
8533 case IrInstructionIdCast:8583 case IrInstructionIdCast:
8534 case IrInstructionIdStructFieldPtr:8584 case IrInstructionIdStructFieldPtr:
8535 case IrInstructionIdEnumFieldPtr:8585 case IrInstructionIdEnumFieldPtr:
...@@ -8675,6 +8725,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -8675,6 +8725,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
8675 case IrInstructionIdBoolNot:8725 case IrInstructionIdBoolNot:
8676 case IrInstructionIdAlloca:8726 case IrInstructionIdAlloca:
8677 case IrInstructionIdSlice:8727 case IrInstructionIdSlice:
8728 case IrInstructionIdMemberCount:
8678 return false;8729 return false;
8679 case IrInstructionIdAsm:8730 case IrInstructionIdAsm:
8680 {8731 {
...@@ -8736,23 +8787,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -8736,23 +8787,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
8736// align_in_bytes, false);8787// align_in_bytes, false);
8737// }8788// }
8738// }8789// }
8739// case BuiltinFnIdMemberCount:
8740// {
8741// AstNode *type_node = node->data.fn_call_expr.params.at(0);
8742// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
8743//
8744// if (type_entry->id == TypeTableEntryIdInvalid) {
8745// return type_entry;
8746// } else if (type_entry->id == TypeTableEntryIdEnum) {
8747// uint64_t value_count = type_entry->data.enumeration.src_field_count;
8748// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
8749// value_count, false);
8750// } else {
8751// add_node_error(g, node,
8752// buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
8753// return g->builtin_types.entry_invalid;
8754// }
8755// }
8756// case BuiltinFnIdBreakpoint:8790// case BuiltinFnIdBreakpoint:
8757// mark_impure_fn(g, context, node);8791// mark_impure_fn(g, context, node);
8758// return g->builtin_types.entry_void;8792// return g->builtin_types.entry_void;
...@@ -8997,7 +9031,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -8997,7 +9031,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
8997// case BuiltinFnIdAlignof:9031// case BuiltinFnIdAlignof:
8998// case BuiltinFnIdMinValue:9032// case BuiltinFnIdMinValue:
8999// case BuiltinFnIdMaxValue:9033// case BuiltinFnIdMaxValue:
9000// case BuiltinFnIdMemberCount:
9001// // caught by constant expression eval codegen9034// // caught by constant expression eval codegen
9002// zig_unreachable();9035// zig_unreachable();
9003// case BuiltinFnIdCompileVar:9036// case BuiltinFnIdCompileVar:
src/ir_print.cpp+9
...@@ -806,6 +806,12 @@ static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {...@@ -806,6 +806,12 @@ static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {
806 fprintf(irp->f, "const");806 fprintf(irp->f, "const");
807}807}
808808
809static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) {
810 fprintf(irp->f, "@memberCount(");
811 ir_print_other_instruction(irp, instruction->container);
812 fprintf(irp->f, ")");
813}
814
809static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {815static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
810 ir_print_prefix(irp, instruction);816 ir_print_prefix(irp, instruction);
811 switch (instruction->id) {817 switch (instruction->id) {
...@@ -1000,6 +1006,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1000,6 +1006,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1000 case IrInstructionIdSlice:1006 case IrInstructionIdSlice:
1001 ir_print_slice(irp, (IrInstructionSlice *)instruction);1007 ir_print_slice(irp, (IrInstructionSlice *)instruction);
1002 break;1008 break;
1009 case IrInstructionIdMemberCount:
1010 ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);
1011 break;
1003 }1012 }
1004 fprintf(irp->f, "\n");1013 fprintf(irp->f, "\n");
1005}1014}