aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>2025-08-18 13:33:59 -0700
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>2025-08-19 08:55:14 -0700
commit6ece2d7274059265468833fb491db44bd90de72a (patch)
tree24c07034d5ecafb0f7833d50f770cca976bbbca1 /gcc
parent0ab1e31807a19d699c462937ca639718360eac0c (diff)
downloadgcc-6ece2d7274059265468833fb491db44bd90de72a.zip
gcc-6ece2d7274059265468833fb491db44bd90de72a.tar.gz
gcc-6ece2d7274059265468833fb491db44bd90de72a.tar.bz2
middle-end: Fix malloc like functions when calling with void "return" [PR120024]
When expanding malloc like functions, we copy the return register into a temporary and then mark that temporary register with a noalias regnote and the alignment. This works fine unless you are calling the function with a return type of void. At this point then the valreg will be null and a crash will happen. A few cleanups are included in this patch because it was easier to do the fix with the cleanups added. The start_sequence/end_sequence for ECF_MALLOC is no longer needed; I can't tell if it was ever needed. The emit_move_insn function returns the last emitted instruction anyways so there is no reason to call get_last_insn as we can just use the return value of emit_move_insn. This has been true since this code was originally added so I don't understand why it was done that way beforehand. Bootstrapped and tested on x86_64-linux-gnu. PR middle-end/120024 gcc/ChangeLog: * calls.cc (expand_call): Remove start_sequence/end_sequence for ECF_MALLOC. Check valreg before deferencing it when it comes to malloc like functions. Use the return value of emit_move_insn instead of calling get_last_insn. gcc/testsuite/ChangeLog: * gcc.dg/torture/malloc-1.c: New test. * gcc.dg/torture/malloc-2.c: New test. Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/calls.cc19
-rw-r--r--gcc/testsuite/gcc.dg/torture/malloc-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/malloc-2.c12
3 files changed, 28 insertions, 13 deletions
diff --git a/gcc/calls.cc b/gcc/calls.cc
index 2711c4e..bb8a6d0 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -3235,11 +3235,6 @@ expand_call (tree exp, rtx target, int ignore)
if (pass)
precompute_arguments (num_actuals, args);
- /* Now we are about to start emitting insns that can be deleted
- if a libcall is deleted. */
- if (pass && (flags & ECF_MALLOC))
- start_sequence ();
-
/* Check the canary value for sibcall or function which doesn't
return and could throw. */
if ((pass == 0
@@ -3771,25 +3766,23 @@ expand_call (tree exp, rtx target, int ignore)
valreg = gen_rtx_REG (TYPE_MODE (rettype), REGNO (valreg));
}
- if (pass && (flags & ECF_MALLOC))
+ /* If the return register exists, for malloc like
+ function calls, mark the return register with the
+ alignment and noalias reg note. */
+ if (pass && (flags & ECF_MALLOC) && valreg)
{
rtx temp = gen_reg_rtx (GET_MODE (valreg));
- rtx_insn *last, *insns;
+ rtx_insn *last;
/* The return value from a malloc-like function is a pointer. */
if (TREE_CODE (rettype) == POINTER_TYPE)
mark_reg_pointer (temp, MALLOC_ABI_ALIGNMENT);
- emit_move_insn (temp, valreg);
+ last = emit_move_insn (temp, valreg);
/* The return value from a malloc-like function cannot alias
anything else. */
- last = get_last_insn ();
add_reg_note (last, REG_NOALIAS, temp);
-
- /* Write out the sequence. */
- insns = end_sequence ();
- emit_insn (insns);
valreg = temp;
}
diff --git a/gcc/testsuite/gcc.dg/torture/malloc-1.c b/gcc/testsuite/gcc.dg/torture/malloc-1.c
new file mode 100644
index 0000000..ba24153
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/malloc-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* PR middle-end/120024 */
+
+void *f(unsigned) __attribute__((malloc));
+void g()
+{
+ void *(*g)(unsigned) = f;
+ void (*h)(unsigned) = (void (*)(unsigned))g;
+ h(1);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/malloc-2.c b/gcc/testsuite/gcc.dg/torture/malloc-2.c
new file mode 100644
index 0000000..8eeca9d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/malloc-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* PR middle-end/120024 */
+
+void *f(unsigned) __attribute__((malloc));
+void h1(void);
+void g(void)
+{
+ void *(*g)(unsigned) = f;
+ void (*h)(unsigned) = (void (*)(unsigned))g;
+ h(1);
+ h1();
+}