Here are a pair of patches to add an attribute to automatically gcroot
things based on type. It currently works for pointers to structures
only because a) that's all I need, and b) I think that's all that
makes sense really. I could remove the restriction if someone can come
up with a good use case for other types. Note that we're also zeroing
out automatic variables as well so if we do a collection before
they're initialized we don't end up following garbage.
Tested on x86-darwin.
-eric
Index: gcc/tree.h
===================================================================
--- gcc/tree.h (revision 42184)
+++ gcc/tree.h (working copy)
@@ -1704,6 +1704,8 @@ struct tree_block GTY(())
/* Indicated that objects of this type should be laid out in as
compact a way as possible. */
#define TYPE_PACKED(NODE) (TYPE_CHECK (NODE)->type.packed_flag)
+/* APPLE LOCAL LLVM */
+#define TYPE_GCROOT(NODE) (TYPE_CHECK (NODE)->type.gcroot_flag)
/* Used by type_contains_placeholder_p to avoid recomputation.
Values are: 0 (unknown), 1 (false), 2 (true). Never access
@@ -1732,6 +1734,8 @@ struct tree_type GTY(())
unsigned packed_flag : 1;
unsigned restrict_flag : 1;
unsigned contains_placeholder_bits : 2;
+ /* APPLE LOCAL LLVM */
+ unsigned gcroot_flag : 1;
unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1;
Index: gcc/llvm-convert.cpp
===================================================================
--- gcc/llvm-convert.cpp (revision 42184)
+++ gcc/llvm-convert.cpp (working copy)
@@ -655,6 +655,11 @@ void TreeToLLVM::StartFunctionBody() {
// Emit annotate intrinsic if arg has annotate attr
if (DECL_ATTRIBUTES(Args))
EmitAnnotateIntrinsic(Tmp, Args);
+
+ // Emit gcroot intrinsic if arg has attribute
+ if (POINTER_TYPE_P(TREE_TYPE(Args))
+ && TYPE_GCROOT(TREE_TYPE(Args)))
+ EmitTypeGcroot(Tmp, Args);
Client.setName(Name);
Client.setLocation(Tmp);
@@ -1420,6 +1425,25 @@ void TreeToLLVM::AddBranchFixup(BranchIn
BranchFixups.push_back(BranchFixup(BI, isExceptionEdge));
}
+// Emits code to do something for a type attribute
+void TreeToLLVM::EmitTypeGcroot(Value *V, tree decl) {
+
+ Function *gcrootFun = Intrinsic::getDeclaration(TheModule,
+ Intrinsic::gcroot);
+
+ // The idea is that it's a pointer to type "Value"
+ // which is opaque* but the routine expects i8** and i8*.
+ const PointerType *Ty = PointerType::get(Type::Int8Ty);
+ V = Builder.CreateBitCast(V, PointerType::get(Ty), "tmp");
+
+ Value *Ops[2] = {
+ V,
+ ConstantPointerNull::get(Ty)
+ };
+
+ Builder.CreateCall(gcrootFun, Ops, Ops+2);
+}
+
// Emits annotate intrinsic if the decl has the annotate attribute set.
void TreeToLLVM::EmitAnnotateIntrinsic(Value *V, tree decl) {
@@ -1581,6 +1605,17 @@ void TreeToLLVM::EmitAutomaticVariableDe
// Handle annotate attributes
if (DECL_ATTRIBUTES(decl))
EmitAnnotateIntrinsic(AI, decl);
+
+ // Handle gcroot attribute
+ if (POINTER_TYPE_P(TREE_TYPE (decl))
+ && TYPE_GCROOT(TREE_TYPE (decl)))
+ {
+ // We should null out local variables so that a stack crawl
+ // before initialization doesn't get garbage results to follow.
+ const Type *T = cast<PointerType>(AI->getType())->getElementType();
+ EmitTypeGcroot(AI, decl);
+ Builder.CreateStore(Constant::getNullValue(T), AI);
+ }
if (TheDebugInfo) {
if (DECL_NAME(decl)) {
Index: gcc/llvm-internal.h
===================================================================
--- gcc/llvm-internal.h (revision 42184)
+++ gcc/llvm-internal.h (working copy)
@@ -472,7 +472,9 @@ private:
/// EmitAnnotateIntrinsic - Emits call to annotate attr intrinsic
void EmitAnnotateIntrinsic(Value *V, tree_node *decl);
-
+
+ /// EmitTypeGcroot - Emits call to make type a gcroot
+ void EmitTypeGcroot(Value *V, tree_node *decl);
private:
/// GatherTypeInfo - Walk through the expression gathering all the
/// typeinfos that are used.
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c (revision 42184)
+++ gcc/c-common.c (working copy)
@@ -663,6 +663,7 @@ static tree handle_sentinel_attribute (t
/* APPLE LOCAL begin LLVM */
#ifdef ENABLE_LLVM
static tree handle_annotate_attribute (tree*, tree, tree, int, bool *);
+static tree handle_gcroot_attribute (tree *, tree, tree, int, bool *);
#endif
/* APPLE LOCAL end LLVM */
@@ -757,6 +758,8 @@ const struct attribute_spec c_common_att
#ifdef ENABLE_LLVM
{ "annotate", 0, -1, true, false, false,
handle_annotate_attribute },
+ { "gcroot", 0, 0, false, true, false,
+ handle_gcroot_attribute },
#endif
/* APPLE LOCAL end LLVM */
{ NULL, 0, 0, false, false, false, NULL }
@@ -5812,6 +5815,27 @@ handle_annotate_attribute (tree *node, t
return NULL_TREE;
}
+
+/* Handle the "gcroot" attribute */
+static tree
+handle_gcroot_attribute (tree *node, tree name, tree ARG_UNUSED(args),
+ int ARG_UNUSED(flags), bool *ARG_UNUSED(no_add_attrs))
+{
+ if (TYPE_P (*node))
+ {
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_variant_type_copy (*node);
+
+ TYPE_GCROOT (*node) = 1;
+ }
+ else
+ {
+ warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
#endif
/* APPLE LOCAL end LLVM */
Index: test/CFrontend/2007-09-20-GcrootAttribute.c
===================================================================
--- test/CFrontend/2007-09-20-GcrootAttribute.c (revision 0)
+++ test/CFrontend/2007-09-20-GcrootAttribute.c (revision 0)
@@ -0,0 +1,28 @@
+// RUN: %llvmgxx -c -emit-llvm %s -o - | llvm-dis | grep llvm.gcroot
+// RUN: %llvmgxx -c -emit-llvm %s -o - | llvm-dis | grep llvm.gcroot | count 6
+
+typedef struct foo_s
+{
+ int a;
+} foo, __attribute__ ((gcroot)) *foo_p;
+
+foo my_foo;
+
+int alpha ()
+{
+ foo my_foo2 = my_foo;
+
+ return my_foo2.a;
+}
+
+int bar (foo a)
+{
+ foo_p b;
+ return b->a;
+}
+
+foo_p baz (foo_p a, foo_p b, foo_p *c)
+{
+ a = b = *c;
+ return a;
+}
_______________________________________________
llvm-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits