Skip to content

Commit

Permalink
impl native functions
Browse files Browse the repository at this point in the history
  • Loading branch information
omdxp committed Sep 9, 2024
1 parent 57e2d8b commit 65a3ca2
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 9 deletions.
86 changes: 86 additions & 0 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,31 @@ static struct compile_process *current_process = NULL;
static struct node *current_function = NULL;
static bool add_tab = false;

void asm_push(const char *ins, ...);
void codegen_generate_expression(struct generator *generator, struct node *node,
int flags);
void codegen_end_expression(struct generator *generator);
void codegen_entity_address(struct generator *generator,
struct resolver_entity *entity,
struct generator_entity_address *address_out);
void asm_push_ins_with_datatype(struct datatype *dtype, const char *fmt, ...);

struct history;
struct _x86_generator_private {
struct x86_generator_remembered {
struct history *history;
} remembered;
} _x86_generator_private;

struct generator x86_codegen = {
.asm_push = asm_push,
.generate_expression = codegen_generate_expression,
.end_expression = codegen_end_expression,
.entity_address = codegen_entity_address,
.ret = asm_push_ins_with_datatype,
.private = &_x86_generator_private,
};

enum {
CODEGEN_ENTITY_RULE_IS_STRUCT_OR_UNION_NO_POINTER = 0b00000001,
CODEGEN_ENTITY_RULE_IS_FUNCTION_CALL = 0b00000010,
Expand Down Expand Up @@ -143,6 +168,18 @@ codegen_entity_private(struct resolver_entity *entity) {
return resolver_default_entity_private(entity);
}

void codegen_entity_address(struct generator *generator,
struct resolver_entity *entity,
struct generator_entity_address *address_out) {
struct resolver_default_entity_data *entity_data =
codegen_entity_private(entity);
address_out->address = entity_data->address;
address_out->base_address = entity_data->base_address;
address_out->is_stack =
entity_data->flags & RESOLVER_DEFAULT_ENTITY_FLAG_IS_LOCAL_STACK;
address_out->offset = entity_data->offset;
}

int codegen_label_count() {
static int label_count = 0;
return label_count++;
Expand Down Expand Up @@ -172,6 +209,24 @@ void asm_push(const char *ins, ...) {
va_end(args);
}

void asm_push_ins_with_datatype(struct datatype *dtype, const char *fmt, ...) {
char tmp_buf[200];
sprintf(tmp_buf, "push %s", fmt);
va_list args;
va_start(args, fmt);
asm_push_args(tmp_buf, args);
va_end(args);

assert(current_function);
stackframe_push(current_function,
&(struct stack_frame_element){
.type = STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE,
.name = "result_value",
.flags = STACK_FRAME_ELEMENT_FLAG_HAS_DATA_TYPE,
.data.dtype = *dtype,
});
}

void asm_push_no_nl(const char *ins, ...) {
va_list args;
va_start(args, ins);
Expand Down Expand Up @@ -1015,6 +1070,19 @@ void codegen_generate_expressionable(struct node *node,
}
}

struct _x86_generator_private *x86_generator_private(struct generator *gen) {
return gen->private;
}

void codegen_generate_expression(struct generator *generator, struct node *node,
int flags) {
codegen_generate_expressionable(
node, history_down(x86_generator_private(generator)->remembered.history,
flags));
}

void codegen_end_expression(struct generator *generator) {}

const char *codegen_sub_register(const char *original_register, size_t size) {
const char *reg = NULL;
if (S_EQ(original_register, "eax")) {
Expand Down Expand Up @@ -1513,6 +1581,23 @@ void codegen_generate_entity_access(
struct resolver_result *result,
struct resolver_entity *root_assignment_entity, struct node *top_most_node,
struct history *history) {
// for native entity access
if (root_assignment_entity->type == RESOLVER_ENTITY_TYPE_NATIVE_FUNCTION) {
struct native_function *native_func =
native_function_get(current_process, root_assignment_entity->name);
if (native_func) {
asm_push("; native function %s", root_assignment_entity->name);
struct resolver_entity *func_call_entity =
resolver_entity_next(root_assignment_entity);
assert(func_call_entity &&
func_call_entity->type == RESOLVER_ENTITY_TYPE_FUNCTION_CALL);
native_func->callbacks.call(&x86_codegen, native_func,
func_call_entity->function_call_data.args);
return;
}
}

// for normal entity access
codegen_generate_entity_access_start(result, root_assignment_entity, history);
struct resolver_entity *current =
resolver_entity_next(root_assignment_entity);
Expand Down Expand Up @@ -2374,6 +2459,7 @@ void codegen_generate_data_section_add_ons() {

int codegen(struct compile_process *process) {
current_process = process;
x86_codegen.compiler = current_process;
scope_create_root(process);
vector_set_peek_pointer(process->node_tree_vec, 0);
codegen_new_scope(0);
Expand Down
65 changes: 65 additions & 0 deletions compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,61 @@ typedef void (*PREPROCESSOR_STATIC_INCLUDE_HANDLER_POST_CREATION)(
PREPROCESSOR_STATIC_INCLUDE_HANDLER_POST_CREATION
preprocessor_static_include_handler_for(const char *filename);

struct generator;
struct native_function;
struct node;
struct resolver_entity;
struct datatype;
struct generator_entity_address {
bool is_stack;
long offset;
const char *address;
const char *base_address;
};

#define GENERATOR_BEGIN_EXPRESSION(gen)
#define GENERATOR_END_EXPRESSION(gen) (gen)->end_expression(gen)

typedef void (*ASM_PUSH_PROTOTYPE)(const char *ins, ...);
typedef void (*NATIVE_FUNCTION_CALL)(struct generator *generator,
struct native_function *func,
struct vector *args);
typedef void (*GENERATOR_GENERATE_EXPRESSION)(struct generator *generator,
struct node *node, int flags);
typedef void (*GENERATOR_ENTITY_ADDRESS)(
struct generator *generator, struct resolver_entity *entity,
struct generator_entity_address *address_out);
typedef void (*GENERATOR_END_EXPRESSION)(struct generator *generator);
typedef void (*GENERATOR_FUNCTION_RETURN)(struct datatype *dtype,
const char *fmt, ...);

struct generator {
ASM_PUSH_PROTOTYPE asm_push;
GENERATOR_GENERATE_EXPRESSION generate_expression;
GENERATOR_END_EXPRESSION end_expression;
GENERATOR_ENTITY_ADDRESS entity_address;
GENERATOR_FUNCTION_RETURN ret;

struct compile_process *compiler;

void *private;
};

struct native_function_callbacks {
NATIVE_FUNCTION_CALL call;
};

struct native_function {
const char *name;
struct native_function_callbacks callbacks;
};

struct symbol *
native_create_function(struct compile_process *compiler, const char *name,
struct native_function_callbacks *callbacks);
struct native_function *native_function_get(struct compile_process *compiler,
const char *name);

struct preprocessor {
// vector of struct_definition*
struct vector *defs;
Expand Down Expand Up @@ -741,6 +796,7 @@ enum {
enum {
RESOLVER_ENTITY_TYPE_VARIABLE,
RESOLVER_ENTITY_TYPE_FUNCTION,
RESOLVER_ENTITY_TYPE_NATIVE_FUNCTION,
RESOLVER_ENTITY_TYPE_STRUCT,
RESOLVER_ENTITY_TYPE_FUNCTION_CALL,
RESOLVER_ENTITY_TYPE_ARRAY_BRACKET,
Expand Down Expand Up @@ -981,6 +1037,11 @@ struct resolver_entity {
// depth of the indirection
int depth;
} indirection;

struct resolver_native_function {
// native function symbol
struct symbol *symbol;
} native_func;
};

// last resolver entity
Expand Down Expand Up @@ -1172,6 +1233,7 @@ struct datatype datatype_for_string();
struct datatype *datatype_thats_a_pointer(struct datatype *d1,
struct datatype *d2);
struct datatype *datatype_pointer_reduce(struct datatype *dtype, int by);
void datatype_set_void(struct datatype *dtype);

bool is_access_operator(const char *op);
bool is_access_node(struct node *node);
Expand Down Expand Up @@ -1321,6 +1383,9 @@ struct symbol *symresolver_get_symbol(struct compile_process *process,
struct symbol *
symresolver_get_symbol_for_native_function(struct compile_process *process,
const char *name);
struct symbol *symresolver_register_symbol(struct compile_process *process,
const char *sym_name, int type,
void *data);

#define TOTAL_OPERATOR_GROUPS 14
#define MAX_OPERATORS_IN_GROUP 12
Expand Down
6 changes: 6 additions & 0 deletions datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,9 @@ struct datatype *datatype_pointer_reduce(struct datatype *dtype, int by) {

return new_datatype;
}

void datatype_set_void(struct datatype *dtype) {
dtype->type = DATA_TYPE_VOID;
dtype->type_str = "void";
dtype->size = 0;
}
24 changes: 24 additions & 0 deletions preprocessor/native.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "compiler.h"
#include <stdlib.h>

int preprocessor_line_macro_evaluate(struct preprocessor_definition *def,
struct preprocessor_function_args *args) {
Expand Down Expand Up @@ -30,3 +31,26 @@ void preprocessor_create_defs(struct preprocessor *preprocessor) {
"__LINE__", preprocessor_line_macro_evaluate,
preprocessor_line_macro_value, preprocessor);
}

struct symbol *
native_create_function(struct compile_process *compiler, const char *name,
struct native_function_callbacks *callbacks) {
struct native_function *native_function =
malloc(sizeof(struct native_function));
memcpy(&native_function->callbacks, callbacks,
sizeof(native_function->callbacks));
native_function->name = name;
return symresolver_register_symbol(
compiler, name, SYMBOL_TYPE_NATIVE_FUNCTION, native_function);
}

struct native_function *native_function_get(struct compile_process *compiler,
const char *name) {
struct symbol *symbol =
symresolver_get_symbol_for_native_function(compiler, name);
if (!symbol) {
return NULL;
}

return symbol->data;
}
12 changes: 12 additions & 0 deletions preprocessor/static_includes/stdarg.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
#include "compiler.h"

void native_test_function(struct generator *generator,
struct native_function *func, struct vector *args) {
generator->asm_push("; test");
struct datatype dtype;
dtype.type = DATA_TYPE_INT;
dtype.size = sizeof(int);
generator->ret(&dtype, "42");
}

void preprocessor_stdarg_include(
struct preprocessor *preprocessor,
struct preprocessor_included_file *included_file) {
#warning "create va_list"
native_create_function(
preprocessor->compiler, "test",
&(struct native_function_callbacks){.call = native_test_function});
}
41 changes: 39 additions & 2 deletions resolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ struct resolver_entity *resolver_create_new_entity_for_function_call(
}

entity->dtype = left_operand_entity->dtype;
entity->name = left_operand_entity->name;
entity->function_call_data.args = vector_create(sizeof(struct node *));
return entity;
}
Expand All @@ -482,6 +483,26 @@ resolver_register_function(struct resolver_process *process,
return entity;
}

struct resolver_entity *resolver_create_new_entity_for_native_function(
struct resolver_process *process, const char *name,
struct symbol *native_func_symbol) {
struct resolver_entity *entity = resolver_create_new_entity(
NULL, RESOLVER_ENTITY_TYPE_NATIVE_FUNCTION, NULL);
if (!entity) {
return NULL;
}

// make void return type
datatype_set_void(&entity->dtype);
make_function_node(&entity->dtype, name, NULL, NULL);
entity->node = node_pop();
entity->name = name;
entity->native_func.symbol = native_func_symbol;
entity->scope = resolver_process_scope_current(process);
vector_push(process->scopes.root->entities, &entity);
return entity;
}

struct resolver_entity *resolver_get_entity_in_scope_with_entity_type(
struct resolver_result *result, struct resolver_process *process,
struct resolver_scope *scope, const char *entity_name, int entity_type) {
Expand Down Expand Up @@ -572,8 +593,14 @@ struct resolver_entity *resolver_get_variable(struct resolver_result *result,
struct resolver_entity *resolver_get_function_in_scope(
struct resolver_result *result, struct resolver_process *process,
const char *func_name, struct resolver_scope *scope) {
return resolver_get_entity_for_type(result, process, func_name,
RESOLVER_ENTITY_TYPE_FUNCTION);
struct resolver_entity *entity = resolver_get_entity_for_type(
result, process, func_name, RESOLVER_ENTITY_TYPE_FUNCTION);
if (!entity) {
entity = resolver_get_entity_for_type(result, process, func_name,
RESOLVER_ENTITY_TYPE_NATIVE_FUNCTION);
}

return entity;
}

struct resolver_entity *resolver_get_function(struct resolver_result *result,
Expand Down Expand Up @@ -614,6 +641,16 @@ resolver_follow_identifier(struct resolver_process *process, struct node *node,
struct resolver_result *result) {
struct resolver_entity *entity =
resolver_follow_for_name(process, node->sval, result);
if (!entity) {
struct symbol *symbol = symresolver_get_symbol_for_native_function(
process->compile_process, node->sval);
if (symbol) {
entity = resolver_create_new_entity_for_native_function(
process, node->sval, symbol);
resolver_result_entity_push(result, entity);
}
}

if (entity) {
entity->last_resolve.referencing_node = node;
}
Expand Down
9 changes: 2 additions & 7 deletions test.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#include <stddef.h>
#include <stdarg_internal.h>

struct abc {
int a;
int b;
};

int main() { return offsetof(struct abc, b); }
int main() { test(); }

0 comments on commit 65a3ca2

Please sign in to comment.