void subprograms(int level) { char *tmp = malloc(35*sizeof(char)); FTYPE type; while(token == TK_PROCEDURE || token == TK_FUNCTION) { if (token == TK_PROCEDURE) { type = PROC; } else { type = FUNC; } debug(level,"SUBPROGRAMS"); debug_lex(); id(&tmp, level+1); new_function(tmp, type); push_scope(tmp); funcbody(tmp, level+1); } }
void PSIVisitor::visit_package(IPackage *pkg) { std::vector<IBaseItem *>::const_iterator it=pkg->getItems().begin(); for (int32_t i=0; i<pkg->getItems().size(); i++) { IBaseItem *it = pkg->getItems().at(i); push_scope(it); m_removed = false; switch (it->getType()) { case IBaseItem::TypeAction: // TODO: break; case IBaseItem::TypeStruct: visit_struct(dynamic_cast<IStruct *>(it)); break; case IBaseItem::TypeExtend: visit_extend(dynamic_cast<IExtend *>(it)); break; case IBaseItem::TypeImportFunc: visit_import_func(dynamic_cast<IImportFunc *>(it)); break; default: fprintf(stdout, "Error: Unhandled package item: %d\n", it->getType()); } pop_scope(); if (m_removed) { dynamic_cast<PackageImpl *>(pkg)->remove(it); delete it; } } m_removed = false; }
/** * FnLit = "\" [{ Pattern }] "->" Expr */ static ast* parseFnLit (parserCtx* ctx) { match(ctx, "\\"); /*Enter a new scope*/ sym* oldscope = push_scope(ctx, symAddScope(ctx->scope)); /*Arg patterns*/ vector(ast*) args = vectorInit(2, malloc); while (!see(ctx, "->")) vectorPush(&args, parserPattern(ctx)); /*Body*/ match(ctx, "->"); ast* expr = parseExpr(ctx); /*Pop scope*/ ctx->scope = oldscope; return astCreateFnLit(args, expr); }
void PSIVisitor::visit_comp_pkg_body(const std::vector<IBaseItem *> &items) { std::vector<IBaseItem *>::const_iterator it=items.begin(); for (; it!=items.end(); it++) { fprintf(stdout, " -- item %p %d\n", *it, (*it)->getType()); fflush(stdout); push_scope(*it); switch ((*it)->getType()) { case IBaseItem::TypeAction: fprintf(stdout, "---> visit_action\n"); fflush(stdout); visit_action(dynamic_cast<IAction *>(*it)); fprintf(stdout, "<--- visit_action\n"); fflush(stdout); break; case IBaseItem::TypeStruct: visit_struct(dynamic_cast<IStruct *>(*it)); break; } pop_scope(); } }
static void scan_item(unsigned depth, vpiHandle item, int skip) { struct t_cb_data cb; struct vcd_info* info; const char* name; const char* ident; int nexus_id; /* list of types to iterate upon */ int i; static int types[] = { /* Value */ vpiNet, vpiReg, vpiVariables, /* Scope */ vpiFunction, vpiModule, vpiNamedBegin, vpiNamedFork, vpiTask, -1 }; switch (vpi_get(vpiType, item)) { case vpiMemoryWord: if (vpi_get(vpiConstantSelect, item) == 0) { /* Turn a non-constant array word select into a * constant word select. */ vpiHandle array = vpi_handle(vpiParent, item); PLI_INT32 idx = vpi_get(vpiIndex, item); item = vpi_handle_by_index(array, idx); } case vpiIntegerVar: case vpiBitVar: case vpiByteVar: case vpiShortIntVar: case vpiIntVar: case vpiLongIntVar: case vpiTimeVar: case vpiReg: case vpiNet: /* An array word is implicitly escaped so look for an * escaped identifier that this could conflict with. */ if (vpi_get(vpiType, item) == vpiMemoryWord && vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) { vpi_printf("LXT2 warning: dumping array word %s will " "conflict with an escaped identifier.\n", vpi_get_str(vpiFullName, item)); } if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); nexus_id = vpi_get(_vpiNexusId, item); if (nexus_id) { ident = find_nexus_ident(nexus_id); } else { ident = 0; } if (!ident) { char*tmp = create_full_name(name); ident = strdup_sh(&name_heap, tmp); free(tmp); if (nexus_id) set_nexus_ident(nexus_id, ident); info = new_vcd_info(); info->item = item; info->sym = lxt2_wr_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiLeftRange, item), vpi_get(vpiRightRange, item), LXT2_WR_SYM_F_BITS); info->dmp_next = 0; cb.time = 0; cb.user_data = (char*)info; cb.value = NULL; cb.obj = item; cb.reason = cbValueChange; cb.cb_rtn = variable_cb_1; info->cb = vpi_register_cb(&cb); } else { char *n = create_full_name(name); lxt2_wr_symbol_alias(dump_file, ident, n, vpi_get(vpiSize, item)-1, 0); free(n); } break; case vpiRealVar: if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); { char*tmp = create_full_name(name); ident = strdup_sh(&name_heap, tmp); free(tmp); } info = new_vcd_info(); info->item = item; info->sym = lxt2_wr_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiSize, item)-1, 0, LXT2_WR_SYM_F_DOUBLE); info->dmp_next = 0; cb.time = 0; cb.user_data = (char*)info; cb.value = NULL; cb.obj = item; cb.reason = cbValueChange; cb.cb_rtn = variable_cb_1; info->cb = vpi_register_cb(&cb); break; case vpiModule: case vpiNamedBegin: case vpiTask: case vpiFunction: case vpiNamedFork: if (depth > 0) { int nskip; vpiHandle argv; const char* fullname = vpi_get_str(vpiFullName, item); #if 0 vpi_printf("LXT2 info: scanning scope %s, %u levels\n", fullname, depth); #endif nskip = vcd_scope_names_test(fullname); if (!nskip) vcd_scope_names_add(fullname); else vpi_printf("LXT2 warning: ignoring signals in " "previously scanned scope %s\n", fullname); name = vpi_get_str(vpiName, item); push_scope(name); for (i=0; types[i]>0; i++) { vpiHandle hand; argv = vpi_iterate(types[i], item); while (argv && (hand = vpi_scan(argv))) { scan_item(depth-1, hand, nskip); } } pop_scope(); } break; default: vpi_printf("LXT2 warning: $dumpvars: Unsupported parameter " "type (%s)\n", vpi_get_str(vpiType, item)); } }
void block(char *name, int level) { LIST *S = (LIST*)malloc(sizeof(LIST)); SYMBOL *tmp = NULL; /* initial block call */ if(is_program_block == 1) { is_program_block = 0; if(token == TK_LBRAC) { debug(level,"BLOCK"); push_scope(name); new_function(name, PROG); debug_lex(level+1); declerations(level+1); subprograms(level+1); tmp = lookup(name); tmp->func.genquad = qlabel; main_start_quad = qlabel; genquad("begin_block", program_name, "_", "_"); sequence(S, level+1); if(token == TK_RBRAC) { pop_scope(); debug_lex(); } else { /* syntax error lpar expected */ syntax_error("a '}' expected"); } } else { /* syntax error rpar expected */ syntax_error("'{' expected"); } backpatch(S->next, int2string(nextquad())); genquad("halt", "_", "_", "_"); genquad("end_block", program_name, "_", "_"); } else { if(token == TK_LBRAC) { debug(level,"BLOCK"); debug_lex(level+1); declerations(level+1); subprograms(level+1); tmp = lookup(name); tmp->func.genquad = qlabel; genquad("begin_block", name, "_", "_"); fprintf(stderr, "quad quad %s %d\n", tmp->name, tmp->func.genquad); sequence(S, level+1); if(token == TK_RBRAC) { if (!strcmp(assembly, "x86")) { generate_final_x86( program_name); } else { generate_final( program_name); } pop_scope(); debug_lex(); } else { /* syntax error lpar expected */ syntax_error("a '}' expected"); } } else { /* syntax error rpar expected */ syntax_error("'{' expected"); } backpatch(S->next, int2string(nextquad())); genquad("end_block", name,"_", "_"); } }
/* Cover both external declarations, functions, and local declarations (with * optional initialization code) inside functions. */ struct block *declaration(struct block *parent) { struct typetree *base; enum symtype symtype; enum linkage linkage; int stc = '$'; base = declaration_specifiers(&stc); switch (stc) { case EXTERN: symtype = SYM_DECLARATION; linkage = LINK_EXTERN; break; case STATIC: symtype = SYM_TENTATIVE; linkage = LINK_INTERN; break; case TYPEDEF: symtype = SYM_TYPEDEF; linkage = LINK_NONE; break; default: if (!ns_ident.current_depth) { symtype = SYM_TENTATIVE; linkage = LINK_EXTERN; } else { symtype = SYM_DEFINITION; linkage = LINK_NONE; } break; } while (1) { struct definition *def; const char *name = NULL; const struct typetree *type; struct symbol *sym; type = declarator(base, &name); if (!name) { consume(';'); return parent; } sym = sym_add(&ns_ident, name, type, symtype, linkage); if (ns_ident.current_depth) { assert(ns_ident.current_depth > 1); def = current_func(); def->locals = sym_list_add(def->locals, sym); } switch (peek().token) { case ';': consume(';'); return parent; case '=': if (sym->symtype == SYM_DECLARATION) { error("Extern symbol '%s' cannot be initialized.", sym->name); exit(1); } if (!sym->depth && sym->symtype == SYM_DEFINITION) { error("Symbol '%s' was already defined.", sym->name); exit(1); } consume('='); sym->symtype = SYM_DEFINITION; if (sym->linkage == LINK_NONE) { assert(parent); parent = initializer(parent, var_direct(sym)); } else { assert(sym->depth || !parent); def = push_back_definition(sym); initializer(def->body, var_direct(sym)); } assert(size_of(&sym->type) > 0); if (peek().token != ',') { consume(';'); return parent; } break; case '{': { int i; if (!is_function(&sym->type) || sym->depth) { error("Invalid function definition."); exit(1); } assert(!parent); assert(sym->linkage != LINK_NONE); sym->symtype = SYM_DEFINITION; def = push_back_definition(sym); push_scope(&ns_ident); define_builtin__func__(sym->name); for (i = 0; i < nmembers(&sym->type); ++i) { name = get_member(&sym->type, i)->name; type = get_member(&sym->type, i)->type; symtype = SYM_DEFINITION; linkage = LINK_NONE; if (!name) { error("Missing parameter name at position %d.", i + 1); exit(1); } def->params = sym_list_add(def->params, sym_add(&ns_ident, name, type, symtype, linkage)); } parent = block(def->body); pop_scope(&ns_ident); return parent; } default: break; } consume(','); } }
static void member_declaration_list(struct typetree *type) { struct namespace ns = {0}; struct typetree *decl_base, *decl_type; const char *name; push_scope(&ns); do { decl_base = declaration_specifiers(NULL); do { name = NULL; decl_type = declarator(decl_base, &name); if (!name) { error("Missing name in member declarator."); exit(1); } else if (!size_of(decl_type)) { error("Field '%s' has incomplete type '%t'.", name, decl_type); exit(1); } else { sym_add(&ns, name, decl_type, SYM_DECLARATION, LINK_NONE); type_add_member(type, name, decl_type); } if (peek().token == ',') { consume(','); continue; } } while (peek().token != ';'); consume(';'); } while (peek().token != '}'); pop_scope(&ns); } static struct typetree *struct_or_union_declaration(void) { struct symbol *sym = NULL; struct typetree *type = NULL; enum type kind = (next().token == STRUCT) ? T_STRUCT : T_UNION; if (peek().token == IDENTIFIER) { const char *name = consume(IDENTIFIER).strval; sym = sym_lookup(&ns_tag, name); if (!sym) { type = type_init(kind); sym = sym_add(&ns_tag, name, type, SYM_TYPEDEF, LINK_NONE); } else if (is_integer(&sym->type)) { error("Tag '%s' was previously declared as enum.", sym->name); exit(1); } else if (sym->type.type != kind) { error("Tag '%s' was previously declared as %s.", sym->name, (sym->type.type == T_STRUCT) ? "struct" : "union"); exit(1); } /* Retrieve type from existing symbol, possibly providing a complete * definition that will be available for later declarations. Overwrites * existing type information from symbol table. */ type = &sym->type; if (peek().token == '{' && type->size) { error("Redefiniton of '%s'.", sym->name); exit(1); } } if (peek().token == '{') { if (!type) { /* Anonymous structure; allocate a new standalone type, * not part of any symbol. */ type = type_init(kind); } consume('{'); member_declaration_list(type); assert(type->size); consume('}'); } /* Return to the caller a copy of the root node, which can be overwritten * with new type qualifiers without altering the tag registration. */ return (sym) ? type_tagged_copy(&sym->type, sym->name) : type; } static void enumerator_list(void) { struct var val; struct symbol *sym; int enum_value = 0; consume('{'); do { const char *name = consume(IDENTIFIER).strval; if (peek().token == '=') { consume('='); val = constant_expression(); if (!is_integer(val.type)) { error("Implicit conversion from non-integer type in enum."); } enum_value = val.imm.i; } sym = sym_add( &ns_ident, name, &basic_type__int, SYM_ENUM_VALUE, LINK_NONE); sym->enum_value = enum_value++; if (peek().token != ',') break; consume(','); } while (peek().token != '}'); consume('}'); } static struct typetree *enum_declaration(void) { struct typetree *type = type_init(T_SIGNED, 4); consume(ENUM); if (peek().token == IDENTIFIER) { struct symbol *tag = NULL; const char *name = consume(IDENTIFIER).strval; tag = sym_lookup(&ns_tag, name); if (!tag || tag->depth < ns_tag.current_depth) { tag = sym_add(&ns_tag, name, type, SYM_TYPEDEF, LINK_NONE); } else if (!is_integer(&tag->type)) { error("Tag '%s' was previously defined as aggregate type.", tag->name); exit(1); } /* Use enum_value as a sentinel to represent definition, checked on * lookup to detect duplicate definitions. */ if (peek().token == '{') { if (tag->enum_value) { error("Redefiniton of enum '%s'.", tag->name); } enumerator_list(); tag->enum_value = 1; } } else { enumerator_list(); } /* Result is always integer. Do not care about the actual enum definition, * all enums are ints and no type checking is done. */ return type; } static struct typetree get_basic_type_from_specifier(unsigned short spec) { switch (spec) { case 0x0001: /* void */ return basic_type__void; case 0x0002: /* char */ case 0x0012: /* signed char */ return basic_type__char; case 0x0022: /* unsigned char */ return basic_type__unsigned_char; case 0x0004: /* short */ case 0x0014: /* signed short */ case 0x000C: /* short int */ case 0x001C: /* signed short int */ return basic_type__short; case 0x0024: /* unsigned short */ case 0x002C: /* unsigned short int */ return basic_type__unsigned_short; case 0x0008: /* int */ case 0x0010: /* signed */ case 0x0018: /* signed int */ return basic_type__int; case 0x0020: /* unsigned */ case 0x0028: /* unsigned int */ return basic_type__unsigned_int; case 0x0040: /* long */ case 0x0050: /* signed long */ case 0x0048: /* long int */ case 0x0058: /* signed long int */ case 0x00C0: /* long long */ case 0x00D0: /* signed long long */ case 0x00D8: /* signed long long int */ return basic_type__long; case 0x0060: /* unsigned long */ case 0x0068: /* unsigned long int */ case 0x00E0: /* unsigned long long */ case 0x00E8: /* unsigned long long int */ return basic_type__unsigned_long; case 0x0100: /* float */ return basic_type__float; case 0x0200: /* double */ case 0x0240: /* long double */ return basic_type__double; default: error("Invalid type specification."); exit(1); } } /* Parse type, qualifiers and storage class. Do not assume int by default, but * require at least one type specifier. Storage class is returned as token * value, unless the provided pointer is NULL, in which case the input is parsed * as specifier-qualifier-list. */ struct typetree *declaration_specifiers(int *stc) { struct typetree *type = NULL; struct token tok; int done = 0; /* Use a compact bit representation to hold state about declaration * specifiers. Initialize storage class to sentinel value. */ unsigned short spec = 0x0000; enum qualifier qual = Q_NONE; if (stc) *stc = '$'; #define set_specifier(d) \ if (spec & d) error("Duplicate type specifier '%s'.", tok.strval); \ next(); spec |= d; #define set_qualifier(d) \ if (qual & d) error("Duplicate type qualifier '%s'.", tok.strval); \ next(); qual |= d; #define set_storage_class(t) \ if (!stc) error("Unexpected storage class in qualifier list."); \ else if (*stc != '$') error("Multiple storage class specifiers."); \ next(); *stc = t; do { switch ((tok = peek()).token) { case VOID: set_specifier(0x001); break; case CHAR: set_specifier(0x002); break; case SHORT: set_specifier(0x004); break; case INT: set_specifier(0x008); break; case SIGNED: set_specifier(0x010); break; case UNSIGNED: set_specifier(0x020); break; case LONG: if (spec & 0x040) { set_specifier(0x080); } else { set_specifier(0x040); } break; case FLOAT: set_specifier(0x100); break; case DOUBLE: set_specifier(0x200); break; case CONST: set_qualifier(Q_CONST); break; case VOLATILE: set_qualifier(Q_VOLATILE); break; case IDENTIFIER: { struct symbol *tag = sym_lookup(&ns_ident, tok.strval); if (tag && tag->symtype == SYM_TYPEDEF && !type) { consume(IDENTIFIER); type = type_init(T_STRUCT); *type = tag->type; } else { done = 1; } break; } case UNION: case STRUCT: if (!type) { type = struct_or_union_declaration(); } else { done = 1; } break; case ENUM: if (!type) { type = enum_declaration(); } else { done = 1; } break; case AUTO: case REGISTER: case STATIC: case EXTERN: case TYPEDEF: set_storage_class(tok.token); break; default: done = 1; break; } if (type && spec) { error("Invalid combination of declaration specifiers."); exit(1); } } while (!done); #undef set_specifier #undef set_qualifier #undef set_storage_class if (type) { if (qual & type->qualifier) { error("Duplicate type qualifier:%s%s.", (qual & Q_CONST) ? " const" : "", (qual & Q_VOLATILE) ? " volatile" : ""); } } else if (spec) { type = type_init(T_STRUCT); *type = get_basic_type_from_specifier(spec); } else { error("Missing type specifier."); exit(1); } type->qualifier |= qual; return type; } /* Set var = 0, using simple assignment on members for composite types. This * rule does not consume any input, but generates a series of assignments on the * given variable. Point is to be able to zero initialize using normal simple * assignment rules, although IR can become verbose for large structures. */ static void zero_initialize(struct block *block, struct var target) { int i; struct var var; assert(target.kind == DIRECT); switch (target.type->type) { case T_STRUCT: case T_UNION: target.type = unwrapped(target.type); var = target; for (i = 0; i < nmembers(var.type); ++i) { target.type = get_member(var.type, i)->type; target.offset = var.offset + get_member(var.type, i)->offset; zero_initialize(block, target); } break; case T_ARRAY: assert(target.type->size); var = target; target.type = target.type->next; assert(is_struct(target.type) || !target.type->next); for (i = 0; i < var.type->size / var.type->next->size; ++i) { target.offset = var.offset + i * var.type->next->size; zero_initialize(block, target); } break; case T_POINTER: var = var_zero(8); var.type = type_init(T_POINTER, &basic_type__void); eval_assign(block, target, var); break; case T_UNSIGNED: case T_SIGNED: var = var_zero(target.type->size); eval_assign(block, target, var); break; default: error("Invalid type to zero-initialize, was '%t'.", target.type); exit(1); } }
environment section_cmd(parser & p) { p.push_local_scope(); return push_scope(p.env(), p.ios()); }
PUBLIC void start_rec_type(void) { push_scope(); }
Scope_guard(Scope_kind k) { push_scope(k); }