Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
bc96df4
chore: better bug info
linsyking Sep 12, 2024
025b41f
fix: bb loop checking
linsyking Sep 12, 2024
912da8a
fix: ir
linsyking Sep 12, 2024
cdc9fdd
fix: use SP reg
linsyking Sep 12, 2024
5eac697
docs: cg
linsyking Sep 12, 2024
8c3d5bc
fix: erase instructions
linsyking Sep 13, 2024
275f064
feat: remove redundant alu
linsyking Sep 13, 2024
0ad4da7
fix: debugger
linsyking Sep 13, 2024
a3872f9
feat: add debug util
linsyking Sep 14, 2024
0a23af5
fix: allow erasing self
linsyking Sep 14, 2024
587823b
fix: testing programs
linsyking Sep 14, 2024
aea0047
feat: init cli
linsyking Sep 14, 2024
64936e3
feat: userspace runner
linsyking Sep 14, 2024
ec8c562
fix: compiler warning
linsyking Sep 14, 2024
796fcbc
fix: free env
linsyking Sep 14, 2024
ca152ce
fix: spilled & spilled size
linsyking Sep 14, 2024
f4aa485
feat: init allocarray
linsyking Sep 14, 2024
98ef58c
feat: start proto
linsyking Sep 14, 2024
bd4bb5f
feat: init ctor
linsyking Sep 14, 2024
1a0f24f
feat: script
linsyking Sep 14, 2024
37c0b92
fix: proto
linsyking Sep 14, 2024
62b0215
feat: init ctor generator
linsyking Sep 14, 2024
c263e96
fix: env
linsyking Sep 14, 2024
376deb9
refactor: name
linsyking Sep 14, 2024
bc69f72
chore: improve makefile
linsyking Sep 14, 2024
ba7c25a
feat: add allocarray instruction constructor
linsyking Sep 14, 2024
3a179c6
fix: use sp instead of args[10]
linsyking Sep 14, 2024
526e4ed
feat: add getelemptr instruction
linsyking Sep 14, 2024
8a743b8
fix: get operands
linsyking Sep 14, 2024
9aff0a3
fix: spelling
linsyking Sep 14, 2024
a4ddf21
feat: add check for getelemptr
linsyking Sep 14, 2024
3256ea2
feat: helper
linsyking Sep 14, 2024
e9c84c6
feat: start writing counter pass
linsyking Sep 14, 2024
db18107
feat: add counter pass
linsyking Sep 14, 2024
c5d64ac
fix: getelemptr user
linsyking Sep 14, 2024
cd2d1de
feat: pass the exception
linsyking Sep 14, 2024
186f476
feat: do not clean allocarray spilled info
linsyking Sep 14, 2024
c0cbf80
fix: spilled
linsyking Sep 14, 2024
e82fc6f
feat: spill getelemptr
linsyking Sep 14, 2024
6b0f6a2
fix: getelemptr
linsyking Sep 14, 2024
88c8775
fix: getelemptr prog check
linsyking Sep 14, 2024
ed27331
feat: start normalization
linsyking Sep 15, 2024
5f86c07
feat: getelemptr
linsyking Sep 15, 2024
cd2117a
feat: no users strictly
linsyking Sep 15, 2024
2c06dc1
fix: users
linsyking Sep 15, 2024
7385838
chore: counter
linsyking Sep 15, 2024
6001e6e
feat: add store/load array from ptr
linsyking Sep 15, 2024
d4a45fc
feat: check load store elem
linsyking Sep 15, 2024
971936a
feat: add new insn ctor
linsyking Sep 15, 2024
e2ef0b0
chore: header
linsyking Sep 15, 2024
9da7caf
feat: add storeraw normalize
linsyking Sep 15, 2024
b604df7
feat: add normalize for loadraw
linsyking Sep 15, 2024
3a5e374
feat: add optimization
linsyking Sep 15, 2024
65f5cf4
chore: format
linsyking Sep 15, 2024
a29f7f5
fix: imm
linsyking Sep 15, 2024
2899d44
fix: alu imm src
linsyking Sep 15, 2024
b35d8fa
feat: test counter 500
linsyking Sep 15, 2024
331ebaa
chore: format
linsyking Sep 15, 2024
24672f3
fix: cond jmp src
linsyking Sep 15, 2024
a66b536
fix: run
linsyking Sep 15, 2024
46d7ef8
fix: counter
linsyking Sep 15, 2024
00073ba
feat: add tests
linsyking Sep 15, 2024
788bbde
test: no counter
linsyking Sep 15, 2024
7e67f33
fix: need_modify not or
linsyking Sep 15, 2024
79a3e99
fix: counter limit
linsyking Sep 15, 2024
890d2b4
fix: loop3 test
linsyking Sep 15, 2024
656d5f0
fix: spilled nonvr
linsyking Sep 16, 2024
aefc6fd
feat: temporarily remove coalescing
linsyking Sep 16, 2024
a5a9ebd
refactor: use value as dst
linsyking Sep 17, 2024
1731cce
feat: check dst insn
linsyking Sep 17, 2024
86b3066
refactor: remove check_cgir
linsyking Sep 17, 2024
5cf7626
refactor: cg
linsyking Sep 17, 2024
7df62ea
feat: normalize change val
linsyking Sep 17, 2024
0dc693a
fix: spill callee
linsyking Sep 17, 2024
fad1acc
chore: comment
linsyking Sep 17, 2024
46d9e4f
fix: spilling
linsyking Sep 17, 2024
e12cc5b
fix: remove debug lines
linsyking Sep 17, 2024
616e041
feat: coalescing
linsyking Sep 18, 2024
5b3f3fb
feat: coalescing
linsyking Sep 18, 2024
04abbc6
feat: enable pass
linsyking Sep 18, 2024
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
38 changes: 38 additions & 0 deletions IR/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"cSpell.words": [
"addrval",
"ALLOC",
"ALLOCARRAY",
"cgir",
"CSSA",
"DBGASSERT",
"dsts",
"elemptr",
"FUNCTIONARG",
"GETELEMPTR",
"insn",
"ipos",
"jbin",
"LOADELEM",
"loadimm",
"LOADRAW",
"loadrawextra",
"newbb",
"nonvr",
"notag",
"preds",
"printk",
"RAWOFF",
"repr",
"SIZET",
"STACKOFF",
"stackptr",
"STOREELEM",
"STORERAW",
"struct",
"succs",
"tdst",
"TSSA",
"vpos"
]
}
3 changes: 2 additions & 1 deletion IR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
project(bpf_ir)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wstrict-prototypes -Wunused-variable -O3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wstrict-prototypes -Wenum-compare -Wunused-variable -Wunused-but-set-variable -Wsign-compare -O3")

