TI ABI has non-conventional requirements for bit-fields, which cannot
be implemented with the current target hooks in GCC.
Target hooks are focused on packing and alignment. But PRU uses packed
structs by default, and has 1 byte alignment for all types. As an
example, this makes it difficult to implement the TI ABI requirement
for the following struct to be sized to 4 bytes, per the bit-field type:
struct S { int i : 1; }
Instead of introducing new target hooks and making risky changes to
common GCC code, simply declare bit-fields as not supported in TI ABI
mode.
PRU is a baremetal target. It has neither support for interrupts nor an
RTOS. Hence ABI compatibility is not that critical. I have not seen
any projects which rely on ABI compatibility in order to mix object
files from GCC and the TI proprietary compiler.
The target-specific pass to scan for TI ABI compatibility was rewritten
as an IPA pass. This allowed scanning not only of function bodies, but
also global variable declarations. Diagnostic locations should now be
more accurate. Thus some test cases had to be adjusted.
Pushed to trunk as r16-4017-g2948d12f92d1d2.
PR target/116205
gcc/ChangeLog:
* config/pru/pru-passes.cc (class pass_pru_tiabi_check): Make
this an IPA pass.
(chkp_type_has_function_pointer): Remove.
(check_type_tiabi_compatibility): New function.
(chk_function_decl): Rename.
(check_function_decl): Simplify.
(check_op_callback): Rework to use
check_type_tiabi_compatibility.
(pass_pru_tiabi_check::execute): Rework to scan all symbols and
gimple contents of all defined functions.
* config/pru/pru-passes.def (INSERT_PASS_AFTER): Move after
pass_ipa_auto_profile_offline.
* config/pru/pru-protos.h (make_pru_tiabi_check): New
declaration to mark as IPA pass.
(make_pru_minrt_check): Specify it is making a gimple pass.
* doc/invoke.texi: Document that bit-fields are now rejected for
TI ABI.
gcc/testsuite/ChangeLog:
* gcc.target/pru/mabi-ti-1.c: Adjust diagnostic location.
* gcc.target/pru/mabi-ti-2.c: Ditto.
* gcc.target/pru/mabi-ti-3.c: Ditto.
* gcc.target/pru/mabi-ti-5.c: Ditto.
* gcc.target/pru/mabi-ti-6.c: Ditto.
* gcc.target/pru/mabi-ti-7.c: Adjust diagnostic locations and
add global variables for checking.
* gcc.target/pru/mabi-ti-11.c: New test.
* gcc.target/pru/mabi-ti-12.c: New test.
* gcc.target/pru/mabi-ti-8.c: New test.
* gcc.target/pru/mabi-ti-9.c: New test.
Signed-off-by: Dimitar Dimitrov <[email protected]>
---
gcc/config/pru/pru-passes.cc | 189 ++++++++++++++--------
gcc/config/pru/pru-passes.def | 2 +-
gcc/config/pru/pru-protos.h | 8 +-
gcc/doc/invoke.texi | 23 +++
gcc/testsuite/gcc.target/pru/mabi-ti-1.c | 4 +-
gcc/testsuite/gcc.target/pru/mabi-ti-11.c | 14 ++
gcc/testsuite/gcc.target/pru/mabi-ti-12.c | 15 ++
gcc/testsuite/gcc.target/pru/mabi-ti-2.c | 4 +-
gcc/testsuite/gcc.target/pru/mabi-ti-3.c | 4 +-
gcc/testsuite/gcc.target/pru/mabi-ti-5.c | 10 +-
gcc/testsuite/gcc.target/pru/mabi-ti-6.c | 4 +-
gcc/testsuite/gcc.target/pru/mabi-ti-7.c | 22 ++-
gcc/testsuite/gcc.target/pru/mabi-ti-8.c | 48 ++++++
gcc/testsuite/gcc.target/pru/mabi-ti-9.c | 16 ++
14 files changed, 274 insertions(+), 89 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-11.c
create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-12.c
create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-8.c
create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-9.c
diff --git a/gcc/config/pru/pru-passes.cc b/gcc/config/pru/pru-passes.cc
index a763e1ee65e..ba95bc41441 100644
--- a/gcc/config/pru/pru-passes.cc
+++ b/gcc/config/pru/pru-passes.cc
@@ -35,6 +35,7 @@
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "gimple-expr.h"
+#include "cgraph.h"
#include "tree-pass.h"
#include "pru-protos.h"
@@ -46,11 +47,11 @@ namespace {
output a conforming code, raise an error. */
const pass_data pass_data_pru_tiabi_check =
{
- GIMPLE_PASS, /* type */
+ SIMPLE_IPA_PASS, /* type */
"*pru_tiabi_check", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_NONE, /* tv_id */
- PROP_gimple_any, /* properties_required */
+ 0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
@@ -58,11 +59,11 @@ const pass_data pass_data_pru_tiabi_check =
};
/* Implementation class for the TI ABI compliance-check pass. */
-class pass_pru_tiabi_check : public gimple_opt_pass
+class pass_pru_tiabi_check : public simple_ipa_opt_pass
{
public:
pass_pru_tiabi_check (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_pru_tiabi_check, ctxt)
+ : simple_ipa_opt_pass (pass_data_pru_tiabi_check, ctxt)
{}
/* opt_pass methods: */
@@ -75,54 +76,79 @@ public:
}; // class pass_pru_tiabi_check
-/* Return 1 if type TYPE is a pointer to function type or a
- structure having a pointer to function type as one of its fields.
- Otherwise return 0. */
-static bool
-chkp_type_has_function_pointer (const_tree type)
+/* Issue an error diagnostic if the given TYPE is not compatible with
+ TI's ABI. */
+static void
+check_type_tiabi_compatibility (tree type, location_t loc,
+ hash_set<tree> *visited_nodes)
{
- bool res = false;
+ /* Do not visit the same type twice. */
+ if (visited_nodes->add (type))
+ return;
- if (POINTER_TYPE_P (type) && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (type)))
- res = true;
+ if (POINTER_TYPE_P (type))
+ {
+ /* TODO: All declarations and statements share the same object for a
+ function pointer tree type. So if there are several variables
+ with the same type (function pointer with same function signature),
+ only the first declaration would get a diagnostic. */
+ if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (type)))
+ {
+ location_t ptrloc = DECL_P (type) ? DECL_SOURCE_LOCATION (type) : loc;
+ error_at (ptrloc,
+ "function pointers not supported with %<-mabi=ti%> option");
+ }
+ else
+ check_type_tiabi_compatibility (TREE_TYPE (type), loc, visited_nodes);
+ }
else if (RECORD_OR_UNION_TYPE_P (type))
{
- tree field;
-
- for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
- res = res || chkp_type_has_function_pointer (TREE_TYPE (field));
+ {
+ if (DECL_BIT_FIELD (field))
+ error_at (DECL_SOURCE_LOCATION (field),
+ "bit-fields not supported with %<-mabi=ti%> option");
+
+ check_type_tiabi_compatibility (TREE_TYPE (field),
+ DECL_SOURCE_LOCATION (field),
+ visited_nodes);
+ }
}
else if (TREE_CODE (type) == ARRAY_TYPE)
- res = chkp_type_has_function_pointer (TREE_TYPE (type));
-
- return res;
+ check_type_tiabi_compatibility (TREE_TYPE (type), loc, visited_nodes);
}
-/* Check the function declaration FNTYPE for TI ABI compatibility. */
+/* Check the GCC function declaration FNTYPE for TI ABI compatibility. */
static void
-chk_function_decl (const_tree fntype, location_t call_location)
+check_function_decl (tree fntype, location_t loc,
+ hash_set<tree> *visited_nodes)
{
+ /* Do not visit the same type twice. */
+ if (visited_nodes->add (fntype))
+ return;
+
/* GCC does not check if the RETURN VALUE pointer is NULL,
so do not allow GCC functions with large return values. */
if (!VOID_TYPE_P (TREE_TYPE (fntype))
&& pru_return_in_memory (TREE_TYPE (fntype), fntype))
- error_at (call_location,
+ error_at (loc,
"large return values not supported with %<-mabi=ti%> option");
+ /* Rest of checks for the returned type. */
+ check_type_tiabi_compatibility (TREE_TYPE (fntype), loc, visited_nodes);
+
/* Check this function's arguments. */
for (tree p = TYPE_ARG_TYPES (fntype); p; p = TREE_CHAIN (p))
- {
- tree arg_type = TREE_VALUE (p);
- if (chkp_type_has_function_pointer (arg_type))
- error_at (call_location,
- "function pointers not supported with %<-mabi=ti%> option");
- }
+ check_type_tiabi_compatibility (TREE_VALUE (p), loc, visited_nodes);
}
-/* Callback for walk_gimple_seq that checks TP tree for TI ABI compliance. */
+/* Callback for walk_gimple_seq that checks TP tree for TI ABI compliance.
+ Note that TP would have been marked as visited before calling
+ this function. But the underlying type of TP may or may not have
+ been visited before. */
static tree
-check_op_callback (tree *tp, int *walk_subtrees, void *data)
+check_op_callback (tree *tp, int *, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
@@ -150,66 +176,91 @@ check_op_callback (tree *tp, int *walk_subtrees, void
*data)
{
case FUNCTION_TYPE:
case METHOD_TYPE:
- {
- /* Note: Do not enforce a small return value. It is safe to
- call any TI ABI function from GCC, since GCC will
- never pass NULL. */
-
- /* Check arguments for function pointers. */
- for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
- {
- tree arg_type = TREE_VALUE (p);
- if (chkp_type_has_function_pointer (arg_type))
- error_at (gimple_location (wi->stmt), "function pointers "
- "not supported with %<-mabi=ti%> option");
- }
- break;
- }
+ {
+ /* Has this function already been inspected? */
+ if (wi->pset->add (type))
+ return NULL;
+
+ /* Note: Do not enforce a small return value. It is safe to
+ call any TI ABI function from GCC, since GCC will
+ never pass NULL. */
+
+ /* Check arguments for function pointers. */
+ for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+ check_type_tiabi_compatibility (TREE_VALUE (p),
+ gimple_location (wi->stmt),
+ wi->pset);
+ break;
+ }
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- case POINTER_TYPE:
- {
- if (chkp_type_has_function_pointer (type))
- {
- error_at (gimple_location (wi->stmt),
- "function pointers not supported with "
- "%<-mabi=ti%> option");
- *walk_subtrees = false;
- }
- break;
- }
+ {
+ /* walk_tree would not descend and visit field declarations.
+ So do it here. */
+ check_type_tiabi_compatibility (type,
+ gimple_location (wi->stmt),
+ wi->pset);
+ break;
+ }
default:
- break;
+ break;
}
return NULL;
}
/* Pass implementation. */
unsigned
-pass_pru_tiabi_check::execute (function *fun)
+pass_pru_tiabi_check::execute (function *)
{
- struct walk_stmt_info wi;
- const_tree fntype = TREE_TYPE (fun->decl);
+ struct cgraph_node *node;
+ hash_set<tree> visited_nodes;
+ symtab_node *snode;
- gimple_seq body = gimple_body (current_function_decl);
+ FOR_EACH_SYMBOL (snode)
+ {
+ tree decl = snode->decl;
+ if (decl)
+ {
+ if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (decl)))
+ check_function_decl (TREE_TYPE (decl),
+ DECL_SOURCE_LOCATION (decl),
+ &visited_nodes);
+ else
+ check_type_tiabi_compatibility (TREE_TYPE (decl),
+ DECL_SOURCE_LOCATION (decl),
+ &visited_nodes);
+ }
+ }
- memset (&wi, 0, sizeof (wi));
- wi.info = NULL;
- wi.want_locations = true;
+ FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+ {
+ function *fn = node->get_fun ();
+ gimple_stmt_iterator gsi;
+ basic_block bb;
- /* Check the function body. */
- walk_gimple_seq (body, NULL, check_op_callback, &wi);
+ FOR_EACH_BB_FN (bb, fn)
+ {
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ struct walk_stmt_info wi;
+ memset (&wi, 0, sizeof (wi));
+ wi.info = NULL;
+ wi.want_locations = true;
- /* Check the function declaration. */
- chk_function_decl (fntype, fun->function_start_locus);
+ wi.pset = &visited_nodes;
+ /* Check the function body. */
+ walk_gimple_stmt (&gsi, NULL, check_op_callback, &wi);
+ }
+ }
+ }
return 0;
}
} // anon namespace
-gimple_opt_pass *
+simple_ipa_opt_pass *
make_pru_tiabi_check (gcc::context *ctxt)
{
return new pass_pru_tiabi_check (ctxt);
diff --git a/gcc/config/pru/pru-passes.def b/gcc/config/pru/pru-passes.def
index da48a2c2098..c0d3528c734 100644
--- a/gcc/config/pru/pru-passes.def
+++ b/gcc/config/pru/pru-passes.def
@@ -21,7 +21,7 @@
that the compiled code by GCC conforms to the TI ABI specification.
If GCC cannot output a conforming code, then an error is raised. */
-INSERT_PASS_AFTER (pass_warn_unused_result, 1, pru_tiabi_check);
+INSERT_PASS_AFTER (pass_ipa_auto_profile_offline, 1, pru_tiabi_check);
/* If -minrt option is used, then this pass would validate
that the compiled code by GCC is compatible with the minimal
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index 4750f0e1007..d2e51ea44d2 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -72,8 +72,12 @@ extern int pru_get_ctable_base_offset (HOST_WIDE_INT caddr);
extern int pru_symref2ioregno (rtx op);
-extern rtl_opt_pass *make_pru_tiabi_check (gcc::context *);
-extern rtl_opt_pass *make_pru_minrt_check (gcc::context *);
+/* Forward declarations to avoid unnecessarily including headers. */
+class simple_ipa_opt_pass;
+class gimple_opt_pass;
+
+extern simple_ipa_opt_pass *make_pru_tiabi_check (gcc::context *);
+extern gimple_opt_pass *make_pru_minrt_check (gcc::context *);
#endif /* RTX_CODE */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 26e6e5bea60..2eab5140bc2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -31367,6 +31367,29 @@ pointer as the first argument of the function. TI
ABI, though, mandates that
the pointer can be NULL in case the caller is not using the returned value.
GNU always passes and expects a valid return value pointer.
+@item Size Of Struct Containing Bit-fields
+TI ABI mandates that struct size is determined by the bit-field type, if it
+contains any. Whereas GNU allocates the smallest amount of bytes which would
+fit the bit-field.
+
+For example, TI ABI reserves 4 bytes for this struct, whereas GNU reserves
+a single byte:
+
+@smallexample
+struct S @{ int i:1; @};
+@end smallexample
+
+@item Access Size For Volatile Bit-fields
+TI ABI mandates that volatile bit-fields are accessed using their type.
+In contrast, GNU ABI uses the smallest integer type fitting the bit-field.
+
+For example, TI ABI requires a single load of 4 bytes for the
+following bit-field. Whereas GNU generates a load of 1 byte:
+
+@smallexample
+struct S @{ volatile int i:1; @};
+@end smallexample
+
@end table
The current @option{-mabi=ti} implementation simply raises a compile error
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-1.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-1.c
index 117ae8fd176..44f5202f330 100644
--- a/gcc/testsuite/gcc.target/pru/mabi-ti-1.c
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-1.c
@@ -4,7 +4,7 @@
/* { dg-options "-O1 -mabi=ti" } */
-int test(int a, int b, void (*fp)(void))
-{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+int test(int a, int b, void (*fp)(void)) /* { dg-error "function pointers not
supported with '-mabi=ti' option" } */
+{
return a+b;
}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-11.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-11.c
new file mode 100644
index 00000000000..c5df2ad3980
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-11.c
@@ -0,0 +1,14 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+struct s1 {
+ int (*f)(void); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
+ int a;
+};
+
+int test1(void)
+{
+ return ((struct s1 *)0x11223344)->a;
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-12.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-12.c
new file mode 100644
index 00000000000..4658f60b971
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-12.c
@@ -0,0 +1,15 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+struct s1 {
+ int (*f)(void); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
+ int a;
+};
+
+struct s1 g1;
+struct s1 g2;
+struct s1 g3;
+
+int (*g_f1)(char); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-2.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-2.c
index d4a3aff546c..66bdfd0aa90 100644
--- a/gcc/testsuite/gcc.target/pru/mabi-ti-2.c
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-2.c
@@ -8,8 +8,8 @@ struct big {
char c[9];
};
-struct big test(void)
-{ /* { dg-error "large return values not supported with '-mabi=ti' option" } */
+struct big test(void) /* { dg-error "large return values not supported with
'-mabi=ti' option" } */
+{
static struct big b;
return b;
}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-3.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-3.c
index c49f6653589..472452b499a 100644
--- a/gcc/testsuite/gcc.target/pru/mabi-ti-3.c
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-3.c
@@ -4,9 +4,9 @@
/* { dg-options "-O1 -mabi=ti" } */
-extern void extfunc(void (*fp)(void));
+extern void extfunc(void (*fp)(void)); /* { dg-error "function pointers not
supported with '-mabi=ti' option" } */
void test(void)
{
- extfunc(test); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
+ extfunc(test);
}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-5.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-5.c
index 38eeaa4435d..9ef73b1754c 100644
--- a/gcc/testsuite/gcc.target/pru/mabi-ti-5.c
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-5.c
@@ -4,13 +4,13 @@
/* { dg-options "-O1 -mabi=ti" } */
struct s1 {
- void (*f)(void);
+ void (*f)(void); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
int a;
};
struct s2 {
union {
- void (*f)(void);
+ void (*f)(int); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
int a;
long b;
} u;
@@ -18,16 +18,16 @@ struct s2 {
int test1(struct s1 *p)
{
- return p->a; /* { dg-error "function pointers not supported with '-mabi=ti'
option" } */
+ return p->a;
return 1;
}
int test1_unused_arg(struct s1 p, int a)
-{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+{
return a;
}
int test2(struct s2 v)
-{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+{
return 2;
}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-6.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-6.c
index c8aa018a21e..b94971878db 100644
--- a/gcc/testsuite/gcc.target/pru/mabi-ti-6.c
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-6.c
@@ -4,9 +4,9 @@
/* { dg-options "-O1 -mabi=ti" } */
-extern void (*extfuncp)(int);
+extern void (*extfuncp)(int); /* { dg-error "function pointers not supported
with '-mabi=ti' option" } */
void test(void)
{
- extfuncp(1); /* { dg-error "function pointers not supported with '-mabi=ti'
option" } */
+ extfuncp(1);
}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-7.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-7.c
index cc095facf64..7738255fafa 100644
--- a/gcc/testsuite/gcc.target/pru/mabi-ti-7.c
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-7.c
@@ -4,18 +4,32 @@
/* { dg-options "-O1 -mabi=ti" } */
struct s1 {
- int (*f)(void);
+ int (*f)(void); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
int a;
};
-extern struct s1 s;
+struct s2 {
+ int (*f)(short); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
+ int a;
+};
+
+struct s3 {
+ int (*f)(char); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
+ int a;
+ int b;
+ int c;
+};
+
+extern struct s1 g_s1;
+extern struct s2 g_s2;
+struct s3 g_s3;
int test1(void)
{
- return s.f(); /* { dg-error "function pointers not supported with '-mabi=ti'
option" } */
+ return g_s1.f();
}
int test2(void)
{
- return s.a; /* { dg-error "function pointers not supported with '-mabi=ti'
option" } */
+ return g_s2.a;
}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-8.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-8.c
new file mode 100644
index 00000000000..6f4a91a6b5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-8.c
@@ -0,0 +1,48 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+struct s0 {
+ int f0 : 2; /* { dg-error "bit-fields not supported with '-mabi=ti'
option" } */
+ int f1;
+};
+struct s0 g_s;
+
+struct s1 {
+ int f : 2; /* { dg-error "bit-fields not supported with '-mabi=ti' option"
} */
+ int a;
+};
+struct s1 g_s1;
+int test1(void)
+{
+ struct s1 s;
+
+ return sizeof(s);
+}
+
+struct s2 {
+ int a2;
+ int f2 : 3; /* { dg-error "bit-fields not supported with '-mabi=ti'
option" } */
+};
+struct s22 {
+ struct s2 *p;
+};
+int test2(struct s22 *s)
+{
+ return s->p->f2 + s->p->a2;
+}
+
+int test2a(struct s2 *s)
+{
+ return s->f2 - s->a2;
+}
+
+struct s3 {
+ int a3;
+ int f3 : 3; /* { dg-error "bit-fields not supported with '-mabi=ti'
option" } */
+};
+int test3(struct s3 s)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-9.c
b/gcc/testsuite/gcc.target/pru/mabi-ti-9.c
new file mode 100644
index 00000000000..37c74e0616d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-9.c
@@ -0,0 +1,16 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+struct s1 {
+ int (*f)(void); /* { dg-error "function pointers not supported with
'-mabi=ti' option" } */
+ int a;
+};
+
+struct s2 {
+ struct s1 *s;
+ int a;
+};
+
+struct s2 g_s2;
--
2.51.0