diff --git a/src/all_types.hpp b/src/all_types.hpp index 5f209f61b..7e0655eac 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1139,6 +1139,7 @@ enum BuiltinFnId { BuiltinFnIdFence, BuiltinFnIdDivExact, BuiltinFnIdTruncate, + BuiltinFnIdIntType, }; struct BuiltinFnEntry { diff --git a/src/analyze.cpp b/src/analyze.cpp index cdfc2aca4..8726c4f00 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4790,6 +4790,52 @@ static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import, return g->builtin_types.entry_invalid; } +static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import, + BlockContext *context, AstNode *node) +{ + AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0); + AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1); + AstNode **is_wrap_node = &node->data.fn_call_expr.params.at(2); + + TypeTableEntry *bool_type = g->builtin_types.entry_bool; + TypeTableEntry *usize_type = g->builtin_types.entry_usize; + TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node); + TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node); + TypeTableEntry *is_wrap_type = analyze_expression(g, import, context, bool_type, *is_wrap_node); + + if (is_signed_type->id == TypeTableEntryIdInvalid || + bit_count_type->id == TypeTableEntryIdInvalid || + is_wrap_type->id == TypeTableEntryIdInvalid) + { + return g->builtin_types.entry_invalid; + } + + ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val; + ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val; + ConstExprValue *is_wrap_val = &get_resolved_expr(*is_wrap_node)->const_val; + + AstNode *bad_node = nullptr; + if (!is_signed_val->ok) { + bad_node = *is_signed_node; + } else if (!bit_count_val->ok) { + bad_node = *bit_count_node; + } else if (!is_wrap_val->ok) { + bad_node = *is_wrap_node; + } + if (bad_node) { + add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression")); + return g->builtin_types.entry_invalid; + } + + bool depends_on_compile_var = is_signed_val->depends_on_compile_var || + bit_count_val->depends_on_compile_var || is_wrap_val->depends_on_compile_var; + + TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool, is_wrap_val->data.x_bool, + bit_count_val->data.x_bignum.data.x_uint); + return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var); + +} + static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node) { @@ -5136,6 +5182,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry return analyze_truncate(g, import, context, node); case BuiltinFnIdCompileErr: return analyze_compile_err(g, import, context, node); + case BuiltinFnIdIntType: + return analyze_int_type(g, import, context, node); } zig_unreachable(); } diff --git a/src/codegen.cpp b/src/codegen.cpp index b8ffb1869..122dac5b4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -540,6 +540,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { case BuiltinFnIdImport: case BuiltinFnIdCImport: case BuiltinFnIdCompileErr: + case BuiltinFnIdIntType: zig_unreachable(); case BuiltinFnIdCtz: case BuiltinFnIdClz: @@ -4657,6 +4658,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn_with_arg_count(g, BuiltinFnIdDivExact, "div_exact", 2); create_builtin_fn_with_arg_count(g, BuiltinFnIdTruncate, "truncate", 2); create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileErr, "compile_err", 1); + create_builtin_fn_with_arg_count(g, BuiltinFnIdIntType, "int_type", 3); } static void init(CodeGen *g, Buf *source_path) { diff --git a/src/eval.cpp b/src/eval.cpp index baefad0f6..ca5338838 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -834,6 +834,7 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_ case BuiltinFnIdFrameAddress: case BuiltinFnIdReturnAddress: case BuiltinFnIdCompileErr: + case BuiltinFnIdIntType: zig_unreachable(); } diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 7539092c8..f9889e2c8 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -1689,3 +1689,26 @@ struct DivResult { quotient: u64, remainder: u64, } + +#attribute("test") +fn int_type_builtin() { + assert(@int_type(true, 8, false) == i8); + assert(@int_type(true, 16, false) == i16); + assert(@int_type(true, 32, false) == i32); + assert(@int_type(true, 64, false) == i64); + + assert(@int_type(false, 8, false) == u8); + assert(@int_type(false, 16, false) == u16); + assert(@int_type(false, 32, false) == u32); + assert(@int_type(false, 64, false) == u64); + + assert(@int_type(true, 8, true) == i8w); + assert(@int_type(true, 16, true) == i16w); + assert(@int_type(true, 32, true) == i32w); + assert(@int_type(true, 64, true) == i64w); + + assert(@int_type(false, 8, true) == u8w); + assert(@int_type(false, 16, true) == u16w); + assert(@int_type(false, 32, true) == u32w); + assert(@int_type(false, 64, true) == u64w); +}