diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-11-06 22:07:19 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-11-06 22:07:19 -0500 |
| commit | 634e8713c394bacfe080d03256d1dd4f9a43dd8c (patch) | |
| tree | 8fa396aa96acfa556217f83eb90ecb6a14d88c4d /src/ir.cpp | |
| parent | f0dafd3f209a342f055850108651545bea9b065b (diff) | |
| download | zig-634e8713c394bacfe080d03256d1dd4f9a43dd8c.tar.gz zig-634e8713c394bacfe080d03256d1dd4f9a43dd8c.zip | |
add @memberType and @memberName builtin functions
see #383
there is a plan to unify most of the reflection into 2
builtin functions, as outlined in the above issue,
but this gives us needed features for now, and we can
iterate on the design in future commits
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 556f255a0a..ae48c1d369 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -411,6 +411,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) { return IrInstructionIdMemberCount; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberType *) { + return IrInstructionIdMemberType; +} + +static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberName *) { + return IrInstructionIdMemberName; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) { return IrInstructionIdBreakpoint; } @@ -1783,6 +1791,32 @@ static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } +static IrInstruction *ir_build_member_type(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *container_type, IrInstruction *member_index) +{ + IrInstructionMemberType *instruction = ir_build_instruction<IrInstructionMemberType>(irb, scope, source_node); + instruction->container_type = container_type; + instruction->member_index = member_index; + + ir_ref_instruction(container_type, irb->current_basic_block); + ir_ref_instruction(member_index, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstruction *ir_build_member_name(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *container_type, IrInstruction *member_index) +{ + IrInstructionMemberName *instruction = ir_build_instruction<IrInstructionMemberName>(irb, scope, source_node); + instruction->container_type = container_type; + instruction->member_index = member_index; + + ir_ref_instruction(container_type, irb->current_basic_block); + ir_ref_instruction(member_index, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_breakpoint(IrBuilder *irb, Scope *scope, AstNode *source_node) { IrInstructionBreakpoint *instruction = ir_build_instruction<IrInstructionBreakpoint>(irb, scope, source_node); return &instruction->base; @@ -2727,6 +2761,22 @@ static IrInstruction *ir_instruction_membercount_get_dep(IrInstructionMemberCoun } } +static IrInstruction *ir_instruction_membertype_get_dep(IrInstructionMemberType *instruction, size_t index) { + switch (index) { + case 0: return instruction->container_type; + case 1: return instruction->member_index; + default: return nullptr; + } +} + +static IrInstruction *ir_instruction_membername_get_dep(IrInstructionMemberName *instruction, size_t index) { + switch (index) { + case 0: return instruction->container_type; + case 1: return instruction->member_index; + default: return nullptr; + } +} + static IrInstruction *ir_instruction_breakpoint_get_dep(IrInstructionBreakpoint *instruction, size_t index) { return nullptr; } @@ -3143,6 +3193,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_slice_get_dep((IrInstructionSlice *) instruction, index); case IrInstructionIdMemberCount: return ir_instruction_membercount_get_dep((IrInstructionMemberCount *) instruction, index); + case IrInstructionIdMemberType: + return ir_instruction_membertype_get_dep((IrInstructionMemberType *) instruction, index); + case IrInstructionIdMemberName: + return ir_instruction_membername_get_dep((IrInstructionMemberName *) instruction, index); case IrInstructionIdBreakpoint: return ir_instruction_breakpoint_get_dep((IrInstructionBreakpoint *) instruction, index); case IrInstructionIdReturnAddress: @@ -4379,6 +4433,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_member_count(irb, scope, node, arg0_value); } + case BuiltinFnIdMemberType: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + + return ir_build_member_type(irb, scope, node, arg0_value, arg1_value); + } + case BuiltinFnIdMemberName: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + + return ir_build_member_name(irb, scope, node, arg0_value, arg1_value); + } case BuiltinFnIdBreakpoint: return ir_build_breakpoint(irb, scope, node); case BuiltinFnIdReturnAddress: @@ -14337,6 +14421,90 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns return ira->codegen->builtin_types.entry_num_lit_int; } +static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstructionMemberType *instruction) { + IrInstruction *container_type_value = instruction->container_type->other; + TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); + if (type_is_invalid(container_type)) + return ira->codegen->builtin_types.entry_invalid; + + uint64_t member_index; + IrInstruction *index_value = instruction->member_index->other; + if (!ir_resolve_usize(ira, index_value, &member_index)) + return ira->codegen->builtin_types.entry_invalid; + + if (container_type->id == TypeTableEntryIdStruct) { + if (member_index >= container_type->data.structure.src_field_count) { + ir_add_error(ira, index_value, + buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", + member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); + return ira->codegen->builtin_types.entry_invalid; + } + TypeStructField *field = &container_type->data.structure.fields[member_index]; + + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + out_val->data.x_type = field->type_entry; + return ira->codegen->builtin_types.entry_type; + } else if (container_type->id == TypeTableEntryIdEnum) { + if (member_index >= container_type->data.enumeration.src_field_count) { + ir_add_error(ira, index_value, + buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", + member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count)); + return ira->codegen->builtin_types.entry_invalid; + } + TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; + + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + out_val->data.x_type = field->type_entry; + return ira->codegen->builtin_types.entry_type; + } else { + ir_add_error(ira, container_type_value, + buf_sprintf("type '%s' does not support @memberType", buf_ptr(&container_type->name))); + return ira->codegen->builtin_types.entry_invalid; + } +} + +static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstructionMemberName *instruction) { + IrInstruction *container_type_value = instruction->container_type->other; + TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); + if (type_is_invalid(container_type)) + return ira->codegen->builtin_types.entry_invalid; + + uint64_t member_index; + IrInstruction *index_value = instruction->member_index->other; + if (!ir_resolve_usize(ira, index_value, &member_index)) + return ira->codegen->builtin_types.entry_invalid; + + if (container_type->id == TypeTableEntryIdStruct) { + if (member_index >= container_type->data.structure.src_field_count) { + ir_add_error(ira, index_value, + buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", + member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); + return ira->codegen->builtin_types.entry_invalid; + } + TypeStructField *field = &container_type->data.structure.fields[member_index]; + + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + init_const_str_lit(ira->codegen, out_val, field->name); + return out_val->type; + } else if (container_type->id == TypeTableEntryIdEnum) { + if (member_index >= container_type->data.enumeration.src_field_count) { + ir_add_error(ira, index_value, + buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", + member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count)); + return ira->codegen->builtin_types.entry_invalid; + } + TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; + + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + init_const_str_lit(ira->codegen, out_val, field->name); + return out_val->type; + } else { + ir_add_error(ira, container_type_value, + buf_sprintf("type '%s' does not support @memberName", buf_ptr(&container_type->name))); + return ira->codegen->builtin_types.entry_invalid; + } +} + static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) { ir_build_breakpoint_from(&ira->new_irb, &instruction->base); return ira->codegen->builtin_types.entry_void; @@ -15606,6 +15774,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction); case IrInstructionIdMemberCount: return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); + case IrInstructionIdMemberType: + return ir_analyze_instruction_member_type(ira, (IrInstructionMemberType *)instruction); + case IrInstructionIdMemberName: + return ir_analyze_instruction_member_name(ira, (IrInstructionMemberName *)instruction); case IrInstructionIdBreakpoint: return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction); case IrInstructionIdReturnAddress: @@ -15815,6 +15987,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdBoolNot: case IrInstructionIdSlice: case IrInstructionIdMemberCount: + case IrInstructionIdMemberType: + case IrInstructionIdMemberName: case IrInstructionIdAlignOf: case IrInstructionIdReturnAddress: case IrInstructionIdFrameAddress: |