add_library(bpf_ir STATIC
bpf_ir.c
Expand All @@ -15,6 +15,7 @@ add_library(bpf_ir STATIC
passes/cut_bb_pass.c
aux/prog_check.c
aux/disasm.c
aux/optimization.c
ir_code_gen.c
lii.c
)
Expand Down
10 changes: 8 additions & 2 deletions IR/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
build: format
cmake --build build

buildall: genctor
cmake --build build

format:
./scripts/format.sh

build: format
cmake --build build
genctor:
./scripts/gen_insn_ctor.py
./scripts/format.sh

kernel: build
./scripts/gen_kernel.sh
Expand Down
5 changes: 2 additions & 3 deletions IR/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ One opinion, one benefit of designing the raw constraint from is that our runtim
- [x] Env
- [x] If ALU ops (including cond jmp) use 64 bits const, load it to register
- [x] Switch back for ALU spill
- [ ] CGIR-I and CGIR-II formalization
- [ ] Test adding counter & print some result
- [x] CGIR-I and CGIR-II formalization

## Bugs

- `loop2`: Loop BB detected
- `STACK_PTR` Change to R10 insn
- `erase_insn_cg` Not working in the normalization. Should spilling use `safe` list iterations?

# TODO

Expand Down
12 changes: 12 additions & 0 deletions IR/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ void bpf_ir_array_clone(struct bpf_ir_env *env, struct array *res,
memcpy(res->data, arr->data, arr->num_elem * arr->elem_size);
}

// Merge b into a
void bpf_ir_array_merge(struct bpf_ir_env *env, struct array *a,
struct array *b)
{
struct ir_insn **pos;
array_for(pos, (*b))
{
struct ir_insn *insn = *pos;
bpf_ir_array_push_unique(env, a, &insn);
CHECK_ERR();
}
}
void bpf_ir_array_free(struct array *arr)
{
if (arr->data) {
Expand Down
2 changes: 1 addition & 1 deletion IR/aux/disasm.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "linux/bpf_ir.h"
#include <linux/bpf_ir.h>
#include <linux/bpf.h>

// #include "disasm.h"
Expand Down
82 changes: 82 additions & 0 deletions IR/aux/optimization.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <linux/bpf_ir.h>

static void remove_no_user_insn(struct bpf_ir_env *env, struct ir_function *fun)
{
// Remove all instructions that have no users, except for void instructions & calls

struct ir_basic_block **pos;
array_for(pos, fun->reachable_bbs)
{
struct ir_basic_block *bb = *pos;
struct ir_insn *insn, *tmp;
list_for_each_entry_safe(insn, tmp, &bb->ir_insn_head,
list_ptr) {
if (bpf_ir_is_void(insn) || insn->op == IR_INSN_CALL) {
continue;
}
if (insn->users.num_elem == 0) {
bpf_ir_erase_insn(env, insn);
CHECK_ERR();
}
}
}
}

static void remove_unused_alloc(struct bpf_ir_env *env, struct ir_function *fun)
{
// Remove all alloc instructions that have no users
struct array alloc_insns;
INIT_ARRAY(&alloc_insns, struct ir_insn *);

struct ir_basic_block **pos;
array_for(pos, fun->reachable_bbs)
{
struct ir_basic_block *bb = *pos;
struct ir_insn *insn, *tmp;
list_for_each_entry_safe(insn, tmp, &bb->ir_insn_head,
list_ptr) {
if (insn->op == IR_INSN_ALLOC) {
bpf_ir_array_push(env, &alloc_insns, &insn);
}
}
}

struct ir_insn **pos2;
array_for(pos2, alloc_insns)
{
bool has_load = false;
struct ir_insn *insn = *pos2;
struct ir_insn **pos3;
array_for(pos3, insn->users)
{
struct ir_insn *user = *pos3;
if (user->op == IR_INSN_LOAD) {
has_load = true;
break;
}
}
if (!has_load) {
// Remove all its store
array_for(pos3, insn->users)
{
struct ir_insn *user = *pos3;
bpf_ir_erase_insn(env, user);
CHECK_ERR();
}
// Remove itself
bpf_ir_erase_insn(env, insn);
CHECK_ERR();
}
}

bpf_ir_array_free(&alloc_insns);
}

void bpf_ir_optimize_ir(struct bpf_ir_env *env, struct ir_function *fun)
{
remove_no_user_insn(env, fun);
CHECK_ERR();

remove_unused_alloc(env, fun);
CHECK_ERR();
}
54 changes: 40 additions & 14 deletions IR/aux/prog_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,19 @@ static void check_insn(struct bpf_ir_env *env, struct ir_function *fun)
struct ir_basic_block *bb = *pos;
struct ir_insn *insn;
list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) {
struct array operands = bpf_ir_get_operands(env, insn);
struct ir_value **vpos;
if (insn->parent_bb != bb) {
print_ir_insn_err(
env, insn,
"Instruction's parent BB wrong");
RAISE_ERROR("Parent BB error");
}
if (insn->op == IR_INSN_LOADRAW ||
insn->op == IR_INSN_ALLOC ||
insn->op == IR_INSN_JA || insn->op == IR_INSN_PHI) {
insn->op == IR_INSN_JA || insn->op == IR_INSN_PHI ||
insn->op == IR_INSN_ALLOCARRAY) {
if (!(insn->value_num == 0)) {
print_ir_insn_err(env, insn, NULL);
RAISE_ERROR(

"Instruction should have no value");
}
}
Expand All @@ -62,13 +66,14 @@ static void check_insn(struct bpf_ir_env *env, struct ir_function *fun)
if (!(insn->value_num == 1)) {
print_ir_insn_err(env, insn, NULL);
RAISE_ERROR(

"Instruction should have 1 values");
}
}

if (insn->op == IR_INSN_STORE || (is_alu(insn)) ||
(is_cond_jmp(insn))) {
if (insn->op == IR_INSN_STORE ||
(bpf_ir_is_alu(insn)) ||
(bpf_ir_is_cond_jmp(insn)) ||
insn->op == IR_INSN_GETELEMPTR) {
if (!(insn->value_num == 2)) {
print_ir_insn_err(env, insn, NULL);
RAISE_ERROR(
Expand All @@ -89,16 +94,28 @@ static void check_insn(struct bpf_ir_env *env, struct ir_function *fun)
}
}

if (insn->op == IR_INSN_GETELEMPTR) {
if (!(insn->values[1].type == IR_VALUE_INSN &&
insn->values[1].data.insn_d->op ==
IR_INSN_ALLOCARRAY)) {
print_ir_insn_err(env, insn, NULL);
RAISE_ERROR(
"Value should be an allocarray instruction");
}
}

// TODO: Check: users of alloc instructions must be STORE/LOAD

if (is_alu(insn) || is_cond_jmp(insn)) {
if (bpf_ir_is_alu(insn) || bpf_ir_is_cond_jmp(insn)) {
// Binary ALU
if (!bpf_ir_valid_alu_type(insn->alu_op)) {
print_ir_insn_err(env, insn, NULL);
RAISE_ERROR("Binary ALU type error!");
}
}

struct array operands = bpf_ir_get_operands(env, insn);
struct ir_value **vpos;
if (insn->op == IR_INSN_ALLOC ||
insn->op == IR_INSN_LOADRAW ||
insn->op == IR_INSN_STORERAW) {
Expand All @@ -107,6 +124,8 @@ static void check_insn(struct bpf_ir_env *env, struct ir_function *fun)
RAISE_ERROR("Invalid VR type");
}
}

// Checking operands
array_for(vpos, operands)
{
struct ir_value *val = *vpos;
Expand All @@ -115,6 +134,12 @@ static void check_insn(struct bpf_ir_env *env, struct ir_function *fun)
val->const_type)) {
print_ir_insn_err(env, insn,
NULL);

PRINT_LOG(
env,
"Constant type: %d, operand number: %d\n",
val->const_type,
operands.num_elem);
RAISE_ERROR(
"Invalid Constant type");
}
Expand Down Expand Up @@ -168,6 +193,7 @@ static void check_users(struct bpf_ir_env *env, struct ir_function *fun)
struct ir_insn *insn = fun->function_arg[i];
check_insn_users_use_insn(env, insn);
}
check_insn_users_use_insn(env, fun->sp);
struct ir_basic_block **pos;
array_for(pos, fun->reachable_bbs)
{
Expand Down Expand Up @@ -237,7 +263,7 @@ static void check_jumping(struct bpf_ir_env *env, struct ir_function *fun)
struct ir_insn *insn;
int jmp_exists = 0;
list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) {
if (is_jmp(insn)) {
if (bpf_ir_is_jmp(insn)) {
jmp_exists = 1;
if (!bpf_ir_is_last_insn(insn)) {
// Error
Expand All @@ -259,7 +285,7 @@ static void check_jumping(struct bpf_ir_env *env, struct ir_function *fun)
continue;
}
// For conditional jumps, both BB1 and BB2 should be successors
if (is_cond_jmp(insn)) {
if (bpf_ir_is_cond_jmp(insn)) {
// Get the two basic blocks that the conditional jump statement jumps to
struct ir_basic_block *bb1 =
insn->bb1;
Expand Down Expand Up @@ -359,7 +385,7 @@ static void bpf_ir_fix_bb_succ(struct ir_function *fun)
{
struct ir_basic_block *bb = *pos;
struct ir_insn *insn = bpf_ir_get_last_insn(bb);
if (insn && is_cond_jmp(insn)) {
if (insn && bpf_ir_is_cond_jmp(insn)) {
// Conditional jmp
if (bb->succs.num_elem != 2) {
CRITICAL(
Expand All @@ -385,11 +411,11 @@ static void add_reach(struct bpf_ir_env *env, struct ir_function *fun,
bpf_ir_array_push(env, &fun->reachable_bbs, &bb);

struct ir_basic_block **succ;
u8 i = 0;
bool first = false;
array_for(succ, bb->succs)
{
if (i == 0) {
i = 1;
if (!first && bb->succs.num_elem > 1) {
first = true;
// Check if visited
if ((*succ)->_visited) {
RAISE_ERROR("Loop BB detected");
Expand Down
Loading