Skip to content

Commit

Permalink
codegen function body with assignments
Browse files Browse the repository at this point in the history
  • Loading branch information
omdxp committed Aug 29, 2024
1 parent 0051ac4 commit 4387ff5
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 4 deletions.
150 changes: 149 additions & 1 deletion codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ void codegen_generate_number_node(struct node *node, struct history *history) {
asm_push_ins_push_with_data(
"dword %i", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE, "result_value",
STACK_FRAME_ELEMENT_FLAG_IS_NUMERICAL,
&(struct stack_frame_data){.type = datatype_for_numeric()}, node->llnum);
&(struct stack_frame_data){.dtype = datatype_for_numeric()}, node->llnum);
}

bool codegen_is_exp_root_for_flags(int flags) {
Expand Down Expand Up @@ -509,11 +509,159 @@ void codegen_generate_scope_variable(struct node *node) {
}
}

void codegen_generate_entity_access_start(
struct resolver_result *result,
struct resolver_entity *root_assignment_entity, struct history *history) {
if (root_assignment_entity->type == RESOLVER_ENTITY_TYPE_UNSUPPORTED) {
codegen_generate_expressionable(root_assignment_entity->node, history);
} else if (result->flags & RESOLVER_RESULT_FLAG_FIRST_ENTITY_PUSH_VALUE) {
asm_push_ins_push_with_data(
"dword [%s]", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE, "result_value", 0,
&(struct stack_frame_data){.dtype = root_assignment_entity->dtype},
result->base.address);
} else if (result->flags & RESOLVER_RESULT_FLAG_FIRST_ENTITY_LOAD_TO_EBX) {
if (root_assignment_entity->next &&
root_assignment_entity->next->flags &
RESOLVER_ENTITY_FLAG_IS_POINTER_ARRAY_ENTITY) {
asm_push("mov ebx, [%s]", result->base.address);
} else {
asm_push("lea ebx, [%s]", result->base.address);
}

asm_push_ins_push_with_data(
"ebx", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE, "result_value", 0,
&(struct stack_frame_data){.dtype = root_assignment_entity->dtype});
}
}

void codegen_generate_entity_access_for_variable_or_general(
struct resolver_result *result, struct resolver_entity *entity) {
// restore ebx register
asm_push_ins_pop("ebx", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE,
"result_value");
if (entity->flags & RESOLVER_ENTITY_FLAG_DO_INDIRECTION) {
asm_push("mov ebx, [ebx]");
}

asm_push("add ebx, %d", entity->offset_from_bp);
asm_push_ins_push_with_data(
"ebx", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE, "result_value", 0,
&(struct stack_frame_data){.dtype = entity->dtype});
}

void codegen_generate_entity_access_for_entity_assignment_left_operand(
struct resolver_result *result, struct resolver_entity *entity,
struct history *history) {
switch (entity->type) {
case RESOLVER_ENTITY_TYPE_ARRAY_BRACKET:
#warning "not implemented"
break;

case RESOLVER_ENTITY_TYPE_VARIABLE:
case RESOLVER_ENTITY_TYPE_GENERAL:
codegen_generate_entity_access_for_variable_or_general(result, entity);
break;

case RESOLVER_ENTITY_TYPE_FUNCTION_CALL:
#warning "not implemented"
break;

case RESOLVER_ENTITY_TYPE_UNARY_INDIRECTION:
#warning "not implemented"
break;

case RESOLVER_ENTITY_TYPE_UNARY_GET_ADDRESS:
#warning "not implemented"
break;

case RESOLVER_ENTITY_TYPE_UNSUPPORTED:
#warning "not implemented"
break;

case RESOLVER_ENTITY_TYPE_CAST:
#warning "not implemented"
break;

default:
compiler_error(current_process, "Unknown entity type");
break;
}
}

void codegen_generate_entity_access_for_assignment_left_operand(
struct resolver_result *result,
struct resolver_entity *root_assignment_entity, struct node *top_most_node,
struct history *history) {
codegen_generate_entity_access_start(result, root_assignment_entity, history);
struct resolver_entity *current =
resolver_entity_next(root_assignment_entity);
while (current) {
codegen_generate_entity_access_for_entity_assignment_left_operand(
result, current, history);
current = resolver_entity_next(current);
}
}

