Skip to content

Commit

Permalink
fix switch default case and function calls
Browse files Browse the repository at this point in the history
  • Loading branch information
omdxp committed Sep 3, 2024
1 parent 0b13695 commit 97997a0
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 18 deletions.
40 changes: 36 additions & 4 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,14 @@ void asm_pop_ebp() {
"function_entry_saved_ebp");
}

void codegen_data_section_add(const char *data, ...) {
va_list args;
va_start(args, data);
char *new_data = malloc(256);
vsprintf(new_data, data, args);
vector_push(current_process->generator->custom_data_section, &new_data);
}

void codegen_stack_add_no_compile_time_stack_frame_restore(size_t stack_size) {
if (stack_size != 0) {
asm_push("add esp, %lld", stack_size);
Expand Down Expand Up @@ -364,6 +372,7 @@ struct code_generator *codegenerator_new(struct compile_process *process) {
generator->responses = vector_create(sizeof(struct response *));
generator->_switch.switches =
vector_create(sizeof(struct generator_switch_stmt_entity));
generator->custom_data_section = vector_create(sizeof(const char *));
return generator;
}

Expand Down Expand Up @@ -686,7 +695,7 @@ bool codegen_is_exp_root(struct history *history) {
}

void codegen_reduce_register(const char *reg, size_t size, bool is_signed) {
if (size != DATA_SIZE_DWORD) {
if (size != DATA_SIZE_DWORD && size > 0) {
const char *ins = "movsx";
if (!is_signed) {
ins = "movzx";
Expand Down Expand Up @@ -1381,9 +1390,11 @@ void codegen_generate_entity_access_for_function_call(
vector_set_peek_pointer_end(entity->function_call_data.args);

struct node *node = vector_peek_ptr(entity->function_call_data.args);
int function_call_label_id = codegen_label_count();
codegen_data_section_add("function_call_%d: dd 0", function_call_label_id);
asm_push_ins_pop("ebx", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE,
"result_value");
asm_push("mov ecx, ebx");
asm_push("mov dword [function_call_%d], ebx", function_call_label_id);
if (datatype_is_struct_or_union_no_pointer(&entity->dtype)) {
asm_push("; subtract room for returned struct or union datatype");
codegen_stack_sub_with_name(
Expand All @@ -1399,7 +1410,7 @@ void codegen_generate_entity_access_for_function_call(
node = vector_peek_ptr(entity->function_call_data.args);
}

asm_push("call ecx");
asm_push("call [function_call_%d]", function_call_label_id);
size_t stack_size = entity->function_call_data.stack_size;
if (datatype_is_struct_or_union_no_pointer(&entity->dtype)) {
stack_size += DATA_SIZE_DWORD;
Expand Down Expand Up @@ -1541,7 +1552,15 @@ bool codegen_resolve_node_for_value(struct node *node,

struct datatype dtype;
assert(asm_datatype_back(&dtype));
if (datatype_is_struct_or_union_no_pointer(&dtype)) {
if (result->flags & RESOLVER_RESULT_FLAG_DOES_GET_ADDRESS) {
// do nothing
} else if (result->last_entity->type == RESOLVER_ENTITY_TYPE_FUNCTION_CALL &&
datatype_is_struct_or_union_no_pointer(
&result->last_entity->dtype)) {
// do nothing
}

else if (datatype_is_struct_or_union_no_pointer(&dtype)) {
codegen_generate_struct_push(result->last_entity, history, 0);
} else if (!(dtype.flags & DATATYPE_FLAG_IS_POINTER)) {
asm_push_ins_pop("eax", STACK_FRAME_ELEMENT_TYPE_PUSHED_VALUE,
Expand Down Expand Up @@ -2335,6 +2354,17 @@ void codegen_generate_rod() {
codegen_write_strings();
}

void codegen_generate_data_section_add_ons() {
asm_push("section .data");
vector_set_peek_pointer(current_process->generator->custom_data_section, 0);
const char *str =
vector_peek_ptr(current_process->generator->custom_data_section);
while (str) {
asm_push(str);
str = vector_peek_ptr(current_process->generator->custom_data_section);
}
}

int codegen(struct compile_process *process) {
current_process = process;
scope_create_root(process);
Expand All @@ -2345,6 +2375,8 @@ int codegen(struct compile_process *process) {
codegen_generate_root();
codegen_finish_scope();

codegen_generate_data_section_add_ons();

// generate read only data section
codegen_generate_rod();
return 0;
Expand Down
3 changes: 3 additions & 0 deletions compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ struct code_generator {
// vector of struct codegen_exit_point*
struct vector *exit_points;

// vector of const char*
struct vector *custom_data_section;

// vector of struct response*
struct vector *responses;
};
Expand Down
13 changes: 7 additions & 6 deletions parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ struct history_cases {
struct history {
int flags;
struct parser_history_switch {
struct history_cases case_data;
struct history_cases *case_data;
} _switch;
};

Expand All @@ -86,7 +86,8 @@ static struct history *history_down(struct history *history, int flags) {
struct parser_history_switch
parser_new_switch_statement(struct history *history) {
memset(&history->_switch, 0, sizeof(struct parser_history_switch));
history->_switch.case_data.cases =
history->_switch.case_data = calloc(1, sizeof(struct history_cases));
history->_switch.case_data->cases =
vector_create(sizeof(struct parsed_switch_case));
history->flags |= HISTORY_FLAG_IN_SWITCH_STATEMENT;
return history->_switch;
Expand All @@ -100,7 +101,7 @@ void parser_register_case(struct history *history, struct node *case_node) {
assert(history->flags & HISTORY_FLAG_IN_SWITCH_STATEMENT);
struct parsed_switch_case scase;
scase.index = case_node->stmt._case.exp->llnum;
vector_push(history->_switch.case_data.cases, &scase);
vector_push(history->_switch.case_data->cases, &scase);
}

void parse_body(size_t *variable_size, struct history *history);
Expand Down Expand Up @@ -1526,7 +1527,7 @@ void parse_default(struct history *history) {
expect_keyword("default");
expect_sym(':');
make_default_node();
history->_switch.case_data.has_default_case = true;
history->_switch.case_data->has_default_case = true;
}

void parse_case(struct history *history) {
Expand All @@ -1551,8 +1552,8 @@ void parse_switch(struct history *history) {
size_t variable_size = 0;
parse_body(&variable_size, history);
struct node *body_node = node_pop();
make_switch_node(switch_exp_node, body_node, _switch.case_data.cases,
_switch.case_data.has_default_case);
make_switch_node(switch_exp_node, body_node, _switch.case_data->cases,
_switch.case_data->has_default_case);
parser_end_switch_statement(&_switch);
}

Expand Down
11 changes: 3 additions & 8 deletions test.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
int printf(const char *s, ...);

int main() {
int x = 1;
x++;
++x;
x--;
--x;
printf("%d\n", ++x);
}
int sum(int x, int y) { return x + y; }

int main() { printf("%d\n", sum(20, 30)); }

0 comments on commit 97997a0

Please sign in to comment.