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.4.5
+version: 3.2.4.6
 license: BSD3
 license-file: LICENSE
 author: Benjamin S.Scarlet <fgthb0@greynode.net>
@@ -16,13 +16,14 @@
 	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.4.5/doc/html/llvm-general/index.html>.
+  For haddock, see <http://bscarlet.github.io/llvm-general/3.2.4.6/doc/html/llvm-general/index.html>.
 extra-source-files:
   src/LLVM/General/Internal/FFI/Analysis.h
   src/LLVM/General/Internal/FFI/Function.h
   src/LLVM/General/Internal/FFI/GlobalValue.h
   src/LLVM/General/Internal/FFI/InlineAssembly.h
   src/LLVM/General/Internal/FFI/Instruction.h
+  src/LLVM/General/Internal/FFI/Module.h
   src/LLVM/General/Internal/FFI/SMDiagnostic.h
   src/LLVM/General/Internal/FFI/Target.h
   src/LLVM/General/Internal/FFI/Type.h
@@ -36,7 +37,7 @@
   type: git
   location: git://github.com/bscarlet/llvm-general.git
   branch: llvm-3.2
-  tag: v3.2.4.5
+  tag: v3.2.4.6
 
 flag shared-llvm
   description: link against llvm shared rather than static library
@@ -218,6 +219,7 @@
     LLVM.General.Test.Global
     LLVM.General.Test.InlineAssembly
     LLVM.General.Test.Instructions
+    LLVM.General.Test.Linking
     LLVM.General.Test.Metadata
     LLVM.General.Test.Module
     LLVM.General.Test.Optimization
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
@@ -9,6 +9,7 @@
 #include "llvm-c/Core.h"
 #include "llvm-c/Target.h"
 #include "llvm-c/TargetMachine.h"
+#include "llvm-c/Linker.h"
 #include "LLVM/General/Internal/FFI/Instruction.h"
 #include "LLVM/General/Internal/FFI/Value.h"
 #include "LLVM/General/Internal/FFI/SMDiagnostic.h"
@@ -18,6 +19,7 @@
 #include "LLVM/General/Internal/FFI/GlobalValue.h"
 #include "LLVM/General/Internal/FFI/Type.h"
 #include "LLVM/General/Internal/FFI/Analysis.h"
+#include "LLVM/General/Internal/FFI/Module.h"
 
 import Language.Haskell.TH.Quote
 
@@ -190,3 +192,8 @@
   deriving (Eq, Read, Show, Bits, Typeable, Data, Num)
 #define VFA_Rec(n) { #n, LLVM ## n ## Action },
 #{inject VERIFIER_FAILURE_ACTION, VerifierFailureAction, VerifierFailureAction, verifierFailureAction, VFA_Rec}
+
+newtype LinkerMode = LinkerMode CUInt
+  deriving (Eq, Read, Show, Bits, Typeable, Data, Num)
+#define LM_Rec(n) { #n, LLVMLinker ## n },
+#{inject LINKER_MODE, LinkerMode, LinkerMode, linkerMode, LM_Rec}
diff --git a/src/LLVM/General/Internal/FFI/Module.h b/src/LLVM/General/Internal/FFI/Module.h
new file mode 100644
--- /dev/null
+++ b/src/LLVM/General/Internal/FFI/Module.h
@@ -0,0 +1,8 @@
+#ifndef __LLVM_GENERAL_INTERNAL_FFI__MODULE__H__
+#define __LLVM_GENERAL_INTERNAL_FFI__MODULE__H__
+
+#define LLVM_GENERAL_FOR_EACH_LINKER_MODE(macro) \
+	macro(DestroySource) \
+	macro(PreserveSource) 
+
+#endif
diff --git a/src/LLVM/General/Internal/FFI/Module.hs b/src/LLVM/General/Internal/FFI/Module.hs
--- a/src/LLVM/General/Internal/FFI/Module.hs
+++ b/src/LLVM/General/Internal/FFI/Module.hs
@@ -88,3 +88,6 @@
 
 foreign import ccall unsafe "LLVM_General_WriteBitcodeToFile" writeBitcodeToFile ::
   Ptr Module -> CString -> Ptr MallocedCString -> IO LLVMBool
