aboutsummaryrefslogtreecommitdiffstats
path: root/symbol.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@penguin.transmeta.com>2003-03-24 13:14:37 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 20:59:41 -0700
commit510f939a5a71ac88ddbbb4af52b32c94f8fd1285 (patch)
tree68a0e71082860c52872d042864ccb0781138ac1e /symbol.c
parentdd70c1f2ceb662e396256e11b9edd44cc7f7724c (diff)
downloadsparse-510f939a5a71ac88ddbbb4af52b32c94f8fd1285.tar.gz
Add type size and alignment information to 'struct symbol'.
Add 'target.h' to describe size of target-dependent types. Add parsing of size information to gather the size for simple types, pointers and structures/unions.
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/symbol.c b/symbol.c
index 19b39411..424823af 100644
--- a/symbol.c
+++ b/symbol.c
@@ -14,6 +14,8 @@
#include "symbol.h"
#include "scope.h"
+#include "target.h"
+
struct symbol *lookup_symbol(struct ident *ident, enum namespace ns)
{
struct symbol *sym;
@@ -33,6 +35,136 @@ struct symbol *alloc_symbol(struct token *token, int type)
return sym;
}
+struct struct_union_info {
+ int advance;
+ unsigned long max_align;
+ unsigned long bit_size;
+ unsigned long offset;
+ unsigned long bit_offset;
+};
+
+static void examine_one_member(struct symbol *sym, void *_info, int flags)
+{
+ struct struct_union_info *info = _info;
+ unsigned long offset = info->offset;
+
+ examine_symbol_type(sym);
+ if (sym->alignment > info->max_align)
+ info->max_align = sym->alignment;
+ if (info->advance) {
+ offset += sym->alignment-1;
+ offset &= ~(sym->alignment-1);
+ sym->offset = offset;
+ info->offset = offset + (sym->bit_size >> 3);
+ }
+ info->bit_size = (offset << 3) + sym->bit_size;
+}
+
+static void examine_struct_union_type(struct symbol *sym, int advance)
+{
+ struct struct_union_info info = { advance, 1, 0, 0 };
+ unsigned long bit_size, bit_align;
+
+ symbol_iterate(sym->symbol_list, examine_one_member, &info);
+ bit_size = info.bit_size;
+ bit_align = (info.max_align << 3)-1;
+ bit_size = (bit_size + bit_align) & ~bit_align;
+ sym->bit_size = bit_size;
+ sym->alignment = info.max_align;
+}
+
+/*
+ * Fill in type size and alignment information for
+ * regular SYM_TYPE things.
+ */
+void examine_symbol_type(struct symbol * sym)
+{
+ unsigned int bit_size, alignment;
+ struct symbol *base_type;
+ unsigned long modifiers;
+
+ /* Already done? */
+ if (sym->bit_size)
+ return;
+ base_type = sym->ctype.base_type;
+ modifiers = sym->ctype.modifiers;
+
+ /* If this symbol doesn't have a type yet, we'll just have to punt */
+ if (!base_type) {
+ warn(sym->token, "no type");
+ return;
+ }
+
+ switch (base_type->type) {
+ case SYM_STRUCT:
+ examine_struct_union_type(base_type, 1);
+ break;
+ case SYM_UNION:
+ examine_struct_union_type(base_type, 0);
+ break;
+ case SYM_PTR:
+ if (!base_type->bit_size)
+ base_type->bit_size = BITS_IN_POINTER;
+ if (!base_type->alignment)
+ base_type->alignment = POINTER_ALIGNMENT;
+ break;
+ default:
+ break;
+ }
+
+ bit_size = base_type->bit_size;
+ alignment = base_type->alignment;
+ if (bit_size) {
+ if (!sym->alignment)
+ sym->alignment = alignment;
+ sym->bit_size = bit_size;
+ return;
+ }
+
+ if (base_type == &int_type) {
+ bit_size = BITS_IN_INT;
+ if (modifiers & MOD_LONGLONG) {
+ bit_size = BITS_IN_LONGLONG;
+ } else if (modifiers & MOD_LONG) {
+ bit_size = BITS_IN_LONG;
+ } else if (modifiers & MOD_SHORT) {
+ bit_size = BITS_IN_SHORT;
+ } else if (modifiers & MOD_CHAR) {
+ bit_size = BITS_IN_CHAR;
+ }
+ if (!alignment) {
+ alignment = bit_size >> 3;
+ if (alignment > MAX_INT_ALIGNMENT)
+ alignment = MAX_INT_ALIGNMENT;
+ }
+ if (!sym->alignment)
+ sym->alignment = alignment;
+ sym->bit_size = bit_size;
+ return;
+ }
+
+ if (base_type == &fp_type) {
+ bit_size = BITS_IN_FLOAT;
+ if (modifiers & MOD_LONGLONG) {
+ bit_size = BITS_IN_LONGDOUBLE;
+ } else if (modifiers & MOD_LONG) {
+ bit_size = BITS_IN_DOUBLE;
+ }
+ if (!alignment) {
+ alignment = bit_size >> 3;
+ if (alignment > MAX_FP_ALIGNMENT)
+ alignment = MAX_FP_ALIGNMENT;
+ }
+ if (!sym->alignment)
+ sym->alignment = alignment;
+ sym->bit_size = bit_size;
+ return;
+ }
+
+ warn(sym->token, "unknown type");
+ return;
+}
+
void bind_symbol(struct symbol *sym, struct ident *ident, enum namespace ns)
{
if (sym->id_list) {