From 31ce3fd0cd21e1a808c417f813b3b5285aeb938a Mon Sep 17 00:00:00 2001 From: Serhei Makarov Date: Tue, 6 Nov 2018 12:32:38 -0500 Subject: [PATCH 21/32] bpf behind-the-scenes :: useful DEBUG_CODEGEN diagnostic --- bpf-base.cxx | 10 ++++++++++ bpf-internal.h | 21 +++++++++++++++++++++ bpf-opt.cxx | 28 +++++++++++++++++----------- bpf-translate.cxx | 26 ++++++++++++++++++++++++-- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/bpf-base.cxx b/bpf-base.cxx index 24b610cf3..5d132bcd1 100644 --- a/bpf-base.cxx +++ b/bpf-base.cxx @@ -368,6 +368,10 @@ opcode_name(opcode op) std::ostream & insn::print(std::ostream &o) const { +#ifdef DEBUG_CODEGEN + if (note != "") + o << "{" << note << "} "; +#endif const char *opn = opcode_name (code); switch (code) @@ -541,6 +545,12 @@ insn * insn_inserter::new_insn() { insn *n = new insn; +#ifdef DEBUG_CODEGEN + if (!notes.empty()) + n->note = notes.top(); + else + n->note = ""; +#endif insert(n); return n; } diff --git a/bpf-internal.h b/bpf-internal.h index 82cba2c79..75fefb769 100644 --- a/bpf-internal.h +++ b/bpf-internal.h @@ -48,6 +48,8 @@ namespace bpf { // TODO: BPF_MAX{STRING,FORMAT}LEN,BPF_MAXMAPENTRIES,BPF_MAXSPRINTFLEN should be user-configurable. // XXX: BPF_MAXMAPENTRIES may depend on kernel version. May need to experiment with rlimit in instantiate_maps(). +// #define DEBUG_CODEGEN + typedef unsigned short regno; static const regno max_regno = BPF_MAXINSNS; static const regno noreg = -1; @@ -135,6 +137,9 @@ struct insn value *src0; // The destination input, pre-allocation value *src1; // The usual source register operand insn *prev, *next; // Linked list of insns in the block +#ifdef DEBUG_CODEGEN + std::string note; // For additional diagnostics. +#endif insn(); @@ -198,8 +203,18 @@ private: public: block *b; insn *i; +#ifdef DEBUG_CODEGEN + std::stack notes; +#endif insn_inserter(block *bb, insn *ii) : b(bb), i(ii) { } + insn_inserter(block *bb, insn *ii, const std::string& note) : b(bb), i(ii) { +#ifdef DEBUG_CODEGEN + notes.push(note); +#else + (void)note; // unused +#endif + } virtual ~insn_inserter() { } virtual void insert(insn *i) = 0; @@ -214,6 +229,8 @@ struct insn_before_inserter : public insn_inserter { insn_before_inserter() : insn_inserter(NULL, NULL) { } insn_before_inserter(block *b, insn *i) : insn_inserter(b,i) { } + insn_before_inserter(block *b, insn *i, const std::string& note) + : insn_inserter(b,i,note) { } virtual void insert(insn *i); }; @@ -221,6 +238,8 @@ struct insn_after_inserter : public insn_inserter { insn_after_inserter() : insn_inserter(NULL, NULL) { } insn_after_inserter(block *b, insn *i) : insn_inserter(b,i) { } + insn_after_inserter(block *b, insn *i, const std::string& note) + : insn_inserter(b,i,note) { } virtual void insert(insn *i); }; @@ -228,6 +247,8 @@ struct insn_append_inserter : public insn_after_inserter { insn_append_inserter() : insn_after_inserter(NULL, NULL) { } insn_append_inserter(block *b) : insn_after_inserter(b, NULL) { } + insn_append_inserter(block *b, const std::string& note) + : insn_after_inserter(b, NULL, note) { } }; struct program diff --git a/bpf-opt.cxx b/bpf-opt.cxx index c2e30a690..904b33b46 100644 --- a/bpf-opt.cxx +++ b/bpf-opt.cxx @@ -59,7 +59,7 @@ lower_str_values(program &p) value *s0 = j->src0; if (s0 && s0->is_str()) { - insn_before_inserter ins(b, j); + insn_before_inserter ins(b, j, "str"); std::string str0 = s0->str(); value *new_s0 = alloc_literal_str(p, ins, str0); j->src0 = new_s0; @@ -68,7 +68,7 @@ lower_str_values(program &p) value *s1 = j->src1; if (s1 && s1->is_str()) { - insn_before_inserter ins(b, j); + insn_before_inserter ins(b, j, "str"); std::string str1 = s1->str(); value *new_s1 = alloc_literal_str(p, ins, str1); j->src1 = new_s1; @@ -97,7 +97,7 @@ fixup_operands(program &p) if (s1 && s1->is_imm() && s1->imm() != (int32_t)s1->imm()) { value *n = p.new_reg(); - insn_before_inserter ins(b, j); + insn_before_inserter ins(b, j, "opt"); p.mk_mov(ins, n, s1); j->src1 = s1 = n; } @@ -121,13 +121,13 @@ fixup_operands(program &p) // Special care for x = y - x value *n = p.new_reg(); { - insn_before_inserter ins(b, j); + insn_before_inserter ins(b, j, "opt"); p.mk_mov(ins, n, s0); } j->src0 = n; j->dest = n; { - insn_after_inserter ins(b, j); + insn_after_inserter ins(b, j, "opt"); p.mk_mov(ins, d, n); } } @@ -135,7 +135,7 @@ fixup_operands(program &p) else { // Transform { x = y - z } to { x = y; x -= z; } - insn_before_inserter ins(b, j); + insn_before_inserter ins(b, j, "opt"); p.mk_mov(ins, d, s0); j->src0 = d; } @@ -144,7 +144,7 @@ fixup_operands(program &p) { // Comparisons can't have src0 constant. value *n = p.new_reg(); - insn_before_inserter ins(b, j); + insn_before_inserter ins(b, j, "opt"); p.mk_mov(ins, n, s0); j->src0 = n; } @@ -293,7 +293,7 @@ reorder_blocks(program &p) if (t) { block *n = p.new_block (); - insn_append_inserter ins(n); + insn_append_inserter ins(n, "opt"); p.mk_jmp (ins, o); ordered.push_back (n); f->redirect_next (n); @@ -301,7 +301,7 @@ reorder_blocks(program &p) else { delete f; - insn_after_inserter ins(b, b->last); + insn_after_inserter ins(b, b->last, "opt"); p.mk_jmp (ins, o); } } @@ -780,7 +780,7 @@ spill(unsigned reg, unsigned num_spills, program &p) // If reg is a source, insert a load before j if ((src0 && src0->reg_val == reg) || (src1 && src1->reg_val == reg)) { - insn_before_inserter ins(b, j); + insn_before_inserter ins(b, j, "regalloc"); new_tmp = p.new_reg(); p.mk_ld (ins, BPF_DW, new_tmp, frame, -off); @@ -795,7 +795,7 @@ spill(unsigned reg, unsigned num_spills, program &p) // If reg is the destination, insert a store after j if (dest && dest->reg_val == reg) { - insn_after_inserter ins(b, j); + insn_after_inserter ins(b, j, "regalloc"); new_tmp = new_tmp ?: p.new_reg(); p.mk_st (ins, BPF_DW, frame, -off, new_tmp); @@ -935,6 +935,9 @@ post_alloc_cleanup (program &p) void program::generate() { +#ifdef DEBUG_CODEGEN + std::cerr << "DEBUG BEFORE OPT " << *this << std::endl; +#endif lower_str_values(*this); fixup_operands(*this); thread_jumps(*this); @@ -942,6 +945,9 @@ program::generate() reorder_blocks(*this); reg_alloc(*this); post_alloc_cleanup(*this); +#ifdef DEBUG_CODEGEN + std::cerr << "DEBUG AFTER OPT " << *this << std::endl; +#endif } } // namespace bpf diff --git a/bpf-translate.cxx b/bpf-translate.cxx index d46dae44a..57a4cb107 100644 --- a/bpf-translate.cxx +++ b/bpf-translate.cxx @@ -310,7 +310,7 @@ bpf_unparser::get_exit_block() return exit_block; block *b = this_prog.new_block(); - insn_append_inserter ins(b); + insn_append_inserter ins(b, "exit_block"); this_prog.mk_exit(ins); @@ -325,7 +325,7 @@ bpf_unparser::get_ret0_block() return ret0_block; block *b = this_prog.new_block(); - insn_append_inserter ins(b); + insn_append_inserter ins(b, "ret0_block"); this_prog.mk_mov(ins, this_prog.lookup_reg(BPF_REG_0), this_prog.new_imm(0)); b->fallthru = new edge(b, get_exit_block()); @@ -1166,6 +1166,9 @@ bpf_unparser::emit_asm_opcode (const asm_stmt &stmt, void bpf_unparser::visit_embeddedcode (embeddedcode *s) { +#ifdef DEBUG_CODEGEN + this_ins.notes.push("asm"); +#endif std::vector statements; asm_stmt stmt; @@ -1429,6 +1432,10 @@ bpf_unparser::visit_embeddedcode (embeddedcode *s) it != adjusted_toks.end(); it++) delete *it; adjusted_toks.clear(); + +#ifdef DEBUG_CODEGEN + this_ins.notes.pop(); // asm +#endif } void @@ -2507,6 +2514,10 @@ value * emit_simple_literal_str(program &this_prog, insn_inserter &this_ins, value *dest, int ofs, std::string &src, bool zero_pad) { +#ifdef DEBUG_CODEGEN + this_ins.notes.push("str"); +#endif + size_t str_bytes = src.size() + 1; size_t str_words = (str_bytes + 3) / 4; @@ -2546,6 +2557,10 @@ emit_simple_literal_str(program &this_prog, insn_inserter &this_ins, value *out = this_prog.new_reg(); this_prog.mk_binary(this_ins, BPF_ADD, out, dest, this_prog.new_imm(ofs)); + +#ifdef DEBUG_CODEGEN + this_ins.notes.pop(); // str +#endif return out; } @@ -2567,6 +2582,10 @@ bpf_unparser::emit_string_copy(value *dest, int ofs, value *src, bool zero_pad) dest, ofs, str, zero_pad); } +#ifdef DEBUG_CODEGEN + this_ins.notes.push("strcpy"); +#endif + size_t str_bytes = BPF_MAXSTRINGLEN; size_t str_words = (str_bytes + 3) / 4; @@ -2674,6 +2693,9 @@ bpf_unparser::emit_string_copy(value *dest, int ofs, value *src, bool zero_pad) value *out = this_prog.new_reg(); this_prog.mk_binary(this_ins, BPF_ADD, out, dest, this_prog.new_imm(ofs)); +#ifdef DEBUG_CODEGEN + this_ins.notes.pop(); // strcpy +#endif return out; } -- 2.14.5