From aaf2230ae89d74497042b7fada8c8023bf274dbd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 8 Mar 2018 17:15:55 -0500 Subject: [PATCH] fix partial inlining of binary math operator using old value the code was abusing the internal IR API. fixed now. closes #699 --- src/ir.cpp | 16 ++++++++-------- test/cases/eval.zig | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 811744e9d0..67caa84a93 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10595,9 +10595,9 @@ static TypeTableEntry *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp * if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) { ConstExprValue *op1_val = &op1->value; ConstExprValue *op2_val = &casted_op2->value; - ConstExprValue *out_val = &bin_op_instruction->base.value; - - bin_op_instruction->base.other = &bin_op_instruction->base; + IrInstruction *result_instruction = ir_get_const(ira, &bin_op_instruction->base); + ir_link_new_instruction(result_instruction, &bin_op_instruction->base); + ConstExprValue *out_val = &result_instruction->value; int err; if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, out_val))) { @@ -10613,7 +10613,7 @@ static TypeTableEntry *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp * return ira->codegen->builtin_types.entry_invalid; } - ir_num_lit_fits_in_other_type(ira, &bin_op_instruction->base, op1->value.type, false); + ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false); return op1->value.type; } else if (op1->value.type->id == TypeTableEntryIdNumLitInt) { ir_add_error(ira, &bin_op_instruction->base, @@ -10765,9 +10765,9 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) { ConstExprValue *op1_val = &casted_op1->value; ConstExprValue *op2_val = &casted_op2->value; - ConstExprValue *out_val = &bin_op_instruction->base.value; - - bin_op_instruction->base.other = &bin_op_instruction->base; + IrInstruction *result_instruction = ir_get_const(ira, &bin_op_instruction->base); + ir_link_new_instruction(result_instruction, &bin_op_instruction->base); + ConstExprValue *out_val = &result_instruction->value; int err; if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, out_val))) { @@ -10789,7 +10789,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp return ira->codegen->builtin_types.entry_invalid; } - ir_num_lit_fits_in_other_type(ira, &bin_op_instruction->base, resolved_type, false); + ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false); return resolved_type; } diff --git a/test/cases/eval.zig b/test/cases/eval.zig index fc67d8f135..e5e826effc 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -395,3 +395,28 @@ test "comptime slice of undefined pointer of length 0" { const slice2 = (&i32)(undefined)[100..100]; assert(slice2.len == 0); } + +fn copyWithPartialInline(s: []u32, b: []u8) void { + comptime var i: usize = 0; + inline while (i < 4) : (i += 1) { + s[i] = 0; + s[i] |= u32(b[i*4+0]) << 24; + s[i] |= u32(b[i*4+1]) << 16; + s[i] |= u32(b[i*4+2]) << 8; + s[i] |= u32(b[i*4+3]) << 0; + } +} + +test "binary math operator in partially inlined function" { + var s: [4]u32 = undefined; + var b: [16]u8 = undefined; + + for (b) |*r, i| + *r = u8(i + 1); + + copyWithPartialInline(s[0..], b[0..]); + assert(s[0] == 0x1020304); + assert(s[1] == 0x5060708); + assert(s[2] == 0x90a0b0c); + assert(s[3] == 0xd0e0f10); +}