diff --git a/llvm-general.cabal b/llvm-general.cabal
--- a/llvm-general.cabal
+++ b/llvm-general.cabal
@@ -1,5 +1,5 @@
 name: llvm-general
-version: 3.2.5.0
+version: 3.2.6.0
 license: BSD3
 license-file: LICENSE
 author: Benjamin S.Scarlet <fgthb0@greynode.net>
@@ -16,7 +16,7 @@
 	handles almost all of the stateful complexities of using the LLVM API to build IR; and it supports moving IR not
 	only from Haskell into LLVM C++ objects, but the other direction - from LLVM C++ into Haskell.
   .
-  For haddock, see <http://bscarlet.github.io/llvm-general/3.2.5.0/doc/html/llvm-general/index.html>.
+  For haddock, see <http://bscarlet.github.io/llvm-general/3.2.6.0/doc/html/llvm-general/index.html>.
 extra-source-files:
   src/LLVM/General/Internal/FFI/Analysis.h
   src/LLVM/General/Internal/FFI/Function.h
@@ -37,7 +37,7 @@
   type: git
   location: git://github.com/bscarlet/llvm-general.git
   branch: llvm-3.2
-  tag: v3.2.5.0
+  tag: v3.2.6.0
 
 flag shared-llvm
   description: link against llvm shared rather than static library
@@ -151,6 +151,7 @@
     LLVM.General.Internal.FFI.CommandLine
     LLVM.General.Internal.FFI.Constant
     LLVM.General.Internal.FFI.Context
+    LLVM.General.Internal.FFI.DataLayout
     LLVM.General.Internal.FFI.ExecutionEngine
     LLVM.General.Internal.FFI.Function
     LLVM.General.Internal.FFI.GlobalAlias
diff --git a/src/LLVM/General/AST.hs b/src/LLVM/General/AST.hs
--- a/src/LLVM/General/AST.hs
+++ b/src/LLVM/General/AST.hs
@@ -27,7 +27,7 @@
 data Definition 
   = GlobalDefinition Global
   | TypeDefinition Name (Maybe Type)
-  | MetadataNodeDefinition MetadataNodeID [Operand]
+  | MetadataNodeDefinition MetadataNodeID [Maybe Operand]
   | NamedMetadataDefinition String [MetadataNodeID]
   | ModuleInlineAssembly String
     deriving (Eq, Read, Show)
diff --git a/src/LLVM/General/AST/Operand.hs b/src/LLVM/General/AST/Operand.hs
--- a/src/LLVM/General/AST/Operand.hs
+++ b/src/LLVM/General/AST/Operand.hs
@@ -15,7 +15,7 @@
 
 -- | <http://llvm.org/docs/LangRef.html#metadata>
 data MetadataNode 
-  = MetadataNode [Operand]
+  = MetadataNode [Maybe Operand]
   | MetadataNodeReference MetadataNodeID
   deriving (Eq, Ord, Read, Show)
 
diff --git a/src/LLVM/General/Internal/Atomicity.hs b/src/LLVM/General/Internal/Atomicity.hs
--- a/src/LLVM/General/Internal/Atomicity.hs
+++ b/src/LLVM/General/Internal/Atomicity.hs
@@ -14,7 +14,7 @@
 
 import qualified LLVM.General.AST as A
 
