All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
To: linux-sparse@vger.kernel.org
Cc: Christopher Li <sparse@chrisli.org>,
	Dibyendu Majumdar <mobile@majumdar.org.uk>,
	Jeff Garzik <jeff@garzik.org>, Pekka Enberg <penberg@kernel.org>,
	Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Subject: [PATCH v4 07/63] give function's arguments a type via OP_PUSH
Date: Tue, 21 Mar 2017 01:15:11 +0100	[thread overview]
Message-ID: <20170321001607.75169-8-luc.vanoostenryck@gmail.com> (raw)
In-Reply-To: <20170321001607.75169-1-luc.vanoostenryck@gmail.com>

The linearized code, sparse's IR, have no use of C's complex type
system. Those types are checked in previous phases and the pseudos
doesn't a type directly attached to them as all needed type info
are now conveyed by the instructions (like (register) size,
signedness (OP_DIVU vs OP_DIVS), ...).

In particular, PSEUDO_VAL (used for integer and address constants)
are completely typeless.
There is a problem with this when calling a variadic function
with a constant argument as in this case there is no type in the
function prototype (for the variadic part, of course) and there is
no defining instructions holding the type of the argument.

Fix this by adding a new instruction, OP_PUSH, which will be used
to pass arguments to function calls and whose purpose is to give
a correct type/size to function's arguments.

Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Idea-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 example.c                       |  4 ++--
 linearize.c                     | 35 +++++++++++++++++++++++++++--------
 linearize.h                     | 10 +++++++++-
 liveness.c                      | 14 ++++++++------
 simplify.c                      | 11 ++++++++++-
 sparse-llvm.c                   |  4 ++--
 validation/call-variadic.c      | 31 +++++++++++++++++++++++++++++++
 validation/loop-linearization.c |  9 ++++++---
 8 files changed, 95 insertions(+), 23 deletions(-)
 create mode 100644 validation/call-variadic.c

