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 {
14181418 IrInstructionIdMemset,
14191419 IrInstructionIdMemcpy,
14201420 IrInstructionIdSlice,
1421 IrInstructionIdMemberCount,
14211422};
14221423
14231424struct IrInstruction {
......@@ -1953,6 +1954,12 @@ struct IrInstructionSlice {
19531954 LLVMValueRef tmp_ptr;
19541955};
19551956
1957struct IrInstructionMemberCount {
1958 IrInstruction base;
1959
1960 IrInstruction *container;
1961};
1962
19561963enum LValPurpose {
19571964 LValPurposeNone,
19581965 LValPurposeAssign,
src/analyze.cpp+2-2
......@@ -1648,10 +1648,10 @@ static void resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
16481648 case TypeTableEntryIdStruct:
16491649 resolve_struct_type(g, tld_container->type_entry);
16501650 return;
1651 case ContainerKindEnum:
1651 case TypeTableEntryIdEnum:
16521652 resolve_enum_type(g, tld_container->type_entry);
16531653 return;
1654 case ContainerKindUnion:
1654 case TypeTableEntryIdUnion:
16551655 resolve_union_type(g, tld_container->type_entry);
16561656 return;
16571657 default:
src/codegen.cpp+1
......@@ -2094,6 +2094,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
20942094 case IrInstructionIdCUndef:
20952095 case IrInstructionIdEmbedFile:
20962096 case IrInstructionIdIntType:
2097 case IrInstructionIdMemberCount:
20972098 zig_unreachable();
20982099 case IrInstructionIdReturn:
20992100 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+52-19
......@@ -387,6 +387,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) {
387387 return IrInstructionIdSlice;
388388}
389389
390static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {
391 return IrInstructionIdMemberCount;
392}
393
390394template<typename T>
391395static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
392396 T *special_instruction = allocate<T>(1);
......@@ -1596,6 +1600,15 @@ static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_ins
15961600 return new_instruction;
15971601}
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
15991612static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
16001613 bool gen_error_defers, bool gen_maybe_defers)
16011614{
......@@ -2469,8 +2482,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
24692482
24702483 return ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value);
24712484 }
2472 case BuiltinFnIdAlignof:
24732485 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:
24742495 case BuiltinFnIdAddWithOverflow:
24752496 case BuiltinFnIdSubWithOverflow:
24762497 case BuiltinFnIdMulWithOverflow:
......@@ -8408,6 +8429,33 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
84088429 return return_type;
84098430}
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
84118459static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
84128460 switch (instruction->id) {
84138461 case IrInstructionIdInvalid:
......@@ -8530,6 +8578,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
85308578 return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction);
85318579 case IrInstructionIdSlice:
85328580 return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);
8581 case IrInstructionIdMemberCount:
8582 return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);
85338583 case IrInstructionIdCast:
85348584 case IrInstructionIdStructFieldPtr:
85358585 case IrInstructionIdEnumFieldPtr:
......@@ -8675,6 +8725,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
86758725 case IrInstructionIdBoolNot:
86768726 case IrInstructionIdAlloca:
86778727 case IrInstructionIdSlice:
8728 case IrInstructionIdMemberCount:
86788729 return false;
86798730 case IrInstructionIdAsm:
86808731 {
......@@ -8736,23 +8787,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
87368787// align_in_bytes, false);
87378788// }
87388789// }
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// }
87568790// case BuiltinFnIdBreakpoint:
87578791// mark_impure_fn(g, context, node);
87588792// return g->builtin_types.entry_void;
......@@ -8997,7 +9031,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
89979031// case BuiltinFnIdAlignof:
89989032// case BuiltinFnIdMinValue:
89999033// case BuiltinFnIdMaxValue:
9000// case BuiltinFnIdMemberCount:
90019034// // caught by constant expression eval codegen
90029035// zig_unreachable();
90039036// case BuiltinFnIdCompileVar:
src/ir_print.cpp+9
......@@ -806,6 +806,12 @@ static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {
806806 fprintf(irp->f, "const");
807807}
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
809815static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
810816 ir_print_prefix(irp, instruction);
811817 switch (instruction->id) {
......@@ -1000,6 +1006,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10001006 case IrInstructionIdSlice:
10011007 ir_print_slice(irp, (IrInstructionSlice *)instruction);
10021008 break;
1009 case IrInstructionIdMemberCount:
1010 ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);
1011 break;
10031012 }
10041013 fprintf(irp->f, "\n");
10051014}