builder_t* builder_create(const char* description) { if(description == NULL) return NULL; source_t* source = source_open_string(description); symtab_t* symtab = symtab_new(); ast_t* ast = build_ast(source, symtab); if(ast == NULL) { // Error, tidy up source_close(source); symtab_free(symtab); return NULL; } // Success, create builder builder_t* builder = POOL_ALLOC(builder_t); builder->sources = NULL; builder->defs = symtab; builder->dummy_root = ast_blank(TK_TEST); ast_add(builder->dummy_root, ast); add_source(builder, source); return builder; }
void check_block(SymTab *st, Block* b) { if(!b) return; SymTab *local_scope; local_scope = symtab_new(st); check_declrlist(local_scope, b->declrs); check_commlist(local_scope, b->comms); symtab_free(local_scope); }
void ast_clear_local(ast_t* ast) { if(ast->symtab != NULL) { symtab_free(ast->symtab); ast_scope(ast); } }
void cook_reset(void) { leaf_reset(); string_list_destructor(&cook_auto_list); /* Don't nuke cook_auto_list_nonleaf, we need it for later */ cook_implicit_nth_by_name(0, 0); if (explicit_stp) { symtab_free(explicit_stp); explicit_stp = 0; } if (implicit_stp) { symtab_free(implicit_stp); implicit_stp = 0; } recipe_list_destructor(&explicit); recipe_list_destructor(&implicit); cascade_reset(); }
static void compile(const char *pgm, int framework) { struct patch *patch; patch = patch_do_compile("/", pgm, report, framework); if (!patch) { symtab_free(); exit(1); } if (!quiet) show_patch(patch); if (trace_var) play_midi(patch); symtab_free(); stim_put(patch->stim); /* * We can't use patch_free here because that function also accesses * image data, which isn't available in standalone builds. A simple * free(3) has the same effect in this case. */ free(patch); }
void ast_clear(ast_t* ast) { if(ast->symtab != NULL) { symtab_free(ast->symtab); ast_scope(ast); } ast_t* child = ast->child; while(child != NULL) { ast_clear(child); child = child->sibling; } }
static struct s_fn_decl *s_fn_decl(struct p_fn_decl *p) { struct s_fn_decl *s; struct symtab *tab; tab = symtab_new(NULL); s = malloc(sizeof(*s)); s->name = p->name; s_arg_list(tab, s->name, p->args); s->body = s_expr(tab, p->body); symtab_free(tab); return s; }
void check_declr(SymTab *st, Declr* d) { switch(d->tag) { case DECLR_VAR: { if(st->prev) check_array_sizes(d->type); else check_array_empty(d->type); if(!symtab_add(st, d)) print_error("double declaration of variable", d->line); break; } case DECLR_FUNC: { check_array_empty(d->type); if(d->u.func.block) { Declr *proto; SymTab *param; proto = symtab_find(st, d->u.func.name); if(!proto) { symtab_add(st, d); proto = d; } else if(proto->u.func.block) { print_error("double declaration of function", d->line); } else { proto->u.func.block = d->u.func.block; } return_type = d->type; param = symtab_new(st); check_paramlist(param, proto->u.func.params, d->line); check_block(param, proto->u.func.block); symtab_free(param); } else { if(!symtab_add(st, d)) print_error("double declaration of function prototype", d->line); } break; } default: print_error("bug in compiler!", 0); } }
void builder_free(builder_t* builder) { if(builder == NULL) return; ast_free(builder->dummy_root); symtab_free(builder->defs); builder_src_t* p = builder->sources; while(p != NULL) { builder_src_t* next = p->next; source_close(p->source); POOL_FREE(builder_src_t, p); p = next; } POOL_FREE(builder_t, builder); }
void ast_free(ast_t* ast) { if(ast == NULL) return; ast_t* child = ast->child; ast_t* next; while(child != NULL) { next = child->sibling; ast_free(child); child = next; } ast_free(ast->type); switch(token_get_id(ast->t)) { case TK_PROGRAM: program_free((program_t*)ast->data); break; case TK_PACKAGE: package_free((package_t*)ast->data); break; case TK_MODULE: source_close((source_t*)ast->data); break; default: break; } token_free(ast->t); symtab_free(ast->symtab); POOL_FREE(ast_t, ast); }
// Add methods from provided traits into the given entity static bool build_entity_def(ast_t* entity) { assert(entity != NULL); ast_state_t state = (ast_state_t)(uint64_t)ast_data(entity); // Check for recursive definitions switch(state) { case AST_STATE_INITIAL: ast_setdata(entity, (void*)AST_STATE_INPROGRESS); break; case AST_STATE_INPROGRESS: ast_error(entity, "traits can't be recursive"); return false; case AST_STATE_DONE: return true; default: assert(0); return false; } symtab_t* symtab = symtab_new(); ast_t* name_lists = ast_blank(TK_MEMBERS); methods_t method_info = { symtab, name_lists, NULL }; bool r = process_provides(entity, &method_info); symtab_free(symtab); ast_free(name_lists); ast_setdata(entity, (void*)AST_STATE_DONE); return r; }
static void compile_vm(const char *pgm) { struct fpvm_fragment fragment; struct parser_comm comm = { .u.fragment = &fragment, .assign_default = assign_raw, .assign_per_frame = assign_raw, .assign_per_vertex = assign_raw_fail, .assign_image_name = assign_image_fail, }; int ok; init_fpvm(&fragment, 0); fpvm_set_bind_mode(&fragment, FPVM_BIND_ALL); symtab_init(); ok = parse(pgm, TOK_START_ASSIGN, &comm); if (ok) fpvm_dump(&fragment); symtab_free(); if (ok) return; fflush(stdout); fprintf(stderr, "%s\n", comm.msg); free((void *) comm.msg); exit(1); } /* ----- Command-line processing ------------------------------------------- */ static void free_buffer(void) { free((void *) buffer); }
void check_prog(DeclrListNode *ast) { SymTab *global; global = symtab_new(NULL); check_declrlist(global, ast); symtab_free(global); }
static void parse_only(const char *pgm) { static struct patch patch; static struct compiler_sc sc = { .p = &patch, }; struct parser_comm comm = { .u.sc = &sc, .assign_default = assign_default, .assign_per_frame = assign_per_frame, .assign_per_vertex = assign_per_vertex, .assign_image_name = assign_image_name, }; int ok; symtab_init(); ok = parse(pgm, TOK_START_ASSIGN, &comm); if (symbols) { const struct sym *sym; int user = 0; foreach_sym(sym) { if (!user && !(sym->flags & SF_SYSTEM)) { printf("\n"); user = 1; } if (sym->flags & SF_CONST) printf("%s = %g\n", sym->fpvm_sym.name, sym->f); else printf("%s\n", sym->fpvm_sym.name); } } symtab_free(); stim_db_free(); /* @@@ */ stim_put(patch.stim); if (ok) return; fflush(stdout); fprintf(stderr, "%s\n", comm.msg); free((void *) comm.msg); exit(1); } /* ----- Compile the patch into PFPU code ---------------------------------- */ /* * "sym" and "field" are used to access a field chosen by the caller in the * "struct sym". For this, the caller provides a buffer (sym) and a pointer to * the respective field inside the buffer. This way, it's perfectly type-safe * and we don't need offsetof acrobatics. */ static const char *lookup_name(int idx, struct sym *sym, const int *field) { const struct sym *walk; foreach_sym(walk) { *sym = *walk; if (*field == idx) return walk->fpvm_sym.name; } return NULL; } static void dump_regs(const int *alloc, struct sym *sym, const int *field, const float *values, int n) { const char *mapped[n]; int i; for (i = 0; i != n; i++) mapped[i] = NULL; for (i = 0; i != n; i++) if (alloc[i] != -1) mapped[alloc[i]] = lookup_name(i, sym, field); for (i = 0; i != n; i++) { if (!values[i] && !mapped[i]) continue; printf("R%03d = %f", i, values[i]); if (mapped[i]) printf(" %s", mapped[i]); printf("\n"); } } static void show_patch(const struct patch *patch) { int i; struct sym sym; printf("global:\n"); for (i = 0; i != COMP_PFV_COUNT; i++) if (patch->pfv_initial[i]) printf("R%03d = %f %s\n", i, patch->pfv_initial[i], lookup_name(i, &sym, &sym.pfv_idx)); printf("per-frame PFPU fragment:\n"); dump_regs(patch->pfv_allocation, &sym, &sym.pfv_idx, patch->perframe_regs, COMP_PFV_COUNT); pfpu_dump(patch->perframe_prog, patch->perframe_prog_length); printf("per-vertex PFPU fragment:\n"); dump_regs(patch->pvv_allocation, &sym, &sym.pvv_idx, patch->pervertex_regs, COMP_PVV_COUNT); pfpu_dump(patch->pervertex_prog, patch->pervertex_prog_length); }
void VG_(redir_notify_delete_SegInfo)( SegInfo* delsi ) { TopSpec* ts; TopSpec* tsPrev; Spec* sp; Spec* sp_next; OSet* tmpSet; Active* act; Bool delMe; Addr* addrP; vg_assert(delsi); /* Search for it, and make tsPrev point to the previous entry, if any. */ tsPrev = NULL; ts = topSpecs; while (True) { if (ts == NULL) break; if (ts->seginfo == delsi) break; tsPrev = ts; ts = ts->next; } vg_assert(ts); /* else we don't have the deleted SegInfo */ vg_assert(ts->seginfo == delsi); /* Traverse the actives, copying the addresses of those we intend to delete into tmpSet. */ tmpSet = VG_(OSet_Create)( 0/*keyOff*/, NULL/*fastCmp*/, symtab_alloc, symtab_free); ts->mark = True; VG_(OSet_ResetIter)( activeSet ); while ( (act = VG_(OSet_Next)(activeSet)) ) { delMe = act->parent_spec != NULL && act->parent_sym != NULL && act->parent_spec->seginfo != NULL && act->parent_sym->seginfo != NULL && (act->parent_spec->mark || act->parent_sym->mark); /* While we're at it, a bit of paranoia: delete any actives which don't have both feet in valid client executable areas. But don't delete hardwired-at-startup ones; these are denoted by having parent_spec or parent_sym being NULL. */ if ( (!delMe) && act->parent_spec != NULL && act->parent_sym != NULL ) { if (!is_plausible_guest_addr(act->from_addr)) delMe = True; if (!is_plausible_guest_addr(act->to_addr)) delMe = True; } if (delMe) { addrP = VG_(OSet_AllocNode)( tmpSet, sizeof(Addr) ); *addrP = act->from_addr; VG_(OSet_Insert)( tmpSet, addrP ); /* While we have our hands on both the 'from' and 'to' of this Active, do paranoid stuff with tt/tc. */ VG_(discard_translations)( (Addr64)act->from_addr, 1, "redir_del_SegInfo(from_addr)"); VG_(discard_translations)( (Addr64)act->to_addr, 1, "redir_del_SegInfo(to_addr)"); } } /* Now traverse tmpSet, deleting corresponding elements in activeSet. */ VG_(OSet_ResetIter)( tmpSet ); while ( (addrP = VG_(OSet_Next)(tmpSet)) ) { act = VG_(OSet_Remove)( activeSet, addrP ); vg_assert(act); VG_(OSet_FreeNode)( activeSet, act ); } VG_(OSet_Destroy)( tmpSet, NULL ); /* The Actives set is now cleaned up. Free up this TopSpec and everything hanging off it. */ for (sp = ts->specs; sp; sp = sp_next) { if (sp->from_sopatt) symtab_free(sp->from_sopatt); if (sp->from_fnpatt) symtab_free(sp->from_fnpatt); sp_next = sp->next; symtab_free(sp); } if (tsPrev == NULL) { /* first in list */ topSpecs = ts->next; } else { tsPrev->next = ts->next; } symtab_free(ts); if (VG_(clo_trace_redir)) show_redir_state("after VG_(redir_notify_delete_SegInfo)"); }