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