Index: tools/llc/llc.cpp
===================================================================
--- tools/llc/llc.cpp	(revision 41695)
+++ tools/llc/llc.cpp	(working copy)
@@ -15,6 +15,8 @@
 
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/CodeGen/FileWriters.h"
+#include "llvm/CodeGen/Collector.h"
+#include "llvm/CodeGen/Collectors.h"
 #include "llvm/CodeGen/LinkAllCodegenComponents.h"
 #include "llvm/Target/SubtargetFeature.h"
 #include "llvm/Target/TargetData.h"
@@ -72,6 +74,9 @@
   cl::desc("Target specific attributes (-mattr=help for details)"),
   cl::value_desc("a1,+a2,-a3,..."));
 
+static cl::opt<const CollectorRegistry::entry*,false,CollectorRegistry::Parser>
+GCOpt("gc", cl::desc("Enable garbage collection."));
+
 cl::opt<TargetMachine::CodeGenFileType>
 FileType("filetype", cl::init(TargetMachine::AssemblyFile),
   cl::desc("Choose a file type (not all types are supported by all targets):"),
@@ -221,6 +226,14 @@
   assert(target.get() && "Could not allocate target machine!");
   TargetMachine &Target = *target.get();
 
+  if (GCOpt)
+    TheCollector = GCOpt->instantiate();
+  
+  // FIXME: Detect collector/target compatibility instead of silently doing the
+  //        wrong thing.
+  //   - ocaml supports most standard code generator.
+  //   - shadow-stack should support that plus CBackend.
+  
   // Figure out where we are going to send the output...
   std::ostream *Out = GetOutputStream(argv[0]);
   if (Out == 0) return 1;

Index: include/llvm/CodeGen/AsmPrinter.h
===================================================================
--- include/llvm/CodeGen/AsmPrinter.h	(revision 41695)
+++ include/llvm/CodeGen/AsmPrinter.h	(working copy)
@@ -113,6 +113,10 @@
     virtual void EmitExternalGlobal(const GlobalVariable *GV);
 
   protected:
+    /// getAnalysisUsage - Record analysis usage.
+    /// 
+    void getAnalysisUsage(AnalysisUsage &AU) const;
+    
     /// doInitialization - Set up the AsmPrinter when we are working on a new
     /// module.  If your pass overrides this, it must make sure to explicitly
     /// call this implementation.
Index: include/llvm/CodeGen/LinkAllCodegenComponents.h
===================================================================
--- include/llvm/CodeGen/LinkAllCodegenComponents.h	(revision 41695)
+++ include/llvm/CodeGen/LinkAllCodegenComponents.h	(working copy)
@@ -17,6 +17,7 @@
 
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/CodeGen/Collectors.h"
 
 namespace {
   struct ForceCodegenLinking {
@@ -33,6 +34,9 @@
       (void) llvm::createBigBlockRegisterAllocator();
       (void) llvm::createLinearScanRegisterAllocator();
       
+      (void) llvm::createOcamlCollector();
+      (void) llvm::createShadowStackCollector();
+      
       (void) llvm::createBFS_DAGScheduler(NULL, NULL, NULL);
       (void) llvm::createSimpleDAGScheduler(NULL, NULL, NULL);
       (void) llvm::createNoItinsDAGScheduler(NULL, NULL, NULL);
Index: include/llvm/CodeGen/SelectionDAGISel.h
===================================================================
--- include/llvm/CodeGen/SelectionDAGISel.h	(revision 41695)
+++ include/llvm/CodeGen/SelectionDAGISel.h	(working copy)
@@ -30,6 +30,7 @@
   class TargetLowering;
   class FunctionLoweringInfo;
   class HazardRecognizer;
+  class CollectorMetadata;
  
 /// SelectionDAGISel - This is the common base class used for SelectionDAG-based
 /// pattern-matching instruction selectors.
@@ -42,10 +43,11 @@
   AliasAnalysis *AA;
   std::vector<SDNode*> TopOrder;
   unsigned DAGSize;
+  CollectorMetadata *GCI;
   static char ID;
 
   explicit SelectionDAGISel(TargetLowering &tli) : 
-    FunctionPass((intptr_t)&ID), TLI(tli), DAGSize(0) {}
+    FunctionPass((intptr_t)&ID), TLI(tli), DAGSize(0), GCI(0) {}
   
   TargetLowering &getTargetLowering() { return TLI; }
 
Index: lib/CodeGen/AsmPrinter.cpp
===================================================================
--- lib/CodeGen/AsmPrinter.cpp	(revision 41695)
+++ lib/CodeGen/AsmPrinter.cpp	(working copy)
@@ -16,6 +16,8 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
 #include "llvm/Module.h"
+#include "llvm/CodeGen/Collector.h"
+#include "llvm/CodeGen/CollectorMetadata.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/Support/CommandLine.h"
@@ -92,9 +94,18 @@
 }
 
 
+void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
+  MachineFunctionPass::getAnalysisUsage(AU);
+  if (TheCollector)
+    AU.addRequired<CollectorModuleMetadata>();
+}
+
 bool AsmPrinter::doInitialization(Module &M) {
   Mang = new Mangler(M, TAI->getGlobalPrefix());
   
+  if (TheCollector)
+    TheCollector->beginAssembly(M, O, *this, *TAI);
+  
   if (!M.getModuleInlineAsm().empty())
     O << TAI->getCommentString() << " Start of file scope inline assembly\n"
       << M.getModuleInlineAsm()
@@ -149,6 +160,10 @@
     }
   }
 