diff --git a/example.c b/example.c
index 691e0f97c..69e00b325 100644
--- a/example.c
+++ b/example.c
@@ -1121,11 +1121,11 @@ static void generate_ret(struct bb_state *state, struct instruction *ret)
  */
 static void generate_call(struct bb_state *state, struct instruction *insn)
 {
+	struct instruction *arg;
 	int offset = 0;
-	pseudo_t arg;
 
 	FOR_EACH_PTR(insn->arguments, arg) {
-		output_insn(state, "pushl %s", generic(state, arg));
+		output_insn(state, "pushl %s", generic(state, arg->src));
 		offset += 4;
 	} END_FOR_EACH_PTR(arg);
 	flush_reg(state, hardregs+0);
diff --git a/linearize.c b/linearize.c
index 66d5204d7..34a5125a0 100644
--- a/linearize.c
+++ b/linearize.c
@@ -233,6 +233,7 @@ static const char *opcodes[] = {
 	[OP_FPCAST] = "fpcast",
 	[OP_PTRCAST] = "ptrcast",
 	[OP_INLINED_CALL] = "# call",
+	[OP_PUSH] = "push",
 	[OP_CALL] = "call",
 	[OP_VANEXT] = "va_next",
 	[OP_VAARG] = "va_arg",
@@ -407,17 +408,21 @@ const char *show_instruction(struct instruction *insn)
 	case OP_STORE: case OP_SNOP:
 		buf += sprintf(buf, "%s -> %d[%s]", show_pseudo(insn->target), insn->offset, show_pseudo(insn->src));
 		break;
+	case OP_PUSH:
+		buf += sprintf(buf, "%s", show_pseudo(insn->src));
+		break;
 	case OP_INLINED_CALL:
-	case OP_CALL: {
-		struct pseudo *arg;
+	case OP_CALL:
 		if (insn->target && insn->target != VOID)
 			buf += sprintf(buf, "%s <- ", show_pseudo(insn->target));
 		buf += sprintf(buf, "%s", show_pseudo(insn->func));
-		FOR_EACH_PTR(insn->arguments, arg) {
-			buf += sprintf(buf, ", %s", show_pseudo(arg));
-		} END_FOR_EACH_PTR(arg);
+		if (opcode == OP_INLINED_CALL) {
+			struct pseudo *arg;
+			FOR_EACH_PTR(insn->inlined_args, arg) {
+				buf += sprintf(buf, ", %s", show_pseudo(arg));
+			} END_FOR_EACH_PTR(arg);
+		}
 		break;
-	}
 	case OP_CAST:
 	case OP_SCAST:
 	case OP_FPCAST:
@@ -1197,6 +1202,20 @@ static pseudo_t linearize_assignment(struct entrypoint *ep, struct expression *e
 	return value;
 }
 
+/*
+ * Add an argument for a call.
+ *   -) insn->opcode == O_CALL | OP_INLINE_CALL
+ *   -) ctype = typeof(arg)
+ */
+static void push_argument(struct entrypoint *ep, struct instruction *insn, pseudo_t arg, struct symbol *ctype)
+{
+	struct instruction *push = alloc_typed_instruction(OP_PUSH, ctype);
+	push->call = insn;
+	use_pseudo(push, arg, &push->src);
+	add_instruction(&insn->arguments, push);
+	add_one_insn(ep, push);
+}
+
 static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expression *expr)
 {
 	struct expression *arg, *fn;
@@ -1213,7 +1232,7 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi
 
 	FOR_EACH_PTR(expr->args, arg) {
 		pseudo_t new = linearize_expression(ep, arg);
-		use_pseudo(insn, new, add_pseudo(&insn->arguments, new));
+		push_argument(ep, insn, new, arg->ctype);
 	} END_FOR_EACH_PTR(arg);
 
 	fn = expr->fn;
@@ -1680,7 +1699,7 @@ static pseudo_t linearize_inlined_call(struct entrypoint *ep, struct statement *
 		concat_symbol_list(args->declaration, &ep->syms);
 		FOR_EACH_PTR(args->declaration, sym) {
 			pseudo_t value = linearize_one_symbol(ep, sym);
-			add_pseudo(&insn->arguments, value);
+			add_pseudo(&insn->inlined_args, value);
 		} END_FOR_EACH_PTR(sym);
 	}
 
diff --git a/linearize.h b/linearize.h
index bac82d7ff..0cdd0fa9a 100644
--- a/linearize.h
+++ b/linearize.h
@@ -112,9 +112,16 @@ struct instruction {
 		};
 		struct /* call */ {
 			pseudo_t func;
-			struct pseudo_list *arguments;
+			union {
+				struct instruction_list *arguments;
+				struct pseudo_list *inlined_args;
+			};
 			struct symbol *fntype;
 		};
+		struct /* push/arg */ {
+			pseudo_t arg;			/* same as src, src1 & symbol */
+			struct instruction *call;
+		};
 		struct /* context */ {
 			int increment;
 			int check;
@@ -201,6 +208,7 @@ enum opcode {
 	OP_FPCAST,
 	OP_PTRCAST,
 	OP_INLINED_CALL,
+	OP_PUSH,
 	OP_CALL,
 	OP_VANEXT,
 	OP_VAARG,
diff --git a/liveness.c b/liveness.c
index 7461738b4..7b5b1693a 100644
--- a/liveness.c
+++ b/liveness.c
@@ -46,13 +46,12 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
 	void (*def)(struct basic_block *, pseudo_t),
 	void (*use)(struct basic_block *, pseudo_t))
 {
-	pseudo_t pseudo;
-
 	#define USES(x)		use(bb, insn->x)
 	#define DEFINES(x)	def(bb, insn->x)
 
 	switch (insn->opcode) {
 	case OP_RET:
+	case OP_PUSH:
 		USES(src);
 		break;
 
@@ -118,14 +117,17 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
 		USES(src); DEFINES(target);
 		break;
 
-	case OP_CALL:
+	case OP_CALL: {
+		struct instruction *arg;
+
 		USES(func);
 		if (insn->target != VOID)
 			DEFINES(target);
-		FOR_EACH_PTR(insn->arguments, pseudo) {
-			use(bb, pseudo);
-		} END_FOR_EACH_PTR(pseudo);
+		FOR_EACH_PTR(insn->arguments, arg) {
+			use(bb, arg->src);
+		} END_FOR_EACH_PTR(arg);
 		break;
+	}
 
 	case OP_SLICE:
 		USES(base); DEFINES(target);
diff --git a/simplify.c b/simplify.c
index da40caa65..3f398196d 100644
--- a/simplify.c
+++ b/simplify.c
@@ -182,6 +182,14 @@ static void kill_use_list(struct pseudo_list *list)
 	} END_FOR_EACH_PTR(p);
 }
 
+static void kill_insn_list(struct instruction_list *list)
+{
+	struct instruction *insn;
+	FOR_EACH_PTR(list, insn) {
+		kill_insn(insn, 0);
+	} END_FOR_EACH_PTR(insn);
+}
+
 /*
  * kill an instruction:
  * - remove it from its bb
@@ -213,6 +221,7 @@ void kill_insn(struct instruction *insn, int force)
 	case OP_SETVAL:
 	case OP_NOT: case OP_NEG:
 	case OP_SLICE:
+	case OP_PUSH:
 		kill_use(&insn->src1);
 		break;
 
@@ -240,7 +249,7 @@ void kill_insn(struct instruction *insn, int force)
 			if (!(insn->func->sym->ctype.modifiers & MOD_PURE))
 				return;
 		}
-		kill_use_list(insn->arguments);
+		kill_insn_list(insn->arguments);
 		if (insn->func->type == PSEUDO_REG)
 			kill_use(&insn->func);
 		break;
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 9f362b3ed..ecc4f032f 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -707,7 +707,7 @@ static void output_op_call(struct function *fn, struct instruction *insn)
 {
 	LLVMValueRef target, func;
 	int n_arg = 0, i;
-	struct pseudo *arg;
+	struct instruction *arg;
 	LLVMValueRef *args;
 
 	FOR_EACH_PTR(insn->arguments, arg) {
@@ -718,7 +718,7 @@ static void output_op_call(struct function *fn, struct instruction *insn)
 
 	i = 0;
 	FOR_EACH_PTR(insn->arguments, arg) {
-		args[i++] = pseudo_to_value(fn, insn, arg);
+		args[i++] = pseudo_to_value(fn, arg, arg->src);
 	} END_FOR_EACH_PTR(arg);
 
 	func = pseudo_to_value(fn, insn, insn->func);
diff --git a/validation/call-variadic.c b/validation/call-variadic.c
new file mode 100644
index 000000000..cbb8aa68b
--- /dev/null
+++ b/validation/call-variadic.c
@@ -0,0 +1,31 @@
+#define NULL	((void*)0)
+
+extern int print(const char *msg, ...);
+
+int foo(const char *fmt, int a, long l, int *p)
+{
+	print("msg %c: %d %d/%ld %ld/%p %p\n", 'x', a, __LINE__, l, 0L, p, NULL);
+}
+
+/*
+ * check-name: call-variadic
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-start
+foo:
+.L0:
+	<entry-point>
+	push.64     "msg %c: %d %d/%ld %ld/%p %p\n"
+	push.32     $120
+	push.32     %arg2
+	push.32     $7
+	push.64     %arg3
+	push.64     $0
+	push.64     %arg4
+	push.64     $0
+	call.32     %r5 <- print
+	ret.32      %r5
+
+
+ * check-output-end
+ */
diff --git a/validation/loop-linearization.c b/validation/loop-linearization.c
index 25c6dfb87..d53366bde 100644
--- a/validation/loop-linearization.c
+++ b/validation/loop-linearization.c
@@ -48,7 +48,8 @@ ffor:
 	cbr         %r2, .L1, .L3
 
 .L1:
-	call.32     %r4 <- p, %r1(i)
+	push.32     %r1(i)
+	call.32     %r4 <- p
 	cbr         %r4, .L2, .L5
 
 .L5:
@@ -81,7 +82,8 @@ fwhile:
 	cbr         %r9, .L9, .L11
 
 .L9:
-	call.32     %r11 <- p, %r8(i)
+	push.32     %r8(i)
+	call.32     %r11 <- p
 	cbr         %r11, .L14, .L13
 
 .L13:
@@ -110,7 +112,8 @@ fdo:
 
 .L17:
 	phi.32      %r15(i) <- %phi16(i), %phi17(i)
-	call.32     %r16 <- p, %r15(i)
+	push.32     %r15(i)
+	call.32     %r16 <- p
 	cbr         %r16, .L18, .L20
 
 .L20:
-- 
2.12.0


  parent reply	other threads:[~2017-03-21  0:16 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-21  0:15 [PATCH v4 00/63] LLVM fixes Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 01/63] only output internal pointer value when verbose is set Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 02/63] allow binop simplification after canonicalization Luc Van Oostenryck
2017-03-24  5:00   ` Christopher Li
2017-03-24  9:43     ` Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 03/63] canonicalize compare instructions Luc Van Oostenryck
2017-03-24  5:12   ` Christopher Li
2017-03-24  8:11     ` Luc Van Oostenryck
2017-03-24 23:47       ` Christopher Li
2017-03-25  0:03         ` Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 04/63] add is_signed_type() Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 05/63] fix usage of inlined calls Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 06/63] inlined calls should not block BB packing Luc Van Oostenryck
2017-03-21  0:15 ` Luc Van Oostenryck [this message]
2017-03-21  0:15 ` [PATCH v4 08/63] give a type to OP_PHISOURCE Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 09/63] give a type to OP_SEL, always Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 10/63] give a type to OP_SWITCH Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 11/63] add doc about sparse's instructions/IR Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 12/63] add support for wider type in switch-case Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 13/63] llvm: remove unneeded arg 'module' Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 14/63] llvm: remove unneeded 'generation' Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 15/63] llvm: remove unneeded function::type Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 16/63] llvm: reduce scope of 'bb_nr' Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 17/63] llvm: use pseudo_list_size() instead of open coding it Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 18/63] llvm: give arguments a name Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 19/63] llvm: give a name to call's return values Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 20/63] llvm: avoid useless temp variable Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 21/63] llvm: extract get_sym_value() from pseudo_to_value() Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 22/63] llvm: fix test of floating-point type Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 23/63] llvm: fix translation of PSEUDO_VALs into a ValueRefs Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 24/63] llvm: fix output_op_store() which modify its operand Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 25/63] llvm: fix output_op_[ptr]cast() Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 26/63] llvm: take care of degenerated rvalues Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 27/63] llvm: add test cases for symbol's address Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 28/63] llvm: add test cases for pointers passed as argument Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 29/63] llvm: add test cases for arrays " Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 30/63] llvm: add test cases for degenerated pointers Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 31/63] llvm: add support for OP_NEG Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 32/63] llvm: add support for OP_SETVAL with floats Luc Van Oostenryck
2017-03-24  5:53   ` Christopher Li
2017-03-24  7:48     ` Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 33/63] llvm: add support for OP_SETVAL with labels Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 34/63] llvm: ignore OP_INLINED_CALL Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 35/63] llvm: fix pointer/float mixup in comparisons Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 36/63] llvm: fix type in comparison with an address constant Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 37/63] llvm: give correct type to binops Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 38/63] llvm: adjust OP_RET's type Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 39/63] llvm: variadic functions are not being marked as such Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 40/63] llvm: fix type of switch constants Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 41/63] llvm: make pseudo_name() more flexible Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 42/63] llvm: give a name to all values Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 43/63] llvm: add support for OP_SWITCH with a range Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 44/63] llvm: fix OP_SWITCH has no target Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 45/63] llvm: make value_to_pvalue() more flexible Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 46/63] llvm: make value_to_ivalue() " Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 47/63] llvm: add test case pointer compare with cast Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 48/63] llvm: let pseudo_to_value() directly use the type Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 49/63] llvm: remove unneeded pseudo_to_value() unneeded argument Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 50/63] llvm: introduce get_ioperand() Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 51/63] llvm: fix mutating function pointer Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 52/63] llvm: fix mutated OP_RET Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 53/63] llvm: fix mutated OP_SEL Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 54/63] llvm: fix mutated OP_SWITCH Luc Van Oostenryck
2017-03-21  0:15 ` [PATCH v4 55/63] llvm: fix mutated OP_PHISOURCE Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 56/63] llvm: fix mutated OP_[PTR]CAST Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 57/63] llvm: add support for restricted types Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 58/63] llvm: fix get value from initialized symbol Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 59/63] llvm: fix get value from non-anonymous symbol Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 60/63] llvm: fix type of bitfields Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 61/63] llvm: add support for OP_FPCAST Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 62/63] llvm: add support for cast from floats Luc Van Oostenryck
2017-03-21  0:16 ` [PATCH v4 63/63] llvm: cleanup of output_[ptr]cast() Luc Van Oostenryck
2017-03-21 10:29 ` [PATCH v4 00/63] LLVM fixes Pekka Enberg
2017-03-21 11:24 ` Dibyendu Majumdar
2017-03-21 13:00   ` Luc Van Oostenryck
2017-03-21 13:36     ` Dibyendu Majumdar
2017-03-21 14:55       ` Luc Van Oostenryck

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=20170321001607.75169-8-luc.vanoostenryck@gmail.com \
    --to=luc.vanoostenryck@gmail.com \
    --cc=jeff@garzik.org \
    --cc=linux-sparse@vger.kernel.org \
    --cc=mobile@majumdar.org.uk \
    --cc=penberg@kernel.org \
    --cc=sparse@chrisli.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.