improve names of error sets when using merge error sets operator

This commit is contained in:
Andrew Kelley 2019-10-09 13:34:49 -04:00
parent 8a547d9e81
commit 2286003666
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
4 changed files with 111 additions and 26 deletions

View File

@ -398,6 +398,7 @@ struct LazyValueErrUnionType {
IrAnalyze *ira;
IrInstruction *err_set_type;
IrInstruction *payload_type;
Buf *type_name;
};
struct ConstExprValue {
@ -2407,6 +2408,7 @@ enum IrInstructionId {
IrInstructionIdPhi,
IrInstructionIdUnOp,
IrInstructionIdBinOp,
IrInstructionIdMergeErrSets,
IrInstructionIdLoadPtr,
IrInstructionIdLoadPtrGen,
IrInstructionIdStorePtr,
@ -2713,7 +2715,6 @@ enum IrBinOp {
IrBinOpRemMod,
IrBinOpArrayCat,
IrBinOpArrayMult,
IrBinOpMergeErrorSets,
};
struct IrInstructionBinOp {
@ -2725,6 +2726,14 @@ struct IrInstructionBinOp {
bool safety_check_on;
};
struct IrInstructionMergeErrSets {
IrInstruction base;
IrInstruction *op1;
IrInstruction *op2;
Buf *type_name;
};
struct IrInstructionLoadPtr {
IrInstruction base;
@ -3633,6 +3642,7 @@ struct IrInstructionErrorUnion {
IrInstruction *err_set;
IrInstruction *payload;
Buf *type_name;
};
struct IrInstructionAtomicRmw {

View File

@ -2776,7 +2776,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpArrayCat:
case IrBinOpArrayMult:
case IrBinOpRemUnspecified:
case IrBinOpMergeErrorSets:
zig_unreachable();
case IrBinOpBoolOr:
return LLVMBuildOr(g->builder, op1_value, op2_value, "");
@ -6040,6 +6039,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdAllocaGen:
case IrInstructionIdAwaitSrc:
case IrInstructionIdSplatSrc:
case IrInstructionIdMergeErrSets:
zig_unreachable();
case IrInstructionIdDeclVarGen:

View File

@ -198,6 +198,8 @@ static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,
LVal lval, ResultLoc *parent_result_loc);
static void ir_reset_result(ResultLoc *result_loc);
static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name,
Scope *scope, AstNode *source_node, Buf *out_bare_name);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@ -469,6 +471,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
return IrInstructionIdBinOp;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionMergeErrSets *) {
return IrInstructionIdMergeErrSets;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
return IrInstructionIdExport;
}
@ -1290,6 +1296,20 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *sou
return &bin_op_instruction->base;
}
static IrInstruction *ir_build_merge_err_sets(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *op1, IrInstruction *op2, Buf *type_name)
{
IrInstructionMergeErrSets *merge_err_sets_instruction = ir_build_instruction<IrInstructionMergeErrSets>(irb, scope, source_node);
merge_err_sets_instruction->op1 = op1;
merge_err_sets_instruction->op2 = op2;
merge_err_sets_instruction->type_name = type_name;
ir_ref_instruction(op1, irb->current_basic_block);
ir_ref_instruction(op2, irb->current_basic_block);
return &merge_err_sets_instruction->base;
}
static IrInstruction *ir_build_var_ptr_x(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var,
ScopeFnDef *crossed_fndef_scope)
{
@ -3894,6 +3914,20 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no
return ir_build_bin_op(irb, scope, node, op_id, op1, op2, true);
}
static IrInstruction *ir_gen_merge_err_sets(IrBuilder *irb, Scope *scope, AstNode *node) {
IrInstruction *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);
IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
if (op1 == irb->codegen->invalid_instruction || op2 == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
// TODO only pass type_name when the || operator is the top level AST node in the var decl expr
Buf bare_name = BUF_INIT;
Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", scope, node, &bare_name);
return ir_build_merge_err_sets(irb, scope, node, op1, op2, type_name);
}
static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {
IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
if (lvalue == irb->codegen->invalid_instruction)
@ -3913,6 +3947,19 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node)
return ir_build_const_void(irb, scope, node);
}
static IrInstruction *ir_gen_assign_merge_err_sets(IrBuilder *irb, Scope *scope, AstNode *node) {
IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
if (lvalue == irb->codegen->invalid_instruction)
return lvalue;
IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
if (op2 == irb->codegen->invalid_instruction)
return op2;
IrInstruction *result = ir_build_merge_err_sets(irb, scope, node, op1, op2, nullptr);
ir_build_store_ptr(irb, scope, node, lvalue, result);
return ir_build_const_void(irb, scope, node);
}
static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
if (lvalue == irb->codegen->invalid_instruction)
@ -4153,7 +4200,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node,
case BinOpTypeAssignBitOr:
return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinOr), lval, result_loc);
case BinOpTypeAssignMergeErrorSets:
return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMergeErrorSets), lval, result_loc);
return ir_lval_wrap(irb, scope, ir_gen_assign_merge_err_sets(irb, scope, node), lval, result_loc);
case BinOpTypeBoolOr:
return ir_lval_wrap(irb, scope, ir_gen_bool_or(irb, scope, node), lval, result_loc);
case BinOpTypeBoolAnd:
@ -4201,7 +4248,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node,
case BinOpTypeArrayMult:
return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult), lval, result_loc);
case BinOpTypeMergeErrorSets:
return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets), lval, result_loc);
return ir_lval_wrap(irb, scope, ir_gen_merge_err_sets(irb, scope, node), lval, result_loc);
case BinOpTypeUnwrapOptional:
return ir_gen_orelse(irb, scope, node, lval, result_loc);
case BinOpTypeErrorUnion:
@ -7859,7 +7906,9 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope,
}
// errors should be populated with set1's values
static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigType *set1, ZigType *set2) {
static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigType *set1, ZigType *set2,
Buf *type_name)
{
assert(set1->id == ZigTypeIdErrorSet);
assert(set2->id == ZigTypeIdErrorSet);
@ -7867,8 +7916,12 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp
err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits;
err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align;
err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size;
buf_resize(&err_set_type->name, 0);
buf_appendf(&err_set_type->name, "error{");
if (type_name == nullptr) {
buf_resize(&err_set_type->name, 0);
buf_appendf(&err_set_type->name, "error{");
} else {
buf_init_from_buf(&err_set_type->name, type_name);
}
for (uint32_t i = 0, count = set1->data.error_set.err_count; i < count; i += 1) {
assert(errors[set1->data.error_set.errors[i]->value] == set1->data.error_set.errors[i]);
@ -7885,21 +7938,27 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp
err_set_type->data.error_set.err_count = count;
err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(count);
bool need_comma = false;
for (uint32_t i = 0; i < set1->data.error_set.err_count; i += 1) {
ErrorTableEntry *error_entry = set1->data.error_set.errors[i];
buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name));
if (type_name == nullptr) {
const char *comma = need_comma ? "," : "";
need_comma = true;
buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&error_entry->name));
}
err_set_type->data.error_set.errors[i] = error_entry;
}
uint32_t index = set1->data.error_set.err_count;
bool need_comma = false;
for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) {
ErrorTableEntry *error_entry = set2->data.error_set.errors[i];
if (errors[error_entry->value] == nullptr) {
errors[error_entry->value] = error_entry;
const char *comma = need_comma ? "," : "";
need_comma = true;
buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&error_entry->name));
if (type_name == nullptr) {
const char *comma = need_comma ? "," : "";
need_comma = true;
buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&error_entry->name));
}
err_set_type->data.error_set.errors[index] = error_entry;
index += 1;
}
@ -7907,7 +7966,9 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp
assert(index == count);
assert(count != 0);
buf_appendf(&err_set_type->name, "}");
if (type_name == nullptr) {
buf_appendf(&err_set_type->name, "}");
}
return err_set_type;
@ -9967,7 +10028,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
}
// neither of them are supersets. so we invent a new error set type that is a union of both of them
err_set_type = get_error_set_union(ira->codegen, errors, cur_type, err_set_type);
err_set_type = get_error_set_union(ira->codegen, errors, cur_type, err_set_type, nullptr);
assert(errors != nullptr);
continue;
} else if (cur_type->id == ZigTypeIdErrorUnion) {
@ -10018,7 +10079,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
}
// not a subset. invent new error set type, union of both of them
err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, err_set_type);
err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, err_set_type, nullptr);
prev_inst = cur_inst;
assert(errors != nullptr);
continue;
@ -10074,7 +10135,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
continue;
}
// not a subset. invent new error set type, union of both of them
err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_type);
err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_type, nullptr);
assert(errors != nullptr);
continue;
}
@ -10160,7 +10221,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
continue;
}
err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, prev_err_set_type);
err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, prev_err_set_type, nullptr);
continue;
}
}
@ -10286,7 +10347,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
update_errors_helper(ira->codegen, &errors, &errors_count);
err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_err_set_type);
err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_err_set_type, nullptr);
}
prev_inst = cur_inst;
continue;
@ -13795,7 +13856,6 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in
case IrBinOpArrayCat:
case IrBinOpArrayMult:
case IrBinOpRemUnspecified:
case IrBinOpMergeErrorSets:
zig_unreachable();
case IrBinOpBinOr:
assert(is_int);
@ -14102,7 +14162,6 @@ static bool ok_float_op(IrBinOp op) {
case IrBinOpRemUnspecified:
case IrBinOpArrayCat:
case IrBinOpArrayMult:
case IrBinOpMergeErrorSets:
return false;
}
zig_unreachable();
@ -14603,7 +14662,9 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
return result;
}
static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {
static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,
IrInstructionMergeErrSets *instruction)
{
ZigType *op1_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op1->child);
if (type_is_invalid(op1_type))
return ira->codegen->invalid_instruction;
@ -14632,12 +14693,13 @@ static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionB
assert(errors[error_entry->value] == nullptr);
errors[error_entry->value] = error_entry;
}
ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type);
ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type, instruction->type_name);
free(errors);
return ir_const_type(ira, &instruction->base, result_type);
}
static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
IrBinOp op_id = bin_op_instruction->op_id;
switch (op_id) {
@ -14679,8 +14741,6 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
return ir_analyze_array_cat(ira, bin_op_instruction);
case IrBinOpArrayMult:
return ir_analyze_array_mult(ira, bin_op_instruction);
case IrBinOpMergeErrorSets:
return ir_analyze_merge_error_sets(ira, bin_op_instruction);
}
zig_unreachable();
}
@ -25945,6 +26005,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
case IrInstructionIdBinOp:
return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
case IrInstructionIdMergeErrSets:
return ir_analyze_instruction_merge_err_sets(ira, (IrInstructionMergeErrSets *)instruction);
case IrInstructionIdDeclVarSrc:
return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
case IrInstructionIdLoadPtr:
@ -26370,6 +26432,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPhi:
case IrInstructionIdUnOp:
case IrInstructionIdBinOp:
case IrInstructionIdMergeErrSets:
case IrInstructionIdLoadPtr:
case IrInstructionIdConst:
case IrInstructionIdCast:

