Linux SPARSE checker discussions
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: linux-sparse@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Bart Van Assche <bvanassche@acm.org>
Subject: [PATCH 15/73] linearize, flow: Fix asm operands, switch case bounds, and DSE
Date: Mon,  9 Nov 2026 12:32:01 -0800	[thread overview]
Message-ID: <20261109203259.362845-16-bvanassche@acm.org> (raw)
In-Reply-To: <20261109203259.362845-1-bvanassche@acm.org>

Fix IR linearization and dead-store elimination issues in flow.c and
linearize.c:
- Continue scanning past OP_CALL for non-escaping locals while stopping
  at OP_ASM in kill_dead_stores_bb().
- Enlarge show_pseudo() formatting buffers and replace sprintf() with
  bounded snprintf().
- Guard VOID phi sources in linearize_logical(), register read-write
  '+r' asm outputs as inputs, guard non-string asm clobbers, and extend
  switch case values to the controlling expression width.
- Add regression test validation/linear/control-flow-fixes.c.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 flow.c                                 |  3 ++
 linearize.c                            | 46 ++++++++++++++++----------
 validation/linear/control-flow-fixes.c | 44 ++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 18 deletions(-)
 create mode 100644 validation/linear/control-flow-fixes.c

diff --git a/flow.c b/flow.c
index 48755501e464..f89cd755a1ae 100644
--- a/flow.c
+++ b/flow.c
@@ -518,6 +518,9 @@ static void kill_dead_stores_bb(pseudo_t pseudo, unsigned long generation, struc
 		case OP_CALL:
 			if (!local)
 				return;
+			continue;
+		case OP_ASM:
+			return;
 		default:
 			continue;
 		}
diff --git a/linearize.c b/linearize.c
index 75850df0a90f..c6ec3703b149 100644
--- a/linearize.c
+++ b/linearize.c
@@ -98,7 +98,7 @@ const char *show_label(struct basic_block *bb)
 const char *show_pseudo(pseudo_t pseudo)
 {
 	static int n;
-	static char buffer[4][64];
+	static char buffer[4][256];
 	char *buf;
 	int i;
 
@@ -113,23 +113,23 @@ const char *show_pseudo(pseudo_t pseudo)
 		struct expression *expr;
 
 		if (!sym) {
-			snprintf(buf, 64, "<bad symbol>");
+			snprintf(buf, sizeof(buffer[0]), "<bad symbol>");
 			break;
 		}
 		if (sym->bb_target) {
-			snprintf(buf, 64, "%s", show_label(sym->bb_target));
+			snprintf(buf, sizeof(buffer[0]), "%s", show_label(sym->bb_target));
 			break;
 		}
 		if (sym->ident) {
-			snprintf(buf, 64, "%s", show_ident(sym->ident));
+			snprintf(buf, sizeof(buffer[0]), "%s", show_ident(sym->ident));
 			break;
 		}
 		expr = sym->initializer;
-		snprintf(buf, 64, "<anon symbol:%p>", verbose ? sym : NULL);
+		snprintf(buf, sizeof(buffer[0]), "<anon symbol:%p>", verbose ? sym : NULL);
 		if (expr) {
 			switch (expr->type) {
 			case EXPR_VALUE:
-				snprintf(buf, 64, "<symbol value: %lld>", expr->value);
+				snprintf(buf, sizeof(buffer[0]), "<symbol value: %lld>", expr->value);
 				break;
 			case EXPR_STRING:
 				return show_string(expr->string);
@@ -140,30 +140,30 @@ const char *show_pseudo(pseudo_t pseudo)
 		break;
 	}
 	case PSEUDO_REG:
-		i = snprintf(buf, 64, "%%r%d", pseudo->nr);
-		if (pseudo->ident)
-			sprintf(buf+i, "(%s)", show_ident(pseudo->ident));
+		i = snprintf(buf, sizeof(buffer[0]), "%%r%d", pseudo->nr);
+		if (pseudo->ident && i < (int)sizeof(buffer[0]))
+			snprintf(buf+i, sizeof(buffer[0]) - i, "(%s)", show_ident(pseudo->ident));
 		break;
 	case PSEUDO_VAL: {
 		long long value = pseudo->value;
 		if (value > 1000 || value < -1000)
-			snprintf(buf, 64, "$%#llx", value);
+			snprintf(buf, sizeof(buffer[0]), "$%#llx", value);
 		else
-			snprintf(buf, 64, "$%lld", value);
+			snprintf(buf, sizeof(buffer[0]), "$%lld", value);
 		break;
 	}
 	case PSEUDO_ARG:
-		snprintf(buf, 64, "%%arg%d", pseudo->nr);
+		snprintf(buf, sizeof(buffer[0]), "%%arg%d", pseudo->nr);
 		break;
 	case PSEUDO_PHI:
-		i = snprintf(buf, 64, "%%phi%d", pseudo->nr);
-		if (pseudo->ident)
-			sprintf(buf+i, "(%s)", show_ident(pseudo->ident));
+		i = snprintf(buf, sizeof(buffer[0]), "%%phi%d", pseudo->nr);
+		if (pseudo->ident && i < (int)sizeof(buffer[0]))
+			snprintf(buf+i, sizeof(buffer[0]) - i, "(%s)", show_ident(pseudo->ident));
 		break;
 	case PSEUDO_UNDEF:
 		return "UNDEF";
 	default:
-		snprintf(buf, 64, "<bad pseudo type %d>", pseudo->type);
+		snprintf(buf, sizeof(buffer[0]), "<bad pseudo type %d>", pseudo->type);
 	}
 	return buf;
 }
