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

Reply via email to