View File

@ -70,6 +70,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
return "UnOp";
case IrInstructionIdBinOp:
return "BinOp";
case IrInstructionIdMergeErrSets:
return "MergeErrSets";
case IrInstructionIdLoadPtr:
return "LoadPtr";
case IrInstructionIdLoadPtrGen:
@ -497,8 +499,6 @@ static const char *ir_bin_op_id_str(IrBinOp op_id) {
return "++";
case IrBinOpArrayMult:
return "**";
case IrBinOpMergeErrorSets:
return "||";
}
zig_unreachable();
}
@ -535,6 +535,15 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
}
}
static void ir_print_merge_err_sets(IrPrint *irp, IrInstructionMergeErrSets *instruction) {
ir_print_other_instruction(irp, instruction->op1);
fprintf(irp->f, " || ");
ir_print_other_instruction(irp, instruction->op2);
if (instruction->type_name != nullptr) {
fprintf(irp->f, " // name=%s", buf_ptr(instruction->type_name));
}
}
static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
const char *name = decl_var_instruction->var->name;
@ -1974,6 +1983,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
case IrInstructionIdBinOp:
ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
break;
case IrInstructionIdMergeErrSets:
ir_print_merge_err_sets(irp, (IrInstructionMergeErrSets *)instruction);
break;
case IrInstructionIdDeclVarSrc:
ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
break;