[llvm-commits] CVS: llvm-gcc/gcc/llvm-expand.c
Chris Lattner
lattner at cs.uiuc.edu
Fri Feb 11 11:26:58 PST 2005
Changes in directory llvm-gcc/gcc:
llvm-expand.c updated: 1.77 -> 1.78
---
Log message:
Implement support for anonymous automatic unions, fixing PR501: http://llvm.cs.uiuc.edu/PR501 and
test/Regression/C++Frontend/2005-02-11-AnonymousUnion.cpp
---
Diffs of the changes: (+50 -4)
llvm-expand.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 50 insertions(+), 4 deletions(-)
Index: llvm-gcc/gcc/llvm-expand.c
diff -u llvm-gcc/gcc/llvm-expand.c:1.77 llvm-gcc/gcc/llvm-expand.c:1.78
--- llvm-gcc/gcc/llvm-expand.c:1.77 Thu Jan 13 11:16:36 2005
+++ llvm-gcc/gcc/llvm-expand.c Fri Feb 11 13:26:43 2005
@@ -2616,6 +2616,52 @@
}
}
+/* llvm_expand_anon_union_decl - This function, which corresponds to
+ * expand_anon_union_decl, expands an anonymous union. An anonymous union is
+ * where the user can refer to the elements as if they were defined in the same
+ * scope as the union itself. These appear to always be automatic variables.
+ */
+static void llvm_expand_anon_union_decl(llvm_function *Fn, tree decl,
+ tree decl_elts) {
+ llvm_nesting *InnermostCleanupScope = Fn->ExpandInfo->InnermostBlockScope;
+ llvm_value *x;
+ tree t;
+
+ /* If any of the elements are addressable, so is the entire union. */
+ for (t = decl_elts; t; t = TREE_CHAIN (t))
+ if (TREE_ADDRESSABLE (TREE_VALUE (t)))
+ {
+ TREE_ADDRESSABLE (decl) = 1;
+ break;
+ }
+
+ llvm_expand_decl(Fn, decl);
+ x = DECL_LLVM(decl);
+
+ /* Go through the elements, assigning the LLVM location to each. */
+ for (t = decl_elts; t; t = TREE_CHAIN (t))
+ {
+ tree decl_elt = TREE_VALUE (t);
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
+
+ /* If any of the elements are used, so is the entire union. */
+ if (TREE_USED (decl_elt))
+ TREE_USED (decl) = 1;
+
+ /* Propagate the union's alignment to the elements. */
+ DECL_ALIGN (decl_elt) = DECL_ALIGN (decl);
+ DECL_USER_ALIGN (decl_elt) = DECL_USER_ALIGN (decl);
+
+ /* If the element has BLKmode and the union doesn't, the union is
+ aligned such that the element doesn't need to have BLKmode, so
+ change the element's mode to the appropriate one for its size. */
+ if (mode == BLKmode && DECL_MODE (decl) != BLKmode)
+ DECL_MODE (decl_elt) = mode
+ = mode_for_size_tree (DECL_SIZE (decl_elt), MODE_INT, 1);
+ SET_DECL_LLVM(decl_elt, x);
+ }
+}
+
/* Generate LLVM code for T, which is a DECL_STMT. */
static void genllvm_decl_stmt(llvm_function *F, tree t) {
@@ -2633,10 +2679,10 @@
if (!anon_aggr_type_p (TREE_TYPE (decl))) {
llvm_emit_local_var (F, decl);
} else {
- /* LLVM: See info about lhd_tree_inlining_anon_aggr_type_p */
- LLVM_TODO_TREE(t);
- expand_anon_union_decl (decl, NULL_TREE,
- DECL_ANON_UNION_ELEMS (decl));
+ /* This is an anonymous aggregate object on the stack: the elements of
+ * this declaration are actually automatic objects themselves.
+ */
+ llvm_expand_anon_union_decl(F, decl, DECL_ANON_UNION_ELEMS(decl));
}
} else if (TREE_STATIC (decl)) {
make_llvm_for_local_static(decl);
More information about the llvm-commits
mailing list