diff -urN sparse-bk/evaluate.c sparse-current/evaluate.c --- sparse-bk/evaluate.c Fri Aug 6 19:00:26 2004 +++ sparse-current/evaluate.c Wed Aug 11 14:47:07 2004 @@ -342,7 +342,13 @@ /* Special case: adding zero commonly happens as a result of 'array[0]' */ if (i->type == EXPR_VALUE && !i->value) { *expr = *ptr; - } else if (bit_size > bits_in_char) { + expr->ctype = ctype; + return ctype; + } + + /* FIXME: 'i' needs a cast here */ + + if (bit_size > bits_in_char) { struct expression *add = expr; struct expression *mul = alloc_expression(expr->pos, EXPR_BINOP); struct expression *val = alloc_expression(expr->pos, EXPR_VALUE); @@ -351,15 +357,17 @@ val->value = bit_size >> 3; mul->op = '*'; - mul->ctype = size_t_ctype; + mul->ctype = ssize_t_ctype; mul->left = i; mul->right = val; /* Leave 'add->op' as 'expr->op' - either '+' or '-' */ add->left = ptr; add->right = mul; + } else { + expr->left = ptr; + expr->right = i; } - expr->ctype = ctype; return ctype; } @@ -892,10 +900,10 @@ } } - // FIXME!! Cast it? warn(expr->pos, "incorrect type in %s (%s)", where, typediff); info(expr->pos, " expected %s", show_typename(target)); info(expr->pos, " got %s", show_typename(source)); + *rp = cast_to(*rp, target); return 0; Cast: *rp = cast_to(*rp, target); @@ -1063,11 +1071,42 @@ base = ctype->ctype.base_type; /* * Arrays degenerate into pointers to the entries, while - * functions degenerate into pointers to themselves + * functions degenerate into pointers to themselves. + * If array was part of non-lvalue compound, we create a copy + * of that compound first and then act as if we were dealing with + * the corresponding field in there. */ switch (base->type) { - case SYM_FN: case SYM_ARRAY: + if (expr->type == EXPR_RCOMP) { + struct symbol *a = alloc_symbol(expr->pos, SYM_NODE); + struct expression *addr, *add; + + a->ctype.base_type = expr->base->ctype; + a->initializer = expr->base; + a->bit_size = expr->base->ctype->bit_size; + a->array_size = expr->base->ctype->array_size; + + addr = alloc_expression(expr->pos, EXPR_SYMBOL); + addr->symbol = a; + addr->ctype = &lazy_ptr_ctype; + + if (expr->r_bitpos) { + add = alloc_expression(expr->pos, EXPR_BINOP); + add->op = '+'; + add->left = addr; + add->right = alloc_const_expression(expr->pos, + expr->r_bitpos >> 3); + add->ctype = &lazy_ptr_ctype; + } else { + add = addr; + } + + expr->unop = add; + expr->type = EXPR_PREOP; + expr->op = '*'; + } + case SYM_FN: if (expr->op != '*' || expr->type != EXPR_PREOP) { warn(expr->pos, "strange non-value function or array"); return NULL; @@ -1338,12 +1377,6 @@ address_space |= ctype->ctype.as; mod |= ctype->ctype.modifiers; } - if (!lvalue_expression(deref)) { - warn(deref->pos, "expected lvalue for member dereference"); - return NULL; - } - deref = deref->unop; - expr->deref = deref; if (!ctype || (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION)) { warn(expr->pos, "expected structure or union"); return NULL; @@ -1363,14 +1396,38 @@ return NULL; } + /* * The member needs to take on the address space and modifiers of * the "parent" type. */ member = convert_to_as_mod(member, address_space, mod); - add = evaluate_offset(deref, offset); - ctype = member->ctype.base_type; + + if (!lvalue_expression(deref)) { + if (deref->type != EXPR_RCOMP) { + expr->base = deref; + expr->r_bitpos = 0; + } else { + expr->base = deref->base; + expr->r_bitpos = deref->r_bitpos; + } + expr->type = EXPR_RCOMP; + if (ctype->type == SYM_BITFIELD) { + expr->r_bitpos += member->bit_offset; + expr->r_nrbits = member->fieldwidth; + } else { + expr->r_bitpos += offset << 3; + expr->r_nrbits = member->bit_size; + } + expr->ctype = member; + return member; + } + + deref = deref->unop; + expr->deref = deref; + + add = evaluate_offset(deref, offset); if (ctype->type == SYM_BITFIELD) { expr->type = EXPR_BITFIELD; expr->bitpos = member->bit_offset; @@ -1885,6 +1942,9 @@ case EXPR_INDEX: case EXPR_POS: warn(expr->pos, "internal front-end error: initializer in expression"); + return NULL; + case EXPR_RCOMP: + warn(expr->pos, "internal front-end error: RCOMP re-evaluated"); return NULL; } return NULL; diff -urN sparse-bk/expression.h sparse-current/expression.h --- sparse-bk/expression.h Mon Aug 2 19:00:23 2004 +++ sparse-current/expression.h Wed Aug 11 11:58:09 2004 @@ -40,6 +40,7 @@ EXPR_INDEX, // index in initializer EXPR_POS, // position in initializer EXPR_FVALUE, + EXPR_RCOMP, }; struct expression { @@ -77,6 +78,11 @@ struct /* deref_arg */ { struct expression *deref; struct ident *member; + }; + // EXPR_RCOMP + struct /* rval_composite */ { + struct expression *base; + unsigned r_bitpos, r_nrbits; }; // EXPR_CAST and EXPR_SIZEOF struct /* cast_arg */ { diff -urN sparse-bk/inline.c sparse-current/inline.c --- sparse-bk/inline.c Wed Aug 4 19:00:23 2004 +++ sparse-current/inline.c Wed Aug 11 12:38:08 2004 @@ -91,6 +91,13 @@ break; } + case EXPR_RCOMP: { + struct expression *base = copy_expression(expr->base); + expr = dup_expression(expr); + expr->base = base; + break; + } + /* Binops: copy left/right expressions */ case EXPR_BINOP: case EXPR_COMMA: diff -urN sparse-bk/linearize.c sparse-current/linearize.c --- sparse-bk/linearize.c Mon Aug 2 19:00:23 2004 +++ sparse-current/linearize.c Wed Aug 11 12:15:17 2004 @@ -190,6 +190,12 @@ break; } + case OP_CHUNK: + printf("\t%%r%d <- chunk %%r%d, %d, %d\n", + insn->target->nr, + insn->base->nr, insn->from, insn->len); + break; + case OP_BINCMP ... OP_BINCMP_END: { static const char *opname[] = { [OP_SET_EQ - OP_BINCMP] = "seteq", @@ -477,6 +483,19 @@ return new; } +static pseudo_t linearize_fetch(struct entrypoint *ep, struct expression *expr) +{ + pseudo_t pre = linearize_expression(ep, expr->base); + pseudo_t new = alloc_pseudo(); + struct instruction *insn = alloc_instruction(OP_CHUNK, expr->ctype); + insn->target = new; + insn->base = pre; + insn->from = expr->r_bitpos; + insn->len = expr->r_nrbits; + add_one_insn(ep, expr->pos, insn); + return new; +} + static pseudo_t linearize_regular_preop(struct entrypoint *ep, struct expression *expr) { pseudo_t pre = linearize_expression(ep, expr->unop); @@ -802,6 +821,9 @@ case EXPR_BITFIELD: return linearize_access(ep, expr); + + case EXPR_RCOMP: + return linearize_fetch(ep, expr); default: warn(expr->pos, "unknown expression (%d %d)", expr->type, expr->op); diff -urN sparse-bk/linearize.h sparse-current/linearize.h --- sparse-bk/linearize.h Mon Aug 2 19:00:23 2004 +++ sparse-current/linearize.h Wed Aug 11 12:13:15 2004 @@ -51,6 +51,10 @@ struct /* binops */ { pseudo_t src1, src2; }; + struct /* chunk */ { + pseudo_t base; + unsigned from, len; + }; struct /* multijump */ { int begin, end; }; @@ -131,6 +135,7 @@ OP_CALL, OP_VANEXT, OP_VAARG, + OP_CHUNK, }; struct basic_block_list; diff -urN sparse-bk/parse.c sparse-current/parse.c --- sparse-bk/parse.c Fri Aug 6 19:00:27 2004 +++ sparse-current/parse.c Tue Aug 10 05:19:08 2004 @@ -591,6 +591,11 @@ bitfield->fieldwidth = get_expression_value(expr); } else error(token->pos, "Invalid bitfield specifier for type %s.", show_typename (ctype->base_type)); + while (match_idents(token, &__attribute___ident, &__attribute_ident, NULL)) { + struct ctype thistype = { 0, }; + token = attribute_specifier(token->next, &thistype); + apply_ctype(token->pos, &thistype, ctype); + } break; } break; diff -urN sparse-bk/token.h sparse-current/token.h --- sparse-bk/token.h Sat Jul 24 19:00:32 2004 +++ sparse-current/token.h Tue Aug 10 02:31:48 2004 @@ -80,12 +80,13 @@ "&&", "&=", \ "||", "|=", \ "^=", "##", \ - " @ ", \ + "", \ + "<", ">", "<=", ">=" \ } enum special_token { SPECIAL_BASE = 256, - SPECIAL_ADD_ASSIGN = 256, + SPECIAL_ADD_ASSIGN = SPECIAL_BASE, SPECIAL_INCREMENT, SPECIAL_SUB_ASSIGN, SPECIAL_DECREMENT, diff -urN sparse-bk/tokenize.c sparse-current/tokenize.c --- sparse-bk/tokenize.c Thu Jul 22 19:00:17 2004 +++ sparse-current/tokenize.c Tue Aug 10 02:31:48 2004 @@ -607,7 +607,7 @@ unsigned char combinations[][3] = COMBINATION_STRINGS; -#define NR_COMBINATIONS (sizeof(combinations)/3) +#define NR_COMBINATIONS (SPECIAL_ARG_SEPARATOR - SPECIAL_BASE) static int get_one_special(int c, stream_t *stream) {