From a922d5d42a3ba9bbded0740e1eb3246e7b57ad2a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 23 Jan 2016 00:34:47 -0700 Subject: [PATCH] implement literal error values See #23 --- src/all_types.hpp | 2 ++ src/analyze.cpp | 34 +++++++++++++++++++++++++++++----- src/codegen.cpp | 13 +++++++++++++ test/run_tests.cpp | 16 ++++++++++++++++ 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 8ea25ad8c3..8b5d65584e 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -310,6 +310,7 @@ enum CastOp { CastOpToUnknownSizeArray, CastOpMaybeWrap, CastOpPointerReinterpret, + CastOpErrToInt, }; struct AstNodeFnCallExpr { @@ -999,6 +1000,7 @@ struct CodeGen { bool error_during_imports; uint32_t next_node_index; uint32_t next_error_index; + TypeTableEntry *err_tag_type; }; struct VariableTableEntry { diff --git a/src/analyze.cpp b/src/analyze.cpp index 1137915519..8f19dbd777 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -233,11 +233,10 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { entry->data.error.child_type = child_type; if (child_type->size_in_bits == 0) { - TypeTableEntry *tag_type = get_smallest_unsigned_int_type(g, g->next_error_index); - entry->type_ref = tag_type->type_ref; - entry->size_in_bits = tag_type->size_in_bits; - entry->align_in_bits = tag_type->align_in_bits; - entry->di_type = tag_type->di_type; + entry->type_ref = g->err_tag_type->type_ref; + entry->size_in_bits = g->err_tag_type->size_in_bits; + entry->align_in_bits = g->err_tag_type->align_in_bits; + entry->di_type = g->err_tag_type->di_type; } else { zig_panic("TODO get_error_type non-void"); @@ -2869,6 +2868,10 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex const_val->data.x_maybe = other_val; const_val->ok = true; break; + case CastOpErrToInt: + bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_err->value); + const_val->ok = true; + break; } } @@ -2975,6 +2978,24 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B } } + // explicit cast from %void to integer type which can fit it + if (actual_type->id == TypeTableEntryIdError && + actual_type->data.error.child_type->size_in_bits == 0 && + wanted_type->id == TypeTableEntryIdInt) + { + BigNum bn; + bignum_init_unsigned(&bn, g->next_error_index); + if (bignum_fits_in_bits(&bn, wanted_type->size_in_bits, wanted_type->data.integral.is_signed)) { + node->data.fn_call_expr.cast_op = CastOpErrToInt; + eval_const_expr_implicit_cast(g, node, expr_node); + return wanted_type; + } else { + add_node_error(g, node, + buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name))); + return g->builtin_types.entry_invalid; + } + } + add_node_error(g, node, buf_sprintf("invalid cast from type '%s' to '%s'", buf_ptr(&actual_type->name), @@ -4353,6 +4374,9 @@ void semantic_analyze(CodeGen *g) { } } } + + g->err_tag_type = get_smallest_unsigned_int_type(g, g->next_error_index); + { auto it = g->import_table.entry_iterator(); for (;;) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 08d191a505..e81437c66a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -284,6 +284,13 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { zig_unreachable(); case CastOpNoop: return expr_val; + case CastOpErrToInt: + assert(actual_type->id == TypeTableEntryIdError); + if (actual_type->data.error.child_type->size_in_bits == 0) { + return expr_val; + } else { + zig_panic("TODO"); + } case CastOpMaybeWrap: { assert(cast_expr->tmp_ptr); @@ -2122,6 +2129,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE } else { return global_value; } + } else if (type_entry->id == TypeTableEntryIdError) { + if (type_entry->data.error.child_type->size_in_bits == 0) { + return LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err->value, false); + } else { + zig_panic("TODO"); + } } else { zig_unreachable(); } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index fe8dc39ae0..a112eeb43a 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1258,6 +1258,22 @@ pub fn main(args: [][]u8) i32 => { } )SOURCE", "OK\n"); + add_simple_case("error values", R"SOURCE( +import "std.zig"; +%.err1; +%.err2; +pub fn main(args: [][]u8) i32 => { + const a = i32(%.err1); + const b = i32(%.err2); + if (a == b) { + print_str("BAD\n"); + } + + print_str("OK\n"); + return 0; +} + )SOURCE", "OK\n"); + }