Commit a6d2bdf605

Andrew Kelley <superjoe30@gmail.com>
2016-12-13 07:48:40
IR: implement breakpoint builtin
1 parent 76a849b
src/all_types.hpp
@@ -1419,6 +1419,7 @@ enum IrInstructionId {
     IrInstructionIdMemcpy,
     IrInstructionIdSlice,
     IrInstructionIdMemberCount,
+    IrInstructionIdBreakpoint,
 };
 
 struct IrInstruction {
@@ -1960,6 +1961,10 @@ struct IrInstructionMemberCount {
     IrInstruction *container;
 };
 
+struct IrInstructionBreakpoint {
+    IrInstruction base;
+};
+
 enum LValPurpose {
     LValPurposeNone,
     LValPurposeAssign,
src/codegen.cpp
@@ -2053,6 +2053,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
     }
 }
 
+static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, IrInstructionBreakpoint *instruction) {
+    LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
+    return nullptr;
+}
+
 static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
     AstNode *source_node = instruction->source_node;
     Scope *scope = instruction->scope;
@@ -2162,6 +2167,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
             return ir_render_memcpy(g, executable, (IrInstructionMemcpy *)instruction);
         case IrInstructionIdSlice:
             return ir_render_slice(g, executable, (IrInstructionSlice *)instruction);
+        case IrInstructionIdBreakpoint:
+            return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction);
         case IrInstructionIdSwitchVar:
         case IrInstructionIdContainerInitList:
         case IrInstructionIdStructInit:
src/ir.cpp
@@ -391,6 +391,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {
     return IrInstructionIdMemberCount;
 }
 
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) {
+    return IrInstructionIdBreakpoint;
+}
+
 template<typename T>
 static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
     T *special_instruction = allocate<T>(1);
@@ -1609,6 +1613,17 @@ static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNod
     return &instruction->base;
 }
 
+static IrInstruction *ir_build_breakpoint(IrBuilder *irb, Scope *scope, AstNode *source_node) {
+    IrInstructionBreakpoint *instruction = ir_build_instruction<IrInstructionBreakpoint>(irb, scope, source_node);
+    return &instruction->base;
+}
+
+static IrInstruction *ir_build_breakpoint_from(IrBuilder *irb, IrInstruction *old_instruction) {
+    IrInstruction *new_instruction = ir_build_breakpoint(irb, old_instruction->scope, old_instruction->source_node);
+    ir_link_new_instruction(new_instruction, old_instruction);
+    return new_instruction;
+}
+
 static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
         bool gen_error_defers, bool gen_maybe_defers)
 {
@@ -2491,12 +2506,13 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
 
                 return ir_build_member_count(irb, scope, node, arg0_value);
             }
+        case BuiltinFnIdBreakpoint:
+            return ir_build_breakpoint(irb, scope, node);
         case BuiltinFnIdAlignof:
         case BuiltinFnIdAddWithOverflow:
         case BuiltinFnIdSubWithOverflow:
         case BuiltinFnIdMulWithOverflow:
         case BuiltinFnIdShlWithOverflow:
-        case BuiltinFnIdBreakpoint:
         case BuiltinFnIdReturnAddress:
         case BuiltinFnIdFrameAddress:
             zig_panic("TODO IR gen more builtin functions");
@@ -8456,6 +8472,11 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns
     return ira->codegen->builtin_types.entry_num_lit_int;
 }
 
+static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) {
+    ir_build_breakpoint_from(&ira->new_irb, &instruction->base);
+    return ira->codegen->builtin_types.entry_void;
+}
+
 static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
     switch (instruction->id) {
         case IrInstructionIdInvalid:
@@ -8580,6 +8601,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
             return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);
         case IrInstructionIdMemberCount:
             return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);
+        case IrInstructionIdBreakpoint:
+            return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction);
         case IrInstructionIdCast:
         case IrInstructionIdStructFieldPtr:
         case IrInstructionIdEnumFieldPtr:
@@ -8683,6 +8706,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
         case IrInstructionIdFence:
         case IrInstructionIdMemset:
         case IrInstructionIdMemcpy:
+        case IrInstructionIdBreakpoint:
             return true;
         case IrInstructionIdPhi:
         case IrInstructionIdUnOp:
@@ -8787,9 +8811,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
 //                            align_in_bytes, false);
 //                }
 //            }
-//        case BuiltinFnIdBreakpoint:
-//            mark_impure_fn(g, context, node);
-//            return g->builtin_types.entry_void;
 //        case BuiltinFnIdReturnAddress:
 //        case BuiltinFnIdFrameAddress:
 //            mark_impure_fn(g, context, node);
@@ -9035,8 +9056,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
 //            zig_unreachable();
 //        case BuiltinFnIdCompileVar:
 //            return nullptr;
-//        case BuiltinFnIdBreakpoint:
-//            return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
 //        case BuiltinFnIdFrameAddress:
 //        case BuiltinFnIdReturnAddress:
 //            {
src/ir_print.cpp
@@ -812,6 +812,10 @@ static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instru
     fprintf(irp->f, ")");
 }
 
+static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instruction) {
+    fprintf(irp->f, "@breakpoint()");
+}
+
 static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
     ir_print_prefix(irp, instruction);
     switch (instruction->id) {
@@ -1009,6 +1013,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
         case IrInstructionIdMemberCount:
             ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);
             break;
+        case IrInstructionIdBreakpoint:
+            ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction);
+            break;
     }
     fprintf(irp->f, "\n");
 }