gimple *stmt = gsi_stmt (bsi);
tree op;
ssa_op_iter iter;
- tree decl;
if (is_gimple_debug (stmt))
continue;
can_split = false;
}
- /* Check builtins that prevent splitting. */
- if (gimple_code (stmt) == GIMPLE_CALL
- && (decl = gimple_call_fndecl (stmt)) != NULL_TREE
- && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
- switch (DECL_FUNCTION_CODE (decl))
- {
- /* FIXME: once we will allow passing non-parm values to split part,
- we need to be sure to handle correct builtin_stack_save and
- builtin_stack_restore. At the moment we are safe; there is no
- way to store builtin_stack_save result in non-SSA variable
- since all calls to those are compiler generated. */
- case BUILT_IN_APPLY:
- case BUILT_IN_APPLY_ARGS:
- case BUILT_IN_VA_START:
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file,
- "Cannot split: builtin_apply and va_start.\n");
- can_split = false;
- break;
- case BUILT_IN_EH_POINTER:
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Cannot split: builtin_eh_pointer.\n");
- can_split = false;
- break;
- default:
- break;
- }
+ /* Check calls that would prevent splitting. */
+ if (gimple_code (stmt) == GIMPLE_CALL)
+ {
+ if (tree decl = gimple_call_fndecl (stmt))
+ {
+ /* Check builtins that would prevent splitting. */
+ if (fndecl_built_in_p (decl, BUILT_IN_NORMAL))
+ switch (DECL_FUNCTION_CODE (decl))
+ {
+ /* FIXME: once we will allow passing non-parm values to
+ split part, we need to be sure to handle correct
+ builtin_stack_save and builtin_stack_restore. At the
+ moment we are safe; there is no way to store
+ builtin_stack_save result in non-SSA variable since all
+ calls to those are compiler generated. */
+ case BUILT_IN_APPLY:
+ case BUILT_IN_APPLY_ARGS:
+ case BUILT_IN_VA_START:
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Cannot split: builtin_apply and va_start.\n");
+ can_split = false;
+ break;
+ case BUILT_IN_EH_POINTER:
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Cannot split: builtin_eh_pointer.\n");
+ can_split = false;
+ break;
+ default:
+ break;
+ }
+
+ /* Calls that function has either the warning or error
+ attribute on it should not be split off into another
+ function. */
+ if (lookup_attribute ("warning", DECL_ATTRIBUTES (decl))
+ || lookup_attribute ("error", DECL_ATTRIBUTES (decl)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Cannot split: warning or error attribute.\n");
+ can_split = false;
+ }
+ }
+ }
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
bitmap_set_bit (set_ssa_names, SSA_NAME_VERSION (op));
--- /dev/null
+/* { dg-additional-options "-fconserve-stack" } */
+
+/* Check to make sure that if
+ rfc4106_set_hash_subkey gets split,
+ the error function does not gets split away
+ from the if statement conditionalizing it. */
+
+struct crypto_aes_ctx {
+ char key_dec[128];
+};
+
+int rfc4106_set_hash_subkey_hash_subkey;
+
+void __write_overflow(void)__attribute__((__error__("")));
+void __write_overflow1(void);
+void aes_encrypt(void*);
+
+void fortify_panic(const char*) __attribute__((__noreturn__)) ;
+
+char *rfc4106_set_hash_subkey(struct crypto_aes_ctx *ctx) {
+ void *a = &ctx->key_dec[0];
+ unsigned p_size = __builtin_object_size(a, 0);
+#ifdef __OPTIMIZE__
+ if (p_size < 16) {
+ __write_overflow1();
+ fortify_panic(__func__);
+ }
+ if (p_size < 32) {
+ __write_overflow();
+ fortify_panic(__func__);
+ }
+#endif
+ aes_encrypt(ctx);
+ return ctx->key_dec;
+}
+
+char *(*gg)(struct crypto_aes_ctx *) = rfc4106_set_hash_subkey;
+
+void a(void)
+{
+ struct crypto_aes_ctx ctx;
+ rfc4106_set_hash_subkey(&ctx);
+}
+void b(void)
+{
+ struct crypto_aes_ctx ctx;
+ ctx.key_dec[0] = 0;
+ rfc4106_set_hash_subkey(&ctx);
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fconserve-stack -fdump-tree-optimized" } */
+/* Check to make sure that if
+ rfc4106_set_hash_subkey gets split,
+ the error function does not gets split away
+ from the if statement conditionalizing it.
+ Checking this via the scan tree also. */
+struct crypto_aes_ctx {
+ char key_dec[128];
+};
+
+int rfc4106_set_hash_subkey_hash_subkey;
+
+void __write_overflow(void)__attribute__((__error__("")));
+void __write_overflow1(void);
+void aes_encrypt(void*);
+
+void fortify_panic(const char*) __attribute__((__noreturn__)) ;
+
+char *rfc4106_set_hash_subkey(struct crypto_aes_ctx *ctx) {
+ void *a = &ctx->key_dec[0];
+ unsigned p_size = __builtin_object_size(a, 0);
+#ifdef __OPTIMIZE__
+ if (p_size < 16) {
+ __write_overflow1();
+ fortify_panic(__func__);
+ }
+ if (p_size < 32) {
+ __write_overflow();
+ fortify_panic(__func__);
+ }
+#endif
+ aes_encrypt(ctx);
+ return ctx->key_dec;
+}
+
+char *(*gg)(struct crypto_aes_ctx *) = rfc4106_set_hash_subkey;
+
+void a(void)
+{
+ struct crypto_aes_ctx ctx;
+ rfc4106_set_hash_subkey(&ctx);
+}
+void b(void)
+{
+ struct crypto_aes_ctx ctx;
+ ctx.key_dec[0] = 0;
+ rfc4106_set_hash_subkey(&ctx);
+}
+
+/* This testcase should still split out one of the above basic blocks dealing
+ with __write_overflow. */
+/* { dg-final { scan-tree-dump-times "Function rfc4106_set_hash_subkey.part" 1 "optimized" } } */