126 lines
2.6 KiB
C
126 lines
2.6 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#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;
|
|
}
|