+  if (TheCollector)
+    TheCollector->finishAssembly(M, getAnalysis<CollectorModuleMetadata>(),
+                                 O, *this, *TAI);
+
   delete Mang; Mang = 0;
   return false;
 }
Index: lib/CodeGen/LLVMTargetMachine.cpp
===================================================================
--- lib/CodeGen/LLVMTargetMachine.cpp	(revision 41695)
+++ lib/CodeGen/LLVMTargetMachine.cpp	(working copy)
@@ -17,6 +17,7 @@
 #include "llvm/Assembly/PrintModulePass.h"
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/Collector.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Support/CommandLine.h"
@@ -28,6 +29,8 @@
     cl::desc("Print LLVM IR input to isel pass"));
 static cl::opt<bool> PrintEmittedAsm("print-emitted-asm", cl::Hidden,
     cl::desc("Dump emitter generated instructions as assembly"));
+static cl::opt<bool> PrintGCInfo("print-gc", cl::Hidden,
+    cl::desc("Dump garbage collector data"));
 
 FileModel::Model
 LLVMTargetMachine::addPassesToEmitFile(FunctionPassManager &PM,
@@ -43,8 +46,8 @@
       PM.add(new PrintFunctionPass("\n\n*** Code after LSR *** \n", &cerr));
   }
   
-  // FIXME: Implement efficient support for garbage collection intrinsics.
-  PM.add(createLowerGCPass());
+  if (TheCollector)
+    TheCollector->addLoweringPasses(PM);
 
   if (!ExceptionHandling)
     PM.add(createLowerInvokePass(getTargetLowering()));
@@ -93,6 +96,15 @@
   if (!Fast)
     PM.add(createBranchFoldingPass(getEnableTailMergeDefault()));
     
+  if (TheCollector) {
+    TheCollector->addGenericMachineCodePass(PM, *this, Fast);
+    if (PrintMachineCode)
+      PM.add(createMachineFunctionPrinterPass(cerr));
+  }
+  
+  if (PrintGCInfo)
+    PM.add(createCollectorMetadataPrinter(*cerr));
+  
   // Fold redundant debug labels.
   PM.add(createDebugLabelFoldingPass());
   
@@ -127,6 +139,9 @@
                                                   bool Fast) {
   if (MCE)
     addSimpleCodeEmitter(PM, Fast, PrintEmittedAsm, *MCE);
+    
+  if (TheCollector)
+    PM.add(createCollectorMetadataDeleter());
 
   // Delete machine code for this function
   PM.add(createMachineCodeDeleter());
@@ -152,8 +167,8 @@
       PM.add(new PrintFunctionPass("\n\n*** Code after LSR *** \n", &cerr));
   }
   
-  // FIXME: Implement efficient support for garbage collection intrinsics.
-  PM.add(createLowerGCPass());
+  if (TheCollector)
+    TheCollector->addLoweringPasses(PM);
   
   // FIXME: Implement the invoke/unwind instructions!
   PM.add(createLowerInvokePass(getTargetLowering()));
