diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-08-14 15:55:46 +0200 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-06-23 07:46:40 +0200 |
| commit | dc4117c69ef98d2e79de1fab18ea0ba9d1496344 (patch) | |
| tree | c27eba2819576ac4878a1c92672cc79b62407c76 /linearize.c | |
| parent | 52856c815a191b73530557133bd44ec478f3fece (diff) | |
| download | sparse-dev-dc4117c69ef98d2e79de1fab18ea0ba9d1496344.tar.gz | |
cast: specialize casts from unsigned to pointers
Currently all casts to pointers are processed alike.
This is simple but rather unconvenient as it correspond to
different operations that obeys to different rules and
which later need extra checks.
Change this by using a specific instructions (OP_UTPTR) for
unsigned integer to pointers.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'linearize.c')
| -rw-r--r-- | linearize.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/linearize.c b/linearize.c index a7d2b068..0f40682c 100644 --- a/linearize.c +++ b/linearize.c @@ -268,6 +268,7 @@ static const char *opcodes[] = { [OP_UCVTF] = "ucvtf", [OP_SCVTF] = "scvtf", [OP_FCVTF] = "fcvtf", + [OP_UTPTR] = "utptr", [OP_PTRCAST] = "ptrcast", [OP_INLINED_CALL] = "# call", [OP_CALL] = "call", @@ -452,6 +453,7 @@ const char *show_instruction(struct instruction *insn) case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: + case OP_UTPTR: case OP_PTRCAST: buf += sprintf(buf, "%s <- (%d) %s", show_pseudo(insn->target), @@ -1221,7 +1223,17 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src) return OP_BADOP; } case MTYPE_PTR: - return OP_PTRCAST; + switch (stype) { + case MTYPE_UINT: + case MTYPE_SINT: + if (is_ptr_type(src)) // must be a void pointer + return OP_PTRCAST;// FIXME: to be removed? + return OP_UTPTR; + case MTYPE_PTR: + return OP_PTRCAST; + default: + return OP_BADOP; + } case MTYPE_UINT: case MTYPE_SINT: switch (stype) { @@ -1254,6 +1266,14 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol * switch (opcode) { case OP_NOP: return src; + case OP_UTPTR: + if (from->bit_size == to->bit_size) + break; + if (src == value_pseudo(0)) + break; + if (Wint_to_pointer_cast) + warning(to->pos, "non size-preserving integer to pointer cast"); + break; default: break; } |
