Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion core/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"program": "${workspaceFolder}/build/epasstool/epass",
"args": [
"read",
"bpftests/output/empty.o"
"bpftests/output/loop1.o",
"--gopt",
"verbose=3,cgv2"
],
"cwd": "${workspaceFolder}"
}
Expand Down
2 changes: 2 additions & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ add_library(
aux/disasm.c
aux/kern_utils.c
ir_cg.c
ir_cg_v2.c
ir_cg_norm.c
ir_cg_norm_v2.c
lli.c
include/linux/bpf_ir.h)

Expand Down
2 changes: 2 additions & 0 deletions core/aux/kern_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ static int apply_global_opt(struct bpf_ir_env *env, const char *opt)
env->opts.enable_printk_log = true;
} else if (strcmp(opt, "throw_msg") == 0) {
env->opts.enable_throw_msg = true;
} else if (strcmp(opt, "cgv2") == 0) {
env->opts.cg_v2 = true;
} else if (strncmp(opt, "verbose=", 8) == 0) {
int res = 0;
int err = parse_int(opt + 8, &res);
Expand Down
50 changes: 18 additions & 32 deletions core/bpf_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,7 @@ void bpf_ir_free_function(struct ir_function *fun)
bpf_ir_array_free(&fun->reachable_bbs);
bpf_ir_array_free(&fun->end_bbs);
bpf_ir_array_free(&fun->cg_info.all_var);
bpf_ir_ptrset_free(&fun->cg_info.all_var_v2);
}