void codegen_generate_assignment_part(struct node *node, const char *op,
struct history *history) {
struct datatype right_operand_dtype;
struct resolver_result *result =
resolver_follow(current_process->resolver, node);
assert(resolver_result_ok(result));

struct resolver_entity *root_assignment_entity =
resolver_result_entity_root(result);
const char *reg_to_use = "eax";
const char *mov_type = codegen_byte_word_or_dword_or_ddword(
datatype_element_size(&result->last_entity->dtype), &reg_to_use);
struct resolver_entity *next_entity =
resolver_entity_next(root_assignment_entity);
if (!next_entity) {
if (datatype_is_struct_or_union_no_pointer(&result->last_entity->dtype)) {
#warning "gen mov for struct or union"
} else {
asm_push_ins_pop("eax", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE,
"result_value");
codegen_generate_assignment_instruction_for_operator(
mov_type, result->base.address, reg_to_use, op,
result->last_entity->dtype.flags & DATATYPE_FLAG_IS_SIGNED);
}
} else {
codegen_generate_entity_access_for_assignment_left_operand(
result, root_assignment_entity, node, history);
asm_push_ins_pop("edx", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE,
"result_value");
asm_push_ins_pop("eax", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE,
"result_value");
codegen_generate_assignment_instruction_for_operator(
mov_type, "edx", reg_to_use, op,
result->last_entity->flags & DATATYPE_FLAG_IS_SIGNED);
}
}
void codegen_generate_assignment_expression(struct node *node,
struct history *history) {
codegen_generate_expressionable(
node->exp.right,
history_down(history,
EXPRESSION_IS_ASSIGNMENT | IS_RIGHT_OPERAND_OF_ASSIGNMENT));
codegen_generate_assignment_part(node->exp.left, node->exp.op, history);
}

void codegen_generate_exp_node(struct node *node, struct history *history) {
if (is_node_assignment(node)) {
codegen_generate_assignment_expression(node, history);
}
}

void codegen_generate_statement(struct node *node, struct history *history) {
switch (node->type) {
case NODE_TYPE_VARIABLE:
codegen_generate_scope_variable(node);
break;

case NODE_TYPE_EXPRESSION:
codegen_generate_exp_node(node, history_begin(history->flags));
break;
}
}

Expand Down
8 changes: 7 additions & 1 deletion compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ struct datatype {

struct stack_frame_data {
// data type that the stack frame is for
struct datatype type;
struct datatype dtype;
};

struct stack_frame_element {
Expand Down Expand Up @@ -1253,6 +1253,12 @@ struct resolver_default_scope_data *
resolver_default_scope_private(struct resolver_scope *scope);
struct resolver_default_entity_data *
resolver_default_entity_private(struct resolver_entity *entity);
struct resolver_result *resolver_follow(struct resolver_process *process,
struct node *node);
bool resolver_result_ok(struct resolver_result *result);
struct resolver_entity *
resolver_result_entity_root(struct resolver_result *result);
struct resolver_entity *resolver_entity_next(struct resolver_entity *entity);

int codegen(struct compile_process *process);
struct code_generator *codegenerator_new(struct compile_process *process);
Expand Down
2 changes: 1 addition & 1 deletion resolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ resolver_follow_for_name(struct resolver_process *process, const char *name,
}

if (entity->type == RESOLVER_ENTITY_TYPE_VARIABLE &&
datatype_is_struct_or_union(entity->var_data.type) ||
datatype_is_struct_or_union(&entity->var_data.type) ||
entity->type == RESOLVER_ENTITY_TYPE_FUNCTION &&
datatype_is_struct_or_union(&entity->dtype)) {
result->last_struct_union_entity = entity;
Expand Down
5 changes: 4 additions & 1 deletion test.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const char *hello = "Hello, World!";

int test() { int b = 2024; }
int test() {
int b = 2024;
b = 19;
}

0 comments on commit 4387ff5

Please sign in to comment.