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)) + && lookup_attribute ("gcroot", TYPE_ATTRIBUTES(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)) + && lookup_attribute("gcroot", TYPE_ATTRIBUTES(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(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,21 @@ 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) + || !POINTER_TYPE_P (*node)) + { + warning ("%qs attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} #endif /* APPLE LOCAL end LLVM */