@@ -205,6 +220,15 @@
   if (!Fast)
     PM.add(createBranchFoldingPass(getEnableTailMergeDefault()));
   
+  if (TheCollector) {
+    TheCollector->addGenericMachineCodePass(PM, *this, Fast);
+    if (PrintMachineCode)
+      PM.add(createMachineFunctionPrinterPass(cerr));
+  }
+  
+  if (PrintGCInfo)
+    PM.add(createCollectorMetadataPrinter(*cerr));
+  
   if (addPreEmitPass(PM, Fast) && PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
 
Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	(revision 41695)
+++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	(working copy)
@@ -26,6 +26,7 @@
 #include "llvm/Intrinsics.h"
 #include "llvm/IntrinsicInst.h"
 #include "llvm/ParameterAttributes.h"
+#include "llvm/CodeGen/Collector.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -425,12 +426,16 @@
   /// FuncInfo - Information about the function as a whole.
   ///
   FunctionLoweringInfo &FuncInfo;
+  
+  /// GCI - Garbage collection metadata for the function.
+  CollectorMetadata *GCI;
 
   SelectionDAGLowering(SelectionDAG &dag, TargetLowering &tli,
                        AliasAnalysis &aa,
-                       FunctionLoweringInfo &funcinfo)
+                       FunctionLoweringInfo &funcinfo,
+                       CollectorMetadata *gci)
     : TLI(tli), DAG(dag), TD(DAG.getTarget().getTargetData()), AA(aa),
-      FuncInfo(funcinfo) {
+      FuncInfo(funcinfo), GCI(gci) {
   }
 
   /// getRoot - Return the current virtual root of the Selection DAG.
@@ -2894,7 +2899,28 @@
     DAG.setRoot(DAG.getNode(ISD::TRAMPOLINE, MVT::Other, Ops, 6));
     return 0;
   }
+  
+  case Intrinsic::gcroot: {
+    if (GCI) {
+      Value *Alloca = I.getOperand(1);
+      Constant *TypeMap = cast<Constant>(I.getOperand(2));
+      
+      FrameIndexSDNode *FI = cast<FrameIndexSDNode>(getValue(Alloca).Val);
+      GCI->addStackRoot(FI->getIndex(), TypeMap);
+    }
+    return 0;
   }
+  
+  case Intrinsic::gcread:
+  case Intrinsic::gcwrite: {
+    assert(!TheCollector &&
+           "Collector failed to lower gcread/gcwrite intrinsics!");
+    cerr << "This code uses garbage collection; it must be compiled using "
+            "the -gc option.\n";
+    abort();
+    return 0;
+  }
+  }
 }
 
 
@@ -4317,6 +4343,8 @@
 
 void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequired<AliasAnalysis>();
+  if (TheCollector)
+    AU.addRequired<CollectorModuleMetadata>();
   AU.setPreservesAll();
 }
 
@@ -4327,6 +4355,10 @@
   AA = &getAnalysis<AliasAnalysis>();
 
   MachineFunction &MF = MachineFunction::construct(&Fn, TLI.getTargetMachine());
+  if (TheCollector)
+    GCI = &getAnalysis<CollectorModuleMetadata>().insert(MF.getFunction());
+  else
+    GCI = 0;
   RegMap = MF.getSSARegMap();
   DOUT << "\n\n\n=== " << Fn.getName() << "\n";
 
@@ -4422,8 +4454,8 @@
 
 void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
        std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
-                                         FunctionLoweringInfo &FuncInfo) {
-  SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo);
+       FunctionLoweringInfo &FuncInfo) {
+  SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo, GCI);
 
   std::vector<SDOperand> UnorderedChains;
 
@@ -4665,7 +4697,7 @@
     if (!BitTestCases[i].Emitted) {
       SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
       CurDAG = &HSDAG;
-      SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo);
+      SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI);
       // Set the current basic block to the mbb we wish to insert the code into
       BB = BitTestCases[i].Parent;
       HSDL.setCurrentBasicBlock(BB);
