diff options
Diffstat (limited to 'linearize.c')
| -rw-r--r-- | linearize.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/linearize.c b/linearize.c index c2010c4b..2e9a5638 100644 --- a/linearize.c +++ b/linearize.c @@ -878,6 +878,7 @@ pseudo_t alloc_phi(struct basic_block *source, pseudo_t pseudo, struct symbol *t */ struct access_data { struct symbol *type; // ctype + struct symbol *btype; // base type of bitfields pseudo_t address; // pseudo containing address .. unsigned int offset; // byte offset }; @@ -934,14 +935,13 @@ static int linearize_address_gen(struct entrypoint *ep, static pseudo_t add_load(struct entrypoint *ep, struct access_data *ad) { - struct symbol *btype = bitfield_base_type(ad->type); struct instruction *insn; pseudo_t new; if (!ep->active) return VOID; - insn = alloc_typed_instruction(OP_LOAD, btype); + insn = alloc_typed_instruction(OP_LOAD, ad->btype); new = alloc_pseudo(insn); insn->target = new; @@ -959,7 +959,7 @@ static void add_store(struct entrypoint *ep, struct access_data *ad, pseudo_t va if (!bb) return; - store = alloc_typed_instruction(OP_STORE, bitfield_base_type(ad->type)); + store = alloc_typed_instruction(OP_STORE, ad->btype); store->offset = ad->offset; use_pseudo(store, value, &store->target); use_pseudo(store, ad->address, &store->src); @@ -990,12 +990,13 @@ static pseudo_t linearize_store_gen(struct entrypoint *ep, struct access_data *ad) { struct symbol *ctype = ad->type; - struct symbol *btype = bitfield_base_type(ctype); + struct symbol *btype; pseudo_t store = value; if (!ep->active) return VOID; + btype = ad->btype = bitfield_base_type(ctype); if (type_size(btype) != type_size(ctype)) { pseudo_t orig = add_load(ep, ad); store = linearize_bitfield_insert(ep, orig, value, ctype, btype); @@ -1079,12 +1080,13 @@ static pseudo_t linearize_bitfield_extract(struct entrypoint *ep, static pseudo_t linearize_load_gen(struct entrypoint *ep, struct access_data *ad) { struct symbol *ctype = ad->type; - struct symbol *btype = bitfield_base_type(ctype); + struct symbol *btype; pseudo_t new; if (!ep->active) return VOID; + btype = ad->btype = bitfield_base_type(ctype); new = add_load(ep, ad); if (ctype->bit_size != type_size(btype)) new = linearize_bitfield_extract(ep, new, ctype, btype); @@ -1105,7 +1107,7 @@ static pseudo_t linearize_access(struct entrypoint *ep, struct expression *expr) static pseudo_t linearize_inc_dec(struct entrypoint *ep, struct expression *expr, int postop) { struct access_data ad = { NULL, }; - pseudo_t old, new, one; + pseudo_t old, new, one; int op = expr->op == SPECIAL_INCREMENT ? OP_ADD : OP_SUB; if (!linearize_address_gen(ep, expr->unop, &ad)) @@ -1117,7 +1119,11 @@ static pseudo_t linearize_inc_dec(struct entrypoint *ep, struct expression *expr one = add_setfval(ep, expr->ctype, expr->op_value); else one = value_pseudo(expr->op_value); - new = add_binary_op(ep, expr->ctype, op, old, one); + if (ad.btype != ad.type) + old = cast_pseudo(ep, old, ad.type, ad.btype); + new = add_binary_op(ep, ad.btype, op, old, one); + if (ad.btype != ad.type) + new = cast_pseudo(ep, new, ad.btype, ad.type); linearize_store_gen(ep, new, &ad); return postop ? old : new; } @@ -1772,14 +1778,6 @@ static pseudo_t linearize_cast(struct entrypoint *ep, struct expression *expr) return cast_pseudo(ep, src, orig->ctype, expr->ctype); } -static pseudo_t linearize_position(struct entrypoint *ep, struct expression *pos, struct access_data *ad) -{ - struct expression *init_expr = pos->init_expr; - - ad->offset = pos->init_offset; - return linearize_initializer(ep, init_expr, ad); -} - static pseudo_t linearize_initializer(struct entrypoint *ep, struct expression *initializer, struct access_data *ad) { switch (initializer->type) { @@ -1791,7 +1789,8 @@ static pseudo_t linearize_initializer(struct entrypoint *ep, struct expression * break; } case EXPR_POS: - linearize_position(ep, initializer, ad); + ad->offset = initializer->init_offset; + linearize_initializer(ep, initializer->init_expr, ad); break; default: { pseudo_t value = linearize_expression(ep, initializer); |