@@ -1746,7 +1746,8 @@ static pseudo_t linearize_logical(struct entrypoint *ep, struct expression *expr
 	src2 = linearize_expression_to_bool(ep, expr->right);
 	src2 = cast_pseudo(ep, src2, &bool_ctype, ctype);
 	phi2 = alloc_phi(ep->active, src2, ctype);
-	link_phi(node, phi2);
+	if (phi2 != VOID)
+		link_phi(node, phi2);
 
 	// join
 	set_activeblock(ep, merge);
@@ -2154,6 +2155,8 @@ static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement
 
 	/* ... and the addresses for memory outputs */
 	FOR_EACH_PTR(stmt->asm_outputs, op) {
+		if (op->is_modify && !op->is_memory)
+			add_asm_input(ep, insn, op);
 		add_asm_output_address(ep, insn, op);
 	} END_FOR_EACH_PTR(op);
 
@@ -2166,7 +2169,8 @@ static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement
 
 	/* and finally, look if it clobbers memory */
 	FOR_EACH_PTR(stmt->asm_clobbers, clob) {
-		if (!strcmp(clob->string->data, "memory"))
+		if (clob->type == EXPR_STRING && clob->string &&
+		    !strcmp(clob->string->data, "memory"))
 			insn->clobber_memory = 1;
 	} END_FOR_EACH_PTR(clob);
 
@@ -2262,11 +2266,17 @@ static pseudo_t linearize_switch(struct entrypoint *ep, struct statement *stmt)
 			continue;
 		} else {
 			struct expression *case_to = case_stmt->case_to;
+			struct symbol *ctype = expr->ctype;
 			long long begin, end;
 
 			begin = end = case_stmt->case_expression->value;
 			if (case_to && case_to->type == EXPR_VALUE)
 				end = case_to->value;
+			if (ctype->bit_size > 0) {
+				bool is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED);
+				begin = bits_extend(begin, ctype->bit_size, is_signed);
+				end = bits_extend(end, ctype->bit_size, is_signed);
+			}
 			if (begin > end)
 				jmp = alloc_multijmp(bb_case, end, begin);
 			else
diff --git a/validation/linear/control-flow-fixes.c b/validation/linear/control-flow-fixes.c
new file mode 100644
index 000000000000..507598d42458
--- /dev/null
+++ b/validation/linear/control-flow-fixes.c
@@ -0,0 +1,44 @@
+/* 1. Statement expression with return inside if condition */
+int stmt_expr_cond(void)
+{
+	if (({ if (0) return 0; 1; }))
+		return 1;
+	return 0;
+}
+
+/* 2. Logical expression with unreachable RHS after return */
+int logical_after_return(int x)
+{
+	return x && ({ return 2; 1; });
+}
+
+/* 3. asm "+r" read-write register and "m" memory operand preserve stores */
+int asm_rw_and_mem(void)
+{
+	int x = 42;
+	int y = 99;
+	asm("" : "+r"(x) : "m"(y));
+	return x;
+}
+
+/* 4. Switch on signed char with negative case label */
+int switch_signed_char(signed char c)
+{
+	switch (c) {
+	case -1:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+/*
+ * check-name: control-flow-fixes
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: VOID
+ * check-output-contains: store\\.32.*\\$99 -> 0\\[y\\]
+ * check-output-contains: in:.*"+r" (\\$42)
+ * check-output-contains: switch\\.8.*-1 ->
+ */

  parent reply	other threads:[~2026-11-09 20:33 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 20:31 Bart Van Assche
2026-11-09 20:31 ` [PATCH 01/73] Makefile: Pass '--' to rm in clean target to handle dash-prefixed files Bart Van Assche
2026-11-09 20:31 ` [PATCH 02/73] sparse-llvm: Use LLVMCreateBuilderForModule() with LLVM 24 and later Bart Van Assche
2026-11-09 20:31 ` [PATCH 03/73] typeof_unqual: Strip qualifiers and address space from types and arrays Bart Van Assche
2026-11-09 20:31 ` [PATCH 04/73] bitfield: Pack consecutive _Bool bitfields into byte containers Bart Van Assche
2026-11-09 20:31 ` [PATCH 05/73] allocate: Harden slab allocation bounds, zeroing, and mmap checks Bart Van Assche
2026-11-09 20:31 ` [PATCH 06/73] tokenize: Support 4096-byte identifiers and fix escape bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 07/73] pre-process: Fix macro expansion and include directive handling Bart Van Assche
2026-11-09 20:31 ` [PATCH 08/73] options, lib: Harden warning buffers and command-line option parsing Bart Van Assche
2026-11-09 20:31 ` [PATCH 09/73] builtin: Fix atomic builtin type checking and object_size bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 10/73] parse, show-parse: Fix attribute propagation, enum overflow, and bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 11/73] target-openrisc: Set target_openrisc.mach to MACH_OPENRISC Bart Van Assche
2026-11-09 20:31 ` [PATCH 12/73] evaluate: Fix pointer arithmetic, incomplete types, and qualifiers Bart Van Assche
2026-11-09 20:31 ` [PATCH 13/73] expand: Fix static initializer folding and floating-point casts Bart Van Assche
2026-11-09 20:32 ` [PATCH 14/73] inline: Copy union cast types and VLA bounds when inlining Bart Van Assche
2026-11-09 20:32 ` Bart Van Assche [this message]
2026-11-09 20:32 ` [PATCH 16/73] memops, ssa: Walk parent insns in reverse and skip mixed-size SSA Bart Van Assche
2026-11-09 20:32 ` [PATCH 17/73] simplify: Prevent overflow on LLONG_MIN negation and fix simplifications Bart Van Assche
2026-11-09 20:32 ` [PATCH 18/73] sparse: Gate context failure warning on Wcontext and catch underflow Bart Van Assche
2026-11-09 20:32 ` [PATCH 19/73] ast-model: Return AST_N_COLUMNS and inspect child nodes lazily Bart Van Assche
2026-11-09 20:32 ` [PATCH 20/73] c2xml: Guard against recursive symbols and free xmlGetProp() string Bart Van Assche
2026-11-09 20:32 ` [PATCH 21/73] compile-i386: Fix buffer bounds, unsigned '<=' codegen, and null checks Bart Van Assche
2026-11-09 20:32 ` [PATCH 22/73] ctags: Fix line comparison order and handle SYM_RESTRICT and SYM_LABEL Bart Van Assche
2026-11-09 20:32 ` [PATCH 23/73] dissect: Unwrap array element type via base_type() Bart Van Assche
2026-11-09 20:32 ` [PATCH 24/73] example: Fix show_op() rotating buffer dimensions Bart Van Assche
2026-11-09 20:32 ` [PATCH 25/73] graph: Check PSEUDO_SYM before dereferencing insn->func->sym Bart Van Assche
2026-11-09 20:32 ` [PATCH 26/73] scheck: Fix slice() upper bit index calculation Bart Van Assche
2026-11-09 20:32 ` [PATCH 27/73] sparse-llvm: Support arbitrary struct member counts and fix operand types Bart Van Assche
2026-11-09 20:32 ` [PATCH 28/73] inline: Duplicate generic expressions instead of evaluating them Bart Van Assche
2026-11-09 20:32 ` [PATCH 29/73] lib: Avoid mutating fmt before va_start() in warning() Bart Van Assche
2026-11-09 20:32 ` [PATCH 30/73] cse, canon: Cast pointers to uintptr_t before relational comparison Bart Van Assche
2026-11-09 20:32 ` [PATCH 31/73] context: Add "conditional context increment" model Bart Van Assche
2026-11-09 20:32 ` [PATCH 32/73] expand: Simplify signed constants early Bart Van Assche
2026-11-09 20:32 ` [PATCH 33/73] bitwise: Allow all-bits-set as a restricted value Bart Van Assche
2026-11-09 20:32 ` [PATCH 34/73] bitwise: Allow restricted ordered compares with unrestricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 35/73] bitwise: Keep unrestricted values unrestricted after a cast Bart Van Assche
2026-11-09 20:32 ` [PATCH 36/73] bitwise: Don't remove MOD_SPECIFIER from 'bitwise' types Bart Van Assche
2026-11-09 20:32 ` [PATCH 37/73] bitwise: Allow both regular casts and forced casts for restricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 38/73] clang-format: Add .clang-format configuration file Bart Van Assche
2026-11-09 20:32 ` [PATCH 39/73] options: Add support for -std=c23, -std=c2x and -std=gnu23 Bart Van Assche
2026-11-09 20:32 ` [PATCH 40/73] preprocessor: Add support for #elifdef and #elifndef Bart Van Assche
2026-11-09 20:32 ` [PATCH 41/73] preprocessor: Add support for __has_include and __has_include_next Bart Van Assche
2026-11-09 20:32 ` [PATCH 42/73] c23: Add support for static_assert, alignas, alignof, thread_local Bart Van Assche
2026-11-09 20:32 ` [PATCH 43/73] c23: Add support for bool, true, and false keywords Bart Van Assche
2026-11-09 20:32 ` [PATCH 44/73] c23: Add support for nullptr and nullptr_t Bart Van Assche
2026-11-09 20:32 ` [PATCH 45/73] c23: Add support for digit separators in numeric literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 46/73] c23: Support unnamed parameters in function definitions Bart Van Assche
2026-11-09 20:32 ` [PATCH 47/73] c23: Support variadic functions without named parameters Bart Van Assche
2026-11-09 20:32 ` [PATCH 48/73] c23: Support labels before declarations and at block ends Bart Van Assche
2026-11-09 20:32 ` [PATCH 49/73] c23: Support auto type inference Bart Van Assche
2026-11-09 20:32 ` [PATCH 50/73] c23: Support constexpr object specifier Bart Van Assche
2026-11-09 20:32 ` [PATCH 51/73] c23: Support enumerations with fixed underlying types Bart Van Assche
2026-11-09 20:32 ` [PATCH 52/73] c23: Support standard [[]] attribute syntax Bart Van Assche
2026-11-09 20:32 ` [PATCH 53/73] preprocessor: Add support for __has_c_attribute Bart Van Assche
2026-11-09 20:32 ` [PATCH 54/73] c23: Support empty initializer braces {} Bart Van Assche
2026-11-09 20:32 ` [PATCH 55/73] preprocessor: Add support for __has_embed Bart Van Assche
2026-11-09 20:32 ` [PATCH 56/73] preprocessor: Add support for #embed directive Bart Van Assche
2026-11-09 20:32 ` [PATCH 57/73] c23: Add support for u8 character constants and string literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 58/73] preprocessor: Add support for __VA_OPT__ Bart Van Assche
2026-11-09 20:32 ` [PATCH 59/73] c23: Treat empty parameter list () as (void) and reject K&R functions Bart Van Assche
2026-11-09 20:32 ` [PATCH 60/73] c23: Support storage-class specifiers in compound literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 61/73] c23: Add support for _BitInt(N) Bart Van Assche
2026-11-09 20:32 ` [PATCH 62/73] enum: Support machine mode attributes on enumeration types Bart Van Assche
2026-11-09 20:32 ` [PATCH 63/73] enum: Support __attribute__((packed)) " Bart Van Assche
2026-11-09 20:32 ` [PATCH 64/73] expand: Ignore top-level non-array address space in compare_types() Bart Van Assche
2026-11-09 20:32 ` [PATCH 65/73] builtin: Support __builtin_infer_alloc_token() as a size_t ICE Bart Van Assche
2026-11-09 20:32 ` [PATCH 66/73] builtin: Add support for Linux kernel compiler builtins Bart Van Assche
2026-11-09 20:32 ` [PATCH 67/73] builtin: Add support for __builtin_has_attribute() Bart Van Assche
2026-11-09 20:32 ` [PATCH 68/73] cleanup: Support __attribute__((cleanup(...))) in linearize and -Wcontext Bart Van Assche
2026-11-09 20:32 ` [PATCH 69/73] builtin: Do not evaluate __builtin_clz(0) and __builtin_ctz(0) Bart Van Assche
2026-11-09 20:32 ` [PATCH 70/73] pre-process: Support long token and string expansions dynamically Bart Van Assche
2026-11-09 20:32 ` [PATCH 71/73] x86: Undefine conflicting bitness macros when parsing -m flags Bart Van Assche
2026-11-09 20:32 ` [PATCH 72/73] evaluate: Accept conditional expressions with only one void side Bart Van Assche
2026-11-09 20:32 ` [PATCH 73/73] ci: Add Linux kernel GitHub Actions workflow and build script Bart Van Assche

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261109203259.362845-16-bvanassche@acm.org \
    --to=bvanassche@acm.org \
    --cc=linux-sparse@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox