aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--Documentation/IR.rst3
-rw-r--r--cse.c2
-rw-r--r--example.c2
-rw-r--r--lib.c2
-rw-r--r--lib.h1
-rw-r--r--linearize.c22
-rw-r--r--linearize.h1
-rw-r--r--simplify.c1
-rw-r--r--sparse-llvm.c1
-rw-r--r--validation/backend/pointer-sub.c2
-rw-r--r--validation/cast-kinds-check.c2
-rw-r--r--validation/cast-weirds.c49
-rw-r--r--validation/linear/cast-kinds.c10
-rw-r--r--validation/optim/kill-casts.c1
14 files changed, 92 insertions, 7 deletions
diff --git a/Documentation/IR.rst b/Documentation/IR.rst
index 5b9155f7..56f02318 100644
--- a/Documentation/IR.rst
+++ b/Documentation/IR.rst
@@ -270,6 +270,9 @@ They all have the following signature:
.. op:: OP_SCAST
Cast to signed integer.
+.. op:: OP_UTPTR
+ Cast from unsigned integer to pointer type.
+
.. op:: OP_PTRCAST
Cast to pointer.
diff --git a/cse.c b/cse.c
index 79d37cfd..2a076709 100644
--- a/cse.c
+++ b/cse.c
@@ -94,6 +94,7 @@ void cse_collect(struct instruction *insn)
case OP_CAST:
case OP_SCAST:
case OP_PTRCAST:
+ case OP_UTPTR:
/*
* This is crap! Many "orig_types" are the
* same as far as casts go, we should generate
@@ -241,6 +242,7 @@ static int insn_compare(const void *_i1, const void *_i2)
case OP_CAST:
case OP_SCAST:
case OP_PTRCAST:
+ case OP_UTPTR:
/*
* This is crap! See the comments on hashing.
*/
diff --git a/example.c b/example.c
index 8f0869c9..2bc9de2c 100644
--- a/example.c
+++ b/example.c
@@ -81,6 +81,7 @@ static const char *opcodes[] = {
[OP_UCVTF] = "ucvtf",
[OP_SCVTF] = "scvtf",
[OP_FCVTF] = "fcvtf",
+ [OP_UTPTR] = "utptr",
[OP_PTRCAST] = "ptrcast",
[OP_CALL] = "call",
[OP_SLICE] = "slice",
@@ -1414,6 +1415,7 @@ static void generate_one_insn(struct instruction *insn, struct bb_state *state)
break;
case OP_CAST: case OP_SCAST: case OP_PTRCAST:
+ case OP_UTPTR:
case OP_FCVTU: case OP_FCVTS:
case OP_UCVTF: case OP_SCVTF:
case OP_FCVTF:
diff --git a/lib.c b/lib.c
index 7d9f4f91..0c92227f 100644
--- a/lib.c
+++ b/lib.c
@@ -258,6 +258,7 @@ int Wdefault_bitfield_sign = 0;
int Wdesignated_init = 1;
int Wdo_while = 0;
int Winit_cstring = 0;
+int Wint_to_pointer_cast = 1;
int Wenum_mismatch = 1;
int Wsparse_error = 0;
int Wmemcpy_max_count = 1;
@@ -687,6 +688,7 @@ static const struct flag warnings[] = {
{ "do-while", &Wdo_while },
{ "enum-mismatch", &Wenum_mismatch },
{ "init-cstring", &Winit_cstring },
+ { "int-to-pointer-cast", &Wint_to_pointer_cast },
{ "memcpy-max-count", &Wmemcpy_max_count },
{ "non-pointer-null", &Wnon_pointer_null },
{ "old-initializer", &Wold_initializer },
diff --git a/lib.h b/lib.h
index 6c3f84cf..33c41672 100644
--- a/lib.h
+++ b/lib.h
@@ -149,6 +149,7 @@ extern int Wdo_while;
extern int Wenum_mismatch;
extern int Wsparse_error;
extern int Winit_cstring;
+extern int Wint_to_pointer_cast;
extern int Wmemcpy_max_count;
extern int Wnon_pointer_null;
extern int Wold_initializer;
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;
}
diff --git a/linearize.h b/linearize.h
index b513d549..c5d98a2d 100644
--- a/linearize.h
+++ b/linearize.h
@@ -226,6 +226,7 @@ enum opcode {
OP_FCVTU, OP_FCVTS,
OP_UCVTF, OP_SCVTF,
OP_FCVTF,
+ OP_UTPTR,
OP_PTRCAST,
OP_UNOP_END = OP_PTRCAST,
diff --git a/simplify.c b/simplify.c
index 3a0926f1..274202fa 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1223,6 +1223,7 @@ int simplify_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:
return simplify_cast(insn);
case OP_PHI:
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 75cac8f9..8732f989 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -1045,6 +1045,7 @@ static void output_insn(struct function *fn, struct instruction *insn)
case OP_FCVTF:
output_op_fpcast(fn, insn);
break;
+ case OP_UTPTR:
case OP_PTRCAST:
output_op_ptrcast(fn, insn);
break;
diff --git a/validation/backend/pointer-sub.c b/validation/backend/pointer-sub.c
index 3cb8f5a9..5c99f4fa 100644
--- a/validation/backend/pointer-sub.c
+++ b/validation/backend/pointer-sub.c
@@ -13,5 +13,5 @@ long subvx3(void *p, int a) { return (p - ((void*)0)) ^ 3; }
/*
* check-name: pointer-sub
- * check-command: sparsec -Wno-decl -c $file -o tmp.o
+ * check-command: sparsec -Wno-int-to-pointer-cast -Wno-decl -c $file -o tmp.o
*/
diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c
index 1f10e0ec..736ab391 100644
--- a/validation/cast-kinds-check.c
+++ b/validation/cast-kinds-check.c
@@ -20,5 +20,7 @@ linear/cast-kinds.c:29:51: warning: cast wasn't removed
linear/cast-kinds.c:34:52: warning: cast wasn't removed
linear/cast-kinds.c:35:54: warning: cast wasn't removed
linear/cast-kinds.c:36:52: warning: cast wasn't removed
+linear/cast-kinds.c:37:42: warning: non size-preserving integer to pointer cast
+linear/cast-kinds.c:38:44: warning: non size-preserving integer to pointer cast
* check-error-end
*/
diff --git a/validation/cast-weirds.c b/validation/cast-weirds.c
new file mode 100644
index 00000000..136137b4
--- /dev/null
+++ b/validation/cast-weirds.c
@@ -0,0 +1,49 @@
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+static int * int_2_iptr(int a) { return (int *)a; }
+static int * uint_2_iptr(uint a) { return (int *)a; }
+
+static void * int_2_vptr(int a) { return (void *)a; }
+static void * uint_2_vptr(uint a) { return (void *)a; }
+
+/*
+ * check-name: cast-weirds
+ * check-command: test-linearize -m64 $file
+ *
+ * check-error-start
+cast-weirds.c:4:42: warning: non size-preserving integer to pointer cast
+cast-weirds.c:5:44: warning: non size-preserving integer to pointer cast
+ * check-error-end
+ *
+ * check-output-start
+int_2_iptr:
+.L0:
+ <entry-point>
+ utptr.64 %r2 <- (32) %arg1
+ ret.64 %r2
+
+
+uint_2_iptr:
+.L2:
+ <entry-point>
+ utptr.64 %r5 <- (32) %arg1
+ ret.64 %r5
+
+
+int_2_vptr:
+.L4:
+ <entry-point>
+ scast.64 %r8 <- (32) %arg1
+ ret.64 %r8
+
+
+uint_2_vptr:
+.L6:
+ <entry-point>
+ cast.64 %r11 <- (32) %arg1
+ ret.64 %r11
+
+
+ * check-output-end
+ */
diff --git a/validation/linear/cast-kinds.c b/validation/linear/cast-kinds.c
index d07a9419..4449d0af 100644
--- a/validation/linear/cast-kinds.c
+++ b/validation/linear/cast-kinds.c
@@ -55,7 +55,7 @@ static double double_2_double(double a) { return a; }
/*
* check-name: cast-kinds
- * check-command: test-linearize -m64 $file
+ * check-command: test-linearize -Wno-int-to-pointer-cast -m64 $file
*
* check-output-start
uint_2_int:
@@ -288,28 +288,28 @@ iptr_2_vptr:
int_2_iptr:
.L66:
<entry-point>
- ptrcast.64 %r101 <- (32) %arg1
+ utptr.64 %r101 <- (32) %arg1
ret.64 %r101
uint_2_iptr:
.L68:
<entry-point>
- ptrcast.64 %r104 <- (32) %arg1
+ utptr.64 %r104 <- (32) %arg1
ret.64 %r104
long_2_iptr:
.L70:
<entry-point>
- ptrcast.64 %r107 <- (64) %arg1
+ utptr.64 %r107 <- (64) %arg1
ret.64 %r107
ulong_2_iptr:
.L72:
<entry-point>
- ptrcast.64 %r110 <- (64) %arg1
+ utptr.64 %r110 <- (64) %arg1
ret.64 %r110
diff --git a/validation/optim/kill-casts.c b/validation/optim/kill-casts.c
index b79335ab..c375f5fb 100644
--- a/validation/optim/kill-casts.c
+++ b/validation/optim/kill-casts.c
@@ -20,4 +20,5 @@ void foo(struct s *x)
* check-output-ignore
* check-output-excludes: cast\\.
* check-output-excludes: fcvt[us]\\.
+ * check-output-excludes: utptr\\.
*/