authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-01 17:09:11-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-01 17:09:11-05:00
logc2cee40aec5a65fa1c0d716f4a0660492717c356
tree5e48324b5a20c761b6aa021b6a320a5ed6d8bd6a
parent8524404f715ea660c4469dadb37701f7a46f85af
signaturelock-open Commit is signed but in an unrecognized format.

add advanced IR debugging support

and use it to improve copy_const_val with regards to parent backrefs

3 files changed, 86 insertions(+), 13 deletions(-)

src/all_types.hpp+2-1
...@@ -2649,8 +2649,9 @@ struct IrInstruction {...@@ -2649,8 +2649,9 @@ struct IrInstruction {
2649 // true if this instruction was generated by zig and not from user code2649 // true if this instruction was generated by zig and not from user code
2650 bool is_gen;2650 bool is_gen;
26512651
2652 // for debugging purposes, this is useful to call to inspect the instruction2652 // for debugging purposes, these are useful to call to inspect the instruction
2653 void dump();2653 void dump();
2654 void src();
2654};2655};
26552656
2656struct IrInstructionDeclVarSrc {2657struct IrInstructionDeclVarSrc {
src/ir.cpp+80-12
...@@ -42,6 +42,7 @@ struct IrAnalyze {...@@ -42,6 +42,7 @@ struct IrAnalyze {
42 ZigList<IrSuspendPosition> resume_stack;42 ZigList<IrSuspendPosition> resume_stack;
43 IrBasicBlock *const_predecessor_bb;43 IrBasicBlock *const_predecessor_bb;
44 size_t ref_count;44 size_t ref_count;
45 size_t break_debug_id; // for debugging purposes
4546
46 // For the purpose of using in a debugger47 // For the purpose of using in a debugger
47 void dump();48 void dump();
...@@ -198,6 +199,14 @@ struct ConstCastIntShorten {...@@ -198,6 +199,14 @@ struct ConstCastIntShorten {
198 ZigType *actual_type;199 ZigType *actual_type;
199};200};
200201
202// for debugging purposes
203struct DbgIrBreakPoint {
204 const char *src_file;
205 uint32_t line;
206};
207DbgIrBreakPoint dbg_ir_breakpoints_buf[20];
208size_t dbg_ir_breakpoints_count = 0;
209
201static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);210static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
202static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,211static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
203 ResultLoc *result_loc);212 ResultLoc *result_loc);
...@@ -11355,8 +11364,12 @@ static void copy_const_val(ZigValue *dest, ZigValue *src) {...@@ -11355,8 +11364,12 @@ static void copy_const_val(ZigValue *dest, ZigValue *src) {
11355 dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);11364 dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);
11356 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {11365 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
11357 copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);11366 copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);
11367 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;
11368 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
11369 dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
11358 }11370 }
11359 }11371 }
11372 dest->parent.id = ConstParentIdNone;
11360}11373}
1136111374
11362static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr,11375static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr,
...@@ -11474,6 +11487,14 @@ static IrInstruction *ir_const_noval(IrAnalyze *ira, IrInstruction *old_instruct...@@ -11474,6 +11487,14 @@ static IrInstruction *ir_const_noval(IrAnalyze *ira, IrInstruction *old_instruct
11474 return &const_instruction->base;11487 return &const_instruction->base;
11475}11488}
1147611489
11490// This function initializes the new IrInstruction with the provided ZigValue,
11491// rather than creating a new one.
11492static IrInstruction *ir_const_move(IrAnalyze *ira, IrInstruction *old_instruction, ZigValue *val) {
11493 IrInstruction *result = ir_const_noval(ira, old_instruction);
11494 result->value = val;
11495 return result;
11496}
11497
11477static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,11498static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
11478 ZigType *wanted_type, CastOp cast_op)11499 ZigType *wanted_type, CastOp cast_op)
11479{11500{
...@@ -14216,9 +14237,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -14216,9 +14237,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
14216}14237}
1421714238
14218static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {14239static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
14219 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);14240 return ir_const_move(ira, &instruction->base, instruction->base.value);
14220 copy_const_val(result->value, instruction->base.value);
14221 return result;
14222}14241}
1422314242
14224static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {14243static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
...@@ -16633,6 +16652,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -16633,6 +16652,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1663316652
16634 ZigType *parent_ptr_type = parent_result_loc->value->type;16653 ZigType *parent_ptr_type = parent_result_loc->value->type;
16635 assert(parent_ptr_type->id == ZigTypeIdPointer);16654 assert(parent_ptr_type->id == ZigTypeIdPointer);
16655
16636 if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type,16656 if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type,
16637 ResolveStatusAlignmentKnown)))16657 ResolveStatusAlignmentKnown)))
16638 {16658 {
...@@ -17283,6 +17303,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17283,6 +17303,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17283 return ira->codegen->invalid_instruction;17303 return ira->codegen->invalid_instruction;
17284 if (dest_val->special != ConstValSpecialRuntime) {17304 if (dest_val->special != ConstValSpecialRuntime) {
17285 copy_const_val(dest_val, value->value);17305 copy_const_val(dest_val, value->value);
17306
17286 if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar &&17307 if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar &&
17287 !ira->new_irb.current_basic_block->must_be_comptime_source_instr)17308 !ira->new_irb.current_basic_block->must_be_comptime_source_instr)
17288 {17309 {
...@@ -17556,9 +17577,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17556,9 +17577,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17556 }17577 }
17557 }17578 }
1755817579
17559 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);17580 IrInstruction *new_instruction = ir_const_move(ira, &call_instruction->base, result);
17560 copy_const_val(new_instruction->value, result);
17561 new_instruction->value->type = return_type;
17562 return ir_finish_anal(ira, new_instruction);17581 return ir_finish_anal(ira, new_instruction);
17563 }17582 }
1756417583
...@@ -27978,7 +27997,24 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -27978,7 +27997,24 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
27978 }27997 }
2797927998
27980 if (ira->codegen->verbose_ir) {27999 if (ira->codegen->verbose_ir) {
27981 fprintf(stderr, "analyze #%" PRIu32 "\n", old_instruction->debug_id);28000 fprintf(stderr, "~ ");
28001 old_instruction->src();
28002 fprintf(stderr, "~ ");
28003 ir_print_instruction(codegen, stderr, old_instruction, 0, IrPassSrc);
28004 bool want_break = false;
28005 if (ira->break_debug_id == old_instruction->debug_id) {
28006 want_break = true;
28007 } else if (old_instruction->source_node != nullptr) {
28008 for (size_t i = 0; i < dbg_ir_breakpoints_count; i += 1) {
28009 if (dbg_ir_breakpoints_buf[i].line == old_instruction->source_node->line + 1 &&
28010 buf_ends_with_str(old_instruction->source_node->owner->data.structure.root_struct->path,
28011 dbg_ir_breakpoints_buf[i].src_file))
28012 {
28013 want_break = true;
28014 }
28015 }
28016 }
28017 if (want_break) BREAKPOINT;
27982 }28018 }
27983 IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);28019 IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
27984 if (new_instruction != nullptr) {28020 if (new_instruction != nullptr) {
...@@ -27986,6 +28022,10 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -27986,6 +28022,10 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
27986 old_instruction->child = new_instruction;28022 old_instruction->child = new_instruction;
2798728023
27988 if (type_is_invalid(new_instruction->value->type)) {28024 if (type_is_invalid(new_instruction->value->type)) {
28025 if (ira->codegen->verbose_ir) {
28026 fprintf(stderr, "-> (invalid)");
28027 }
28028
27989 if (new_exec->first_err_trace_msg != nullptr) {28029 if (new_exec->first_err_trace_msg != nullptr) {
27990 ira->codegen->trace_err = new_exec->first_err_trace_msg;28030 ira->codegen->trace_err = new_exec->first_err_trace_msg;
27991 } else {28031 } else {
...@@ -27999,11 +28039,22 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -27999,11 +28039,22 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
27999 old_instruction->source_node, buf_create_from_str("referenced here"));28039 old_instruction->source_node, buf_create_from_str("referenced here"));
28000 }28040 }
28001 return ira->codegen->builtin_types.entry_invalid;28041 return ira->codegen->builtin_types.entry_invalid;
28042 } else if (ira->codegen->verbose_ir) {
28043 fprintf(stderr, "-> ");
28044 if (instr_is_unreachable(new_instruction)) {
28045 fprintf(stderr, "(noreturn)\n");
28046 } else {
28047 ir_print_instruction(codegen, stderr, new_instruction, 0, IrPassGen);
28048 }
28002 }28049 }
2800328050
28004 // unreachable instructions do their own control flow.28051 // unreachable instructions do their own control flow.
28005 if (new_instruction->value->type->id == ZigTypeIdUnreachable)28052 if (new_instruction->value->type->id == ZigTypeIdUnreachable)
28006 continue;28053 continue;
28054 } else {
28055 if (ira->codegen->verbose_ir) {
28056 fprintf(stderr, "-> (null");
28057 }
28007 }28058 }
2800828059
28009 ira->instruction_index += 1;28060 ira->instruction_index += 1;
...@@ -28667,18 +28718,27 @@ Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val) {...@@ -28667,18 +28718,27 @@ Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val) {
28667 return ErrorNone;28718 return ErrorNone;
28668}28719}
2866928720
28670void IrInstruction::dump() {28721void IrInstruction::src() {
28671 IrInstruction *inst = this;28722 IrInstruction *inst = this;
28672 if (inst->source_node != nullptr) {28723 if (inst->source_node != nullptr) {
28673 inst->source_node->src();28724 inst->source_node->src();
28674 } else {28725 } else {
28675 fprintf(stderr, "(null source node)\n");28726 fprintf(stderr, "(null source node)\n");
28676 }28727 }
28728}
28729
28730void IrInstruction::dump() {
28731 IrInstruction *inst = this;
28732 inst->src();
28677 IrPass pass = (inst->child == nullptr) ? IrPassGen : IrPassSrc;28733 IrPass pass = (inst->child == nullptr) ? IrPassGen : IrPassSrc;
28678 ir_print_instruction(inst->scope->codegen, stderr, inst, 0, pass);28734 if (inst->scope == nullptr) {
28679 if (pass == IrPassSrc) {28735 fprintf(stderr, "(null scope)\n");
28680 fprintf(stderr, "-> ");28736 } else {
28681 ir_print_instruction(inst->scope->codegen, stderr, inst->child, 0, IrPassGen);28737 ir_print_instruction(inst->scope->codegen, stderr, inst, 0, pass);
28738 if (pass == IrPassSrc) {
28739 fprintf(stderr, "-> ");
28740 ir_print_instruction(inst->scope->codegen, stderr, inst->child, 0, IrPassGen);
28741 }
28682 }28742 }
28683}28743}
2868428744
...@@ -28689,3 +28749,11 @@ void IrAnalyze::dump() {...@@ -28689,3 +28749,11 @@ void IrAnalyze::dump() {
28689 ir_print_basic_block(this->codegen, stderr, this->new_irb.current_basic_block, 1, IrPassGen);28749 ir_print_basic_block(this->codegen, stderr, this->new_irb.current_basic_block, 1, IrPassGen);
28690 }28750 }
28691}28751}
28752
28753void dbg_ir_break(const char *src_file, uint32_t line) {
28754 dbg_ir_breakpoints_buf[dbg_ir_breakpoints_count] = {src_file, line};
28755 dbg_ir_breakpoints_count += 1;
28756}
28757void dbg_ir_clear(void) {
28758 dbg_ir_breakpoints_count = 0;
28759}
src/ir.hpp+4
...@@ -35,4 +35,8 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va...@@ -35,4 +35,8 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va
35 AstNode *source_node);35 AstNode *source_node);
36const char *float_op_to_name(BuiltinFnId op, bool llvm_name);36const char *float_op_to_name(BuiltinFnId op, bool llvm_name);
3737
38// for debugging purposes
39void dbg_ir_break(const char *src_file, uint32_t line);
40void dbg_ir_clear(void);
41
38#endif42#endif