diff options
-rw-r--r-- | allocate.c | 1 | ||||
-rw-r--r-- | allocate.h | 1 | ||||
-rw-r--r-- | check.c | 8 | ||||
-rw-r--r-- | linearize.c | 49 | ||||
-rw-r--r-- | linearize.h | 1 | ||||
-rw-r--r-- | parse.c | 36 | ||||
-rw-r--r-- | parse.h | 5 | ||||
-rw-r--r-- | show-parse.c | 17 | ||||
-rw-r--r-- | symbol.c | 9 | ||||
-rw-r--r-- | symbol.h | 12 |
10 files changed, 98 insertions, 41 deletions
@@ -113,6 +113,7 @@ void show_allocations(struct allocator_struct *x) ALLOCATOR(ident, "identifiers"); ALLOCATOR(token, "tokens"); +ALLOCATOR(context, "contexts"); ALLOCATOR(symbol, "symbols"); ALLOCATOR(expression, "expressions"); ALLOCATOR(statement, "statements"); @@ -61,6 +61,7 @@ extern void show_allocations(struct allocator_struct *); DECLARE_ALLOCATOR(ident); DECLARE_ALLOCATOR(token); +DECLARE_ALLOCATOR(context); DECLARE_ALLOCATOR(symbol); DECLARE_ALLOCATOR(expression); DECLARE_ALLOCATOR(statement); @@ -234,6 +234,8 @@ static void check_instructions(struct entrypoint *ep) static void check_context(struct entrypoint *ep) { struct symbol *sym = ep->name; + struct context *context; + unsigned int in_context = 0, out_context = 0; if (verbose && ep->entry->bb->needs) { pseudo_t pseudo; @@ -246,7 +248,11 @@ static void check_context(struct entrypoint *ep) check_instructions(ep); - check_bb_context(ep, ep->entry->bb, sym->ctype.in_context, sym->ctype.out_context); + FOR_EACH_PTR(sym->ctype.contexts, context) { + in_context += context->in; + out_context += context->out; + } END_FOR_EACH_PTR(context); + check_bb_context(ep, ep->entry->bb, in_context, out_context); } static void check_symbols(struct symbol_list *list) diff --git a/linearize.c b/linearize.c index f47bad9..8a8a2d3 100644 --- a/linearize.c +++ b/linearize.c @@ -1183,7 +1183,8 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi struct expression *arg, *fn; struct instruction *insn = alloc_typed_instruction(OP_CALL, expr->ctype); pseudo_t retval, call; - int context_diff, check; + struct ctype *ctype = NULL; + struct context *context; if (!expr->ctype) { warning(expr->pos, "call with no type!"); @@ -1197,21 +1198,8 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi fn = expr->fn; - check = 0; - context_diff = 0; - if (fn->ctype) { - int in = fn->ctype->ctype.in_context; - int out = fn->ctype->ctype.out_context; - if (in < 0) { - check = 1; - in = 0; - } - if (out < 0) { - check = 0; - out = 0; - } - context_diff = out - in; - } + if (fn->ctype) + ctype = &fn->ctype->ctype; if (fn->type == EXPR_PREOP) { if (fn->unop->type == EXPR_SYMBOL) { @@ -1232,11 +1220,29 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi insn->target = retval; add_one_insn(ep, insn); - if (check || context_diff) { - insn = alloc_instruction(OP_CONTEXT, 0); - insn->increment = context_diff; - insn->check = check; - add_one_insn(ep, insn); + if (ctype) { + FOR_EACH_PTR(ctype->contexts, context) { + int in = context->in; + int out = context->out; + int check = 0; + int context_diff; + if (in < 0) { + check = 1; + in = 0; + } + if (out < 0) { + check = 0; + out = 0; + } + context_diff = out - in; + if (check || context_diff) { + insn = alloc_instruction(OP_CONTEXT, 0); + insn->increment = context_diff; + insn->check = check; + insn->context_expr = context->context; + add_one_insn(ep, insn); + } + } END_FOR_EACH_PTR(context); } return retval; @@ -1637,6 +1643,7 @@ static pseudo_t linearize_context(struct entrypoint *ep, struct statement *stmt) value = expr->value; insn->increment = value; + insn->context_expr = stmt->context; add_one_insn(ep, insn); return VOID; } diff --git a/linearize.h b/linearize.h index 66a76dc..ac946f3 100644 --- a/linearize.h +++ b/linearize.h @@ -105,6 +105,7 @@ struct instruction { struct /* context */ { int increment; int check; + struct expression *context_expr; }; struct /* asm */ { const char *string; @@ -434,10 +434,17 @@ static const char * handle_attribute(struct ctype *ctype, struct ident *attribut } if (attribute == &context_ident) { if (expr && expr->type == EXPR_COMMA) { - int input = get_expression_value(expr->left); - int output = get_expression_value(expr->right); - ctype->in_context = input; - ctype->out_context = output; + struct context *context = alloc_context(); + if(expr->left->type == EXPR_COMMA) { + context->context = expr->left->left; + context->in = get_expression_value( + expr->left->right); + } else { + context->context = NULL; + context->in = get_expression_value(expr->left); + } + context->out = get_expression_value(expr->right); + add_ptr_list(&ctype->contexts, context); return NULL; } return "expected context input/output values"; @@ -669,9 +676,9 @@ static void apply_ctype(struct position pos, struct ctype *thistype, struct ctyp ctype->modifiers = old | mod | extra; } - /* Context mask and value */ - ctype->in_context += thistype->in_context; - ctype->out_context += thistype->out_context; + /* Context */ + concat_ptr_list((struct ptr_list *)thistype->contexts, + (struct ptr_list **)&ctype->contexts); /* Alignment */ if (thistype->alignment & (thistype->alignment-1)) { @@ -908,16 +915,15 @@ static struct token *pointer(struct token *token, struct ctype *ctype) struct symbol *ptr = alloc_symbol(token->pos, SYM_PTR); ptr->ctype.modifiers = modifiers & ~MOD_STORAGE; ptr->ctype.as = ctype->as; - ptr->ctype.in_context += ctype->in_context; - ptr->ctype.out_context += ctype->out_context; + concat_ptr_list((struct ptr_list *)ctype->contexts, + (struct ptr_list **)&ptr->ctype.contexts); ptr->ctype.base_type = base_type; base_type = ptr; ctype->modifiers = modifiers & MOD_STORAGE; ctype->base_type = base_type; ctype->as = 0; - ctype->in_context = 0; - ctype->out_context = 0; + free_ptr_list(&ctype->contexts); token = declaration_specifiers(token->next, ctype, 1); modifiers = ctype->modifiers; @@ -1384,6 +1390,14 @@ default_statement: if (token->ident == &__context___ident) { stmt->type = STMT_CONTEXT; token = parse_expression(token->next, &stmt->expression); + if(stmt->expression->type == EXPR_PREOP + && stmt->expression->op == '(' + && stmt->expression->unop->type == EXPR_COMMA) { + struct expression *expr; + expr = stmt->expression->unop; + stmt->context = expr->left; + stmt->expression = expr->right; + } return expect(token, ';', "at end of statement"); } if (token->ident == &__range___ident) { @@ -39,7 +39,10 @@ struct statement { struct symbol *label; struct statement *label_statement; }; - struct expression *expression; + struct { + struct expression *expression; + struct expression *context; + }; struct /* return_statement */ { struct expression *ret_value; struct symbol *ret_target; diff --git a/show-parse.c b/show-parse.c index 70a5b08..5437a62 100644 --- a/show-parse.c +++ b/show-parse.c @@ -50,18 +50,27 @@ static void do_debug_symbol(struct symbol *sym, int indent) [SYM_RESTRICT] = "rstr", [SYM_BAD] = "bad.", }; + struct context *context; + int i; if (!sym) return; - fprintf(stderr, "%.*s%s%3d:%lu %lx %s (as: %d, context: %x:%x) %p (%s:%d:%d)\n", + fprintf(stderr, "%.*s%s%3d:%lu %lx %s (as: %d) %p (%s:%d:%d)\n", indent, indent_string, typestr[sym->type], sym->bit_size, sym->ctype.alignment, - sym->ctype.modifiers, show_ident(sym->ident), - sym->ctype.as, sym->ctype.in_context, sym->ctype.out_context, + sym->ctype.modifiers, show_ident(sym->ident), sym->ctype.as, sym, stream_name(sym->pos.stream), sym->pos.line, sym->pos.pos); + i = 0; + FOR_EACH_PTR(sym->ctype.contexts, context) { + /* FIXME: should print context expression */ + fprintf(stderr, "< context%d: in=%d, out=%d\n", + i, context->in, context->out); + fprintf(stderr, " end context%d >\n", i); + i++; + } END_FOR_EACH_PTR(context); if (sym->type == SYM_FN) { - int i = 1; struct symbol *arg; + i = 0; FOR_EACH_PTR(sym->arguments, arg) { fprintf(stderr, "< arg%d:\n", i); do_debug_symbol(arg, 0); @@ -53,6 +53,11 @@ struct symbol *lookup_symbol(struct ident *ident, enum namespace ns) return sym; } +struct context *alloc_context(void) +{ + return __alloc_context(0); +} + struct symbol *alloc_symbol(struct position pos, int type) { struct symbol *sym = __alloc_symbol(0); @@ -247,8 +252,8 @@ void merge_type(struct symbol *sym, struct symbol *base_type) { sym->ctype.as |= base_type->ctype.as; sym->ctype.modifiers |= (base_type->ctype.modifiers & ~MOD_STORAGE); - sym->ctype.in_context += base_type->ctype.in_context; - sym->ctype.out_context += base_type->ctype.out_context; + concat_ptr_list((struct ptr_list *)base_type->ctype.contexts, + (struct ptr_list **)&sym->ctype.contexts); sym->ctype.base_type = base_type->ctype.base_type; } @@ -55,10 +55,20 @@ enum type { SYM_BAD, }; +struct context { + struct expression *context; + unsigned int in, out; +}; + +extern struct context *alloc_context(void); + +DECLARE_PTR_LIST(context_list, struct context); + struct ctype { unsigned long modifiers; unsigned long alignment; - unsigned int in_context, out_context, as; + struct context_list *contexts; + unsigned int as; struct symbol *base_type; }; |