aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-12-18 19:40:26 -0500
committerAndrew Kelley <superjoe30@gmail.com>2016-12-18 19:40:26 -0500
commita71fbe49cbbf068e00300533d5f3874efadb8c18 (patch)
tree57c6c4150b910efce96251b14003d46f00cf6afa /src
parentf12fbce0f51d58b429afd8a359aeb8a3b27a4eb0 (diff)
downloadzig-a71fbe49cbbf068e00300533d5f3874efadb8c18.tar.gz
zig-a71fbe49cbbf068e00300533d5f3874efadb8c18.zip
IR: add FnProto instruction
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp8
-rw-r--r--src/codegen.cpp1
-rw-r--r--src/ir.cpp86
-rw-r--r--src/ir_print.cpp14
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");
}