aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/calls.c4
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/sparc-getcontext-1.c118
4 files changed, 130 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e133b1..9465d80 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2005-11-10 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR middle-end/22127
+ * calls.c (special_function_p): Set ECF_RETURNS_TWICE for getcontext.
+
2005-11-10 Eric Botcazou <ebotcazou@adacore.com>
* tree.c (int_fits_type_p): Only look at the base type
diff --git a/gcc/calls.c b/gcc/calls.c
index 7dbc21f..1a680ae 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -527,7 +527,9 @@ special_function_p (tree fndecl, int flags)
else if ((tname[0] == 'q' && tname[1] == 's'
&& ! strcmp (tname, "qsetjmp"))
|| (tname[0] == 'v' && tname[1] == 'f'
- && ! strcmp (tname, "vfork")))
+ && ! strcmp (tname, "vfork"))
+ || (tname[0] == 'g' && tname[1] == 'e'
+ && !strcmp (tname, "getcontext")))
flags |= ECF_RETURNS_TWICE;
else if (tname[0] == 'l' && tname[1] == 'o'
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2adff34..7d3254f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2005-11-10 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * gcc.dg/sparc-getcontext-1.c: New test.
+
2005-11-09 Eric Botcazou <ebotcazou@adacore.com>
* gcc.dg/ifcvt-fabs-1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/sparc-getcontext-1.c b/gcc/testsuite/gcc.dg/sparc-getcontext-1.c
new file mode 100644
index 0000000..762804c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sparc-getcontext-1.c
@@ -0,0 +1,118 @@
+/* PR middle-end/22127 */
+/* Testcase by <akr@m17n.org> */
+
+/* [ dg-do run { target sparc*-sun-solaris2.* } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O" } */
+
+typedef unsigned int size_t;
+extern int printf(const char *, ...);
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+typedef unsigned int uint_t;
+typedef char *caddr_t;
+typedef int greg_t;
+typedef greg_t gregset_t[19];
+struct rwindow {
+ greg_t rw_local[8];
+ greg_t rw_in[8];
+};
+typedef struct gwindows {
+ int wbcnt;
+ greg_t *spbuf[31];
+ struct rwindow wbuf[31];
+} gwindows_t;
+struct fpu {
+ union {
+ uint32_t fpu_regs[32];
+ double fpu_dregs[16];
+ } fpu_fr;
+ struct fq *fpu_q;
+ uint32_t fpu_fsr;
+ uint8_t fpu_qcnt;
+ uint8_t fpu_q_entrysize;
+ uint8_t fpu_en;
+};
+typedef struct fpu fpregset_t;
+typedef struct {
+ unsigned int xrs_id;
+ caddr_t xrs_ptr;
+} xrs_t;
+typedef struct {
+ gregset_t gregs;
+ gwindows_t *gwins;
+ fpregset_t fpregs;
+ xrs_t xrs;
+ long filler[19];
+} mcontext_t;
+typedef struct {
+ unsigned int __sigbits[4];
+} sigset_t;
+typedef struct sigaltstack {
+ void *ss_sp;
+ size_t ss_size;
+ int ss_flags;
+} stack_t;
+typedef struct ucontext ucontext_t;
+struct ucontext {
+ uint_t uc_flags;
+ ucontext_t *uc_link;
+ sigset_t uc_sigmask;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ long uc_filler[23];
+};
+extern int getcontext(ucontext_t *);
+extern int setcontext(const ucontext_t *);
+
+int flag;
+ucontext_t cont;
+int pad[100];
+typedef void (*fun_t)(int);
+fun_t p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12;
+
+int global;
+
+extern void abort(void);
+
+void h1(int v)
+{
+ global = v;
+}
+
+void h2(int v)
+{
+ if (v != 1)
+ abort();
+}
+
+void f(void)
+{
+ flag = 1;
+ setcontext(&cont);
+}
+
+int g(void)
+{
+ int ret;
+
+ flag = 0;
+ getcontext(&cont);
+ ret = flag;
+ if (ret == 0) {
+ h1 (flag);
+ p0 = p1 = p2 = p3 = p4 = p5 = p6 = p7 = p8 = h1;
+ f();
+ p0(ret); p1(ret); p2(ret); p3(ret); p4(ret); p5(ret); p6(ret); p7(ret); p8(ret);
+ }
+ else {
+ h2 (flag);
+ }
+ return ret;
+}
+
+int main(void)
+{
+ g();
+ return 0;
+}