static void init_function(struct bpf_ir_env *env, struct ir_function *fun,
Expand All @@ -1426,6 +1427,7 @@ static void init_function(struct bpf_ir_env *env, struct ir_function *fun,
INIT_ARRAY(&fun->reachable_bbs, struct ir_basic_block *);
INIT_ARRAY(&fun->end_bbs, struct ir_basic_block *);
INIT_ARRAY(&fun->cg_info.all_var, struct ir_insn *);
INIT_PTRSET_DEF(&fun->cg_info.all_var_v2);
for (size_t i = 0; i < MAX_BPF_REG; ++i) {
struct array *currentDef = &tenv->currentDef[i];
bpf_ir_array_free(currentDef);
Expand Down Expand Up @@ -1614,33 +1616,39 @@ static void run_single_pass(struct bpf_ir_env *env, struct ir_function *fun,
CHECK_ERR();
}

void bpf_ir_run(struct bpf_ir_env *env, struct ir_function *fun)
void bpf_ir_run_passes(struct bpf_ir_env *env, struct ir_function *fun,
const struct function_pass *passes, const size_t cnt)
{
u64 starttime = get_cur_time_ns();
for (size_t i = 0; i < pre_passes_cnt; ++i) {
for (size_t i = 0; i < cnt; ++i) {
bool has_override = false;
for (size_t j = 0; j < env->opts.builtin_pass_cfg_num; ++j) {
if (strcmp(env->opts.builtin_pass_cfg[j].name,
pre_passes[i].name) == 0) {
passes[i].name) == 0) {
has_override = true;
if (pre_passes[i].force_enable ||
if (passes[i].force_enable ||
env->opts.builtin_pass_cfg[j].enable) {
run_single_pass(
env, fun, &pre_passes[i],
env, fun, &passes[i],
env->opts.builtin_pass_cfg[j]
.param);
}
break;
}
}
if (!has_override) {
if (pre_passes[i].enabled) {
run_single_pass(env, fun, &pre_passes[i], NULL);
if (passes[i].enabled) {
run_single_pass(env, fun, &passes[i], NULL);
}
}

CHECK_ERR();
}
}

void bpf_ir_run(struct bpf_ir_env *env, struct ir_function *fun)
{
u64 starttime = get_cur_time_ns();
bpf_ir_run_passes(env, fun, pre_passes, pre_passes_cnt);
for (size_t i = 0; i < env->opts.custom_pass_num; ++i) {
if (env->opts.custom_passes[i].pass.enabled) {
if (env->opts.custom_passes[i].check_apply) {
Expand All @@ -1662,30 +1670,7 @@ void bpf_ir_run(struct bpf_ir_env *env, struct ir_function *fun)
CHECK_ERR();
}
}
for (size_t i = 0; i < post_passes_cnt; ++i) {
bool has_override = false;
for (size_t j = 0; j < env->opts.builtin_pass_cfg_num; ++j) {
if (strcmp(env->opts.builtin_pass_cfg[j].name,
post_passes[i].name) == 0) {
has_override = true;
if (post_passes[i].force_enable ||
env->opts.builtin_pass_cfg[j].enable) {
run_single_pass(
env, fun, &post_passes[i],
env->opts.builtin_pass_cfg[j]
.param);
}
break;
}
}
if (!has_override) {
if (post_passes[i].enabled) {
run_single_pass(env, fun, &post_passes[i],
NULL);
}
}
CHECK_ERR();
}
bpf_ir_run_passes(env, fun, post_passes, post_passes_cnt);

env->run_time += get_cur_time_ns() - starttime;
}
Expand Down Expand Up @@ -1825,6 +1810,7 @@ struct bpf_ir_opts bpf_ir_default_opts(void)
opts.enable_coalesce = false;
opts.force = false;
opts.verbose = 1;
opts.cg_v2 = false;
opts.max_iteration = 10;
opts.disable_prog_check = false;
opts.enable_throw_msg = false;
Expand Down
10 changes: 0 additions & 10 deletions core/epasstool/epasstool.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,6 @@ static struct function_pass post_passes_def[] = {
DEF_FUNC_PASS(bpf_ir_div_by_zero, "div_by_zero", false),
DEF_FUNC_PASS(msan, "msan", false),
DEF_FUNC_PASS(insn_counter, "insn_counter", false),
/* CG Preparation Passes */
DEF_NON_OVERRIDE_FUNC_PASS(translate_throw, "translate_throw"),
DEF_FUNC_PASS(bpf_ir_optimize_code_compaction, "optimize_compaction",
false),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_optimize_ir, "optimize_ir"),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_cg_change_fun_arg, "change_fun_arg"),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_cg_change_call_pre_cg, "change_call"),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_cg_add_stack_offset_pre_cg,
"add_stack_offset"),
DEF_NON_OVERRIDE_FUNC_PASS(bpr_ir_cg_to_cssa, "to_cssa"),
};

const struct function_pass *pre_passes = pre_passes_def;
Expand Down
29 changes: 29 additions & 0 deletions core/include/ir_cg.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@

#include <linux/bpf_ir.h>

// Number of colors available (r0 - r9)
#define RA_COLORS 10

void bpf_ir_init_insn_cg(struct bpf_ir_env *env, struct ir_insn *insn);

void bpf_ir_init_insn_norm(struct bpf_ir_env *env, struct ir_insn *insn,
struct ir_vr_pos pos);

void bpf_ir_cg_norm_v2(struct bpf_ir_env *env, struct ir_function *fun);

void bpf_ir_init_insn_cg_v2(struct bpf_ir_env *env, struct ir_insn *insn);

void bpf_ir_free_insn_cg(struct ir_insn *insn);

// Extra information needed for code gen
Expand All @@ -32,6 +39,7 @@ struct ir_insn_cg_extra {
struct ir_value dst;

// Liveness analysis
// Array of struct ir_insn*
struct array in;
struct array out;
struct array gen;
Expand Down Expand Up @@ -64,6 +72,25 @@ struct ir_insn_cg_extra {
bool nonvr;
};

struct ir_insn_cg_extra_v2 {
struct ir_insn *dst;

// Liveness analysis
struct ptrset in;
struct ptrset out;

// Adj list in interference graph
struct ptrset adj;

u32 lambda; // used in MCS
u32 w; // number of maximalCl that has this vertex. used in pre-spill

struct ir_vr_pos vr_pos;

// Whether this instruction is a non-VR instruction, like a pre-colored register
bool nonvr;
};

enum val_type {
UNDEF,
REG,
Expand All @@ -74,6 +101,8 @@ enum val_type {

#define insn_cg(insn) ((struct ir_insn_cg_extra *)(insn)->user_data)

#define insn_cg_v2(insn) ((struct ir_insn_cg_extra_v2 *)(insn)->user_data)

/* Dst of a instruction

Note. This could be only applied to an instruction with return value.
Expand Down
63 changes: 57 additions & 6 deletions core/include/linux/bpf_ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ struct bpf_ir_opts {
// Write an error message to trace when throwing an error
bool enable_throw_msg;

// Use new CG pipeline;
bool cg_v2;

// Verbose level
int verbose;

Expand Down Expand Up @@ -200,6 +203,8 @@ void bpf_ir_array_clone(struct bpf_ir_env *env, struct array *res,

#define INIT_ARRAY(arr, type) bpf_ir_array_init(arr, sizeof(type))

#define INIT_PTRSET_DEF(set) bpf_ir_ptrset_init(env, set, 8)

/* Array End */

/* Hashtable Start */
Expand Down Expand Up @@ -281,6 +286,8 @@ void bpf_ir_ptrset_clean(struct ptrset *set);

void bpf_ir_ptrset_free(struct ptrset *set);

void **bpf_ir_ptrset_next(struct ptrset *set, void **keyd);

struct ptrset bpf_ir_ptrset_union(struct bpf_ir_env *env, struct ptrset *set1,
struct ptrset *set2);

Expand All @@ -297,6 +304,10 @@ void bpf_ir_ptrset_add(struct bpf_ir_env *env, struct ptrset *set1,

void bpf_ir_ptrset_minus(struct ptrset *set1, struct ptrset *set2);

#define ptrset_for(pos, set) \
for (pos = (typeof(pos))bpf_ir_ptrset_next(&(set), NULL); pos; \
pos = (typeof(pos))bpf_ir_ptrset_next(&(set), (void **)pos))

/* Ptrset End */

/* DBG Macro Start */
Expand Down Expand Up @@ -368,6 +379,8 @@ int parse_int(const char *str, int *val);

u64 get_cur_time_ns(void);

#ifdef DEBUG_ALLOC

#define SAFE_MALLOC(dst, size) \
{ \
if (size > 10000000) { \
Expand All @@ -392,6 +405,28 @@ u64 get_cur_time_ns(void);
} \
}

#else

#define SAFE_MALLOC(dst, size) \
{ \
dst = malloc_proto(size); \
if (!dst) { \
env->err = -ENOMEM; \
return; \
} \
}

#define SAFE_MALLOC_RET_NULL(dst, size) \
{ \
dst = malloc_proto(size); \
if (!dst) { \
env->err = -ENOMEM; \
return NULL; \
} \
}

#endif

/* LLI End */

#define MAX_FUNC_ARG 5
Expand Down Expand Up @@ -778,6 +813,8 @@ struct code_gen_info {
// Array of struct ir_insn*
struct array all_var;

struct ptrset all_var_v2;

// BPF Register Virtual Instruction (used as dst)
struct ir_insn *regs[BPF_REG_10]; // Only use R0-R9

Expand Down Expand Up @@ -1193,6 +1230,15 @@ struct ir_insn *bpf_ir_create_assign_insn_bb_norm(struct bpf_ir_env *env,
struct ir_value val,
enum insert_position pos);

struct ir_insn *bpf_ir_create_assign_insn_cg_v2(struct bpf_ir_env *env,
struct ir_insn *pos_insn,
struct ir_value val,
enum insert_position pos);

struct ir_insn *bpf_ir_create_assign_insn_bb_cg_v2(
struct bpf_ir_env *env, struct ir_basic_block *pos_bb,
struct ir_value val, enum insert_position pos);

struct ir_insn *bpf_ir_create_phi_insn(struct bpf_ir_env *env,
struct ir_insn *pos_insn,
enum insert_position pos);
Expand Down Expand Up @@ -1352,12 +1398,6 @@ void bpf_ir_div_by_zero(struct bpf_ir_env *env, struct ir_function *fun,
void bpf_ir_optimize_code_compaction(struct bpf_ir_env *env,
struct ir_function *fun, void *param);

extern const struct function_pass *pre_passes;
extern const size_t pre_passes_cnt;

extern const struct function_pass *post_passes;
extern const size_t post_passes_cnt;

void translate_throw(struct bpf_ir_env *env, struct ir_function *fun,
void *param);

Expand All @@ -1369,6 +1409,15 @@ struct function_pass {
char name[BPF_IR_MAX_PASS_NAME_SIZE];
};

extern const struct function_pass *pre_passes;
extern const size_t pre_passes_cnt;

extern const struct function_pass *post_passes;
extern const size_t post_passes_cnt;

void bpf_ir_run_passes(struct bpf_ir_env *env, struct ir_function *fun,
const struct function_pass *passes, const size_t cnt);

struct custom_pass_cfg {
struct function_pass pass;
void *param;
Expand Down Expand Up @@ -1430,6 +1479,8 @@ struct builtin_pass_cfg {

void bpf_ir_compile(struct bpf_ir_env *env, struct ir_function *fun);

void bpf_ir_compile_v2(struct bpf_ir_env *env, struct ir_function *fun);

/* Code Gen End */

/* IR Value Start */
Expand Down
21 changes: 21 additions & 0 deletions core/ir_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
#include <linux/bpf_ir.h>
#include "ir_cg.h"

/* CG Preparation Passes */
static struct function_pass cg_init_passes[] = {
DEF_NON_OVERRIDE_FUNC_PASS(translate_throw, "translate_throw"),
DEF_FUNC_PASS(bpf_ir_optimize_code_compaction, "optimize_compaction",
false),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_optimize_ir, "optimize_ir"),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_cg_change_fun_arg, "change_fun_arg"),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_cg_change_call_pre_cg, "change_call"),
DEF_NON_OVERRIDE_FUNC_PASS(bpf_ir_cg_add_stack_offset_pre_cg,
"add_stack_offset"),
DEF_NON_OVERRIDE_FUNC_PASS(bpr_ir_cg_to_cssa, "to_cssa"),
};

static void set_insn_dst(struct bpf_ir_env *env, struct ir_insn *insn,
struct ir_insn *dst)
{
Expand Down Expand Up @@ -1893,7 +1906,15 @@ static void spill_array(struct bpf_ir_env *env, struct ir_function *fun)

void bpf_ir_compile(struct bpf_ir_env *env, struct ir_function *fun)
{
if (env->opts.cg_v2) {
bpf_ir_compile_v2(env, fun);
return;
}
u64 starttime = get_cur_time_ns();

bpf_ir_run_passes(env, fun, cg_init_passes,
sizeof(cg_init_passes) / sizeof(cg_init_passes[0]));

// Init CG, start code generation
init_cg(env, fun);
CHECK_ERR();
Expand Down
Loading