Commit 05de70017d
Changed files (6)
src/all_types.hpp
@@ -1447,6 +1447,8 @@ enum IrInstructionId {
IrInstructionIdToPtrType,
IrInstructionIdPtrTypeChild,
IrInstructionIdSetFnTest,
+ IrInstructionIdArrayType,
+ IrInstructionIdSliceType,
};
struct IrInstruction {
@@ -1696,6 +1698,20 @@ struct IrInstructionSetFnTest {
IrInstruction *is_test;
};
+struct IrInstructionArrayType {
+ IrInstruction base;
+
+ IrInstruction *size;
+ IrInstruction *child_type;
+};
+
+struct IrInstructionSliceType {
+ IrInstruction base;
+
+ bool is_const;
+ IrInstruction *child_type;
+};
+
enum LValPurpose {
LValPurposeNone,
LValPurposeAssign,
src/analyze.cpp
@@ -369,7 +369,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
}
}
-static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
+TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
if (child_type->error_parent) {
return child_type->error_parent;
} else {
@@ -2582,7 +2582,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
&fn_table_entry->analyzed_executable, expected_type, fn_proto->return_type);
node->data.fn_def.implicit_return_type = block_return_type;
- if (g->verbose) {
+ if (block_return_type->id != TypeTableEntryIdInvalid && g->verbose) {
fprintf(stderr, "fn %s { // (analyzed)\n", buf_ptr(&fn_table_entry->symbol_name));
ir_print(stderr, &fn_table_entry->analyzed_executable, 4);
fprintf(stderr, "}\n");
src/analyze.hpp
@@ -31,6 +31,7 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
ContainerKind kind, AstNode *decl_node, const char *name);
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
+TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
bool handle_is_ptr(TypeTableEntry *type_entry);
void find_libc_include_path(CodeGen *g);
void find_libc_lib_path(CodeGen *g);
src/codegen.cpp
@@ -2966,6 +2966,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdPtrTypeChild:
case IrInstructionIdFieldPtr:
case IrInstructionIdSetFnTest:
+ case IrInstructionIdArrayType:
+ case IrInstructionIdSliceType:
zig_unreachable();
case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp
@@ -189,6 +189,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
return IrInstructionIdSetFnTest;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
+ return IrInstructionIdArrayType;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {
+ return IrInstructionIdSliceType;
+}
+
template<typename T>
static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -716,19 +724,30 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node,
return &instruction->base;
}
-//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
-// size_t result = 0;
-// while (inner_block != outer_block) {
-// if (inner_block->node->type == NodeTypeDefer &&
-// (inner_block->node->data.defer.kind == ReturnKindError ||
-// inner_block->node->data.defer.kind == ReturnKindMaybe))
-// {
-// result += 1;
-// }
-// inner_block = inner_block->parent;
-// }
-// return result;
-//}
+static IrInstruction *ir_build_array_type(IrBuilder *irb, AstNode *source_node, IrInstruction *size,
+ IrInstruction *child_type)
+{
+ IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, source_node);
+ instruction->size = size;
+ instruction->child_type = child_type;
+
+ ir_ref_instruction(size);
+ ir_ref_instruction(child_type);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_slice_type(IrBuilder *irb, AstNode *source_node, bool is_const,
+ IrInstruction *child_type)
+{
+ IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, source_node);
+ instruction->is_const = is_const;
+ instruction->child_type = child_type;
+
+ ir_ref_instruction(child_type);
+
+ return &instruction->base;
+}
static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
bool gen_error_defers, bool gen_maybe_defers)
@@ -777,23 +796,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) {
zig_unreachable();
}
-//static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) {
-// BlockContext *defer_inner_block = source_node->block_context;
-// BlockContext *defer_outer_block = irb->node->block_context;
-// if (rk == ReturnKnowledgeUnknown) {
-// if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {
-// // generate branching code that checks the return value and generates defers
-// // if the return value is error
-// zig_panic("TODO");
-// }
-// } else if (rk != ReturnKnowledgeSkipDefers) {
-// ir_gen_defers_for_block(irb, defer_inner_block, defer_outer_block,
-// rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);
-// }
-//
-// return ir_build_return(irb, source_node, value);
-//}
-
static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
assert(basic_block);
@@ -1588,6 +1590,38 @@ static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, AstNode *node) {
return ir_build_const_bool(irb, node, node->data.bool_literal.value);
}
+static IrInstruction *ir_gen_array_type(IrBuilder *irb, AstNode *node) {
+ assert(node->type == NodeTypeArrayType);
+
+ AstNode *size_node = node->data.array_type.size;
+ AstNode *child_type_node = node->data.array_type.child_type;
+ bool is_const = node->data.array_type.is_const;
+
+ if (size_node) {
+ if (is_const) {
+ add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type"));
+ return irb->codegen->invalid_instruction;
+ }
+
+ IrInstruction *size_value = ir_gen_node(irb, size_node, node->block_context);
+ if (size_value == irb->codegen->invalid_instruction)
+ return size_value;
+
+ IrInstruction *child_type = ir_gen_node(irb, child_type_node, node->block_context);
+ if (child_type == irb->codegen->invalid_instruction)
+ return child_type;
+
+ return ir_build_array_type(irb, node, size_value, child_type);
+ } else {
+ IrInstruction *child_type = ir_gen_node_extra(irb, child_type_node,
+ node->block_context, LValPurposeAddressOf);
+ if (child_type == irb->codegen->invalid_instruction)
+ return child_type;
+
+ return ir_build_slice_type(irb, node, is_const, child_type);
+ }
+}
+
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
LValPurpose lval)
{
@@ -1627,6 +1661,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
return ir_gen_this_literal(irb, node);
case NodeTypeBoolLiteral:
return ir_gen_bool_literal(irb, node);
+ case NodeTypeArrayType:
+ return ir_gen_array_type(irb, node);
case NodeTypeUnwrapErrorExpr:
case NodeTypeDefer:
case NodeTypeSliceExpr:
@@ -1644,7 +1680,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
case NodeTypeZeroesLiteral:
case NodeTypeErrorType:
case NodeTypeTypeLiteral:
- case NodeTypeArrayType:
case NodeTypeVarLiteral:
case NodeTypeRoot:
case NodeTypeFnProto:
@@ -1703,51 +1738,6 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
return ir_gen(codegn, body_node, scope, ir_executable);
}
-/*
-static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) {
- assert(node->type == NodeTypeGoto);
- Buf *label_name = node->data.goto_expr.name;
- BlockContext *context = node->block_context;
- assert(context);
- LabelTableEntry *label = find_label(g, context, label_name);
-
- if (!label) {
- add_node_error(g, node, buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));
- return;
- }
-
- label->used = true;
- node->data.goto_expr.label_entry = label;
-}
-
- for (size_t i = 0; i < fn_table_entry->goto_list.length; i += 1) {
- AstNode *goto_node = fn_table_entry->goto_list.at(i);
- assert(goto_node->type == NodeTypeGoto);
- analyze_goto_pass2(g, import, goto_node);
- }
-
- for (size_t i = 0; i < fn_table_entry->all_labels.length; i += 1) {
- LabelTableEntry *label = fn_table_entry->all_labels.at(i);
- if (!label->used) {
- add_node_error(g, label->decl_node,
- buf_sprintf("label '%s' defined but not used",
- buf_ptr(label->decl_node->data.label.name)));
- }
- }
-*/
-
-//static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf *name) {
-// BlockContext *context = orig_context;
-// while (context && context->fn_entry) {
-// auto entry = context->label_table.maybe_get(name);
-// if (entry) {
-// return entry->value;
-// }
-// context = context->parent;
-// }
-// return nullptr;
-//}
-
static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
TypeTableEntry *other_type_underlying = get_underlying_type(other_type);
@@ -2970,6 +2960,59 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn
return bool_type;
}
+static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
+ assert(un_op_instruction->op_id == IrUnOpError);
+ IrInstruction *value = un_op_instruction->value->other;
+
+ TypeTableEntry *type_entry = value->type_entry;
+ if (type_entry->id == TypeTableEntryIdInvalid)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ TypeTableEntry *meta_type = ir_resolve_type(ira, value);
+ TypeTableEntry *underlying_meta_type = get_underlying_type(meta_type);
+ switch (underlying_meta_type->id) {
+ case TypeTableEntryIdTypeDecl:
+ zig_unreachable();
+ case TypeTableEntryIdInvalid:
+ return ira->codegen->builtin_types.entry_invalid;
+ case TypeTableEntryIdVoid:
+ case TypeTableEntryIdBool:
+ case TypeTableEntryIdInt:
+ case TypeTableEntryIdFloat:
+ case TypeTableEntryIdPointer:
+ case TypeTableEntryIdArray:
+ case TypeTableEntryIdStruct:
+ case TypeTableEntryIdMaybe:
+ case TypeTableEntryIdErrorUnion:
+ case TypeTableEntryIdPureError:
+ case TypeTableEntryIdEnum:
+ case TypeTableEntryIdUnion:
+ case TypeTableEntryIdFn:
+ case TypeTableEntryIdGenericFn:
+ {
+ ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
+ value->static_value.depends_on_compile_var);
+ TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type);
+ out_val->data.x_type = result_type;
+ return ira->codegen->builtin_types.entry_type;
+ }
+ case TypeTableEntryIdMetaType:
+ case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdBlock:
+ case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdVar:
+ add_node_error(ira->codegen, un_op_instruction->base.source_node,
+ buf_sprintf("unable to wrap type '%s' in error type", buf_ptr(&meta_type->name)));
+ // TODO if meta_type is type decl, add note pointing to type decl declaration
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ zig_unreachable();
+}
+
static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
IrUnOp op_id = un_op_instruction->op_id;
switch (op_id) {
@@ -2977,7 +3020,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
zig_unreachable();
case IrUnOpBoolNot:
return ir_analyze_unary_bool_not(ira, un_op_instruction);
- zig_panic("TODO analyze PrefixOpBoolNot");
case IrUnOpBinNot:
zig_panic("TODO analyze PrefixOpBinNot");
//{
@@ -3106,31 +3148,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
// }
//}
case IrUnOpError:
- zig_panic("TODO analyze PrefixOpError");
- //{
- // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
-
- // if (type_entry->id == TypeTableEntryIdInvalid) {
- // return type_entry;
- // } else if (type_entry->id == TypeTableEntryIdMetaType) {
- // TypeTableEntry *meta_type = resolve_type(g, *expr_node);
- // if (meta_type->id == TypeTableEntryIdInvalid) {
- // return meta_type;
- // } else if (meta_type->id == TypeTableEntryIdUnreachable) {
- // add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in error type"));
- // return g->builtin_types.entry_invalid;
- // } else {
- // return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type), false);
- // }
- // } else if (type_entry->id == TypeTableEntryIdUnreachable) {
- // add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type"));
- // return g->builtin_types.entry_invalid;
- // } else {
- // // TODO eval const expr
- // return get_error_type(g, type_entry);
- // }
-
- //}
+ return ir_analyze_unary_prefix_op_err(ira, un_op_instruction);
case IrUnOpUnwrapError:
zig_panic("TODO analyze PrefixOpUnwrapError");
//{
@@ -3691,6 +3709,59 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
return ira->codegen->builtin_types.entry_void;
}
+static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
+ IrInstructionSliceType *slice_type_instruction)
+{
+ IrInstruction *child_type = slice_type_instruction->child_type->other;
+ if (child_type->type_entry->id == TypeTableEntryIdInvalid)
+ return ira->codegen->builtin_types.entry_invalid;
+ bool is_const = slice_type_instruction->is_const;
+
+ TypeTableEntry *resolved_child_type = ir_resolve_type(ira, child_type);
+ TypeTableEntry *canon_child_type = get_underlying_type(resolved_child_type);
+ switch (canon_child_type->id) {
+ case TypeTableEntryIdTypeDecl:
+ zig_unreachable();
+ case TypeTableEntryIdInvalid:
+ return ira->codegen->builtin_types.entry_invalid;
+ case TypeTableEntryIdVar:
+ case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdBlock:
+ add_node_error(ira->codegen, slice_type_instruction->base.source_node,
+ buf_sprintf("slice of type '%s' not allowed", buf_ptr(&resolved_child_type->name)));
+ // TODO if this is a typedecl, add error note showing the declaration of the type decl
+ return ira->codegen->builtin_types.entry_invalid;
+ case TypeTableEntryIdMetaType:
+ case TypeTableEntryIdVoid:
+ case TypeTableEntryIdBool:
+ case TypeTableEntryIdInt:
+ case TypeTableEntryIdFloat:
+ case TypeTableEntryIdPointer:
+ case TypeTableEntryIdArray:
+ case TypeTableEntryIdStruct:
+ case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdMaybe:
+ case TypeTableEntryIdErrorUnion:
+ case TypeTableEntryIdPureError:
+ case TypeTableEntryIdEnum:
+ case TypeTableEntryIdUnion:
+ case TypeTableEntryIdFn:
+ case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdGenericFn:
+ {
+ TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const);
+ ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base,
+ child_type->static_value.depends_on_compile_var);
+ out_val->data.x_type = result_type;
+ return ira->codegen->builtin_types.entry_type;
+ }
+ }
+ zig_unreachable();
+}
+
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -3735,11 +3806,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
case IrInstructionIdSetFnTest:
return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
+ case IrInstructionIdSliceType:
+ return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
case IrInstructionIdSwitchBr:
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
case IrInstructionIdStructFieldPtr:
+ case IrInstructionIdArrayType:
zig_panic("TODO analyze more instructions");
}
zig_unreachable();
@@ -3836,6 +3910,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPtrTypeChild:
case IrInstructionIdReadField:
case IrInstructionIdStructFieldPtr:
+ case IrInstructionIdArrayType:
+ case IrInstructionIdSliceType:
return false;
}
zig_unreachable();
@@ -6782,53 +6858,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
// false, nullptr, false);
//}
//
-//static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
-// TypeTableEntry *expected_type, AstNode *node)
-//{
-// AstNode *size_node = node->data.array_type.size;
-//
-// TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context,
-// node->data.array_type.child_type, true);
-//
-// if (child_type->id == TypeTableEntryIdUnreachable) {
-// add_node_error(g, node, buf_create_from_str("array of unreachable not allowed"));
-// return g->builtin_types.entry_invalid;
-// } else if (child_type->id == TypeTableEntryIdInvalid) {
-// return g->builtin_types.entry_invalid;
-// }
-//
-// if (size_node) {
-// child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type);
-// TypeTableEntry *size_type = analyze_expression(g, import, context,
-// g->builtin_types.entry_usize, size_node);
-// if (size_type->id == TypeTableEntryIdInvalid) {
-// return g->builtin_types.entry_invalid;
-// }
-//
-// ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
-// if (const_val->ok) {
-// if (const_val->data.x_bignum.is_negative) {
-// add_node_error(g, size_node,
-// buf_sprintf("array size %s is negative",
-// buf_ptr(bignum_to_buf(&const_val->data.x_bignum))));
-// return g->builtin_types.entry_invalid;
-// } else {
-// return resolve_expr_const_val_as_type(g, node,
-// get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false);
-// }
-// } else if (context->fn_entry) {
-// return resolve_expr_const_val_as_type(g, node,
-// get_slice_type(g, child_type, node->data.array_type.is_const), false);
-// } else {
-// add_node_error(g, first_executing_node(size_node),
-// buf_sprintf("unable to evaluate constant expression"));
-// return g->builtin_types.entry_invalid;
-// }
-// } else {
-// TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const);
-// return resolve_expr_const_val_as_type(g, node, slice_type, false);
-// }
-//}
//
//static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
// TypeTableEntry *expected_type, AstNode *node)
@@ -7218,3 +7247,126 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
// }
//}
//
+//static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
+// TypeTableEntry *expected_type, AstNode *node)
+//{
+// AstNode *size_node = node->data.array_type.size;
+//
+// TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context,
+// node->data.array_type.child_type, true);
+//
+// if (child_type->id == TypeTableEntryIdUnreachable) {
+// add_node_error(g, node, buf_create_from_str("array of unreachable not allowed"));
+// return g->builtin_types.entry_invalid;
+// } else if (child_type->id == TypeTableEntryIdInvalid) {
+// return g->builtin_types.entry_invalid;
+// }
+//
+// if (size_node) {
+// child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type);
+// TypeTableEntry *size_type = analyze_expression(g, import, context,
+// g->builtin_types.entry_usize, size_node);
+// if (size_type->id == TypeTableEntryIdInvalid) {
+// return g->builtin_types.entry_invalid;
+// }
+//
+// ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
+// if (const_val->ok) {
+// if (const_val->data.x_bignum.is_negative) {
+// add_node_error(g, size_node,
+// buf_sprintf("array size %s is negative",
+// buf_ptr(bignum_to_buf(&const_val->data.x_bignum))));
+// return g->builtin_types.entry_invalid;
+// } else {
+// return resolve_expr_const_val_as_type(g, node,
+// get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false);
+// }
+// } else if (context->fn_entry) {
+// return resolve_expr_const_val_as_type(g, node,
+// get_slice_type(g, child_type, node->data.array_type.is_const), false);
+// } else {
+// add_node_error(g, first_executing_node(size_node),
+// buf_sprintf("unable to evaluate constant expression"));
+// return g->builtin_types.entry_invalid;
+// }
+// } else {
+// TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const);
+// return resolve_expr_const_val_as_type(g, node, slice_type, false);
+// }
+//}
+//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
+// size_t result = 0;
+// while (inner_block != outer_block) {
+// if (inner_block->node->type == NodeTypeDefer &&
+// (inner_block->node->data.defer.kind == ReturnKindError ||
+// inner_block->node->data.defer.kind == ReturnKindMaybe))
+// {
+// result += 1;
+// }
+// inner_block = inner_block->parent;
+// }
+// return result;
+//}
+
+
+//static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) {
+// BlockContext *defer_inner_block = source_node->block_context;
+// BlockContext *defer_outer_block = irb->node->block_context;
+// if (rk == ReturnKnowledgeUnknown) {
+// if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {
+// // generate branching code that checks the return value and generates defers
+// // if the return value is error
+// zig_panic("TODO");
+// }
+// } else if (rk != ReturnKnowledgeSkipDefers) {
+// ir_gen_defers_for_block(irb, defer_inner_block, defer_outer_block,
+// rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);
+// }
+//
+// return ir_build_return(irb, source_node, value);
+//}
+/*
+static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) {
+ assert(node->type == NodeTypeGoto);
+ Buf *label_name = node->data.goto_expr.name;
+ BlockContext *context = node->block_context;
+ assert(context);
+ LabelTableEntry *label = find_label(g, context, label_name);
+
+ if (!label) {
+ add_node_error(g, node, buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));
+ return;
+ }
+
+ label->used = true;
+ node->data.goto_expr.label_entry = label;
+}
+
+ for (size_t i = 0; i < fn_table_entry->goto_list.length; i += 1) {
+ AstNode *goto_node = fn_table_entry->goto_list.at(i);
+ assert(goto_node->type == NodeTypeGoto);
+ analyze_goto_pass2(g, import, goto_node);
+ }
+
+ for (size_t i = 0; i < fn_table_entry->all_labels.length; i += 1) {
+ LabelTableEntry *label = fn_table_entry->all_labels.at(i);
+ if (!label->used) {
+ add_node_error(g, label->decl_node,
+ buf_sprintf("label '%s' defined but not used",
+ buf_ptr(label->decl_node->data.label.name)));
+ }
+ }
+*/
+
+//static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf *name) {
+// BlockContext *context = orig_context;
+// while (context && context->fn_entry) {
+// auto entry = context->label_table.maybe_get(name);
+// if (entry) {
+// return entry->value;
+// }
+// context = context->parent;
+// }
+// return nullptr;
+//}
+
src/ir_print.cpp
@@ -394,6 +394,19 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi
fprintf(irp->f, ")");
}
+static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) {
+ fprintf(irp->f, "[");
+ ir_print_other_instruction(irp, instruction->size);
+ fprintf(irp->f, "]");
+ ir_print_other_instruction(irp, instruction->child_type);
+}
+
+static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) {
+ const char *const_kw = instruction->is_const ? "const " : "";
+ fprintf(irp->f, "[]%s", const_kw);
+ ir_print_other_instruction(irp, instruction->child_type);
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -471,6 +484,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdSetFnTest:
ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
break;
+ case IrInstructionIdArrayType:
+ ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
+ break;
+ case IrInstructionIdSliceType:
+ ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);
+ break;
case IrInstructionIdSwitchBr:
zig_panic("TODO print more IR instructions");
}