ListT* get_loadables(int do_print) { DIR* task_dir; struct dirent *task_dirent; ListT* files; int file_idx; task_dir = opendir(kTaskDir); assert(task_dir != NULL); files = List(10, NULL); file_idx = 0; while ((task_dirent = readdir(task_dir)) != NULL) { // //make sure we are not looking at . and .. files if (is_loadable(task_dirent->d_name)) { list_append(files, task_dirent->d_name); if (do_print) { printf("%d) %s\n", file_idx++, task_dirent->d_name); } } } return files; }
void emit_nodes(struct node *n, const char *assignto, BOOL force, BOOL inloop) { char *fast = NULL; assert(n); if (n->next == NULL && n->type != NODE_CALL && !assignto && !force) { /* do not emit single node, unless it is a call or we really need it */ cry("statement with no effect\n"); return; } switch (n->type) { case NODE_IMM: { fast = AS_IMM(n)->value; maybe_symbol_forward(fast); if (force) { cry("constant expression '%s' in conditional\n", fast); } assert(!assignto); break; } case NODE_LVAL: { struct lval_node *p = AS_LVAL(n); int loadable = is_loadable(n, TRUE); if (loadable < 0) { fast = p->name; } else if (loadable > 0) { make_symbol_used(p->name); emit_load_direct(p->name, p->deref); } else { emit_load_indirect(p->name, p->deref); } break; } case NODE_CALL: { struct call_node *p = AS_CALL(n); struct node *parm; int deref0 = 0; char *args[MAX_FUNC_ARGS]; char *func; int i; BOOL retval = (n->next != NULL) || force || assignto; BOOL direct = FALSE; for (i = 0, parm = p->parm; parm; parm = parm->next, i++) { BOOL r0 = (i == 0 && arch_regparm); assert(i < MAX_FUNC_ARGS); if (parm->type == NODE_IMM) { args[i] = xstrdup(AS_IMM(parm)->value); maybe_symbol_forward(args[i]); } else if (parm->type == NODE_LVAL && is_loadable(parm, r0)) { struct lval_node *q = AS_LVAL(parm); args[i] = xstrdup(q->name); make_symbol_used(args[i]); if (q->deref) { deref0 = 1; } } else if (r0 && parm->next == NULL) { args[i] = NULL; direct = TRUE; emit_nodes(parm, NULL, TRUE, inloop); } else if (r0 && parm->type == NODE_LVAL) { struct lval_node *q = AS_LVAL(parm); args[i] = create_address_str(q->name); deref0 = 1; if (q->deref) { deref0++; } } else { args[i] = new_name("var"); emit_nodes(parm, args[i], FALSE, inloop); make_symbol_used(args[i]); } } func = p->func; if (retval && (p->attr & ATTRIB_NORETURN)) { cry("function '%s' does not return\n", func); } if (!is_loadable_sym(func)) { char *ptr = new_name("ptr"); emit_load_indirect(func, FALSE); add_symbol_forward(ptr, 0); emit_store_indirect(ptr); func = ptr; } else { func = xstrdup(func); } make_symbol_used(func); if (!(p->attr & ATTRIB_NORETURN)) { if ((p->attr & ATTRIB_STACK) || inloop) { if (!(p->attr & ATTRIB_STACK)) { cry("reserved [[stack]] for '%s' because of loop\n", func); } mark_all_used(PROTECTED); } else { mark_all_used(CLOBBERED); } } if (direct) { emit_call(func, NULL, 0, deref0, inloop, retval, p->attr); } else { emit_call(func, args, i, deref0, inloop, retval, p->attr); } free(func); while (--i >= 0) { free(args[i]); } break; } case NODE_ADD: { struct node *term; struct node *prev; int deref0 = 0; char *prev_tmp; prev = AS_ADD(n)->list; if (prev->type == NODE_IMM) { prev_tmp = xstrdup(AS_IMM(prev)->value); maybe_symbol_forward(prev_tmp); } else if (prev->type == NODE_LVAL && is_loadable(prev, TRUE)) { prev_tmp = xstrdup(AS_LVAL(prev)->name); make_symbol_used(prev_tmp); if (AS_LVAL(prev)->deref) { deref0 = TRUE; } } else if (prev->type == NODE_LVAL) { prev_tmp = create_address_str(AS_LVAL(prev)->name); deref0 = 1; if (AS_LVAL(prev)->deref) { deref0++; } } else { prev_tmp = new_name("var"); emit_nodes(prev, prev_tmp, FALSE, inloop); make_symbol_used(prev_tmp); } for (term = prev->next; term; term = term->next) { BOOL swap = FALSE; char *tmp; char *sum = new_name("sum"); if (term->type == NODE_IMM) { tmp = xstrdup(AS_IMM(term)->value); maybe_symbol_forward(tmp); } else if (term->type == NODE_LVAL && is_loadable(term, !deref0)) { tmp = xstrdup(AS_LVAL(term)->name); make_symbol_used(tmp); if (AS_LVAL(term)->deref) { swap = TRUE; deref0 = 1; } } else if (term->type == NODE_LVAL && !deref0) { tmp = create_address_str(AS_LVAL(term)->name); deref0 = 1; if (AS_LVAL(term)->deref) { swap = TRUE; deref0++; } } else { tmp = new_name("var"); emit_nodes(term, tmp, FALSE, inloop); make_symbol_used(tmp); } emit_add(prev_tmp, tmp, deref0, swap); deref0 = 0; if (term->next) { emit_store_indirect(sum); } free(prev_tmp); prev_tmp = sum; free(tmp); } free(prev_tmp); break; } } if (assignto) { add_symbol_forward(assignto, 0); emit_store_indirect(assignto); } else { BOOL loaded = FALSE; for (n = n->next; n; n = n->next) { BOOL later = FALSE; struct lval_node *p = AS_LVAL(n); assert(n->type == NODE_LVAL); if (fast) { if (optimize_imm && !p->deref && !get_symbol(p->name) && ((p->attr & ATTRIB_CONSTANT) || !inloop)) { emit_fast(p->name, fast); add_symbol_defined(p->name, fast, p->attr); continue; } if (!loaded) { loaded = TRUE; if (p->deref && !is_loadable_sym(p->name)) { later = TRUE; } else { emit_load_direct(fast, FALSE); } } } if (p->attr & ATTRIB_CONSTANT) { cry("useless const for '%s'\n", p->name); } if (p->deref) { /* XXX only addresses (imports/vectors) can be derefed */ if (!is_loadable_sym(p->name)) { /* XXX ok, this is very very shitty * tip1: store value to tmp_N for each future p->deref at once * tip2: calculate in advance how many derefs we will need and store pointers before calculating r0 (see above) */ char *ptr = new_name("ptr"); char *tmp; if (!later) { tmp = emit_save(); } emit_load_indirect(p->name, FALSE); emit_store_indirect(ptr); if (!later) { emit_restore(tmp); } else { emit_load_direct(fast, FALSE); } add_symbol_forward(ptr, 0); make_symbol_used(ptr); emit_store_direct(ptr); free(ptr); } else { make_symbol_used(p->name); emit_store_direct(p->name); } } else { add_symbol_forward(p->name, p->attr); if (try_symbol_extern(p->name)) { die("cannot assign to import address '%s'\n", p->name); } if (optimize_imm && (try_symbol_attr(p->name) & ATTRIB_CONSTANT)) { die("'%s' was declared constant\n", p->name); } emit_store_indirect(p->name); } } if (force && fast && !loaded) { emit_load_direct(fast, FALSE); } } }