diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-12-18 19:40:26 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-12-18 19:40:26 -0500 |
| commit | a71fbe49cbbf068e00300533d5f3874efadb8c18 (patch) | |
| tree | 57c6c4150b910efce96251b14003d46f00cf6afa /src | |
| parent | f12fbce0f51d58b429afd8a359aeb8a3b27a4eb0 (diff) | |
| download | zig-a71fbe49cbbf068e00300533d5f3874efadb8c18.tar.gz zig-a71fbe49cbbf068e00300533d5f3874efadb8c18.zip | |
IR: add FnProto instruction
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 8 | ||||
| -rw-r--r-- | src/codegen.cpp | 1 | ||||
| -rw-r--r-- | src/ir.cpp | 86 | ||||
| -rw-r--r-- | src/ir_print.cpp | 14 |
4 files changed, 108 insertions, 1 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index c411bd114c..1a4a3fd694 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1448,6 +1448,7 @@ enum IrInstructionId { IrInstructionIdUnwrapErrPayload, IrInstructionIdErrWrapCode, IrInstructionIdErrWrapPayload, + IrInstructionIdFnProto, }; struct IrInstruction { @@ -2060,6 +2061,13 @@ struct IrInstructionErrWrapCode { LLVMValueRef tmp_ptr; }; +struct IrInstructionFnProto { + IrInstruction base; + + IrInstruction **param_types; + IrInstruction *return_type; +}; + enum LValPurpose { LValPurposeNone, LValPurposeAssign, diff --git a/src/codegen.cpp b/src/codegen.cpp index 6f3d433451..ef72fd76a0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2196,6 +2196,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdIntType: case IrInstructionIdMemberCount: case IrInstructionIdAlignOf: + case IrInstructionIdFnProto: zig_unreachable(); case IrInstructionIdReturn: return ir_render_return(g, executable, (IrInstructionReturn *)instruction); diff --git a/src/ir.cpp b/src/ir.cpp index 29b77476d1..14771f5321 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -439,6 +439,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapCode *) { return IrInstructionIdErrWrapCode; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionFnProto *) { + return IrInstructionIdFnProto; +} + template<typename T> static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { T *special_instruction = allocate<T>(1); @@ -1826,6 +1830,22 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc return new_instruction; } +static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction **param_types, IrInstruction *return_type) +{ + IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node); + instruction->param_types = param_types; + instruction->return_type = return_type; + + assert(source_node->type == NodeTypeFnProto); + for (size_t i = 0; i < source_node->data.fn_proto.params.length; i += 1) { + ir_ref_instruction(param_types[i]); + } + ir_ref_instruction(return_type); + + return &instruction->base; +} + static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { results[ReturnKindUnconditional] = 0; results[ReturnKindError] = 0; @@ -3894,6 +3914,28 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, return ir_build_const_type(irb, parent_scope, node, container_type); } +static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNode *node) { + assert(node->type == NodeTypeFnProto); + + size_t param_count = node->data.fn_proto.params.length; + IrInstruction **param_types = allocate<IrInstruction*>(param_count); + + for (size_t i = 0; i < param_count; i += 1) { + AstNode *param_node = node->data.fn_proto.params.at(i); + AstNode *type_node = param_node->data.param_decl.type; + IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); + if (type_value == irb->codegen->invalid_instruction) + return irb->codegen->invalid_instruction; + param_types[i] = type_value; + } + + IrInstruction *return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); + if (return_type == irb->codegen->invalid_instruction) + return irb->codegen->invalid_instruction; + + return ir_build_fn_proto(irb, parent_scope, node, param_types, return_type); +} + static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, LValPurpose lval) { @@ -3978,11 +4020,15 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop case NodeTypeContainerDecl: return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); case NodeTypeFnProto: + return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); case NodeTypeFnDef: + zig_panic("TODO IR gen NodeTypeFnDef"); case NodeTypeFnDecl: + zig_panic("TODO IR gen NodeTypeFnDecl"); case NodeTypeErrorValueDecl: + zig_panic("TODO IR gen NodeTypeErrorValueDecl"); case NodeTypeTypeDecl: - zig_panic("TODO more IR gen for node types"); + zig_panic("TODO IR gen NodeTypeTypeDecl"); case NodeTypeZeroesLiteral: zig_panic("TODO zeroes is deprecated"); } @@ -9377,6 +9423,41 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, } +static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { + AstNode *proto_node = instruction->base.source_node; + assert(proto_node->type == NodeTypeFnProto); + + FnTypeId fn_type_id = {0}; + init_fn_type_id(&fn_type_id, proto_node); + + bool depends_on_compile_var = false; + + for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { + AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); + assert(param_node->type == NodeTypeParamDecl); + + IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; + + FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; + param_info->is_noalias = param_node->data.param_decl.is_noalias; + param_info->type = ir_resolve_type(ira, param_type_value); + if (param_info->type->id == TypeTableEntryIdInvalid) + return ira->codegen->builtin_types.entry_invalid; + + depends_on_compile_var = depends_on_compile_var || param_type_value->static_value.depends_on_compile_var; + } + + IrInstruction *return_type_value = instruction->return_type->other; + fn_type_id.return_type = ir_resolve_type(ira, return_type_value); + if (fn_type_id.return_type->id == TypeTableEntryIdInvalid) + return ira->codegen->builtin_types.entry_invalid; + depends_on_compile_var = depends_on_compile_var || return_type_value->static_value.depends_on_compile_var; + + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); + out_val->data.x_type = get_fn_type(ira->codegen, &fn_type_id); + return ira->codegen->builtin_types.entry_type; +} + static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { switch (instruction->id) { case IrInstructionIdInvalid: @@ -9517,6 +9598,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction); case IrInstructionIdUnwrapErrPayload: return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction); + case IrInstructionIdFnProto: + return ir_analyze_instruction_fn_proto(ira, (IrInstructionFnProto *)instruction); case IrInstructionIdMaybeWrap: case IrInstructionIdErrWrapCode: case IrInstructionIdErrWrapPayload: @@ -9677,6 +9760,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdMaybeWrap: case IrInstructionIdErrWrapCode: case IrInstructionIdErrWrapPayload: + case IrInstructionIdFnProto: return false; case IrInstructionIdAsm: { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 298f72a202..1251a23c86 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -882,6 +882,17 @@ static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload fprintf(irp->f, ")"); } +static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) { + fprintf(irp->f, "fn("); + for (size_t i = 0; i < instruction->base.source_node->data.fn_proto.params.length; i += 1) { + if (i != 0) + fprintf(irp->f, ","); + ir_print_other_instruction(irp, instruction->param_types[i]); + } + fprintf(irp->f, ")->"); + ir_print_other_instruction(irp, instruction->return_type); +} + static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { ir_print_prefix(irp, instruction); switch (instruction->id) { @@ -1112,6 +1123,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdErrWrapPayload: ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction); break; + case IrInstructionIdFnProto: + ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction); + break; } fprintf(irp->f, "\n"); } |
