authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-07 01:23:38-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-07 01:23:38-05:00
log0ad580f001eb151d0feb7ad884e237b237220800
tree79eee5e187dfb183113187d88360446941cc3791
parent5e4ee659a6796f7cc327c5e1cf1e10b1c032e85e

IR: add minValue, maxValue, and negation


6 files changed, 239 insertions(+), 82 deletions(-)

src/all_types.hpp+14
...@@ -1393,6 +1393,8 @@ enum IrInstructionId {...@@ -1393,6 +1393,8 @@ enum IrInstructionId {
1393 IrInstructionIdImport,1393 IrInstructionIdImport,
1394 IrInstructionIdArrayLen,1394 IrInstructionIdArrayLen,
1395 IrInstructionIdRef,1395 IrInstructionIdRef,
1396 IrInstructionIdMinValue,
1397 IrInstructionIdMaxValue,
1396};1398};
13971399
1398struct IrInstruction {1400struct IrInstruction {
...@@ -1791,6 +1793,18 @@ struct IrInstructionRef {...@@ -1791,6 +1793,18 @@ struct IrInstructionRef {
1791 LLVMValueRef tmp_ptr;1793 LLVMValueRef tmp_ptr;
1792};1794};
17931795
1796struct IrInstructionMinValue {
1797 IrInstruction base;
1798
1799 IrInstruction *value;
1800};
1801
1802struct IrInstructionMaxValue {
1803 IrInstruction base;
1804
1805 IrInstruction *value;
1806};
1807
1794enum LValPurpose {1808enum LValPurpose {
1795 LValPurposeNone,1809 LValPurposeNone,
1796 LValPurposeAssign,1810 LValPurposeAssign,
src/codegen.cpp+2
...@@ -1821,6 +1821,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1821,6 +1821,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1821 case IrInstructionIdStaticEval:1821 case IrInstructionIdStaticEval:
1822 case IrInstructionIdImport:1822 case IrInstructionIdImport:
1823 case IrInstructionIdContainerInitFields:1823 case IrInstructionIdContainerInitFields:
1824 case IrInstructionIdMinValue:
1825 case IrInstructionIdMaxValue:
1824 zig_unreachable();1826 zig_unreachable();
1825 case IrInstructionIdReturn:1827 case IrInstructionIdReturn:
1826 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);1828 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/eval.cpp+2
...@@ -431,6 +431,8 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *...@@ -431,6 +431,8 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
431 } else if (type_entry->id == TypeTableEntryIdBool) {431 } else if (type_entry->id == TypeTableEntryIdBool) {
432 const_val->special = ConstValSpecialStatic;432 const_val->special = ConstValSpecialStatic;
433 const_val->data.x_bool = is_max;433 const_val->data.x_bool = is_max;
434 } else if (type_entry->id == TypeTableEntryIdVoid) {
435 // nothing to do
434 } else {436 } else {
435 zig_unreachable();437 zig_unreachable();
436 }438 }
src/ir.cpp+168-82
...@@ -306,6 +306,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {...@@ -306,6 +306,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {
306 return IrInstructionIdStructInit;306 return IrInstructionIdStructInit;
307}307}
308308
309static constexpr IrInstructionId ir_instruction_id(IrInstructionMinValue *) {
310 return IrInstructionIdMinValue;
311}
312
313static constexpr IrInstructionId ir_instruction_id(IrInstructionMaxValue *) {
314 return IrInstructionIdMaxValue;
315}
316
309template<typename T>317template<typename T>
310static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {318static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
311 T *special_instruction = allocate<T>(1);319 T *special_instruction = allocate<T>(1);
...@@ -1241,6 +1249,25 @@ static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instr...@@ -1241,6 +1249,25 @@ static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instr
1241 return new_instruction;1249 return new_instruction;
1242}1250}
12431251
1252static IrInstruction *ir_build_min_value(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1253 IrInstructionMinValue *instruction = ir_build_instruction<IrInstructionMinValue>(irb, scope, source_node);
1254 instruction->value = value;
1255
1256 ir_ref_instruction(value);
1257
1258 return &instruction->base;
1259}
1260
1261static IrInstruction *ir_build_max_value(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1262 IrInstructionMaxValue *instruction = ir_build_instruction<IrInstructionMaxValue>(irb, scope, source_node);
1263 instruction->value = value;
1264
1265 ir_ref_instruction(value);
1266
1267 return &instruction->base;
1268}
1269
1270
1244static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,1271static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
1245 bool gen_error_defers, bool gen_maybe_defers)1272 bool gen_error_defers, bool gen_maybe_defers)
1246{1273{
...@@ -1879,11 +1906,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -1879,11 +1906,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
18791906
1880 return ir_build_import(irb, scope, node, arg0_value);1907 return ir_build_import(irb, scope, node, arg0_value);
1881 }1908 }
1909 case BuiltinFnIdMaxValue:
1910 {
1911 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1912 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
1913 if (arg0_value == irb->codegen->invalid_instruction)
1914 return arg0_value;
1915
1916 return ir_build_max_value(irb, scope, node, arg0_value);
1917 }
1918 case BuiltinFnIdMinValue:
1919 {
1920 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1921 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
1922 if (arg0_value == irb->codegen->invalid_instruction)
1923 return arg0_value;
1924
1925 return ir_build_min_value(irb, scope, node, arg0_value);
1926 }
1882 case BuiltinFnIdMemcpy:1927 case BuiltinFnIdMemcpy:
1883 case BuiltinFnIdMemset:1928 case BuiltinFnIdMemset:
1884 case BuiltinFnIdAlignof:1929 case BuiltinFnIdAlignof:
1885 case BuiltinFnIdMaxValue:
1886 case BuiltinFnIdMinValue:
1887 case BuiltinFnIdMemberCount:1930 case BuiltinFnIdMemberCount:
1888 case BuiltinFnIdAddWithOverflow:1931 case BuiltinFnIdAddWithOverflow:
1889 case BuiltinFnIdSubWithOverflow:1932 case BuiltinFnIdSubWithOverflow:
...@@ -4670,7 +4713,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -4670,7 +4713,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
4670 if (is_inline || fn_ref->static_value.special != ConstValSpecialRuntime) {4713 if (is_inline || fn_ref->static_value.special != ConstValSpecialRuntime) {
4671 if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {4714 if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {
4672 TypeTableEntry *dest_type = ir_resolve_type(ira, fn_ref);4715 TypeTableEntry *dest_type = ir_resolve_type(ira, fn_ref);
4673 if (!dest_type)4716 if (dest_type->id == TypeTableEntryIdInvalid)
4674 return ira->codegen->builtin_types.entry_invalid;4717 return ira->codegen->builtin_types.entry_invalid;
46754718
4676 size_t actual_param_count = call_instruction->arg_count;4719 size_t actual_param_count = call_instruction->arg_count;
...@@ -4958,6 +5001,48 @@ static TypeTableEntry *ir_analyze_unwrap_maybe(IrAnalyze *ira, IrInstructionUnOp...@@ -4958,6 +5001,48 @@ static TypeTableEntry *ir_analyze_unwrap_maybe(IrAnalyze *ira, IrInstructionUnOp
4958 }5001 }
4959}5002}
49605003
5004static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
5005 IrInstruction *value = un_op_instruction->value->other;
5006 TypeTableEntry *expr_type = value->type_entry;
5007 if (expr_type->id == TypeTableEntryIdInvalid)
5008 return ira->codegen->builtin_types.entry_invalid;
5009
5010 bool is_wrap_op = (un_op_instruction->op_id == IrUnOpNegationWrap);
5011
5012 if ((expr_type->id == TypeTableEntryIdInt && expr_type->data.integral.is_signed) ||
5013 expr_type->id == TypeTableEntryIdNumLitInt ||
5014 ((expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdNumLitFloat) &&
5015 !is_wrap_op))
5016 {
5017 ConstExprValue *target_const_val = &value->static_value;
5018 if (target_const_val->special != ConstValSpecialRuntime) {
5019 bool depends_on_compile_var = value->static_value.depends_on_compile_var;
5020 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, depends_on_compile_var);
5021 bignum_negate(&out_val->data.x_bignum, &target_const_val->data.x_bignum);
5022 if (expr_type->id == TypeTableEntryIdFloat ||
5023 expr_type->id == TypeTableEntryIdNumLitFloat ||
5024 expr_type->id == TypeTableEntryIdNumLitInt)
5025 {
5026 return expr_type;
5027 }
5028
5029 bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum, expr_type->data.integral.bit_count, true);
5030 if (is_wrap_op) {
5031 if (overflow)
5032 out_val->data.x_bignum.is_negative = true;
5033 } else if (overflow) {
5034 ir_add_error(ira, &un_op_instruction->base, buf_sprintf("negation caused overflow"));
5035 return ira->codegen->builtin_types.entry_invalid;
5036 }
5037 return expr_type;
5038 }
5039 }
5040
5041 const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
5042 ir_add_error(ira, &un_op_instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
5043 return ira->codegen->builtin_types.entry_invalid;
5044}
5045
4961static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {5046static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
4962 IrUnOp op_id = un_op_instruction->op_id;5047 IrUnOp op_id = un_op_instruction->op_id;
4963 switch (op_id) {5048 switch (op_id) {
...@@ -4983,51 +5068,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -4983,51 +5068,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
4983 //}5068 //}
4984 case IrUnOpNegation:5069 case IrUnOpNegation:
4985 case IrUnOpNegationWrap:5070 case IrUnOpNegationWrap:
4986 zig_panic("TODO analyze PrefixOpNegation[Wrap]");5071 return ir_analyze_negation(ira, un_op_instruction);
4987 //{
4988 // TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
4989 // if (expr_type->id == TypeTableEntryIdInvalid) {
4990 // return expr_type;
4991 // } else if ((expr_type->id == TypeTableEntryIdInt &&
4992 // expr_type->data.integral.is_signed) ||
4993 // expr_type->id == TypeTableEntryIdNumLitInt ||
4994 // ((expr_type->id == TypeTableEntryIdFloat ||
4995 // expr_type->id == TypeTableEntryIdNumLitFloat) &&
4996 // prefix_op != PrefixOpNegationWrap))
4997 // {
4998 // ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
4999 // if (!target_const_val->ok) {
5000 // return expr_type;
5001 // }
5002 // ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
5003 // const_val->ok = true;
5004 // const_val->depends_on_compile_var = target_const_val->depends_on_compile_var;
5005 // bignum_negate(&const_val->data.x_bignum, &target_const_val->data.x_bignum);
5006 // if (expr_type->id == TypeTableEntryIdFloat ||
5007 // expr_type->id == TypeTableEntryIdNumLitFloat ||
5008 // expr_type->id == TypeTableEntryIdNumLitInt)
5009 // {
5010 // return expr_type;
5011 // }
5012
5013 // bool overflow = !bignum_fits_in_bits(&const_val->data.x_bignum,
5014 // expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
5015 // if (prefix_op == PrefixOpNegationWrap) {
5016 // if (overflow) {
5017 // const_val->data.x_bignum.is_negative = true;
5018 // }
5019 // } else if (overflow) {
5020 // add_node_error(g, *expr_node, buf_sprintf("negation caused overflow"));
5021 // return g->builtin_types.entry_invalid;
5022 // }
5023 // return expr_type;
5024 // } else {
5025 // const char *fmt = (prefix_op == PrefixOpNegationWrap) ?
5026 // "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
5027 // add_node_error(g, node, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
5028 // return g->builtin_types.entry_invalid;
5029 // }
5030 //}
5031 case IrUnOpAddressOf:5072 case IrUnOpAddressOf:
5032 case IrUnOpConstAddressOf:5073 case IrUnOpConstAddressOf:
5033 return ir_analyze_unary_address_of(ira, un_op_instruction, op_id == IrUnOpConstAddressOf);5074 return ir_analyze_unary_address_of(ira, un_op_instruction, op_id == IrUnOpConstAddressOf);
...@@ -6575,7 +6616,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru...@@ -6575,7 +6616,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
6575static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) {6616static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) {
6576 IrInstruction *container_type_value = instruction->container_type->other;6617 IrInstruction *container_type_value = instruction->container_type->other;
6577 TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);6618 TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);
6578 if (!container_type)6619 if (container_type->id == TypeTableEntryIdInvalid)
6579 return ira->codegen->builtin_types.entry_invalid;6620 return ira->codegen->builtin_types.entry_invalid;
65806621
6581 size_t elem_count = instruction->item_count;6622 size_t elem_count = instruction->item_count;
...@@ -6661,7 +6702,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -6661,7 +6702,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
6661static TypeTableEntry *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {6702static TypeTableEntry *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {
6662 IrInstruction *container_type_value = instruction->container_type->other;6703 IrInstruction *container_type_value = instruction->container_type->other;
6663 TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);6704 TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);
6664 if (!container_type)6705 if (container_type->id == TypeTableEntryIdInvalid)
6665 return ira->codegen->builtin_types.entry_invalid;6706 return ira->codegen->builtin_types.entry_invalid;
66666707
6667 bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var;6708 bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var;
...@@ -6670,6 +6711,77 @@ static TypeTableEntry *ir_analyze_instruction_container_init_fields(IrAnalyze *i...@@ -6670,6 +6711,77 @@ static TypeTableEntry *ir_analyze_instruction_container_init_fields(IrAnalyze *i
6670 instruction->field_count, instruction->fields, depends_on_compile_var);6711 instruction->field_count, instruction->fields, depends_on_compile_var);
6671}6712}
66726713
6714static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruction,
6715 IrInstruction *target_type_value, bool is_max)
6716{
6717 TypeTableEntry *target_type = ir_resolve_type(ira, target_type_value);
6718 bool depends_on_compile_var = target_type_value->static_value.depends_on_compile_var;
6719 switch (target_type->id) {
6720 case TypeTableEntryIdInvalid:
6721 return ira->codegen->builtin_types.entry_invalid;
6722 case TypeTableEntryIdInt:
6723 {
6724 ConstExprValue *out_val = ir_build_const_from(ira, source_instruction, depends_on_compile_var);
6725 eval_min_max_value(ira->codegen, target_type, out_val, is_max);
6726 return ira->codegen->builtin_types.entry_num_lit_int;
6727 }
6728 case TypeTableEntryIdFloat:
6729 {
6730 ConstExprValue *out_val = ir_build_const_from(ira, source_instruction, depends_on_compile_var);
6731 eval_min_max_value(ira->codegen, target_type, out_val, is_max);
6732 return ira->codegen->builtin_types.entry_num_lit_float;
6733 }
6734 case TypeTableEntryIdBool:
6735 case TypeTableEntryIdVoid:
6736 {
6737 ConstExprValue *out_val = ir_build_const_from(ira, source_instruction, depends_on_compile_var);
6738 eval_min_max_value(ira->codegen, target_type, out_val, is_max);
6739 return target_type;
6740 }
6741 case TypeTableEntryIdVar:
6742 case TypeTableEntryIdMetaType:
6743 case TypeTableEntryIdUnreachable:
6744 case TypeTableEntryIdPointer:
6745 case TypeTableEntryIdArray:
6746 case TypeTableEntryIdStruct:
6747 case TypeTableEntryIdNumLitFloat:
6748 case TypeTableEntryIdNumLitInt:
6749 case TypeTableEntryIdUndefLit:
6750 case TypeTableEntryIdNullLit:
6751 case TypeTableEntryIdMaybe:
6752 case TypeTableEntryIdErrorUnion:
6753 case TypeTableEntryIdPureError:
6754 case TypeTableEntryIdEnum:
6755 case TypeTableEntryIdUnion:
6756 case TypeTableEntryIdFn:
6757 case TypeTableEntryIdTypeDecl:
6758 case TypeTableEntryIdNamespace:
6759 case TypeTableEntryIdBlock:
6760 case TypeTableEntryIdBoundFn:
6761 {
6762 const char *err_format = is_max ?
6763 "no max value available for type '%s'" :
6764 "no min value available for type '%s'";
6765 ir_add_error(ira, source_instruction,
6766 buf_sprintf(err_format, buf_ptr(&target_type->name)));
6767 return ira->codegen->builtin_types.entry_invalid;
6768 }
6769 }
6770 zig_unreachable();
6771}
6772
6773static TypeTableEntry *ir_analyze_instruction_min_value(IrAnalyze *ira,
6774 IrInstructionMinValue *instruction)
6775{
6776 return ir_analyze_min_max(ira, &instruction->base, instruction->value->other, false);
6777}
6778
6779static TypeTableEntry *ir_analyze_instruction_max_value(IrAnalyze *ira,
6780 IrInstructionMaxValue *instruction)
6781{
6782 return ir_analyze_min_max(ira, &instruction->base, instruction->value->other, true);
6783}
6784
6673static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {6785static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
6674 switch (instruction->id) {6786 switch (instruction->id) {
6675 case IrInstructionIdInvalid:6787 case IrInstructionIdInvalid:
...@@ -6754,6 +6866,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -6754,6 +6866,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
6754 return ir_analyze_instruction_container_init_list(ira, (IrInstructionContainerInitList *)instruction);6866 return ir_analyze_instruction_container_init_list(ira, (IrInstructionContainerInitList *)instruction);
6755 case IrInstructionIdContainerInitFields:6867 case IrInstructionIdContainerInitFields:
6756 return ir_analyze_instruction_container_init_fields(ira, (IrInstructionContainerInitFields *)instruction);6868 return ir_analyze_instruction_container_init_fields(ira, (IrInstructionContainerInitFields *)instruction);
6869 case IrInstructionIdMinValue:
6870 return ir_analyze_instruction_min_value(ira, (IrInstructionMinValue *)instruction);
6871 case IrInstructionIdMaxValue:
6872 return ir_analyze_instruction_max_value(ira, (IrInstructionMaxValue *)instruction);
6757 case IrInstructionIdCast:6873 case IrInstructionIdCast:
6758 case IrInstructionIdStructFieldPtr:6874 case IrInstructionIdStructFieldPtr:
6759 case IrInstructionIdEnumFieldPtr:6875 case IrInstructionIdEnumFieldPtr:
...@@ -6880,6 +6996,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -6880,6 +6996,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
6880 case IrInstructionIdEnumTag:6996 case IrInstructionIdEnumTag:
6881 case IrInstructionIdStaticEval:6997 case IrInstructionIdStaticEval:
6882 case IrInstructionIdRef:6998 case IrInstructionIdRef:
6999 case IrInstructionIdMinValue:
7000 case IrInstructionIdMaxValue:
6883 return false;7001 return false;
6884 case IrInstructionIdAsm:7002 case IrInstructionIdAsm:
6885 {7003 {
...@@ -6892,32 +7010,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -6892,32 +7010,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
68927010
6893// TODO port over all this commented out code into new IR way of doing things7011// TODO port over all this commented out code into new IR way of doing things
68947012
6895//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6896// AstNode *node, const char *err_format, bool is_max)
6897//{
6898// assert(node->type == NodeTypeFnCallExpr);
6899// assert(node->data.fn_call_expr.params.length == 1);
6900//
6901// AstNode *type_node = node->data.fn_call_expr.params.at(0);
6902// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
6903//
6904// if (type_entry->id == TypeTableEntryIdInvalid) {
6905// return g->builtin_types.entry_invalid;
6906// } else if (type_entry->id == TypeTableEntryIdInt) {
6907// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
6908// return g->builtin_types.entry_num_lit_int;
6909// } else if (type_entry->id == TypeTableEntryIdFloat) {
6910// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
6911// return g->builtin_types.entry_num_lit_float;
6912// } else if (type_entry->id == TypeTableEntryIdBool) {
6913// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
6914// return type_entry;
6915// } else {
6916// add_node_error(g, node,
6917// buf_sprintf(err_format, buf_ptr(&type_entry->name)));
6918// return g->builtin_types.entry_invalid;
6919// }
6920//}
69217013
6922//static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,7014//static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,
6923// BlockContext *parent_context, AstNode *node)7015// BlockContext *parent_context, AstNode *node)
...@@ -7393,12 +7485,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7393,12 +7485,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7393// align_in_bytes, false);7485// align_in_bytes, false);
7394// }7486// }
7395// }7487// }
7396// case BuiltinFnIdMaxValue:
7397// return analyze_min_max_value(g, import, context, node,
7398// "no max value available for type '%s'", true);
7399// case BuiltinFnIdMinValue:
7400// return analyze_min_max_value(g, import, context, node,
7401// "no min value available for type '%s'", false);
7402// case BuiltinFnIdMemberCount:7488// case BuiltinFnIdMemberCount:
7403// {7489// {
7404// AstNode *type_node = node->data.fn_call_expr.params.at(0);7490// AstNode *type_node = node->data.fn_call_expr.params.at(0);
src/ir_print.cpp+18
...@@ -658,6 +658,18 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {...@@ -658,6 +658,18 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
658 ir_print_other_instruction(irp, instruction->value);658 ir_print_other_instruction(irp, instruction->value);
659}659}
660660
661static void ir_print_min_value(IrPrint *irp, IrInstructionMinValue *instruction) {
662 fprintf(irp->f, "@minValue(");
663 ir_print_other_instruction(irp, instruction->value);
664 fprintf(irp->f, ")");
665}
666
667static void ir_print_max_value(IrPrint *irp, IrInstructionMaxValue *instruction) {
668 fprintf(irp->f, "@maxValue(");
669 ir_print_other_instruction(irp, instruction->value);
670 fprintf(irp->f, ")");
671}
672
661static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {673static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
662 ir_print_prefix(irp, instruction);674 ir_print_prefix(irp, instruction);
663 switch (instruction->id) {675 switch (instruction->id) {
...@@ -795,6 +807,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -795,6 +807,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
795 case IrInstructionIdRef:807 case IrInstructionIdRef:
796 ir_print_ref(irp, (IrInstructionRef *)instruction);808 ir_print_ref(irp, (IrInstructionRef *)instruction);
797 break;809 break;
810 case IrInstructionIdMinValue:
811 ir_print_min_value(irp, (IrInstructionMinValue *)instruction);
812 break;
813 case IrInstructionIdMaxValue:
814 ir_print_max_value(irp, (IrInstructionMaxValue *)instruction);
815 break;
798 }816 }
799 fprintf(irp->f, "\n");817 fprintf(irp->f, "\n");
800}818}
test/self_hosted2.zig+35
...@@ -204,6 +204,39 @@ fn testStaticAddOne() {...@@ -204,6 +204,39 @@ fn testStaticAddOne() {
204 assert(should_be_1235 == 1235);204 assert(should_be_1235 == 1235);
205}205}
206206
207fn gimme1or2(inline a: bool) -> i32 {
208 const x: i32 = 1;
209 const y: i32 = 2;
210 inline var z: i32 = inline if (a) x else y;
211 return z;
212}
213
214fn testInlineVarsAgain() {
215 assert(gimme1or2(true) == 1);
216 assert(gimme1or2(false) == 2);
217}
218
219fn testMinValueAndMaxValue() {
220 assert(@maxValue(u8) == 255);
221 assert(@maxValue(u16) == 65535);
222 assert(@maxValue(u32) == 4294967295);
223 assert(@maxValue(u64) == 18446744073709551615);
224
225 assert(@maxValue(i8) == 127);
226 assert(@maxValue(i16) == 32767);
227 assert(@maxValue(i32) == 2147483647);
228 assert(@maxValue(i64) == 9223372036854775807);
229
230 assert(@minValue(u8) == 0);
231 assert(@minValue(u16) == 0);
232 assert(@minValue(u32) == 0);
233 assert(@minValue(u64) == 0);
234
235 assert(@minValue(i8) == -128);
236 assert(@minValue(i16) == -32768);
237 assert(@minValue(i32) == -2147483648);
238 assert(@minValue(i64) == -9223372036854775808);
239}
207240
208fn assert(ok: bool) {241fn assert(ok: bool) {
209 if (!ok)242 if (!ok)
...@@ -228,6 +261,8 @@ fn runAllTests() {...@@ -228,6 +261,8 @@ fn runAllTests() {
228 shortCircuit();261 shortCircuit();
229 testGotoLeaveDeferScope(true);262 testGotoLeaveDeferScope(true);
230 testStaticAddOne();263 testStaticAddOne();
264 testInlineVarsAgain();
265 testMinValueAndMaxValue();
231}266}
232267
233export nakedcc fn _start() -> unreachable {268export nakedcc fn _start() -> unreachable {