Skip to content

Commit

Permalink
Initial support for LLVM loader (incomplete)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Oct 4, 2023
1 parent d435e7c commit 6482f6b
Show file tree
Hide file tree
Showing 9 changed files with 1,004 additions and 31 deletions.
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ TARGET = x86_64
BUILD = debug
BUILD_DIR = .
SRC_DIR = .
HAVE_LLVM = no
EXAMPLES_SRC_DIR = $(SRC_DIR)/examples
EXAMPLES_BUILD_DIR = $(BUILD_DIR)/examples

Expand Down Expand Up @@ -39,12 +40,18 @@ ifeq (aarch64, $(TARGET))
DASM_FLAGS = -M
endif

ifeq (yes, $(HAVE_LLVM))
override CFLAGS += -DHAVE_LLVM
LLVM_OBJS=$(BUILD_DIR)/ir_load_llvm.o
LLVM_LIBS=-lLLVM
endif

OBJS_COMMON = $(BUILD_DIR)/ir.o $(BUILD_DIR)/ir_strtab.o $(BUILD_DIR)/ir_cfg.o \
$(BUILD_DIR)/ir_sccp.o $(BUILD_DIR)/ir_gcm.o $(BUILD_DIR)/ir_ra.o $(BUILD_DIR)/ir_emit.o \
$(BUILD_DIR)/ir_load.o $(BUILD_DIR)/ir_save.o $(BUILD_DIR)/ir_emit_c.o $(BUILD_DIR)/ir_dump.o \
$(BUILD_DIR)/ir_disasm.o $(BUILD_DIR)/ir_gdb.o $(BUILD_DIR)/ir_perf.o $(BUILD_DIR)/ir_check.o \
$(BUILD_DIR)/ir_cpuinfo.o $(BUILD_DIR)/ir_emit_llvm.o
OBJS_IR = $(BUILD_DIR)/ir_main.o
OBJS_IR = $(BUILD_DIR)/ir_main.o $(LLVM_OBJS)
OBJS_IR_TEST = $(BUILD_DIR)/ir_test.o
EXAMPLE_EXES = $(EXAMPLES_BUILD_DIR)/0001-basic $(EXAMPLES_BUILD_DIR)/0001-while $(EXAMPLES_BUILD_DIR)/0005-basic-runner-func \
$(EXAMPLES_BUILD_DIR)/0001-pointer $(EXAMPLES_BUILD_DIR)/0001-func
Expand All @@ -58,7 +65,7 @@ $(EXAMPLES_BUILD_DIR):
@mkdir -p $(EXAMPLES_BUILD_DIR)

$(BUILD_DIR)/ir: $(OBJS_COMMON) $(OBJS_IR)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lcapstone
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LLVM_LIBS) -lcapstone

$(BUILD_DIR)/ir_test: $(OBJS_COMMON) $(OBJS_IR_TEST)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lcapstone
Expand Down
2 changes: 1 addition & 1 deletion examples/0001-while.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ void gen_myfunc(ir_ctx *ctx)
/* Declare loop counter. */
ir_ref i = ir_COPY_I32(ir_CONST_I32(0));
ir_ref loop = ir_LOOP_BEGIN(ir_END());
ir_ref phi_i_1 = ir_PHI_2(i, IR_UNUSED);
ir_ref phi_i_1 = ir_PHI_2(IR_I32, i, IR_UNUSED);
ir_ref i_2 = ir_ADD_I32(phi_i_1, ir_CONST_I32(1));
ir_ref cond = ir_IF(ir_LT(phi_i_1, ir_CONST_I32(42)));
ir_IF_TRUE(cond);
Expand Down
124 changes: 111 additions & 13 deletions ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,104 @@ void ir_hashtab_key_sort(ir_hashtab *tab)
} while (--i);
}

static void ir_addrtab_resize(ir_hashtab *tab)
{
uint32_t old_hash_size = (uint32_t)(-(int32_t)tab->mask);
char *old_data = tab->data;
uint32_t size = tab->size * 2;
uint32_t hash_size = ir_hashtab_hash_size(size);
char *data = ir_mem_malloc(hash_size * sizeof(uint32_t) + size * sizeof(ir_addrtab_bucket));
ir_addrtab_bucket *p;
uint32_t pos, i;

memset(data, -1, hash_size * sizeof(uint32_t));
tab->data = data + (hash_size * sizeof(uint32_t));
tab->mask = (uint32_t)(-(int32_t)hash_size);
tab->size = size;

memcpy(tab->data, old_data, tab->count * sizeof(ir_addrtab_bucket));
ir_mem_free(old_data - (old_hash_size * sizeof(uint32_t)));

i = tab->count;
pos = 0;
p = (ir_addrtab_bucket*)tab->data;
do {
uint32_t key = (uint32_t)p->key | tab->mask;
p->next = ((uint32_t*)tab->data)[(int32_t)key];
((uint32_t*)tab->data)[(int32_t)key] = pos;
pos += sizeof(ir_addrtab_bucket);
p++;
} while (--i);
}

