Commit e1d14e73b5

Andrew Kelley <andrew@ziglang.org>
2019-06-11 21:44:06
fix `@bitCast` semantics when there is no parent result loc
1 parent 60c3861
src/all_types.hpp
@@ -44,6 +44,7 @@ struct IrAnalyze;
 struct ResultLoc;
 struct ResultLocPeer;
 struct ResultLocPeerParent;
+struct ResultLocBitCast;
 
 enum X64CABIClass {
     X64CABIClass_Unknown,
@@ -2272,6 +2273,7 @@ enum IrInstructionId {
     IrInstructionIdTestComptime,
     IrInstructionIdPtrCastSrc,
     IrInstructionIdPtrCastGen,
+    IrInstructionIdBitCastSrc,
     IrInstructionIdBitCastGen,
     IrInstructionIdWidenOrShorten,
     IrInstructionIdIntToPtr,
@@ -3159,6 +3161,13 @@ struct IrInstructionPtrCastGen {
     bool safety_check_on;
 };
 
+struct IrInstructionBitCastSrc {
+    IrInstruction base;
+
+    IrInstruction *operand;
+    ResultLocBitCast *result_loc_bit_cast;
+};
+
 struct IrInstructionBitCastGen {
     IrInstruction base;
 
src/codegen.cpp
@@ -5543,6 +5543,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
         case IrInstructionIdContainerInitList:
         case IrInstructionIdSliceSrc:
         case IrInstructionIdRef:
+        case IrInstructionIdBitCastSrc:
             zig_unreachable();
 
         case IrInstructionIdDeclVarGen:
src/ir.cpp
@@ -792,6 +792,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
     return IrInstructionIdPtrCastGen;
 }
 
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastSrc *) {
+    return IrInstructionIdBitCastSrc;
+}
+
 static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
     return IrInstructionIdBitCastGen;
 }
@@ -2515,6 +2519,18 @@ static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *sourc
     return &instruction->base;
 }
 
+static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+        IrInstruction *operand, ResultLocBitCast *result_loc_bit_cast)
+{
+    IrInstructionBitCastSrc *instruction = ir_build_instruction<IrInstructionBitCastSrc>(irb, scope, source_node);
+    instruction->operand = operand;
+    instruction->result_loc_bit_cast = result_loc_bit_cast;
+
+    ir_ref_instruction(operand, irb->current_basic_block);
+
+    return &instruction->base;
+}
+
 static IrInstruction *ir_build_bit_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
         IrInstruction *operand, ZigType *ty)
 {
@@ -4941,7 +4957,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
                 if (arg1_value == irb->codegen->invalid_instruction)
                     return arg1_value;
 
-                return ir_lval_wrap(irb, scope, arg1_value, lval, result_loc);
+                IrInstruction *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast);
+                return ir_lval_wrap(irb, scope, bitcast, lval, result_loc);
             }
         case BuiltinFnIdIntToPtr:
             {
@@ -14910,9 +14927,15 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
                 return ira->codegen->invalid_instruction;
             }
 
+            IrInstruction *bitcasted_value;
+            if (value != nullptr) {
+                bitcasted_value = ir_analyze_bit_cast(ira, result_loc->source_instruction, value, dest_type);
+            } else {
+                bitcasted_value = nullptr;
+            }
 
             IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
-                    dest_type, nullptr);
+                    dest_type, bitcasted_value);
             if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
                 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
             {
@@ -24168,6 +24191,17 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
     return ir_const_void(ira, &instruction->base);
 }
 
+static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) {
+    IrInstruction *operand = instruction->operand->child;
+    if (type_is_invalid(operand->value.type) || instr_is_comptime(operand) ||
+        instruction->result_loc_bit_cast->parent->gen_instruction == nullptr)
+    {
+        return operand;
+    }
+
+    return instruction->result_loc_bit_cast->parent->gen_instruction;
+}
+
 static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
     switch (instruction->id) {
         case IrInstructionIdInvalid:
@@ -24472,6 +24506,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
             return nullptr;
         case IrInstructionIdEndExpr:
             return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction);
+        case IrInstructionIdBitCastSrc:
+            return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);
     }
     zig_unreachable();
 }
@@ -24663,6 +24699,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
         case IrInstructionIdTestComptime:
         case IrInstructionIdPtrCastSrc:
         case IrInstructionIdPtrCastGen:
+        case IrInstructionIdBitCastSrc:
         case IrInstructionIdBitCastGen:
         case IrInstructionIdWidenOrShorten:
         case IrInstructionIdPtrToInt:
src/ir_print.cpp
@@ -1046,6 +1046,13 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
     fprintf(irp->f, ")");
 }
 
+static void ir_print_bit_cast_src(IrPrint *irp, IrInstructionBitCastSrc *instruction) {
+    fprintf(irp->f, "@bitCast(");
+    ir_print_other_instruction(irp, instruction->operand);
+    fprintf(irp->f, ")result=");
+    ir_print_result_loc(irp, &instruction->result_loc_bit_cast->base);
+}
+
 static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) {
     fprintf(irp->f, "@bitCast(");
     ir_print_other_instruction(irp, instruction->operand);
@@ -1860,6 +1867,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
         case IrInstructionIdPtrCastGen:
             ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
             break;
+        case IrInstructionIdBitCastSrc:
+            ir_print_bit_cast_src(irp, (IrInstructionBitCastSrc *)instruction);
+            break;
         case IrInstructionIdBitCastGen:
             ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
             break;