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(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 */