#include #include #include "rifle/codegen.h" #include "rifle/trace.h" #include "rifle/mu.h" static int resolve_func(struct rifle_state *state, struct ast_node *root) { struct symbol *symbol; if (state == NULL || root == NULL) { return -1; } if (root->epilogue) { return mu_gen_ret(state); } if ((symbol = root->symbol) == NULL) { trace_error(state, "internal: no symbol associated with func node\n"); return -1; } return mu_gen_label(state, SECTION_TEXT, symbol->name, symbol->pub); } static int resolve_return(struct rifle_state *state, struct ast_node *root) { struct symbol *func_sym; struct ast_node *rhs; data_type_t type; if (state == NULL || root == NULL) { return -1; } if ((func_sym = state->cur_func) == NULL) { return -1; } if (root->type != AST_RETURN) { return -1; } if ((rhs = root->right) == NULL) { trace_error(state, "internal: return has no rhs\n"); return -1; } type = data_raw_type(&func_sym->dtype) ; switch (rhs->type) { case AST_NUMBER: mu_gen_retimm( state, rhs->v, type_to_msize(type) ); break; default: trace_error(state, "internal: bad ast node in return\n"); return -1; } return 0; } static int resolve_loop(struct rifle_state *state, struct ast_node *root) { char label[32]; if (state == NULL || root == NULL) { return -1; } if (root->epilogue) { snprintf(label, sizeof(label), "L.%zu", state->loop_count - 1); mu_gen_blab(state, label); snprintf(label, sizeof(label), "L.%zu.1", state->loop_count - 1); mu_gen_label(state, SECTION_TEXT, label, false); } else { snprintf(label, sizeof(label), "L.%zu", state->loop_count++); mu_gen_label(state, SECTION_TEXT, label, false); } return 0; } int cg_resolve_node(struct rifle_state *state, struct ast_node *root) { if (state == NULL || root == NULL) { return -1; } switch (root->type) { case AST_FUNC: if (resolve_func(state, root) < 0) { return -1; } break; case AST_RETURN: if (resolve_return(state, root) < 0) { return -1; } break; case AST_LOOP: if (resolve_loop(state, root) < 0) { return -1; } break; default: trace_error(state, "unknown ast node %d\n", root->type); break; } return 0; }