aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linearize.c
diff options
Diffstat (limited to 'linearize.c')
-rw-r--r--linearize.c31
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);