[llvm-commits] CVS: llvm-gcc/gcc/c-common.h c-common.c

Chris Lattner lattner at cs.uiuc.edu
Sat Mar 5 10:49:37 PST 2005



Changes in directory llvm-gcc/gcc:

c-common.h updated: 1.4 -> 1.5
c-common.c updated: 1.8 -> 1.9
---
Log message:

implement new fold-offsetof and getbaseaddress functions.


---
Diffs of the changes:  (+95 -0)

 c-common.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 c-common.h |    2 +
 2 files changed, 95 insertions(+)


Index: llvm-gcc/gcc/c-common.h
diff -u llvm-gcc/gcc/c-common.h:1.4 llvm-gcc/gcc/c-common.h:1.5
--- llvm-gcc/gcc/c-common.h:1.4	Mon Feb 14 15:24:32 2005
+++ llvm-gcc/gcc/c-common.h	Sat Mar  5 12:49:20 2005
@@ -1306,6 +1306,8 @@
 
 extern bool c_dump_tree (void *, tree);
 
+extern tree fold_offsetof (tree);
+
 extern void pch_init (void);
 extern int c_common_valid_pch (cpp_reader *pfile, const char *name, int fd);
 extern void c_common_read_pch (cpp_reader *pfile, const char *name, int fd,


Index: llvm-gcc/gcc/c-common.c
diff -u llvm-gcc/gcc/c-common.c:1.8 llvm-gcc/gcc/c-common.c:1.9
--- llvm-gcc/gcc/c-common.c:1.8	Mon Feb 14 15:24:32 2005
+++ llvm-gcc/gcc/c-common.c	Sat Mar  5 12:49:21 2005
@@ -5566,6 +5566,99 @@
 
   return NULL_TREE;
 }
+
+
+
+/* Given a memory reference expression T, return its base address.
+   The base address of a memory reference expression is the main
+   object being referenced.  For instance, the base address for
+   'array[i].fld[j]' is 'array'.  You can think of this as stripping
+   away the offset part from a memory address.
+
+   This function calls handled_component_p to strip away all the inner
+   parts of the memory reference until it reaches the base object.  */
+
+tree
+get_base_address (tree t)
+{
+  while (handled_component_p (t))
+    t = TREE_OPERAND (t, 0);
+  
+  if (TREE_CODE (t) == STRING_CST
+      || TREE_CODE (t) == CONSTRUCTOR
+      || TREE_CODE (t) == INDIRECT_REF)
+    return t;
+  else
+    return NULL_TREE;
+}
+
+
+/* Build the result of __builtin_offsetof.  EXPR is a nested sequence of
+   component references, with an INDIRECT_REF at the bottom; much like
+   the traditional rendering of offsetof as a macro.  Returns the folded
+   and properly cast result.  */
+
+static tree
+fold_offsetof_1 (tree expr)
+{
+  enum tree_code code = PLUS_EXPR;
+  tree base, off, t;
+
+  switch (TREE_CODE (expr))
+    {
+    case ERROR_MARK:
+      return expr;
+
+    case INDIRECT_REF:
+      return size_zero_node;
+
+    case COMPONENT_REF:
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+      if (base == error_mark_node)
+        return base;
+
+      t = TREE_OPERAND (expr, 1);
+      if (DECL_C_BIT_FIELD (t))
+        {
+          error ("attempt to take address of bit-field structure "
+                 "member %qs", IDENTIFIER_POINTER (DECL_NAME (t)));
+          return error_mark_node;
+        }
+      off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
+                        size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
+                                  / BITS_PER_UNIT));
+      break;
+
+    case ARRAY_REF:
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+      if (base == error_mark_node)
+        return base;
+
+      t = TREE_OPERAND (expr, 1);
+      if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
+        {
+          code = MINUS_EXPR;
+          t = fold (build1 (NEGATE_EXPR, TREE_TYPE (t), t));
+        }
+      t = convert (sizetype, t);
+      off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+      break;
+
+    default:
+      abort ();
+    }
+
+  return size_binop (code, base, off);
+}
+
+tree
+fold_offsetof (tree expr)
+{
+  /* Convert back from the internal sizetype to size_t.  */
+  return convert (size_type_node, fold_offsetof_1 (expr));
+}
+
+
 
 /* Check for valid arguments being passed to a function.  */
 void






More information about the llvm-commits mailing list