+
+foreign import ccall unsafe "LLVMLinkModules" linkModules ::
+  Ptr Module -> Ptr Module -> LinkerMode -> Ptr MallocedCString -> IO LLVMBool
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
@@ -1,6 +1,8 @@
 {-#
   LANGUAGE
-  ScopedTypeVariables
+  TemplateHaskell,
+  ScopedTypeVariables,
+  MultiParamTypeClasses
   #-}
 -- | This Haskell module is for/of functions for handling LLVM modules.
 module LLVM.General.Internal.Module where
@@ -56,6 +58,26 @@
 
 instance Error (Either String Diagnostic) where
     strMsg = Left
+
+genCodingInstance' [t| Bool |] ''FFI.LinkerMode [
+  (FFI.linkerModeDestroySource, False),
+  (FFI.linkerModePreserveSource, True)
+ ]
+
+-- | link LLVM modules - move or copy parts of a source module into a destination module.
+-- Note that this operation is not commutative - not only concretely (e.g. the destination module
+-- is modified, becoming the result) but abstractly (e.g. unused private globals in the source
+-- module do not appear in the result, but similar globals in the destination remain).
+linkModules :: 
+  Bool -- ^ True to leave the right module unmodified, False to cannibalize it (for efficiency's sake).
+  -> Module -- ^ The module into which to link
+  -> Module -- ^ The module to link into the other (and cannibalize or not)
+  -> ErrorT String IO ()
+linkModules preserveRight (Module m) (Module m') = flip runAnyContT return $ do
+  preserveRight <- encodeM preserveRight
+  msgPtr <- alloca
+  result <- decodeM =<< (liftIO $ FFI.linkModules m m' preserveRight msgPtr)
+  when result $ fail =<< decodeM msgPtr
 
 -- | parse 'Module' from LLVM assembly
 withModuleFromString :: Context -> String -> (Module -> IO a) -> ErrorT (Either String Diagnostic) IO a
diff --git a/src/LLVM/General/Module.hs b/src/LLVM/General/Module.hs
--- a/src/LLVM/General/Module.hs
+++ b/src/LLVM/General/Module.hs
@@ -9,7 +9,9 @@
 
     writeBitcodeToFile,
     writeAssemblyToFile,
-    writeObjectToFile
+    writeObjectToFile,
+
+    linkModules
   ) where
 
 import LLVM.General.Internal.Module
diff --git a/test/LLVM/General/Test/Linking.hs b/test/LLVM/General/Test/Linking.hs
new file mode 100644
--- /dev/null
+++ b/test/LLVM/General/Test/Linking.hs
@@ -0,0 +1,72 @@
+module LLVM.General.Test.Linking where
+
+import Test.Framework
+import Test.Framework.Providers.HUnit
+import Test.HUnit
+
+import LLVM.General.Test.Support
+
+import Control.Monad.Error
+import Data.Functor
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+
+import LLVM.General.Module
+import LLVM.General.Context
+import LLVM.General.PassManager
+import LLVM.General.Transforms
+import LLVM.General.Target
+
+import LLVM.General.AST as A
+import LLVM.General.AST.Type
+import LLVM.General.AST.Name
+import LLVM.General.AST.AddrSpace
+import LLVM.General.AST.DataLayout
+import qualified LLVM.General.AST.IntegerPredicate as IPred
+import qualified LLVM.General.AST.Linkage as L
+import qualified LLVM.General.AST.Visibility as V
+import qualified LLVM.General.AST.CallingConvention as CC
+import qualified LLVM.General.AST.Attribute as A
+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 
+      ast0 = Module "<string>" Nothing Nothing [
+          GlobalDefinition $ functionDefaults {
+             G.linkage = L.Private,
+             G.returnType = IntegerType 32,
+             G.name = Name "private0"
+           },
+          GlobalDefinition $ functionDefaults {
+             G.linkage = L.External,
+             G.returnType = IntegerType 32,
+             G.name = Name "external0"
+           }
+        ]
+      ast1 = Module "<string>" Nothing Nothing [
+          GlobalDefinition $ functionDefaults {
+             G.linkage = L.Private,
+             G.returnType = IntegerType 32,
+             G.name = Name "private1"
+           },
+          GlobalDefinition $ functionDefaults {
+             G.linkage = L.External,
+             G.returnType = IntegerType 32,
+             G.name = Name "external1"
+           }
+        ]      
+
+    Module { moduleDefinitions = defs } <- withContext $ \context -> 
+      withModuleFromAST' context ast0 $ \m0 ->
+        withModuleFromAST' context ast1 $ \m1 -> do
+          runErrorT $ linkModules False m0 m1
+          moduleAST m0
+    [ n | GlobalDefinition g <- defs, let Name n = G.name g ] @?= [ "private0", "external0", "external1" ]
+ ]
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
@@ -14,6 +14,7 @@
 import qualified LLVM.General.Test.Target as Target
 import qualified LLVM.General.Test.Analysis as Analysis
 import qualified LLVM.General.Test.PrettyPrint as PrettyPrint
+import qualified LLVM.General.Test.Linking as Linking
 
 tests = testGroup "llvm-general" [
     Constants.tests,
@@ -27,5 +28,6 @@
     Optimization.tests,
     Target.tests,
     Analysis.tests,
-    PrettyPrint.tests
+    PrettyPrint.tests,
+    Linking.tests
   ]
