[PATCH 2/2] sparse, llvm: Function pointer code generation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch implements support for function pointer types and function pointer
calls to the LLVM backend.

Cc: Christopher Li <sparse@xxxxxxxxxxx>
Cc: Jeff Garzik <jgarzik@xxxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Pekka Enberg <penberg@xxxxxxxxxx>
---
 sparse-llvm.c                     |   54 +++++++++++++++++++++++++++++++++++-
 validation/backend/function-ptr.c |   11 +++++++
 2 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 validation/backend/function-ptr.c

diff --git a/sparse-llvm.c b/sparse-llvm.c
index 7f46c8a..c037e02 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -34,6 +34,46 @@ static inline bool symbol_is_fp_type(struct symbol *sym)
 
 static LLVMTypeRef symbol_type(LLVMModuleRef module, struct symbol *sym);
 
+static LLVMTypeRef func_return_type(LLVMModuleRef module, struct symbol *sym)
+{
+	return symbol_type(module, sym->ctype.base_type);
+}
+
+static LLVMTypeRef sym_func_type(LLVMModuleRef module, struct symbol *sym)
+{
+	LLVMTypeRef *arg_type;
+	LLVMTypeRef func_type;
+	LLVMTypeRef ret_type;
+	struct symbol *arg;
+	int n_arg = 0;
+
+	/* to avoid strangeness with varargs [for now], we build
+	 * the function and type anew, for each call.  This
+	 * is probably wrong.  We should look up the
+	 * symbol declaration info.
+	 */
+
+	ret_type = func_return_type(module, sym);
+
+	/* count args, build argument type information */
+	FOR_EACH_PTR(sym->arguments, arg) {
+		n_arg++;
+	} END_FOR_EACH_PTR(arg);
+
+	arg_type = calloc(n_arg, sizeof(LLVMTypeRef));
+
+	int idx = 0;
+	FOR_EACH_PTR(sym->arguments, arg) {
+		struct symbol *arg_sym = arg->ctype.base_type;
+
+		arg_type[idx++] = symbol_type(module, arg_sym);
+	} END_FOR_EACH_PTR(arg);
+	func_type = LLVMFunctionType(ret_type, arg_type, n_arg,
+				     /* varargs? */ 0);
+
+	return func_type;
+}
+
 static LLVMTypeRef sym_array_type(LLVMModuleRef module, struct symbol *sym)
 {
 	LLVMTypeRef elem_type;
@@ -172,6 +212,9 @@ static LLVMTypeRef symbol_type(LLVMModuleRef module, struct symbol *sym)
 	case SYM_ARRAY:
 		ret = sym_array_type(module, sym);
 		break;
+	case SYM_FN:
+		ret = sym_func_type(module, sym);
+		break;
 	default:
 		assert(0);
 	}
@@ -638,7 +681,10 @@ static LLVMTypeRef get_func_type(struct function *fn, struct instruction *insn)
 	int n_arg = 0;
 	LLVMTypeRef *arg_type;
 
-	sprintf(buffer, "%.*s", sym->ident->len, sym->ident->name);
+	if (sym->ident)
+		sprintf(buffer, "%.*s", sym->ident->len, sym->ident->name);
+	else
+		sprintf(buffer, "<anon sym %p>", sym);
 
 	/* VERIFY: is this correct, for functions? */
 	func_type = LLVMGetTypeByName(fn->module, buffer);
@@ -682,7 +728,11 @@ static LLVMValueRef get_function(struct function *fn, struct instruction *insn)
 	LLVMValueRef func;
 	struct llfunc *f;
 
-	sprintf(buffer, "%.*s", sym->ident->len, sym->ident->name);
+	if (sym->ident)
+		sprintf(buffer, "%.*s", sym->ident->len, sym->ident->name);
+	else
+		sprintf(buffer, "<anon sym %p>", sym);
+
 
 	/* search for pre-built function type definition */
 	FOR_EACH_PTR(mi.llfunc_list, f) {
diff --git a/validation/backend/function-ptr.c b/validation/backend/function-ptr.c
new file mode 100644
index 0000000..fc022b3
--- /dev/null
+++ b/validation/backend/function-ptr.c
@@ -0,0 +1,11 @@
+typedef int (*fn_t)(int x, int y);
+
+static int run(fn_t fn, int x, int y)
+{
+	return fn(x, y);
+}
+
+/*
+ * check-name: Function pointer code generation
+ * check-command: ./sparsec -c $file -o tmp.o
+ */
-- 
1.7.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux