mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
IR: add minValue, maxValue, and negation
This commit is contained in:
parent
5e4ee659a6
commit
0ad580f001
@ -1393,6 +1393,8 @@ enum IrInstructionId {
|
||||
IrInstructionIdImport,
|
||||
IrInstructionIdArrayLen,
|
||||
IrInstructionIdRef,
|
||||
IrInstructionIdMinValue,
|
||||
IrInstructionIdMaxValue,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
@ -1791,6 +1793,18 @@ struct IrInstructionRef {
|
||||
LLVMValueRef tmp_ptr;
|
||||
};
|
||||
|
||||
struct IrInstructionMinValue {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionMaxValue {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
enum LValPurpose {
|
||||
LValPurposeNone,
|
||||
LValPurposeAssign,
|
||||
|
||||
@ -1821,6 +1821,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdStaticEval:
|
||||
case IrInstructionIdImport:
|
||||
case IrInstructionIdContainerInitFields:
|
||||
case IrInstructionIdMinValue:
|
||||
case IrInstructionIdMaxValue:
|
||||
zig_unreachable();
|
||||
case IrInstructionIdReturn:
|
||||
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
|
||||
|
||||
@ -431,6 +431,8 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
|
||||
} else if (type_entry->id == TypeTableEntryIdBool) {
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->data.x_bool = is_max;
|
||||
} else if (type_entry->id == TypeTableEntryIdVoid) {
|
||||
// nothing to do
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
250
src/ir.cpp
250
src/ir.cpp
@ -306,6 +306,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {
|
||||
return IrInstructionIdStructInit;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionMinValue *) {
|
||||
return IrInstructionIdMinValue;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionMaxValue *) {
|
||||
return IrInstructionIdMaxValue;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
|
||||
T *special_instruction = allocate<T>(1);
|
||||
@ -1241,6 +1249,25 @@ static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instr
|
||||
return new_instruction;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_min_value(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
|
||||
IrInstructionMinValue *instruction = ir_build_instruction<IrInstructionMinValue>(irb, scope, source_node);
|
||||
instruction->value = value;
|
||||
|
||||
ir_ref_instruction(value);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_max_value(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
|
||||
IrInstructionMaxValue *instruction = ir_build_instruction<IrInstructionMaxValue>(irb, scope, source_node);
|
||||
instruction->value = value;
|
||||
|
||||
ir_ref_instruction(value);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
|
||||
static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
|
||||
bool gen_error_defers, bool gen_maybe_defers)
|
||||
{
|
||||
@ -1879,11 +1906,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
||||
|
||||
return ir_build_import(irb, scope, node, arg0_value);
|
||||
}
|
||||
case BuiltinFnIdMaxValue:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
return ir_build_max_value(irb, scope, node, arg0_value);
|
||||
}
|
||||
case BuiltinFnIdMinValue:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
return ir_build_min_value(irb, scope, node, arg0_value);
|
||||
}
|
||||
case BuiltinFnIdMemcpy:
|
||||
case BuiltinFnIdMemset:
|
||||
case BuiltinFnIdAlignof:
|
||||
case BuiltinFnIdMaxValue:
|
||||
case BuiltinFnIdMinValue:
|
||||
case BuiltinFnIdMemberCount:
|
||||
case BuiltinFnIdAddWithOverflow:
|
||||
case BuiltinFnIdSubWithOverflow:
|
||||
@ -4670,7 +4713,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
|
||||
if (is_inline || fn_ref->static_value.special != ConstValSpecialRuntime) {
|
||||
if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {
|
||||
TypeTableEntry *dest_type = ir_resolve_type(ira, fn_ref);
|
||||
if (!dest_type)
|
||||
if (dest_type->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
size_t actual_param_count = call_instruction->arg_count;
|
||||
@ -4958,6 +5001,48 @@ static TypeTableEntry *ir_analyze_unwrap_maybe(IrAnalyze *ira, IrInstructionUnOp
|
||||
}
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||
IrInstruction *value = un_op_instruction->value->other;
|
||||
TypeTableEntry *expr_type = value->type_entry;
|
||||
if (expr_type->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
bool is_wrap_op = (un_op_instruction->op_id == IrUnOpNegationWrap);
|
||||
|
||||
if ((expr_type->id == TypeTableEntryIdInt && expr_type->data.integral.is_signed) ||
|
||||
expr_type->id == TypeTableEntryIdNumLitInt ||
|
||||
((expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdNumLitFloat) &&
|
||||
!is_wrap_op))
|
||||
{
|
||||
ConstExprValue *target_const_val = &value->static_value;
|
||||
if (target_const_val->special != ConstValSpecialRuntime) {
|
||||
bool depends_on_compile_var = value->static_value.depends_on_compile_var;
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, depends_on_compile_var);
|
||||
bignum_negate(&out_val->data.x_bignum, &target_const_val->data.x_bignum);
|
||||
if (expr_type->id == TypeTableEntryIdFloat ||
|
||||
expr_type->id == TypeTableEntryIdNumLitFloat ||
|
||||
expr_type->id == TypeTableEntryIdNumLitInt)
|
||||
{
|
||||
return expr_type;
|
||||
}
|
||||
|
||||
bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum, expr_type->data.integral.bit_count, true);
|
||||
if (is_wrap_op) {
|
||||
if (overflow)
|
||||
out_val->data.x_bignum.is_negative = true;
|
||||
} else if (overflow) {
|
||||
ir_add_error(ira, &un_op_instruction->base, buf_sprintf("negation caused overflow"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
return expr_type;
|
||||
}
|
||||
}
|
||||
|
||||
const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
|
||||
ir_add_error(ira, &un_op_instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||
IrUnOp op_id = un_op_instruction->op_id;
|
||||
switch (op_id) {
|
||||
@ -4983,51 +5068,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
|
||||
//}
|
||||
case IrUnOpNegation:
|
||||
case IrUnOpNegationWrap:
|
||||
zig_panic("TODO analyze PrefixOpNegation[Wrap]");
|
||||
//{
|
||||
// TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
|
||||
// if (expr_type->id == TypeTableEntryIdInvalid) {
|
||||
// return expr_type;
|
||||
// } else if ((expr_type->id == TypeTableEntryIdInt &&
|
||||
// expr_type->data.integral.is_signed) ||
|
||||
// expr_type->id == TypeTableEntryIdNumLitInt ||
|
||||
// ((expr_type->id == TypeTableEntryIdFloat ||
|
||||
// expr_type->id == TypeTableEntryIdNumLitFloat) &&
|
||||
// prefix_op != PrefixOpNegationWrap))
|
||||
// {
|
||||
// ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
|
||||
// if (!target_const_val->ok) {
|
||||
// return expr_type;
|
||||
// }
|
||||
// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
|
||||
// const_val->ok = true;
|
||||
// const_val->depends_on_compile_var = target_const_val->depends_on_compile_var;
|
||||
// bignum_negate(&const_val->data.x_bignum, &target_const_val->data.x_bignum);
|
||||
// if (expr_type->id == TypeTableEntryIdFloat ||
|
||||
// expr_type->id == TypeTableEntryIdNumLitFloat ||
|
||||
// expr_type->id == TypeTableEntryIdNumLitInt)
|
||||
// {
|
||||
// return expr_type;
|
||||
// }
|
||||
|
||||
// bool overflow = !bignum_fits_in_bits(&const_val->data.x_bignum,
|
||||
// expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
|
||||
// if (prefix_op == PrefixOpNegationWrap) {
|
||||
// if (overflow) {
|
||||
// const_val->data.x_bignum.is_negative = true;
|
||||
// }
|
||||
// } else if (overflow) {
|
||||
// add_node_error(g, *expr_node, buf_sprintf("negation caused overflow"));
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// }
|
||||
// return expr_type;
|
||||
// } else {
|
||||
// const char *fmt = (prefix_op == PrefixOpNegationWrap) ?
|
||||
// "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
|
||||
// add_node_error(g, node, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// }
|
||||
//}
|
||||
return ir_analyze_negation(ira, un_op_instruction);
|
||||
case IrUnOpAddressOf:
|
||||
case IrUnOpConstAddressOf:
|
||||
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
|
||||
static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) {
|
||||
IrInstruction *container_type_value = instruction->container_type->other;
|
||||
TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);
|
||||
if (!container_type)
|
||||
if (container_type->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
size_t elem_count = instruction->item_count;
|
||||
@ -6661,7 +6702,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
|
||||
static TypeTableEntry *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {
|
||||
IrInstruction *container_type_value = instruction->container_type->other;
|
||||
TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);
|
||||
if (!container_type)
|
||||
if (container_type->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
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
|
||||
instruction->field_count, instruction->fields, depends_on_compile_var);
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruction,
|
||||
IrInstruction *target_type_value, bool is_max)
|
||||
{
|
||||
TypeTableEntry *target_type = ir_resolve_type(ira, target_type_value);
|
||||
bool depends_on_compile_var = target_type_value->static_value.depends_on_compile_var;
|
||||
switch (target_type->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdInt:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, source_instruction, depends_on_compile_var);
|
||||
eval_min_max_value(ira->codegen, target_type, out_val, is_max);
|
||||
return ira->codegen->builtin_types.entry_num_lit_int;
|
||||
}
|
||||
case TypeTableEntryIdFloat:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, source_instruction, depends_on_compile_var);
|
||||
eval_min_max_value(ira->codegen, target_type, out_val, is_max);
|
||||
return ira->codegen->builtin_types.entry_num_lit_float;
|
||||
}
|
||||
case TypeTableEntryIdBool:
|
||||
case TypeTableEntryIdVoid:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, source_instruction, depends_on_compile_var);
|
||||
eval_min_max_value(ira->codegen, target_type, out_val, is_max);
|
||||
return target_type;
|
||||
}
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
{
|
||||
const char *err_format = is_max ?
|
||||
"no max value available for type '%s'" :
|
||||
"no min value available for type '%s'";
|
||||
ir_add_error(ira, source_instruction,
|
||||
buf_sprintf(err_format, buf_ptr(&target_type->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_min_value(IrAnalyze *ira,
|
||||
IrInstructionMinValue *instruction)
|
||||
{
|
||||
return ir_analyze_min_max(ira, &instruction->base, instruction->value->other, false);
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_max_value(IrAnalyze *ira,
|
||||
IrInstructionMaxValue *instruction)
|
||||
{
|
||||
return ir_analyze_min_max(ira, &instruction->base, instruction->value->other, true);
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
|
||||
switch (instruction->id) {
|
||||
case IrInstructionIdInvalid:
|
||||
@ -6754,6 +6866,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
||||
return ir_analyze_instruction_container_init_list(ira, (IrInstructionContainerInitList *)instruction);
|
||||
case IrInstructionIdContainerInitFields:
|
||||
return ir_analyze_instruction_container_init_fields(ira, (IrInstructionContainerInitFields *)instruction);
|
||||
case IrInstructionIdMinValue:
|
||||
return ir_analyze_instruction_min_value(ira, (IrInstructionMinValue *)instruction);
|
||||
case IrInstructionIdMaxValue:
|
||||
return ir_analyze_instruction_max_value(ira, (IrInstructionMaxValue *)instruction);
|
||||
case IrInstructionIdCast:
|
||||
case IrInstructionIdStructFieldPtr:
|
||||
case IrInstructionIdEnumFieldPtr:
|
||||
@ -6880,6 +6996,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
case IrInstructionIdEnumTag:
|
||||
case IrInstructionIdStaticEval:
|
||||
case IrInstructionIdRef:
|
||||
case IrInstructionIdMinValue:
|
||||
case IrInstructionIdMaxValue:
|
||||
return false;
|
||||
case IrInstructionIdAsm:
|
||||
{
|
||||
@ -6892,32 +7010,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
|
||||
// TODO port over all this commented out code into new IR way of doing things
|
||||
|
||||
//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
// AstNode *node, const char *err_format, bool is_max)
|
||||
//{
|
||||
// assert(node->type == NodeTypeFnCallExpr);
|
||||
// assert(node->data.fn_call_expr.params.length == 1);
|
||||
//
|
||||
// AstNode *type_node = node->data.fn_call_expr.params.at(0);
|
||||
// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
|
||||
//
|
||||
// if (type_entry->id == TypeTableEntryIdInvalid) {
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// } else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
|
||||
// return g->builtin_types.entry_num_lit_int;
|
||||
// } else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
|
||||
// return g->builtin_types.entry_num_lit_float;
|
||||
// } else if (type_entry->id == TypeTableEntryIdBool) {
|
||||
// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
|
||||
// return type_entry;
|
||||
// } else {
|
||||
// add_node_error(g, node,
|
||||
// buf_sprintf(err_format, buf_ptr(&type_entry->name)));
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// }
|
||||
//}
|
||||
|
||||
//static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,
|
||||
// BlockContext *parent_context, AstNode *node)
|
||||
@ -7393,12 +7485,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
// align_in_bytes, false);
|
||||
// }
|
||||
// }
|
||||
// case BuiltinFnIdMaxValue:
|
||||
// return analyze_min_max_value(g, import, context, node,
|
||||
// "no max value available for type '%s'", true);
|
||||
// case BuiltinFnIdMinValue:
|
||||
// return analyze_min_max_value(g, import, context, node,
|
||||
// "no min value available for type '%s'", false);
|
||||
// case BuiltinFnIdMemberCount:
|
||||
// {
|
||||
// AstNode *type_node = node->data.fn_call_expr.params.at(0);
|
||||
|
||||
@ -658,6 +658,18 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
}
|
||||
|
||||
static void ir_print_min_value(IrPrint *irp, IrInstructionMinValue *instruction) {
|
||||
fprintf(irp->f, "@minValue(");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_max_value(IrPrint *irp, IrInstructionMaxValue *instruction) {
|
||||
fprintf(irp->f, "@maxValue(");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
switch (instruction->id) {
|
||||
@ -795,6 +807,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdRef:
|
||||
ir_print_ref(irp, (IrInstructionRef *)instruction);
|
||||
break;
|
||||
case IrInstructionIdMinValue:
|
||||
ir_print_min_value(irp, (IrInstructionMinValue *)instruction);
|
||||
break;
|
||||
case IrInstructionIdMaxValue:
|
||||
ir_print_max_value(irp, (IrInstructionMaxValue *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
||||
@ -204,6 +204,39 @@ fn testStaticAddOne() {
|
||||
assert(should_be_1235 == 1235);
|
||||
}
|
||||
|
||||
fn gimme1or2(inline a: bool) -> i32 {
|
||||
const x: i32 = 1;
|
||||
const y: i32 = 2;
|
||||
inline var z: i32 = inline if (a) x else y;
|
||||
return z;
|
||||
}
|
||||
|
||||
fn testInlineVarsAgain() {
|
||||
assert(gimme1or2(true) == 1);
|
||||
assert(gimme1or2(false) == 2);
|
||||
}
|
||||
|
||||
fn testMinValueAndMaxValue() {
|
||||
assert(@maxValue(u8) == 255);
|
||||
assert(@maxValue(u16) == 65535);
|
||||
assert(@maxValue(u32) == 4294967295);
|
||||
assert(@maxValue(u64) == 18446744073709551615);
|
||||
|
||||
assert(@maxValue(i8) == 127);
|
||||
assert(@maxValue(i16) == 32767);
|
||||
assert(@maxValue(i32) == 2147483647);
|
||||
assert(@maxValue(i64) == 9223372036854775807);
|
||||
|
||||
assert(@minValue(u8) == 0);
|
||||
assert(@minValue(u16) == 0);
|
||||
assert(@minValue(u32) == 0);
|
||||
assert(@minValue(u64) == 0);
|
||||
|
||||
assert(@minValue(i8) == -128);
|
||||
assert(@minValue(i16) == -32768);
|
||||
assert(@minValue(i32) == -2147483648);
|
||||
assert(@minValue(i64) == -9223372036854775808);
|
||||
}
|
||||
|
||||
fn assert(ok: bool) {
|
||||
if (!ok)
|
||||
@ -228,6 +261,8 @@ fn runAllTests() {
|
||||
shortCircuit();
|
||||
testGotoLeaveDeferScope(true);
|
||||
testStaticAddOne();
|
||||
testInlineVarsAgain();
|
||||
testMinValueAndMaxValue();
|
||||
}
|
||||
|
||||
export nakedcc fn _start() -> unreachable {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user