aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2011-09-07 17:36:40 +0300
committerPekka Enberg <penberg@kernel.org>2011-09-07 20:18:55 +0300
commitf567535353119eae0e57beef52a83519e0ebee3e (patch)
tree500e1544d80cdb57809121b0c94d8e902f1e5497
parent6d233957ef292a9552b7dba126eb1a66ff1ef9cd (diff)
downloadsparse-f567535353119eae0e57beef52a83519e0ebee3e.tar.gz
sparse, llvm: Add support for struct types
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--sparse-llvm.c55
-rw-r--r--validation/backend/struct.c17
2 files changed, 70 insertions, 2 deletions
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 608d3a42..f1c99dd3 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -32,7 +32,33 @@ static inline bool symbol_is_fp_type(struct symbol *sym)
return sym->ctype.base_type == &fp_type;
}
-static LLVMTypeRef symbol_type(struct symbol *sym)
+static LLVMTypeRef symbol_type(struct symbol *sym);
+
+#define MAX_STRUCT_MEMBERS 64
+
+static LLVMTypeRef sym_struct_type(struct symbol *sym)
+{
+ LLVMTypeRef elem_types[MAX_STRUCT_MEMBERS];
+ struct symbol *member;
+ unsigned nr = 0;
+
+ FOR_EACH_PTR(sym->symbol_list, member) {
+ assert(nr < MAX_STRUCT_MEMBERS);
+
+ elem_types[nr++] = symbol_type(member);
+ } END_FOR_EACH_PTR(member);
+
+ return LLVMStructType(elem_types, nr, 0 /* packed? */);
+}
+
+static LLVMTypeRef sym_ptr_type(struct symbol *sym)
+{
+ LLVMTypeRef type = symbol_type(sym->ctype.base_type);
+
+ return LLVMPointerType(type, 0);
+}
+
+static LLVMTypeRef sym_basetype_type(struct symbol *sym)
{
LLVMTypeRef ret = NULL;
@@ -77,6 +103,29 @@ static LLVMTypeRef symbol_type(struct symbol *sym)
return ret;
}
+static LLVMTypeRef symbol_type(struct symbol *sym)
+{
+ LLVMTypeRef ret = NULL;
+
+ switch (sym->type) {
+ case SYM_NODE:
+ ret = symbol_type(sym->ctype.base_type);
+ break;
+ case SYM_BASETYPE:
+ ret = sym_basetype_type(sym);
+ break;
+ case SYM_PTR:
+ ret = sym_ptr_type(sym);
+ break;
+ case SYM_STRUCT:
+ ret = sym_struct_type(sym);
+ break;
+ default:
+ assert(0);
+ }
+ return ret;
+}
+
static LLVMTypeRef insn_symbol_type(struct instruction *insn)
{
if (insn->type)
@@ -902,7 +951,9 @@ static int output_data(LLVMModuleRef module, struct symbol *sym)
else
assert(0);
} else {
- initial_value = LLVMConstInt(symbol_type(sym), 0, 1);
+ LLVMTypeRef type = symbol_type(sym);
+
+ initial_value = LLVMConstNull(type);
}
name = show_ident(sym->ident);
diff --git a/validation/backend/struct.c b/validation/backend/struct.c
new file mode 100644
index 00000000..ef7d0d7e
--- /dev/null
+++ b/validation/backend/struct.c
@@ -0,0 +1,17 @@
+struct ctype {
+ int type;
+};
+
+struct symbol {
+ void *p;
+ const char *name;
+ struct ctype ctype;
+};
+
+static struct symbol sym;
+static struct symbol *sym_p;
+
+/*
+ * check-name: Struct code generation
+ * check-command: ./sparsec -c $file -o tmp.o
+ */