IR: support slice types

This commit is contained in:
Andrew Kelley 2016-11-07 18:58:01 -05:00
parent a2e3293930
commit 05de70017d
6 changed files with 341 additions and 151 deletions

View File

@ -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,

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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;
//}

View File

@ -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");
}