void ir_addrtab_init(ir_hashtab *tab, uint32_t size)
{
IR_ASSERT(size > 0);
uint32_t hash_size = ir_hashtab_hash_size(size);
char *data = ir_mem_malloc(hash_size * sizeof(uint32_t) + size * sizeof(ir_addrtab_bucket));
memset(data, -1, hash_size * sizeof(uint32_t));
tab->data = (data + (hash_size * sizeof(uint32_t)));
tab->mask = (uint32_t)(-(int32_t)hash_size);
tab->size = size;
tab->count = 0;
tab->pos = 0;
}

void ir_addrtab_free(ir_hashtab *tab)
{
uint32_t hash_size = (uint32_t)(-(int32_t)tab->mask);
char *data = (char*)tab->data - (hash_size * sizeof(uint32_t));
ir_mem_free(data);
tab->data = NULL;
}

ir_ref ir_addrtab_find(const ir_hashtab *tab, uint64_t key)
{
const char *data = (const char*)tab->data;
uint32_t pos = ((uint32_t*)data)[(int32_t)(key | tab->mask)];
ir_addrtab_bucket *p;

while (pos != IR_INVALID_IDX) {
p = (ir_addrtab_bucket*)(data + pos);
if (p->key == key) {
return p->val;
}
pos = p->next;
}
return IR_INVALID_VAL;
}

bool ir_addrtab_add(ir_hashtab *tab, uint64_t key, ir_ref val)
{
char *data = (char*)tab->data;
uint32_t pos = ((uint32_t*)data)[(int32_t)(key | tab->mask)];
ir_addrtab_bucket *p;

while (pos != IR_INVALID_IDX) {
p = (ir_addrtab_bucket*)(data + pos);
if (p->key == key) {
return p->val == val;
}
pos = p->next;
}

if (UNEXPECTED(tab->count >= tab->size)) {
ir_addrtab_resize(tab);
data = tab->data;
}

pos = tab->pos;
tab->pos += sizeof(ir_addrtab_bucket);
tab->count++;
p = (ir_addrtab_bucket*)(data + pos);
p->key = key;
p->val = val;
key |= tab->mask;
p->next = ((uint32_t*)data)[(int32_t)key];
((uint32_t*)data)[(int32_t)key] = pos;
return 1;
}

/* Memory API */
#ifdef _WIN32
void *ir_mem_mmap(size_t size)
Expand Down Expand Up @@ -1550,19 +1648,17 @@ ir_ref _ir_VAR(ir_ctx *ctx, ir_type type, const char* name)
return ir_var(ctx, type, ctx->control, name);
}