@@ -4678,7 +4710,7 @@
     for (unsigned j = 0, ej = BitTestCases[i].Cases.size(); j != ej; ++j) {
       SelectionDAG BSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
       CurDAG = &BSDAG;
-      SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo);
+      SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo, GCI);
       // Set the current basic block to the mbb we wish to insert the code into
       BB = BitTestCases[i].Cases[j].ThisBB;
       BSDL.setCurrentBasicBlock(BB);
@@ -4731,7 +4763,7 @@
     if (!JTCases[i].first.Emitted) {
       SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
       CurDAG = &HSDAG;
-      SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo);
+      SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI);
       // Set the current basic block to the mbb we wish to insert the code into
       BB = JTCases[i].first.HeaderBB;
       HSDL.setCurrentBasicBlock(BB);
@@ -4743,7 +4775,7 @@
     
     SelectionDAG JSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
     CurDAG = &JSDAG;
-    SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo);
+    SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo, GCI);
     // Set the current basic block to the mbb we wish to insert the code into
     BB = JTCases[i].second.MBB;
     JSDL.setCurrentBasicBlock(BB);
@@ -4788,7 +4820,7 @@
   for (unsigned i = 0, e = SwitchCases.size(); i != e; ++i) {
     SelectionDAG SDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
     CurDAG = &SDAG;
-    SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo);
+    SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo, GCI);
     
     // Set the current basic block to the mbb we wish to insert the code into
     BB = SwitchCases[i].ThisBB;
Index: lib/Target/ARM/ARMAsmPrinter.cpp
===================================================================
--- lib/Target/ARM/ARMAsmPrinter.cpp	(revision 41695)
+++ lib/Target/ARM/ARMAsmPrinter.cpp	(working copy)
@@ -152,6 +152,7 @@
     }
     
     void getAnalysisUsage(AnalysisUsage &AU) const {
+      AsmPrinter::getAnalysisUsage(AU);
       AU.setPreservesAll();
       AU.addRequired<MachineModuleInfo>();
     }
Index: lib/Target/X86/X86AsmPrinter.h
===================================================================
--- lib/Target/X86/X86AsmPrinter.h	(revision 41695)
+++ lib/Target/X86/X86AsmPrinter.h	(working copy)
@@ -63,7 +63,7 @@
         Subtarget->isTargetCygMing()) {
       AU.addRequired<MachineModuleInfo>();
     }
-    MachineFunctionPass::getAnalysisUsage(AU);
+    AsmPrinter::getAnalysisUsage(AU);
   }
 
   const X86Subtarget *Subtarget;
Index: lib/Target/CBackend/CBackend.cpp
===================================================================
--- lib/Target/CBackend/CBackend.cpp	(revision 41695)
+++ lib/Target/CBackend/CBackend.cpp	(working copy)
@@ -28,6 +28,7 @@
 #include "llvm/Analysis/ConstantsScanner.h"
 #include "llvm/Analysis/FindUsedTypes.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/Collector.h"
 #include "llvm/CodeGen/IntrinsicLowering.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Target/TargetMachineRegistry.h"
@@ -2920,7 +2921,8 @@
                                               bool Fast) {
   if (FileType != TargetMachine::AssemblyFile) return true;
 
-  PM.add(createLowerGCPass());
+  if (TheCollector)
+    TheCollector->addLoweringPasses(PM);
   PM.add(createLowerAllocationsPass(true));
   PM.add(createLowerInvokePass());
   PM.add(createCFGSimplificationPass());   // clean up after lower invoke.
Index: lib/Target/MSIL/MSILWriter.cpp
===================================================================
--- lib/Target/MSIL/MSILWriter.cpp	(revision 41695)
+++ lib/Target/MSIL/MSILWriter.cpp	(working copy)
@@ -24,6 +24,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/CodeGen/Collector.h"
 
 namespace {
   // TargetMachine for the MSIL 
@@ -1646,7 +1647,8 @@
 {
   if (FileType != TargetMachine::AssemblyFile) return true;
   MSILWriter* Writer = new MSILWriter(o);
-  PM.add(createLowerGCPass());
+  if (TheCollector)
+    TheCollector->addLoweringPasses(PM);
   PM.add(createLowerAllocationsPass(true));
   // FIXME: Handle switch trougth native IL instruction "switch"
   PM.add(createLowerSwitchPass());