-genCodingInstance' [t| Maybe A.MemoryOrdering |] ''FFI.MemoryOrdering [
+genCodingInstance [t| Maybe A.MemoryOrdering |] ''FFI.MemoryOrdering [
   (FFI.memoryOrderingNotAtomic, Nothing),
   (FFI.memoryOrderingUnordered, Just A.Unordered),
   (FFI.memoryOrderingMonotonic, Just A.Monotonic),
diff --git a/src/LLVM/General/Internal/Coding.hs b/src/LLVM/General/Internal/Coding.hs
--- a/src/LLVM/General/Internal/Coding.hs
+++ b/src/LLVM/General/Internal/Coding.hs
@@ -9,6 +9,7 @@
 import Language.Haskell.TH
 import Language.Haskell.TH.Quote
 
+import Control.Monad
 import Control.Monad.AnyCont
 import Control.Monad.IO.Class
 
@@ -30,24 +31,8 @@
 class DecodeM d h c where
   decodeM :: c -> d h
 
-genCodingInstance :: Data h => TypeQ -> Name -> [(Integer, h)] -> Q [Dec]
-genCodingInstance ht ctn ihs = do
-  let n = const Nothing
-  TyConI (NewtypeD _ _ _ (NormalC ctcn _) _) <- reify ctn
-  [d| 
-    instance Monad m => EncodeM m $(ht) $(conT ctn) where
-      encodeM h = return $ $(
-        caseE [| h |] [ match (dataToPatQ n h) (normalB (appE (conE ctcn) (litE (integerL i)))) [] | (i,h) <- ihs ] 
-       )
-
-    instance Monad m => DecodeM m $(ht) $(conT ctn) where
-      decodeM i = return $ $(
-        caseE [| i |] [ match (conP ctcn [litP (integerL i)]) (normalB (dataToExpQ n h)) [] | (i,h) <- ihs ]
-       )
-   |]
-
-genCodingInstance' :: (Data c, Data h) => TypeQ -> Name -> [(c, h)] -> Q [Dec]
-genCodingInstance' ht ctn chs = do
+genCodingInstance :: (Data c, Data h) => TypeQ -> Name -> [(c, h)] -> Q [Dec]
+genCodingInstance ht ctn chs = do
   let n = const Nothing
   [d| 
     instance Monad m => EncodeM m $(ht) $(conT ctn) where
@@ -99,6 +84,19 @@
 instance Monad m => DecodeM m Bool FFI.LLVMBool where
   decodeM (FFI.LLVMBool 0) = return $ False
   decodeM (FFI.LLVMBool 1) = return $ True
+
+instance (Monad m, EncodeM m h (Ptr c)) => EncodeM m (Maybe h) (Ptr c) where
+  encodeM = maybe (return nullPtr) encodeM
+
+instance (Monad m, DecodeM m h (Ptr c)) => DecodeM m (Maybe h) (Ptr c) where
+  decodeM p | p == nullPtr = return Nothing
+            | otherwise = liftM Just $ decodeM p
+
+instance Monad m => EncodeM m (Maybe Bool) (FFI.NothingAsMinusOne Bool) where
+  encodeM = return . FFI.NothingAsMinusOne . maybe (-1) (fromIntegral . fromEnum)
+
+instance Monad m => EncodeM m (Maybe Word) (FFI.NothingAsMinusOne Word) where
+  encodeM = return . FFI.NothingAsMinusOne . maybe (-1) fromIntegral
 
 instance Monad m => EncodeM m Word CUInt where
   encodeM = return . fromIntegral
diff --git a/src/LLVM/General/Internal/DataLayout.hs b/src/LLVM/General/Internal/DataLayout.hs
--- a/src/LLVM/General/Internal/DataLayout.hs
+++ b/src/LLVM/General/Internal/DataLayout.hs
@@ -2,15 +2,31 @@
 
 import Text.ParserCombinators.Parsec
 
+import Control.Monad.Error
+import Control.Monad.AnyCont
+import Control.Exception
+
 import Data.Word
 import Data.Functor
 
+import Foreign.Ptr
+
 import qualified Data.List as List
 import qualified Data.Map as Map
 import qualified Data.Set as Set
 
+import qualified LLVM.General.Internal.FFI.DataLayout as FFI
+
 import LLVM.General.AST.DataLayout
 import LLVM.General.AST.AddrSpace
+
+import LLVM.General.Internal.Coding
+import LLVM.General.Internal.String ()
+
+withFFIDataLayout :: DataLayout -> (Ptr FFI.DataLayout -> IO a) -> IO a
+withFFIDataLayout dl f = flip runAnyContT return $ do
+  dls <- encodeM (dataLayoutToString dl)
+  liftIO $ bracket (FFI.createDataLayout dls) FFI.disposeDataLayout f
 
 dataLayoutToString :: DataLayout -> String
 dataLayoutToString dl = 
diff --git a/src/LLVM/General/Internal/Diagnostic.hs b/src/LLVM/General/Internal/Diagnostic.hs
--- a/src/LLVM/General/Internal/Diagnostic.hs
+++ b/src/LLVM/General/Internal/Diagnostic.hs
@@ -15,7 +15,7 @@
 import LLVM.General.Internal.Coding
 import LLVM.General.Internal.String ()
 
-genCodingInstance' [t| DiagnosticKind |] ''FFI.DiagnosticKind [
+genCodingInstance [t| DiagnosticKind |] ''FFI.DiagnosticKind [
     (FFI.diagnosticKindError, ErrorKind),
     (FFI.diagnosticKindWarning, WarningKind),
     (FFI.diagnosticKindNote, NoteKind)
diff --git a/src/LLVM/General/Internal/FFI/Cleanup.hs b/src/LLVM/General/Internal/FFI/Cleanup.hs
--- a/src/LLVM/General/Internal/FFI/Cleanup.hs
+++ b/src/LLVM/General/Internal/FFI/Cleanup.hs
@@ -81,3 +81,4 @@
          | h == ''A.FloatingPointPredicate -> [t| FCmpPredicate |]
          | h == ''A.IntegerPredicate -> [t| ICmpPredicate |]
   AppT ListT x -> foldl1 appT [tupleT 2, [t| CUInt |], appT [t| Ptr |] (typeMapping x)]
+  x -> error $ "type not handled in Cleanup typeMapping: " ++ show x
diff --git a/src/LLVM/General/Internal/FFI/DataLayout.hs b/src/LLVM/General/Internal/FFI/DataLayout.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/General/Internal/FFI/DataLayout.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE
+  ForeignFunctionInterface
+  #-}
+
+module LLVM.General.Internal.FFI.DataLayout where
+
+import Foreign.C.String
+import Foreign.Ptr
+
+import LLVM.General.Internal.FFI.LLVMCTypes
+
+data DataLayout
+
+-- Oooh those wacky LLVM C-API coders: C API called DataLayout TargetData.
+-- Great. Just great.
+
+foreign import ccall unsafe "LLVMCreateTargetData" createDataLayout :: 
+  CString -> IO (Ptr DataLayout)
+
+foreign import ccall unsafe "LLVMDisposeTargetData" disposeDataLayout :: 
+  Ptr DataLayout -> IO ()
+
+foreign import ccall unsafe "LLVMCopyStringRepOfTargetData" dataLayoutToString ::
+  Ptr DataLayout -> IO MallocedCString
diff --git a/src/LLVM/General/Internal/FFI/LLVMCTypes.hsc b/src/LLVM/General/Internal/FFI/LLVMCTypes.hsc
--- a/src/LLVM/General/Internal/FFI/LLVMCTypes.hsc
+++ b/src/LLVM/General/Internal/FFI/LLVMCTypes.hsc
@@ -56,6 +56,12 @@
 newtype MallocedCString = MallocedCString CString
   deriving (Storable)
 
+newtype NothingAsMinusOne h = NothingAsMinusOne CInt
+  deriving (Storable)
+
+newtype NothingAsEmptyString c = NothingAsEmptyString c
+  deriving (Storable)
+
 newtype CPPOpcode = CPPOpcode CUInt
   deriving (Eq, Ord, Show, Typeable, Data)
 
diff --git a/src/LLVM/General/Internal/FFI/PassManager.hs b/src/LLVM/General/Internal/FFI/PassManager.hs
--- a/src/LLVM/General/Internal/FFI/PassManager.hs
+++ b/src/LLVM/General/Internal/FFI/PassManager.hs
@@ -9,7 +9,7 @@
 
 import Control.Monad
 
-import Data.Word (Word)
+import Data.Word
 
 import Foreign.Ptr
 import Foreign.C
@@ -19,6 +19,7 @@
 import LLVM.General.Internal.FFI.Cleanup
 import LLVM.General.Internal.FFI.Module
 import LLVM.General.Internal.FFI.Target
+import LLVM.General.Internal.FFI.DataLayout
 import LLVM.General.Internal.FFI.Transforms
 
 import qualified LLVM.General.Transforms as G
@@ -26,29 +27,36 @@
 data PassManager
 
 foreign import ccall unsafe "LLVMCreatePassManager" createPassManager ::
-    IO (Ptr PassManager)
+  IO (Ptr PassManager)
 
 foreign import ccall unsafe "LLVMDisposePassManager" disposePassManager ::
-    Ptr PassManager -> IO ()
+  Ptr PassManager -> IO ()
 
 foreign import ccall unsafe "LLVMRunPassManager" runPassManager ::
-    Ptr PassManager -> Ptr Module -> IO CUInt
+  Ptr PassManager -> Ptr Module -> IO CUInt
 
 foreign import ccall unsafe "LLVMCreateFunctionPassManagerForModule" createFunctionPassManagerForModule ::
-    Ptr Module -> IO (Ptr PassManager)
+  Ptr Module -> IO (Ptr PassManager)
 
 foreign import ccall unsafe "LLVMInitializeFunctionPassManager" initializeFunctionPassManager ::
-    Ptr PassManager -> IO CUInt
+  Ptr PassManager -> IO CUInt
 
 foreign import ccall unsafe "LLVMRunFunctionPassManager" runFunctionPassManager ::
-    Ptr PassManager -> Ptr Value -> IO CUInt
+  Ptr PassManager -> Ptr Value -> IO CUInt
 
 foreign import ccall unsafe "LLVMFinalizeFunctionPassManager" finalizeFunctionPassManager ::
-    Ptr PassManager -> IO CUInt
+  Ptr PassManager -> IO CUInt
 
-newtype LLVMEncoded i a = LLVMEncoded i
-  deriving (Eq, Ord, Read, Show)
+foreign import ccall unsafe "LLVMAddTargetData" addDataLayoutPass' ::
+  Ptr DataLayout -> Ptr PassManager -> IO ()
 
+addDataLayoutPass = flip addDataLayoutPass'
+
+foreign import ccall unsafe "LLVMAddTargetLibraryInfo" addTargetLibraryInfoPass' ::
+  Ptr TargetLibraryInfo -> Ptr PassManager -> IO ()
+
+addTargetLibraryInfoPass = flip addTargetLibraryInfoPass'
+
 $(do
   let declareForeign :: TH.Name -> [TH.Type] -> TH.DecsQ
       declareForeign hName extraParams = do
@@ -56,12 +64,14 @@
             passTypeMapping :: TH.Type -> TH.TypeQ
             passTypeMapping t = case t of
               TH.ConT h | h == ''Word -> [t| CUInt |]
+                        | h == ''G.GCOVVersion -> [t| LLVMBool |]
               -- some of the LLVM methods for making passes use "-1" as a special value
               -- handle those here
               TH.AppT (TH.ConT mby) t' | mby == ''Maybe ->
                 case t' of
-                  TH.ConT h | h == ''Bool -> [t| LLVMEncoded CInt (Maybe Bool) |]
-                            | h == ''Word -> [t| LLVMEncoded CInt (Maybe Word) |]
+                  TH.ConT h | h == ''Bool -> [t| NothingAsMinusOne Bool |]
+                            | h == ''Word -> [t| NothingAsMinusOne Word |]
+                            | h == ''FilePath -> [t| NothingAsEmptyString CString |]
                   _ -> typeMapping t
               _ -> typeMapping t
         foreignDecl 
@@ -94,13 +104,13 @@
     Ptr PassManagerBuilder -> CUInt -> IO ()
 
 foreign import ccall unsafe "LLVMPassManagerBuilderSetDisableUnitAtATime" passManagerBuilderSetDisableUnitAtATime ::
-    Ptr PassManagerBuilder -> CUInt -> IO () 
+    Ptr PassManagerBuilder -> LLVMBool -> IO () 
 
 foreign import ccall unsafe "LLVMPassManagerBuilderSetDisableUnrollLoops" passManagerBuilderSetDisableUnrollLoops ::
     Ptr PassManagerBuilder -> CUInt -> IO ()
 
 foreign import ccall unsafe "LLVMPassManagerBuilderSetDisableSimplifyLibCalls" passManagerBuilderSetDisableSimplifyLibCalls ::
-    Ptr PassManagerBuilder -> CUInt -> IO () 
+    Ptr PassManagerBuilder -> LLVMBool -> IO () 
 
 foreign import ccall unsafe "LLVMPassManagerBuilderUseInlinerWithThreshold" passManagerBuilderUseInlinerWithThreshold ::
     Ptr PassManagerBuilder -> CUInt -> IO ()
diff --git a/src/LLVM/General/Internal/FFI/PassManagerC.cpp b/src/LLVM/General/Internal/FFI/PassManagerC.cpp
--- a/src/LLVM/General/Internal/FFI/PassManagerC.cpp
+++ b/src/LLVM/General/Internal/FFI/PassManagerC.cpp
@@ -1,8 +1,10 @@
 #define __STDC_LIMIT_MACROS
 #include "llvm/LLVMContext.h"
+#include "llvm/DataLayout.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Vectorize.h"
+#include "llvm/Transforms/Instrumentation.h"
 #include "llvm/PassManager.h"
 
 #include "llvm-c/Core.h"
@@ -26,6 +28,10 @@
 
 extern "C" {
 
+void LLVM_General_AddDataLayoutPass(LLVMPassManagerRef PM, const char *dl) {
+	unwrap(PM)->add(new DataLayout(dl));
+}
+
 #define LLVM_GENERAL_FOR_EACH_PASS_WITHOUT_LLVM_C_BINDING(macro) \
 	macro(BlockPlacement)			\
 	macro(BreakCriticalEdges) \
@@ -125,6 +131,48 @@
 	vectorizeConfig.FastDep = fastDependencyAnalysis;	
 
 	unwrap(PM)->add(createBBVectorizePass(vectorizeConfig));
-}	
+}
+
+void LLVM_General_AddEdgeProfilerPass(LLVMPassManagerRef PM) {
+	unwrap(PM)->add(createEdgeProfilerPass());
+}
+
+void LLVM_General_AddOptimalEdgeProfilerPass(LLVMPassManagerRef PM) {
+	unwrap(PM)->add(createOptimalEdgeProfilerPass());
+}
+
+void LLVM_General_AddPathProfilerPass(LLVMPassManagerRef PM) {
+	unwrap(PM)->add(createPathProfilerPass());
+}
+
+void LLVM_General_AddGCOVProfilerPass(
+	LLVMPassManagerRef PM,
+	LLVMBool emitNotes,
+	LLVMBool emitData,
+	LLVMBool use402Format,
+	LLVMBool useCfgChecksum
+) {
+	unwrap(PM)->add(
+		createGCOVProfilerPass(
+			emitNotes,
+			emitData,
+			use402Format,
+			useCfgChecksum
+		)
+	);
+}
+
+void LLVM_General_AddAddressSanitizerFunctionPass(LLVMPassManagerRef PM) {
+	unwrap(PM)->add(createAddressSanitizerPass()
+	);
+}
+
+void LLVM_General_AddThreadSanitizerPass(LLVMPassManagerRef PM) {
+	unwrap(PM)->add(createThreadSanitizerPass());
+}
+
+void LLVM_General_AddBoundsCheckingPass(LLVMPassManagerRef PM) {
+	unwrap(PM)->add(createBoundsCheckingPass());
+}
 
 }
diff --git a/src/LLVM/General/Internal/FFI/Target.hs b/src/LLVM/General/Internal/FFI/Target.hs
--- a/src/LLVM/General/Internal/FFI/Target.hs
+++ b/src/LLVM/General/Internal/FFI/Target.hs
@@ -98,4 +98,12 @@
 foreign import ccall unsafe "LLVM_General_GetTargetMachineDataLayout" getTargetMachineDataLayout ::
   Ptr TargetMachine -> IO MallocedCString
 
+data TargetLibraryInfo
+
+foreign import ccall unsafe "LLVM_General_CreateTargetLibraryInfo" createTargetLibraryInfo ::
+  CString -> IO (Ptr TargetLibraryInfo)
+
+foreign import ccall unsafe "LLVM_General_DisposeTargetLibraryInfo" disposeTargetLibraryInfo ::
+  Ptr TargetLibraryInfo -> IO ()
+
 foreign import ccall unsafe "LLVM_General_InitializeAllTargets" initializeAllTargets :: IO ()
diff --git a/src/LLVM/General/Internal/FFI/TargetC.cpp b/src/LLVM/General/Internal/FFI/TargetC.cpp
--- a/src/LLVM/General/Internal/FFI/TargetC.cpp
+++ b/src/LLVM/General/Internal/FFI/TargetC.cpp
@@ -3,6 +3,7 @@
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetLibraryInfo.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/ExecutionEngine/Interpreter.h"
 #include "llvm/DataLayout.h"
@@ -14,6 +15,7 @@
 using namespace llvm;
 
 namespace llvm {
+
 static Reloc::Model unwrap(LLVMRelocMode x) {
 	switch(x) {
 #define ENUM_CASE(x,y) case LLVMReloc ## x: return Reloc::y;
@@ -224,6 +226,16 @@
 
 char *LLVM_General_GetTargetMachineDataLayout(LLVMTargetMachineRef t) {
 	return strdup(unwrap(t)->getDataLayout()->getStringRepresentation().c_str());
+}
+
+LLVMTargetLibraryInfoRef LLVM_General_CreateTargetLibraryInfo(
+	const char *triple
+) {
+	return wrap(new TargetLibraryInfo(Triple(triple)));
+}
+
+void LLVM_General_DisposeTargetLibraryInfo(LLVMTargetLibraryInfoRef l) {
+	delete unwrap(l);
 }
 
 void LLVM_General_InitializeAllTargets() {
diff --git a/src/LLVM/General/Internal/FFI/Transforms.hs b/src/LLVM/General/Internal/FFI/Transforms.hs
--- a/src/LLVM/General/Internal/FFI/Transforms.hs
+++ b/src/LLVM/General/Internal/FFI/Transforms.hs
@@ -14,6 +14,7 @@
 -- | as part of this Haskell package ("LLVM_General_" prefix).
 cName n = 
     let core = case n of
+            "AddressSanitizer" -> "AddressSanitizerFunction"
             "AggressiveDeadCodeElimination" -> "AggressiveDCE"
             "AlwaysInline" -> "AlwaysInliner"
             "DeadInstructionElimination" -> "DeadInstElimination"
@@ -35,6 +36,9 @@
             "SparseConditionalConstantPropagation" -> "SCCP"
             h -> h
         patchImpls = [
+         "AddressSanitizer",
+         "AddressSanitizerModule",
+         "BoundsChecking",
          "CodeGenPrepare",
          "GlobalValueNumbering",
          "InternalizeFunctions",
@@ -43,20 +47,28 @@
 	 "BreakCriticalEdges",
 	 "DeadCodeElimination",
 	 "DeadInstructionElimination",
+         "DebugExistingIR",
+         "DebugGeneratedIR",
 	 "DemoteRegisterToMemory",
+         "EdgeProfiler",
+         "GCOVProfiler",
 	 "LoopClosedSingleStaticAssignment",
 	 "LoopInstructionSimplify",
          "LoopStrengthReduce",
 	 "LowerAtomic",
 	 "LowerInvoke",
 	 "LowerSwitch",
+         "MemorySanitizer",
 	 "MergeFunctions",
+         "OptimalEdgeProfiler",
+         "PathProfiler",
 	 "PartialInlining",
          "ScalarReplacementOfAggregates",
 	 "Sinking",
 	 "StripDeadDebugInfo",
 	 "StripDebugDeclare",
-	 "StripNonDebugSymbols"
+	 "StripNonDebugSymbols",
+         "ThreadSanitizer"
          ]
     in
       (if (n `elem` patchImpls) then "LLVM_General_" else "LLVM") ++ "Add" ++ core ++ "Pass"
diff --git a/src/LLVM/General/Internal/FloatingPointPredicate.hs b/src/LLVM/General/Internal/FloatingPointPredicate.hs
--- a/src/LLVM/General/Internal/FloatingPointPredicate.hs
+++ b/src/LLVM/General/Internal/FloatingPointPredicate.hs
@@ -9,7 +9,7 @@
 import qualified LLVM.General.Internal.FFI.LLVMCTypes as FFI
 import qualified LLVM.General.AST.FloatingPointPredicate as A.FPPred
 
-genCodingInstance' [t| A.FPPred.FloatingPointPredicate |] ''FFI.FCmpPredicate [
+genCodingInstance [t| A.FPPred.FloatingPointPredicate |] ''FFI.FCmpPredicate [
   (FFI.fCmpPredFalse, A.FPPred.False),
   (FFI.fCmpPredOEQ, A.FPPred.OEQ),
   (FFI.fCmpPredOGT, A.FPPred.OGT),
diff --git a/src/LLVM/General/Internal/Global.hs b/src/LLVM/General/Internal/Global.hs
--- a/src/LLVM/General/Internal/Global.hs
+++ b/src/LLVM/General/Internal/Global.hs
@@ -22,7 +22,7 @@
 import qualified LLVM.General.AST.Linkage as A.L
 import qualified LLVM.General.AST.Visibility as A.V
 
-genCodingInstance' [t| A.L.Linkage |] ''FFI.Linkage [
+genCodingInstance [t| A.L.Linkage |] ''FFI.Linkage [
   (FFI.linkageExternal, A.L.External),
   (FFI.linkageAvailableExternally, A.L.AvailableExternally),
   (FFI.linkageLinkOnceAny, A.L.LinkOnce),
@@ -46,7 +46,7 @@
 setLinkage :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> A.L.Linkage -> EncodeAST ()
 setLinkage g l = liftIO . FFI.setLinkage (FFI.upCast g) =<< encodeM l
                                                                        
-genCodingInstance' [t| A.V.Visibility |] ''FFI.Visibility [
+genCodingInstance [t| A.V.Visibility |] ''FFI.Visibility [
   (FFI.visibilityDefault, A.V.Default),
   (FFI.visibilityHidden, A.V.Hidden),
   (FFI.visibilityProtected, A.V.Protected)
diff --git a/src/LLVM/General/Internal/InlineAssembly.hs b/src/LLVM/General/Internal/InlineAssembly.hs
--- a/src/LLVM/General/Internal/InlineAssembly.hs
+++ b/src/LLVM/General/Internal/InlineAssembly.hs
@@ -24,7 +24,7 @@
 import LLVM.General.Internal.DecodeAST
 import LLVM.General.Internal.Value
 
-genCodingInstance' [t| A.Dialect |] ''FFI.AsmDialect [
+genCodingInstance [t| A.Dialect |] ''FFI.AsmDialect [
    (FFI.asmDialectATT, A.ATTDialect),
    (FFI.asmDialectIntel, A.IntelDialect)
   ]
diff --git a/src/LLVM/General/Internal/IntegerPredicate.hs b/src/LLVM/General/Internal/IntegerPredicate.hs
--- a/src/LLVM/General/Internal/IntegerPredicate.hs
+++ b/src/LLVM/General/Internal/IntegerPredicate.hs
@@ -9,7 +9,7 @@
 import qualified LLVM.General.Internal.FFI.LLVMCTypes as FFI
 import qualified LLVM.General.AST.IntegerPredicate as A.IPred
 
-genCodingInstance' [t| A.IPred.IntegerPredicate |] ''FFI.ICmpPredicate [
+genCodingInstance [t| A.IPred.IntegerPredicate |] ''FFI.ICmpPredicate [
   (FFI.iCmpPredEQ, A.IPred.EQ),
   (FFI.iCmpPredNE, A.IPred.NE),
   (FFI.iCmpPredUGT, A.IPred.UGT),
diff --git a/src/LLVM/General/Internal/Module.hs b/src/LLVM/General/Internal/Module.hs
--- a/src/LLVM/General/Internal/Module.hs
+++ b/src/LLVM/General/Internal/Module.hs
@@ -59,7 +59,7 @@
 instance Error (Either String Diagnostic) where
     strMsg = Left
 
-genCodingInstance' [t| Bool |] ''FFI.LinkerMode [
+genCodingInstance [t| Bool |] ''FFI.LinkerMode [
   (FFI.linkerModeDestroySource, False),
   (FFI.linkerModePreserveSource, True)
  ]
diff --git a/src/LLVM/General/Internal/Operand.hs b/src/LLVM/General/Internal/Operand.hs
--- a/src/LLVM/General/Internal/Operand.hs
+++ b/src/LLVM/General/Internal/Operand.hs
@@ -70,7 +70,7 @@
     liftIO $ FFI.createMDNodeInContext c ops
   encodeM (A.MetadataNodeReference n) = referMDNode n
 
-instance DecodeM DecodeAST [A.Operand] (Ptr FFI.MDNode) where
+instance DecodeM DecodeAST [Maybe A.Operand] (Ptr FFI.MDNode) where
   decodeM p = scopeAnyCont $ do
     n <- liftIO $ FFI.getMDNodeNumOperands p
     ops <- allocaArray n
diff --git a/src/LLVM/General/Internal/PassManager.hs b/src/LLVM/General/Internal/PassManager.hs
--- a/src/LLVM/General/Internal/PassManager.hs
+++ b/src/LLVM/General/Internal/PassManager.hs
@@ -7,109 +7,123 @@
 import qualified Language.Haskell.TH as TH
 
 import Control.Exception
-import Control.Monad
+import Control.Monad hiding (forM_)
 import Control.Monad.IO.Class
 import Control.Applicative
 
 import Control.Monad.AnyCont
 
-import Data.Word (Word)
-import Foreign.C.Types (CInt)
+import Data.Word
+import Data.Foldable (forM_)
 import Foreign.Ptr
 
 import qualified LLVM.General.Internal.FFI.PassManager as FFI
 import qualified LLVM.General.Internal.FFI.Transforms as FFI
+import qualified LLVM.General.Internal.FFI.LLVMCTypes as FFI
 
 import LLVM.General.Internal.Module
 import LLVM.General.Internal.Target
 import LLVM.General.Internal.Coding
+import LLVM.General.Internal.DataLayout
 import LLVM.General.Transforms
 
+import LLVM.General.AST.DataLayout
+
 -- | <http://llvm.org/doxygen/classllvm_1_1PassManager.html>
+-- Note: a PassManager does substantive behind-the-scenes work, arranging for the
+-- results of various analyses to be available as needed by transform passes, shared
+-- as possible.
 newtype PassManager = PassManager (Ptr FFI.PassManager)
 
--- | There are different ways to get a 'PassManager'. This class embodies them.
-class PassManagerSpecification s where
-    -- | make a 'PassManager'
-    createPassManager :: s -> IO (Ptr FFI.PassManager)
-
--- | This type is a high-level specification of a set of passes. It uses the same
--- collection of passes chosen by the LLVM team in the command line tool 'opt'.  The fields
--- of this spec are much like typical compiler command-line flags - e.g. -O\<n\>, etc.
-data CuratedPassSetSpec = CuratedPassSetSpec {
-    optLevel :: Maybe Int,
-    sizeLevel :: Maybe Int,
-    unitAtATime :: Maybe Bool,
-    simplifyLibCalls :: Maybe Bool,
-    useInlinerWithThreshold :: Maybe Int
-  }
+-- | There are different ways to get a 'PassManager'. This type embodies them.
+data PassSetSpec
+  -- | a 'PassSetSpec' is a lower-level, detailed specification of a set of passes. It
+  -- allows fine-grained control of what passes are to be run when, and the specification
+  -- of passes not available through 'CuratedPassSetSpec'.
+  = PassSetSpec {
+      transforms :: [Pass],
+      dataLayout :: Maybe DataLayout,
+      targetLibraryInfo :: Maybe TargetLibraryInfo,
+      targetLowering :: Maybe TargetLowering
+    }
+  -- | This type is a high-level specification of a set of passes. It uses the same
+  -- collection of passes chosen by the LLVM team in the command line tool 'opt'.  The fields
+  -- of this spec are much like typical compiler command-line flags - e.g. -O\<n\>, etc.
+  | CuratedPassSetSpec {
+      optLevel :: Maybe Word,
+      sizeLevel :: Maybe Word,
+      unitAtATime :: Maybe Bool,
+      simplifyLibCalls :: Maybe Bool,
+      useInlinerWithThreshold :: Maybe Word
+    }
 
--- | Helper to make a 'CuratedPassSetSpec'
+-- | Helper to make a curated 'PassSetSpec'
 defaultCuratedPassSetSpec = CuratedPassSetSpec {
-    optLevel = Nothing,
-    sizeLevel = Nothing,
-    unitAtATime = Nothing,
-    simplifyLibCalls = Nothing,
-    useInlinerWithThreshold = Nothing
-  }
-
-instance PassManagerSpecification CuratedPassSetSpec where
-  createPassManager s = bracket FFI.passManagerBuilderCreate FFI.passManagerBuilderDispose $ \b -> do
-    let handleOption g m = maybe (return ()) (g b . fromIntegral . fromEnum) (m s)
-    handleOption FFI.passManagerBuilderSetOptLevel optLevel
-    handleOption FFI.passManagerBuilderSetSizeLevel sizeLevel
-    handleOption FFI.passManagerBuilderSetDisableUnitAtATime (liftM not . unitAtATime)
-    handleOption FFI.passManagerBuilderSetDisableSimplifyLibCalls (liftM not . simplifyLibCalls)
-    handleOption FFI.passManagerBuilderUseInlinerWithThreshold useInlinerWithThreshold
-    pm <- FFI.createPassManager
-    FFI.passManagerBuilderPopulateModulePassManager b pm
-    return pm
-
-data PassSetSpec = PassSetSpec [Pass] (Maybe TargetLowering)
-
-instance Monad m => EncodeM m (Maybe Bool) (FFI.LLVMEncoded CInt (Maybe Bool)) where
-  encodeM mb = return $ FFI.LLVMEncoded ((maybe (-1) (\b -> if b then 1 else 0) mb) :: CInt)
-
-instance Monad m => EncodeM m (Maybe Word) (FFI.LLVMEncoded CInt (Maybe Word)) where
-  encodeM mw = return  $ FFI.LLVMEncoded ((maybe (-1) fromIntegral mw) :: CInt)
+  optLevel = Nothing,
+  sizeLevel = Nothing,
+  unitAtATime = Nothing,
+  simplifyLibCalls = Nothing,
+  useInlinerWithThreshold = Nothing
+}
 
-instance PassManagerSpecification PassSetSpec where
-  createPassManager (PassSetSpec ps tl') = flip runAnyContT return $ do
-    let tl = maybe nullPtr (\(TargetLowering tl) -> tl) tl'
-    pm <- liftIO $ FFI.createPassManager
-    forM ps $ \p -> $(
-      do
-        TH.TyConI (TH.DataD _ _ _ cons _) <- TH.reify ''Pass
-        TH.caseE [| p |] $ flip map cons $ \con -> do
-          let
-            (n, fns) = case con of
-                          TH.RecC n fs -> (n, [ TH.nameBase fn | (fn, _, _) <- fs ])
-                          TH.NormalC n [] -> (n, [])
-            actions = 
-              [ TH.bindS (TH.varP . TH.mkName $ fn) [| encodeM $(TH.dyn fn) |] | fn <- fns ]
-              ++ [
-               TH.noBindS [|
-                 liftIO $(
-                   foldl1 TH.appE
-                   (map TH.dyn $
-                      ["FFI.add" ++ TH.nameBase n ++ "Pass", "pm"]
-                      ++ ["tl" | FFI.needsTargetLowering (TH.nameBase n)]
-                      ++ fns)
-                  )
-                 |]
-               ]
-          TH.match (TH.conP n $ map (TH.varP . TH.mkName) fns) (TH.normalB (TH.doE actions)) []
-     )
-    return pm
+-- | an empty 'PassSetSpec'
+defaultPassSetSpec = PassSetSpec {
+  transforms = [],
+  dataLayout = Nothing,
+  targetLibraryInfo = Nothing,
+  targetLowering = Nothing
+}
 
-instance PassManagerSpecification [Pass] where
-  createPassManager ps = createPassManager (PassSetSpec ps Nothing)
+instance (Monad m, MonadAnyCont IO m) => EncodeM m GCOVVersion FFI.LLVMBool where
+  encodeM (GCOVVersion "402*") = encodeM True
+  encodeM (GCOVVersion "404*") = encodeM False
+  encodeM s = fail $ "unsupported GCOVVersion: "++ show s ++ ". llvm-3.2 supports only \"402*\" and \"404*\""
 
-instance PassManagerSpecification ([Pass], TargetLowering) where
-  createPassManager (ps, tl) = createPassManager (PassSetSpec ps (Just tl))
+createPassManager :: PassSetSpec -> IO (Ptr FFI.PassManager)
+createPassManager pss = flip runAnyContT return $ do
+  pm <- liftIO $ FFI.createPassManager
+  case pss of
+    s@CuratedPassSetSpec {} -> liftIO $ do
+      bracket FFI.passManagerBuilderCreate FFI.passManagerBuilderDispose $ \b -> do
+        let handleOption g m = forM_ (m s) (g b <=< encodeM) 
+        handleOption FFI.passManagerBuilderSetOptLevel optLevel
+        handleOption FFI.passManagerBuilderSetSizeLevel sizeLevel
+        handleOption FFI.passManagerBuilderSetDisableUnitAtATime (liftM not . unitAtATime)
+        handleOption FFI.passManagerBuilderSetDisableSimplifyLibCalls (liftM not . simplifyLibCalls)
+        handleOption FFI.passManagerBuilderUseInlinerWithThreshold useInlinerWithThreshold
+        FFI.passManagerBuilderPopulateModulePassManager b pm
+    PassSetSpec ps dl tli tl' -> do
+      let tl = maybe nullPtr (\(TargetLowering tl) -> tl) tl'
+      forM_ tli $ \(TargetLibraryInfo tli) -> do
+        liftIO $ FFI.addTargetLibraryInfoPass pm tli
+      forM_ dl $ \dl -> liftIO $ withFFIDataLayout dl $ FFI.addDataLayoutPass pm 
+      forM_ ps $ \p -> $(
+        do
+          TH.TyConI (TH.DataD _ _ _ cons _) <- TH.reify ''Pass
+          TH.caseE [| p |] $ flip map cons $ \con -> do
+            let
+              (n, fns) = case con of
+                            TH.RecC n fs -> (n, [ TH.nameBase fn | (fn, _, _) <- fs ])
+                            TH.NormalC n [] -> (n, [])
+              actions = 
+                [ TH.bindS (TH.varP . TH.mkName $ fn) [| encodeM $(TH.dyn fn) |] | fn <- fns ]
+                ++ [
+                 TH.noBindS [|
+                   liftIO $(
+                     foldl1 TH.appE
+                     (map TH.dyn $
+                        ["FFI.add" ++ TH.nameBase n ++ "Pass", "pm"]
+                        ++ ["tl" | FFI.needsTargetLowering (TH.nameBase n)]
+                        ++ fns)
+                    )
+                   |]
+                 ]
+            TH.match (TH.conP n $ map (TH.varP . TH.mkName) fns) (TH.normalB (TH.doE actions)) []
+       )
+  return pm
 
 -- | bracket the creation of a 'PassManager'
-withPassManager :: PassManagerSpecification s => s -> (PassManager -> IO a) -> IO a
+withPassManager :: PassSetSpec -> (PassManager -> IO a) -> IO a
 withPassManager s = bracket (createPassManager s) FFI.disposePassManager . (. PassManager)
 
 -- | run the passes in a 'PassManager' on a 'Module', modifying the 'Module'.
diff --git a/src/LLVM/General/Internal/PrettyPrint.hs b/src/LLVM/General/Internal/PrettyPrint.hs
--- a/src/LLVM/General/Internal/PrettyPrint.hs
+++ b/src/LLVM/General/Internal/PrettyPrint.hs
@@ -99,6 +99,7 @@
   p <- asks precedence
   parensIfNeeded appPrec (foldl (<+>) name fields)
 
+-- | a class for simple pretty-printing with indentation a function only of syntactic depth.
 class Show a => PrettyShow a where
   prettyShow :: a -> QTree
   prettyShowList :: [a] -> QTree
diff --git a/src/LLVM/General/Internal/RMWOperation.hs b/src/LLVM/General/Internal/RMWOperation.hs
--- a/src/LLVM/General/Internal/RMWOperation.hs
+++ b/src/LLVM/General/Internal/RMWOperation.hs
@@ -10,7 +10,7 @@
 
 import LLVM.General.Internal.Coding
 
-genCodingInstance' [t| RMWOperation |] ''FFI.RMWOperation [
+genCodingInstance [t| RMWOperation |] ''FFI.RMWOperation [
   (FFI.rmwOperationXchg, Xchg),
   (FFI.rmwOperationAdd, Add),
   (FFI.rmwOperationSub, Sub),
diff --git a/src/LLVM/General/Internal/String.hs b/src/LLVM/General/Internal/String.hs
--- a/src/LLVM/General/Internal/String.hs
+++ b/src/LLVM/General/Internal/String.hs
@@ -9,6 +9,7 @@
 import Control.Monad.AnyCont
 import Control.Monad.IO.Class
 import Control.Exception (finally)
+import Data.Maybe (fromMaybe)
 import Foreign.C (CString, CChar)
 import Foreign.Ptr
 import Foreign.Storable (Storable)
@@ -51,3 +52,7 @@
 
 instance (Integral i, Storable i, MonadIO d) => DecodeM d String (Ptr i -> IO (Ptr CChar)) where
   decodeM f = decodeM =<< (liftIO $ F.M.alloca $ \p -> (,) `liftM` f p `ap` peek p)
+
+instance (Monad e, EncodeM e String c) => EncodeM e (Maybe String) (NothingAsEmptyString c) where
+  encodeM = liftM NothingAsEmptyString . encodeM . fromMaybe ""
+  
diff --git a/src/LLVM/General/Internal/Target.hs b/src/LLVM/General/Internal/Target.hs
--- a/src/LLVM/General/Internal/Target.hs
+++ b/src/LLVM/General/Internal/Target.hs
@@ -32,14 +32,14 @@
 import qualified LLVM.General.CodeModel as CodeModel
 import qualified LLVM.General.CodeGenOpt as CodeGenOpt
 
-genCodingInstance' [t| Reloc.Model |] ''FFI.RelocModel [
+genCodingInstance [t| Reloc.Model |] ''FFI.RelocModel [
   (FFI.relocModelDefault, Reloc.Default),
   (FFI.relocModelStatic, Reloc.Static),
   (FFI.relocModelPIC, Reloc.PIC),
   (FFI.relocModelDynamicNoPic, Reloc.DynamicNoPIC)
  ]
 
-genCodingInstance' [t| CodeModel.Model |] ''FFI.CodeModel [
+genCodingInstance [t| CodeModel.Model |] ''FFI.CodeModel [
   (FFI.codeModelDefault,CodeModel.Default),
   (FFI.codeModelJITDefault, CodeModel.JITDefault),
   (FFI.codeModelSmall, CodeModel.Small),
@@ -48,20 +48,20 @@
   (FFI.codeModelLarge, CodeModel.Large)
  ]
 
-genCodingInstance' [t| CodeGenOpt.Level |] ''FFI.CodeGenOptLevel [
+genCodingInstance [t| CodeGenOpt.Level |] ''FFI.CodeGenOptLevel [
   (FFI.codeGenOptLevelNone, CodeGenOpt.None),
   (FFI.codeGenOptLevelLess, CodeGenOpt.Less),
   (FFI.codeGenOptLevelDefault, CodeGenOpt.Default),
   (FFI.codeGenOptLevelAggressive, CodeGenOpt.Aggressive)
  ]
 
-genCodingInstance' [t| TO.FloatABI |] ''FFI.FloatABIType [
+genCodingInstance [t| TO.FloatABI |] ''FFI.FloatABIType [
   (FFI.floatABIDefault, TO.FloatABIDefault),
   (FFI.floatABISoft, TO.FloatABISoft),
   (FFI.floatABIHard, TO.FloatABIHard)
  ]
 
-genCodingInstance' [t| TO.FloatingPointOperationFusionMode |] ''FFI.FPOpFusionMode [
+genCodingInstance [t| TO.FloatingPointOperationFusionMode |] ''FFI.FPOpFusionMode [
   (FFI.fpOpFusionModeFast, TO.FloatingPointOperationFusionFast),
   (FFI.fpOpFusionModeStandard, TO.FloatingPointOperationFusionStandard),
   (FFI.fpOpFusionModeStrict, TO.FloatingPointOperationFusionStrict)
@@ -263,7 +263,6 @@
 getTargetMachineDataLayout (TargetMachine m) =
     fromMaybe (error "parseDataLayout failed") . parseDataLayout <$> (decodeM =<< (FFI.getTargetMachineDataLayout m))
 
-
 -- | Initialize all targets so they can be found by 'lookupTarget'
 initializeAllTargets :: IO ()
 initializeAllTargets = FFI.initializeAllTargets
@@ -278,3 +277,16 @@
   (target, _) <- lookupTarget Nothing triple
   liftIO $ withTargetOptions $ \options ->
       withTargetMachine target triple cpu features options Reloc.Default CodeModel.Default CodeGenOpt.Default f
+
+-- | <http://llvm.org/docs/doxygen/html/classllvm_1_1TargetLibraryInfo.html>
+newtype TargetLibraryInfo = TargetLibraryInfo (Ptr FFI.TargetLibraryInfo)
+
+-- | look up information about the library functions available on a given platform
+withTargetLibraryInfo :: 
+  String -- ^ triple
+  -> (TargetLibraryInfo -> IO a)
+  -> IO a
+withTargetLibraryInfo triple f = flip runAnyContT return $ do
+  triple <- encodeM triple
+  liftIO $ bracket (FFI.createTargetLibraryInfo triple) FFI.disposeTargetLibraryInfo (f . TargetLibraryInfo)
+  
diff --git a/src/LLVM/General/PassManager.hs b/src/LLVM/General/PassManager.hs
--- a/src/LLVM/General/PassManager.hs
+++ b/src/LLVM/General/PassManager.hs
@@ -1,17 +1,12 @@
 -- | A 'PassManager' holds collection of passes, to be run on 'Module's.
 -- Build one with 'withPassManager':
 -- 
---  * from a 'CuratedPassSetSpec' if you want optimization but not to play with your compiler
---
---  * from a ['LLVM.General.Transform.Pass'] if you do want to play with your compiler
+--  * using 'CuratedPassSetSpec' if you want optimization but not to play with your compiler
 --
---  * from a (['LLVM.General.Transform.Pass'], 'LLVM.General.Target.TargetLowering') if you
---    want to provide target-specific information (e.g. instruction costs) to the few passes
---    that use it (see comments on 'LLVM.General.Transforms.Pass').
+--  * using 'PassSetSpec' if you do want to play with your compiler
 module LLVM.General.PassManager (
   PassManager,
-  PassManagerSpecification,
-  CuratedPassSetSpec(..), defaultCuratedPassSetSpec,
+  PassSetSpec(..), defaultPassSetSpec, defaultCuratedPassSetSpec,
   withPassManager,
   runPassManager
   ) where
diff --git a/src/LLVM/General/Target.hs b/src/LLVM/General/Target.hs
--- a/src/LLVM/General/Target.hs
+++ b/src/LLVM/General/Target.hs
@@ -10,7 +10,9 @@
    withTargetMachine, withDefaultTargetMachine,
    getTargetLowering,
    getDefaultTargetTriple, getHostCPUName, getHostCPUFeatures,
-   getTargetMachineDataLayout, initializeNativeTarget, initializeAllTargets
+   getTargetMachineDataLayout, initializeNativeTarget, initializeAllTargets,
+   TargetLibraryInfo,
+   withTargetLibraryInfo
  ) where
 
 import LLVM.General.Internal.Target
diff --git a/src/LLVM/General/Transforms.hs b/src/LLVM/General/Transforms.hs
--- a/src/LLVM/General/Transforms.hs
+++ b/src/LLVM/General/Transforms.hs
@@ -83,30 +83,44 @@
 
   -- here begin the vectorization passes
   | BasicBlockVectorize { 
-    vectorBits :: Word,
-    vectorizeBools :: Bool,
-    vectorizeInts :: Bool,
-    vectorizeFloats :: Bool,
-    vectorizePointers :: Bool,
-    vectorizeCasts :: Bool,
-    vectorizeMath :: Bool,
-    vectorizeFusedMultiplyAdd :: Bool,
-    vectorizeSelect :: Bool,
-    vectorizeCmp :: Bool,
-    vectorizeGetElementPtr :: Bool,
-    vectorizeMemoryOperations :: Bool,
-    alignedOnly :: Bool,
-    requiredChainDepth :: Word,
-    searchLimit :: Word,
-    maxCandidatePairsForCycleCheck :: Word,
-    splatBreaksChain :: Bool,
-    maxInstructions :: Word,
-    maxIterations :: Word,
-    powerOfTwoLengthsOnly :: Bool,
-    noMemoryOperationBoost :: Bool,
-    fastDependencyAnalysis :: Bool
+      vectorBits :: Word,
+      vectorizeBools :: Bool,
+      vectorizeInts :: Bool,
+      vectorizeFloats :: Bool,
+      vectorizePointers :: Bool,
+      vectorizeCasts :: Bool,
+      vectorizeMath :: Bool,
+      vectorizeFusedMultiplyAdd :: Bool,
+      vectorizeSelect :: Bool,
+      vectorizeCmp :: Bool,
+      vectorizeGetElementPtr :: Bool,
+      vectorizeMemoryOperations :: Bool,
+      alignedOnly :: Bool,
+      requiredChainDepth :: Word,
+      searchLimit :: Word,
+      maxCandidatePairsForCycleCheck :: Word,
+      splatBreaksChain :: Bool,
+      maxInstructions :: Word,
+      maxIterations :: Word,
+      powerOfTwoLengthsOnly :: Bool,
+      noMemoryOperationBoost :: Bool,
+      fastDependencyAnalysis :: Bool
     }
   | LoopVectorize
+
+  -- here begin the instrumentation passes
+  | EdgeProfiler
+  | OptimalEdgeProfiler
+  | PathProfiler
+  | GCOVProfiler {
+      emitNotes :: Bool,
+      emitData :: Bool,
+      version :: GCOVVersion,
+      useCfgChecksum :: Bool
+    }
+  | AddressSanitizer
+  | ThreadSanitizer
+  | BoundsChecking
   deriving (Eq, Ord, Read, Show, Typeable, Data)
 
 -- | Defaults for the 'BasicBlockVectorize' pass - copied from the C++ code to keep these defaults
@@ -137,3 +151,21 @@
     noMemoryOperationBoost = False,
     fastDependencyAnalysis = False
   }
+
+-- | See <http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/gcov-io.h?view=markup>.
+newtype GCOVVersion = GCOVVersion String
+  deriving (Eq, Ord, Read, Show, Typeable, Data)
+
+-- | Defaults for 'GCOVProfiler'.
+defaultGCOVProfiler = GCOVProfiler {
+    emitNotes = True,
+    emitData = True,
+    version = GCOVVersion "402*", 
+    useCfgChecksum = False
+  }
+
+-- | Defaults for 'AddressSanitizer'.
+defaultAddressSanitizer = AddressSanitizer
+
+-- | Defaults for 'ThreadSanitizer'.
+defaultThreadSanitizer = ThreadSanitizer
diff --git a/test/LLVM/General/Test/Linking.hs b/test/LLVM/General/Test/Linking.hs
--- a/test/LLVM/General/Test/Linking.hs
+++ b/test/LLVM/General/Test/Linking.hs
@@ -30,11 +30,6 @@
 import qualified LLVM.General.AST.Global as G
 import qualified LLVM.General.AST.Constant as C
 
-optimize :: PassManagerSpecification s => s -> A.Module -> IO A.Module
-optimize s m = withContext $ \context -> withModuleFromAST' context m $ \mIn' -> do
-  withPassManager s $ \pm -> runPassManager pm mIn'
-  moduleAST mIn'
-
 tests = testGroup "Linking" [
   testCase "basic" $ do
     let 
diff --git a/test/LLVM/General/Test/Metadata.hs b/test/LLVM/General/Test/Metadata.hs
--- a/test/LLVM/General/Test/Metadata.hs
+++ b/test/LLVM/General/Test/Metadata.hs
@@ -35,8 +35,9 @@
                 (
                   "my-metadatum", 
                   MetadataNode [
-                   LocalReference (UnName 1),
-                   MetadataStringOperand "super hyper"
+                   Just $ LocalReference (UnName 1),
+                   Just $ MetadataStringOperand "super hyper",
+                   Nothing
                   ]
                 )
               ]
@@ -49,7 +50,7 @@
             \\n\
             \define i32 @foo() {\n\
             \  %1 = load i32* @0\n\
-            \  ret i32 0, !my-metadatum !{i32 %1, metadata !\"super hyper\"}\n\
+            \  ret i32 0, !my-metadatum !{i32 %1, metadata !\"super hyper\", null}\n\
             \}\n"
     strCheck ast s,
 
@@ -67,7 +68,7 @@
               ]
             )
           ],
-          MetadataNodeDefinition (MetadataNodeID 0) [ ConstantOperand (C.Int 32 1) ]
+          MetadataNodeDefinition (MetadataNodeID 0) [ Just $ ConstantOperand (C.Int 32 1) ]
          ]
     let s = "; ModuleID = '<string>'\n\
             \\n\
@@ -80,8 +81,8 @@
 
   testCase "named" $ do
     let ast = Module "<string>" Nothing Nothing [
-          NamedMetadataDefinition "my-module-metadata" [MetadataNodeID 0],
-          MetadataNodeDefinition (MetadataNodeID 0) [ ConstantOperand (C.Int 32 1) ]
+          NamedMetadataDefinition "my-module-metadata" [ MetadataNodeID 0 ],
+          MetadataNodeDefinition (MetadataNodeID 0) [ Just $ ConstantOperand (C.Int 32 1) ]
          ]
     let s = "; ModuleID = '<string>'\n\
             \\n\
@@ -90,15 +91,27 @@
             \!0 = metadata !{i32 1}\n"
     strCheck ast s,
 
+  testCase "null" $ do
+    let ast = Module "<string>" Nothing Nothing [
+          NamedMetadataDefinition "my-module-metadata" [ MetadataNodeID 0 ],
+          MetadataNodeDefinition (MetadataNodeID 0) [ Nothing ]
+         ]
+    let s = "; ModuleID = '<string>'\n\
+            \\n\
+            \!my-module-metadata = !{!0}\n\
+            \\n\
+            \!0 = metadata !{null}\n"
+    strCheck ast s,
+
   testGroup "cyclic" [
     testCase "metadata-only" $ do
       let ast = Module "<string>" Nothing Nothing [
             NamedMetadataDefinition "my-module-metadata" [MetadataNodeID 0],
             MetadataNodeDefinition (MetadataNodeID 0) [
-              MetadataNodeOperand (MetadataNodeReference (MetadataNodeID 1)) 
+              Just $ MetadataNodeOperand (MetadataNodeReference (MetadataNodeID 1)) 
              ],
             MetadataNodeDefinition (MetadataNodeID 1) [
-              MetadataNodeOperand (MetadataNodeReference (MetadataNodeID 0)) 
+              Just $ MetadataNodeOperand (MetadataNodeReference (MetadataNodeID 0)) 
              ]
            ]
       let s = "; ModuleID = '<string>'\n\
@@ -122,7 +135,7 @@
               )
             ],
             MetadataNodeDefinition (MetadataNodeID 0) [
-              ConstantOperand (C.GlobalReference (Name "foo"))
+              Just $ ConstantOperand (C.GlobalReference (Name "foo"))
              ]
            ]
       let s = "; ModuleID = '<string>'\n\
diff --git a/test/LLVM/General/Test/Optimization.hs b/test/LLVM/General/Test/Optimization.hs
--- a/test/LLVM/General/Test/Optimization.hs
+++ b/test/LLVM/General/Test/Optimization.hs
@@ -93,9 +93,9 @@
        ]
       ]
 
-optimize :: PassManagerSpecification s => s -> A.Module -> IO A.Module
-optimize s m = withContext $ \context -> withModuleFromAST' context m $ \mIn' -> do
-  withPassManager s $ \pm -> runPassManager pm mIn'
+optimize :: PassSetSpec -> A.Module -> IO A.Module
+optimize pss m = withContext $ \context -> withModuleFromAST' context m $ \mIn' -> do
+  withPassManager pss $ \pm -> runPassManager pm mIn'
   moduleAST mIn'
 
 tests = testGroup "Optimization" [
@@ -118,7 +118,7 @@
 
   testGroup "individual" [
     testCase "ConstantPropagation" $ do
-      mOut <- optimize [ConstantPropagation] handAST
+      mOut <- optimize defaultPassSetSpec { transforms = [ConstantPropagation] } handAST
 
       mOut @?= Module "<string>" Nothing Nothing [
         GlobalDefinition $ Function L.External V.Default CC.C [] (IntegerType 32) (Name "foo") ([
@@ -210,14 +210,8 @@
            ] (Do $ Ret (Just (LocalReference (Name "r"))) [])
           ]
          ]
-      mOut <- optimize [ 
-               defaultVectorizeBasicBlocks {
-                 vectorizePointers = False,
-                 requiredChainDepth = 3
-               },
-               InstructionCombining,
-               GlobalValueNumbering False
-              ] mIn
+      mOut <- 
+        optimize (defaultPassSetSpec { transforms = [ defaultVectorizeBasicBlocks { vectorizePointers = False, requiredChainDepth = 3 }, InstructionCombining, GlobalValueNumbering False ] }) mIn
       mOut @?= Module "<string>" Nothing Nothing [
        GlobalDefinition $ Function 
         L.External V.Default CC.C [] (FloatingPointType 64 IEEE) (Name "foo") ([
@@ -299,9 +293,9 @@
         (target, _) <- failInIO $ lookupTarget Nothing triple
         withTargetOptions $ \targetOptions -> do
           withTargetMachine target triple "" Set.empty targetOptions
-                            R.Default CM.Default CGO.Default $ \targetMachine -> do
-            targetLowering <- getTargetLowering targetMachine
-            withPassManager ([LowerInvoke False], targetLowering) $ \passManager -> do
+                            R.Default CM.Default CGO.Default $ \tm -> do
+            tl <- getTargetLowering tm
+            withPassManager (defaultPassSetSpec { transforms = [LowerInvoke False], targetLowering = Just tl}) $ \passManager -> do
               let astIn = 
                     Module "<string>" Nothing Nothing [
                      GlobalDefinition $ Function L.External V.Default CC.C [] (IntegerType 32) (Name "foo") ([
diff --git a/test/LLVM/General/Test/Tests.hs b/test/LLVM/General/Test/Tests.hs
--- a/test/LLVM/General/Test/Tests.hs
+++ b/test/LLVM/General/Test/Tests.hs
@@ -15,6 +15,7 @@
 import qualified LLVM.General.Test.Analysis as Analysis
 import qualified LLVM.General.Test.PrettyPrint as PrettyPrint
 import qualified LLVM.General.Test.Linking as Linking
+import qualified LLVM.General.Test.Instrumentation as Instrumentation
 
 tests = testGroup "llvm-general" [
     Constants.tests,
@@ -29,5 +30,6 @@
     Target.tests,
     Analysis.tests,
     PrettyPrint.tests,
-    Linking.tests
+    Linking.tests,
+    Instrumentation.tests
   ]