ir_ref _ir_PHI_2(ir_ctx *ctx, ir_ref src1, ir_ref src2)
ir_ref _ir_PHI_2(ir_ctx *ctx, ir_type type, ir_ref src1, ir_ref src2)
{
ir_type type = ctx->ir_base[src1].type;

IR_ASSERT(ctx->control);
IR_ASSERT(ctx->ir_base[ctx->control].op == IR_MERGE || ctx->ir_base[ctx->control].op == IR_LOOP_BEGIN);
if (src1 == src2) {
if (src1 == src2 && src1 != IR_UNUSED) {
return src1;
}
return ir_emit3(ctx, IR_OPTX(IR_PHI, type, 3), ctx->control, src1, src2);
}

ir_ref _ir_PHI_N(ir_ctx *ctx, ir_ref n, ir_ref *inputs)
ir_ref _ir_PHI_N(ir_ctx *ctx, ir_type type, ir_ref n, ir_ref *inputs)
{
IR_ASSERT(ctx->control);
IR_ASSERT(n > 0);
Expand All @@ -1573,17 +1669,19 @@ ir_ref _ir_PHI_N(ir_ctx *ctx, ir_ref n, ir_ref *inputs)
ir_ref ref = inputs[0];

IR_ASSERT(ctx->ir_base[ctx->control].op == IR_MERGE || ctx->ir_base[ctx->control].op == IR_LOOP_BEGIN);
for (i = 1; i < n; i++) {
if (inputs[i] != ref) {
break;
if (ref != IR_UNUSED) {
for (i = 1; i < n; i++) {
if (inputs[i] != ref) {
break;
}
}
if (i == n) {
/* all the same */
return ref;
}
}
if (i == n) {
/* all the same */
return ref;
}

ref = ir_emit_N(ctx, IR_OPT(IR_PHI, ctx->ir_base[inputs[0]].type), n + 1);
ref = ir_emit_N(ctx, IR_OPT(IR_PHI, type), n + 1);
ir_set_op(ctx, ref, 1, ctx->control);
for (i = 0; i < n; i++) {
ir_set_op(ctx, ref, i + 2, inputs[i]);
Expand Down
4 changes: 4 additions & 0 deletions ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,10 @@ void ir_loader_init(void);
void ir_loader_free(void);
int ir_load(ir_ctx *ctx, FILE *f);

/* IR LLVM load API (implementation in ir_load_llvm.c) */
int ir_load_llvm_bitcode(const char *filename, uint32_t flags);
int ir_load_llvm_asm(const char *filename, uint32_t flags);

/* IR save API (implementation in ir_save.c) */
void ir_save(const ir_ctx *ctx, FILE *f);

Expand Down
9 changes: 5 additions & 4 deletions ir_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,8 @@ extern "C" {
#define ir_COND_D(_op1, _op2, _op3) ir_fold3(_ir_CTX, IR_OPT(IR_COND, IR_DOUBLE), (_op1), (_op2), (_op3))
#define ir_COND_F(_op1, _op2, _op3) ir_fold3(_ir_CTX, IR_OPT(IR_COND, IR_FLOAT), (_op1), (_op2), (_op3))

#define ir_PHI_2(_src1, _src2) _ir_PHI_2(_ir_CTX, (_src1), (_src2))
#define ir_PHI_N(_n, _inputs) _ir_PHI_N(_ir_CTX, (_n), (_inputs))
#define ir_PHI_2(type, _src1, _src2) _ir_PHI_2(_ir_CTX, type, (_src1), (_src2))
#define ir_PHI_N(type, _n, _inputs) _ir_PHI_N(_ir_CTX, type, (_n), (_inputs))
#define ir_PHI_SET_OP(_ref, _pos, _src) _ir_PHI_SET_OP(_ir_CTX, (_ref), (_pos), (_src))

#define ir_COPY_B(_op1) ir_UNARY_OP_B(IR_COPY, (_op1))
Expand Down Expand Up @@ -455,6 +455,7 @@ extern "C" {
#define ir_ALLOCA(_size) _ir_ALLOCA(_ir_CTX, (_size))
#define ir_AFREE(_size) _ir_AFREE(_ir_CTX, (_size))
#define ir_VADDR(_var) ir_emit1(_ir_CTX, IR_OPT(IR_VADDR, IR_ADDR), (_var))
#define ir_VLOAD(_type, _var) _ir_VLOAD(_ir_CTX, (_type), (_var))
#define ir_VLOAD_B(_var) _ir_VLOAD(_ir_CTX, IR_BOOL, (_var))
#define ir_VLOAD_U8(_var) _ir_VLOAD(_ir_CTX, IR_U8, (_var))
#define ir_VLOAD_U16(_var) _ir_VLOAD(_ir_CTX, IR_U16, (_var))
Expand Down Expand Up @@ -539,8 +540,8 @@ extern "C" {
#define ir_MERGE_WITH_EMPTY_FALSE(_if) do {ir_ref end = ir_END(); ir_IF_FALSE(_if); ir_MERGE_2(end, ir_END());} while (0)

ir_ref _ir_ADD_OFFSET(ir_ctx *ctx, ir_ref addr, uintptr_t offset);
ir_ref _ir_PHI_2(ir_ctx *ctx, ir_ref src1, ir_ref src2);
ir_ref _ir_PHI_N(ir_ctx *ctx, ir_ref n, ir_ref *inputs);
ir_ref _ir_PHI_2(ir_ctx *ctx, ir_type type, ir_ref src1, ir_ref src2);
ir_ref _ir_PHI_N(ir_ctx *ctx, ir_type type, ir_ref n, ir_ref *inputs);
void _ir_PHI_SET_OP(ir_ctx *ctx, ir_ref phi, ir_ref pos, ir_ref src);
ir_ref _ir_PARAM(ir_ctx *ctx, ir_type type, const char* name, ir_ref num);
ir_ref _ir_VAR(ir_ctx *ctx, ir_type type, const char* name);
Expand Down
Loading

0 comments on commit 6482f6b

Please sign in to comment.