diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2011, Tristan Ravitch
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Tristan Ravitch nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,37 @@
+This package converts the LLVM IR (either bitcode files or LLVM
+assembly) into a Haskell data type (defined in llvm-base-types).  The
+conversion uses the LLVM libraries to read bitcode.  It then traverses
+the IR and produces a Haskell structure that can be pattern matched
+against in pure code.
+
+After the conversion, no C++ data is referenced and no C++ code is
+called.  This library does link against LLVM directly, and therefore
+also uses libstdc++.  This can make linking tricky sometimes.  For
+example, mixing template-haskell with C++-linked code does not seem to
+work.
+
+Note that this library only works with LLVM 3.0-3.3, and will try to
+retain as much compatibility with future and past versions as is
+reasonable.
+
+# Installation Notes
+
+ * Currently, this library is set up to link against the LLVM shared
+   library (libLLVM-3.X.so).  Most distro packages build the LLVM
+   shared library.  If you make a custom build, be sure to configure
+   with `--enable-shared`.
+
+## Debian and Ubuntu
+
+You need the development libraries and headers, so be sure to install
+the llvm-3.X-dev package, where X is the version you would like to
+use.  You will also need clang.
+
+# Changes
+
+## v0.3.0
+
+ * Support LLVM-3.3 (contributed by Patrick Hulin)
+ * Minor breaking change in MetaDW*Type.  These no longer have a
+   MetaDWFile; instead, they directly contain their file and directory
+   information.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,20 @@
+import Distribution.Simple
+import Distribution.Simple.LocalBuildInfo
+import Distribution.Simple.PackageIndex
+import Distribution.Simple.Setup
+import Distribution.Simple.UserHooks
+import Distribution.PackageDescription
+
+import Data.LLVM.Internal.Paths
+
+main = defaultMainWithHooks autoconfUserHooks { preBuild = extBuild }
+
+extBuild args flags = do
+  -- Use the Paths module exposed by one of the dependencies to find
+  -- the directory containing the enumeration header.  Add that
+  -- directory to the search path for this package.
+  enumHeaderDir <- getDataFileName "src/c++"
+  (Just bi, rest) <- (preBuild autoconfUserHooks) args flags
+  let incdirs = includeDirs bi
+  return (Just bi { includeDirs = enumHeaderDir : incdirs }, rest)
+
diff --git a/configure b/configure
new file mode 100644
--- /dev/null
+++ b/configure
@@ -0,0 +1,4555 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.63 for Haskell LLVM data interoperability 0.3.0.
+#
+# Report bugs to <tristan@nochair.net>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&	 (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+	   done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+	 # Try only shells that exist, to save several forks.
+	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		{ ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+	       as_have_required=yes
+	       if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+	do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+	done
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell bug-autoconf@gnu.org about your system,
+  echo including any error possibly output before this message.
+  echo This can help us improve future autoconf versions.
+  echo Configuration will now proceed without shell functions.
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='Haskell LLVM data interoperability'
+PACKAGE_TARNAME='llvm-data-interop'
+PACKAGE_VERSION='0.3.0'
+PACKAGE_STRING='Haskell LLVM data interoperability 0.3.0'
+PACKAGE_BUGREPORT='tristan@nochair.net'
+
+ac_unique_file="src/LLVM/Internal/Interop.chs"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+llvm_libdir
+llvm_ldoptions
+llvm_includedir
+llvm_target
+llvm_extra_libdirs
+llvm_extra_libs
+llvm_cppflags
+llvm_version
+EGREP
+GREP
+CXXCPP
+llvm_config
+OBJEXT
+EXEEXT
+ac_ct_CXX
+CPPFLAGS
+LDFLAGS
+CXXFLAGS
+CXX
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_compiler
+with_llvm_prefix
+with_llvm_bindir
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC
+CXXCPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { $as_echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { $as_echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2
+   { (exit 1); exit 1; }; } ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { $as_echo "$as_me: error: working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { $as_echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures Haskell LLVM data interoperability 0.3.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root
+                          [DATAROOTDIR/doc/llvm-data-interop]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --target=TARGET   configure for building compilers for TARGET [guessed]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of Haskell LLVM data interoperability 0.3.0:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-compiler         use the given Haskell compiler
+  --with-llvm-prefix      use the version of LLVM at the given location
+  --with-llvm-bindir      use LLVM binaries at the given location
+
+Some influential environment variables:
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXXCPP      C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <tristan@nochair.net>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+Haskell LLVM data interoperability configure 0.3.0
+generated by GNU Autoconf 2.63
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Haskell LLVM data interoperability $as_me 0.3.0, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  $as_echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:$LINENO:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:$LINENO:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+ac_config_files="$ac_config_files llvm-data-interop.buildinfo"
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:$LINENO: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5
+$as_echo_n "checking for C++ compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5
+$as_echo_n "checking whether the C++ compiler works... " >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CXXFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+# Check whether --with-compiler was given.
+if test "${with_compiler+set}" = set; then
+  withval=$with_compiler; compiler="$withval"
+else
+  compiler=ghc
+fi
+
+
+# Check whether --with-llvm_prefix was given.
+if test "${with_llvm_prefix+set}" = set; then
+  withval=$with_llvm_prefix; llvm_prefix="$withval"
+else
+  llvm_prefix="$prefix"
+fi
+
+
+# Check whether --with-llvm_bindir was given.
+if test "${with_llvm_bindir+set}" = set; then
+  withval=$with_llvm_bindir; llvm_bindir="$withval"
+else
+  llvm_bindir="$llvm_prefix/bin"
+fi
+
+for ac_prog in llvm-config-3.3 llvm-config-3.2 llvm-config-3.1 llvm-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_llvm_config+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  case $llvm_config in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_llvm_config="$llvm_config" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy=""$llvm_bindir:$PATH""
+for as_dir in $as_dummy
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_llvm_config="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+llvm_config=$ac_cv_path_llvm_config
+if test -n "$llvm_config"; then
+  { $as_echo "$as_me:$LINENO: result: $llvm_config" >&5
+$as_echo "$llvm_config" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$llvm_config" && break
+done
+test -n "$llvm_config" || llvm_config="{ { $as_echo "$as_me:$LINENO: error: could not find llvm-config in $llvm_bindir" >&5
+$as_echo "$as_me: error: could not find llvm-config in $llvm_bindir" >&2;}
+   { (exit 1); exit 1; }; }"
+
+
+
+
+if test "$target" = ""
+then
+    if test "${compiler}" != ""
+    then
+        target=`${compiler} +RTS --info | grep '^ ,("Target platform"' | sed -e 's/.*, "//' -e 's/")//' | tr -d '\r'`
+        echo "Target platform inferred as: $target"
+    else
+        echo "Can't work out target platform"
+        exit 1
+    fi
+fi
+
+case $target in
+i386-apple-darwin)
+    TARGET_CPPFLAGS="-m32"
+    TAGRET_LDFLAGS="-m32"
+    ;;
+x86_64-apple-darwin)
+    TARGET_CPPFLAGS="-m64"
+    TAGRET_LDFLAGS="-m64"
+    ;;
+esac
+
+llvm_version="`$llvm_config --version`"
+llvm_cppflags="`$llvm_config --cppflags`"
+llvm_includedir="`$llvm_config --includedir`"
+llvm_ldflags="`$llvm_config --ldflags`"
+
+llvm_all_libs="`$llvm_config --libs all`"
+llvm_target="`$llvm_config --libs engine | sed 's/.*LLVM\(.[^ ]*\)CodeGen.*/\1/'`"
+
+llvm_extra_libs=""
+llvm_extra_libdirs=""
+llvm_ldoptions=""
+for opt in $llvm_all_libs $llvm_ldflags; do
+  case $opt in
+    -l*) llvm_extra_libs="$llvm_extra_libs `echo $opt | sed 's/-l//'`";;
+    -L*) llvm_extra_libdirs="$llvm_extra_libdirs `echo $opt | sed 's/-L//'`";;
+    *)   llvm_ldoptions="$llvm_ldoptions $opt";;
+  esac
+done
+
+llvm_libdir="`$llvm_config --libdir`"
+
+CPPFLAGS="$llvm_cppflags $CPPFLAGS $TARGET_CPPFLAGS"
+LDFLAGS="$llvm_ldflags $LDFLAGS $TARGET_LDFLAGS"
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if test "${ac_cv_prog_CXXCPP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:$LINENO: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <llvm/Config/llvm-config.h>
+int
+main ()
+{
+
+      #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 3
+      #error llvm >= 3.3,
+      #endif
+
+  ;
+  return 0;
+}
+
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  llvm_module_h="llvm/Module.h"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  llvm_module_h="llvm/IR/Module.h"
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in ${llvm_module_h}
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5
+$as_echo_n "checking $ac_header usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5
+$as_echo_n "checking $ac_header presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ---------------------------------- ##
+## Report this to tristan@nochair.net ##
+## ---------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+
+fi
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { $as_echo "$as_me:$LINENO: error: could not find LLVM headers" >&5
+$as_echo "$as_me: error: could not find LLVM headers" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+
+# We have to link using the C++ compiler.
+CC=$CXX
+
+save_LIBS="$LIBS"
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <${llvm_module_h}>
+int
+main ()
+{
+llvm::Module *dummy
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  LIBS="-lLLVM-${llvm_version} $LIBS" HAVE_LLVM=1
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ { $as_echo "$as_me:$LINENO: error: \"The llvm-${llvm_version} shared library is not installed\"" >&5
+$as_echo "$as_me: error: \"The llvm-${llvm_version} shared library is not installed\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
+
+
+
+
+
+
+
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Haskell LLVM data interoperability $as_me 0.3.0, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTION]... [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+Haskell LLVM data interoperability config.status 0.3.0
+configured by $0, generated by GNU Autoconf 2.63,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    CONFIG_FILES="$CONFIG_FILES '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { $as_echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "llvm-data-interop.buildinfo") CONFIG_FILES="$CONFIG_FILES llvm-data-interop.buildinfo" ;;
+
+  *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   $as_echo "$as_me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=''
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5
+$as_echo "$as_me: error: could not setup config files machinery" >&2;}
+   { (exit 1); exit 1; }; }
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5
+$as_echo "$as_me: error: invalid tag $ac_tag" >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      ac_file_inputs="$ac_file_inputs '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:$LINENO: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; } ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+ ;;
+
+
+
+  esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/llvm-data-interop.buildinfo.in b/llvm-data-interop.buildinfo.in
new file mode 100644
--- /dev/null
+++ b/llvm-data-interop.buildinfo.in
@@ -0,0 +1,7 @@
+cpp-options: @llvm_cppflags@ -DTARGET=@llvm_target@
+ghc-options: -pgml @CXX@
+extra-libraries: LLVM-@llvm_version@ stdc++
+extra-lib-dirs: @llvm_extra_libdirs@
+x-extra-ghci-libraries: LLVM-@llvm_version@
+ld-options: @llvm_ldoptions@ -Wl,-rpath,@llvm_libdir@
+include-dirs: @llvm_includedir@
diff --git a/llvm-data-interop.cabal b/llvm-data-interop.cabal
new file mode 100644
--- /dev/null
+++ b/llvm-data-interop.cabal
@@ -0,0 +1,50 @@
+name: llvm-data-interop
+version: 0.3.0
+synopsis: A low-level data interoperability binding for LLVM
+license: BSD3
+license-file: LICENSE
+author: Tristan Ravitch
+maintainer: travitch@cs.wisc.edu
+category: Data
+build-type: Custom
+tested-with: GHC == 7.6.3
+cabal-version: >=1.10
+Description: This package converts the LLVM IR (either bitcode files or LLVM
+             assembly) into a Haskell data type (defined in llvm-base-types).
+             The conversion uses the LLVM libraries to read bitcode.  It then
+             traverses the IR and produces a Haskell structure that can be
+             pattern matched against in pure code.
+
+             Note that this library works with LLVM 3.0-3.3.
+
+             There are incompatible changes in this release relative to
+             llvm-data-interop 0.2.0.  See the changelog in llvm-analysis-0.3.0.
+
+extra-source-files: configure,
+                    llvm-data-interop.buildinfo.in,
+                    src/c++/marshal.h,
+                    README.md
+
+library
+  default-language: Haskell2010
+  build-depends: base == 4.*,
+                 data-default >= 0.3,
+                 mtl > 2,
+                 hashable >= 1.1.2.0,
+                 llvm-base-types >= 0.3.0,
+                 loch-th >= 0.2,
+                 unification-fd >= 0.8,
+                 unordered-containers >= 0.2.1.0,
+                 hashtables, vector, transformers, text,
+                 array, bytestring, containers, dwarf, deepseq
+  other-modules: LLVM.Internal.Interop
+                 LLVM.Internal.TypeUnification
+  exposed-modules: LLVM.Parse
+  build-tools: c2hs
+  c-sources: src/c++/marshal.cpp
+  extra-libraries: stdc++
+  ghc-options: -Wall
+  ghc-prof-options: -auto-all
+  include-dirs: src
+  hs-source-dirs: src
+  cc-options: -fvisibility-inlines-hidden -fvisibility=hidden
diff --git a/src/LLVM/Internal/Interop.chs b/src/LLVM/Internal/Interop.chs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Internal/Interop.chs
@@ -0,0 +1,644 @@
+{-# LANGUAGE ForeignFunctionInterface, DeriveDataTypeable, RankNTypes, OverloadedStrings, CPP #-}
+module LLVM.Internal.Interop where
+
+import Control.Applicative
+import Control.Monad ( when )
+import Control.Monad.Trans ( MonadIO, liftIO )
+import Data.Array.Storable ( getElems )
+#if __GLASGOW_HASKELL__ >= 704
+import Data.Array.Unsafe ( unsafeForeignPtrToStorableArray )
+#else
+import Data.Array.Storable ( unsafeForeignPtrToStorableArray )
+#endif
+import qualified Data.ByteString.Char8 as BS
+import Data.Int
+import Data.Text ( Text )
+import Data.Text.Encoding ( decodeUtf8 )
+import Foreign.C
+import Foreign.ForeignPtr
+import Foreign.Marshal.Utils
+import Foreign.Ptr
+import Foreign.Storable
+
+import Data.LLVM.Types
+
+#include "c++/marshal.h"
+
+{#enum TypeTag {} deriving (Show, Eq) #}
+{#enum ValueTag {underscoreToCase} deriving (Show, Eq) #}
+{#enum MetaTag {underscoreToCase} deriving (Show, Eq) #}
+
+data CModule
+{#pointer *CModule as ModulePtr -> CModule #}
+
+makeText :: CString -> IO Text
+makeText p = do
+  s <- BS.packCString p
+  return (decodeUtf8 s)
+
+cModuleIdentifier :: ModulePtr -> IO Text
+cModuleIdentifier m = ({#get CModule->moduleIdentifier#} m) >>= makeText
+
+cModuleDataLayout :: ModulePtr -> IO Text
+cModuleDataLayout m = ({#get CModule->moduleDataLayout#} m) >>= makeText
+
+cModuleTargetTriple :: ModulePtr -> IO Text
+cModuleTargetTriple m = ({#get CModule->targetTriple#} m) >>= makeText
+
+cModuleInlineAsm :: ModulePtr -> IO Text
+cModuleInlineAsm m = ({#get CModule->moduleInlineAsm#} m) >>= makeText
+
+cModuleHasError :: ModulePtr -> IO Bool
+cModuleHasError m = toBool <$> ({#get CModule->hasError#} m)
+
+cModuleErrorMessage :: ModulePtr -> IO (Maybe String)
+cModuleErrorMessage m = do
+  hasError <- cModuleHasError m
+  case hasError of
+    True -> do
+      msgPtr <- ({#get CModule->errMsg#} m)
+      s <- peekCString msgPtr
+      return (Just s)
+    False -> return Nothing
+
+cModuleLittleEndian :: ModulePtr -> IO Bool
+cModuleLittleEndian m = toBool <$> ({#get CModule->littleEndian#} m)
+
+cModulePointerSize :: ModulePtr -> IO Int
+cModulePointerSize m = fromIntegral <$> ({#get CModule->pointerSize#} m)
+
+cModuleGlobalVariables :: ModulePtr -> IO [ValuePtr]
+cModuleGlobalVariables m =
+  peekArray m {#get CModule->globalVariables#} {#get CModule->numGlobalVariables#}
+
+cModuleGlobalAliases :: ModulePtr -> IO [ValuePtr]
+cModuleGlobalAliases m =
+  peekArray m ({#get CModule->globalAliases#}) ({#get CModule->numGlobalAliases#})
+
+cModuleFunctions :: ModulePtr -> IO [ValuePtr]
+cModuleFunctions m =
+  peekArray m ({#get CModule->functions#}) ({#get CModule->numFunctions#})
+
+cModuleEnumMetadata :: ModulePtr -> IO [MetaPtr]
+cModuleEnumMetadata m =
+  peekArray m {#get CModule->enumMetadata#} {#get CModule->numEnumMetadata#}
+
+cModuleRetainedTypeMetadata :: ModulePtr -> IO [MetaPtr]
+cModuleRetainedTypeMetadata m =
+  peekArray m {#get CModule->retainedTypeMetadata#} {#get CModule->numRetainedTypes#}
+
+cModuleTypes :: ModulePtr -> IO [TypePtr]
+cModuleTypes m =
+  peekArray m {#get CModule->types#} {#get CModule->numTypes#}
+
+peekArray :: forall a b c e . (Integral c, Storable e) =>
+             a -> (a -> IO (Ptr b)) -> (a -> IO c) -> IO [e]
+peekArray obj arrAccessor sizeAccessor = do
+  nElts <- sizeAccessor obj
+  arrPtr <- arrAccessor obj
+  case nElts == 0 || arrPtr == nullPtr of
+    True -> return []
+    False -> do
+      fArrPtr <- newForeignPtr_ (castPtr arrPtr)
+      let elementCount :: Int
+          elementCount = fromIntegral nElts
+      arr <- unsafeForeignPtrToStorableArray fArrPtr (1, elementCount)
+      getElems arr
+
+data CType
+{#pointer *CType as TypePtr -> CType #}
+cTypeTag :: TypePtr -> IO TypeTag
+cTypeTag t = toEnum . fromIntegral <$> {#get CType->typeTag#} t
+cTypeSize :: TypePtr -> IO Int
+cTypeSize t = fromIntegral <$> {#get CType->size#} t
+cTypeIsVarArg :: TypePtr -> IO Bool
+cTypeIsVarArg t = toBool <$> {#get CType->isVarArg#} t
+cTypeIsPacked :: TypePtr -> IO Bool
+cTypeIsPacked t = toBool <$> {#get CType->isPacked#} t
+cTypeList :: TypePtr -> IO [TypePtr]
+cTypeList t =
+  peekArray t {#get CType->typeList#} {#get CType->typeListLen#}
+cTypeInner :: TypePtr -> IO TypePtr
+cTypeInner = {#get CType->innerType#}
+cTypeName :: TypePtr -> IO (Maybe String)
+cTypeName t = do
+  n <- optionalField {#get CType->name#} t
+  case n of
+    Nothing -> return Nothing
+    Just n' -> do
+      s <- peekCString n'
+      return (Just s)
+cTypeAddrSpace :: TypePtr -> IO Int
+cTypeAddrSpace t = fromIntegral <$> {#get CType->addrSpace#} t
+
+cTypeSizeInBytes :: TypePtr -> IO Int
+cTypeSizeInBytes t = fromIntegral <$> {#get CType->sizeInBytes#} t
+
+data CValue
+{#pointer *CValue as ValuePtr -> CValue #}
+data CMeta
+{#pointer *CMeta as MetaPtr -> CMeta #}
+
+cValueTag :: ValuePtr -> IO ValueTag
+cValueTag v = toEnum . fromIntegral <$> ({#get CValue->valueTag#} v)
+cValueType :: ValuePtr -> IO TypePtr
+cValueType = {#get CValue->valueType#}
+cValueName :: (InternString m) => ValuePtr -> m (Maybe Identifier)
+cValueName v = do
+  tag <- liftIO $ cValueTag v
+  namePtr <- liftIO $ ({#get CValue->name#}) v
+  case namePtr == nullPtr of
+    True -> return Nothing
+    False -> do
+      rawName <- liftIO $ makeText namePtr
+      name <- internString rawName
+      rawIdent <- case tag of
+        ValFunction -> return $! makeGlobalIdentifier name
+        ValGlobalvariable -> return $! makeGlobalIdentifier name
+        ValAlias -> return $!  makeGlobalIdentifier name
+        _ -> return $! makeLocalIdentifier name
+      ident <- internIdentifier rawIdent
+      return $! (Just ident)
+cValueMetadata :: ValuePtr -> IO [MetaPtr]
+cValueMetadata v = peekArray v {#get CValue->md#} {#get CValue->numMetadata#}
+cValueSrcLoc :: ValuePtr -> IO MetaPtr
+cValueSrcLoc = {#get CValue->srcLoc#}
+cValueData :: ValuePtr -> IO (Ptr ())
+cValueData = {#get CValue->data#}
+
+
+cMetaTypeTag :: MetaPtr -> IO MetaTag
+cMetaTypeTag v = toEnum . fromIntegral <$> {#get CMeta->metaTag #} v
+
+cMetaTag :: MetaPtr -> IO DW_TAG
+cMetaTag p = do
+  t <- {#get CMeta->tag#} p
+  case dw_tag t of
+    Nothing -> return DW_TAG_unspecified_type
+    Just t' -> return t'
+
+cMetaArrayElts :: MetaPtr -> IO [Maybe MetaPtr]
+cMetaArrayElts p = map convertNull <$>
+  peekArray p {#get CMeta->u.metaArrayInfo.arrayElts#} {#get CMeta->u.metaArrayInfo.arrayLen#}
+  where
+    convertNull ptr =
+      case ptr == nullPtr of
+        True -> Nothing
+        False -> Just ptr
+
+cMetaEnumeratorName :: InternString m => MetaPtr -> m Text
+cMetaEnumeratorName = shareString {#get CMeta->u.metaEnumeratorInfo.enumName#}
+cMetaEnumeratorValue :: MetaPtr -> IO Int64
+cMetaEnumeratorValue p = fromIntegral <$> {#get CMeta->u.metaEnumeratorInfo.enumValue#} p
+cMetaGlobalContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaGlobalContext = optionalField {#get CMeta->u.metaGlobalInfo.context #}
+cMetaGlobalName :: InternString m => MetaPtr -> m Text
+cMetaGlobalName = shareString {#get CMeta->u.metaGlobalInfo.name#}
+cMetaGlobalDisplayName :: InternString m => MetaPtr -> m Text
+cMetaGlobalDisplayName = shareString {#get CMeta->u.metaGlobalInfo.displayName#}
+cMetaGlobalLinkageName :: InternString m => MetaPtr -> m Text
+cMetaGlobalLinkageName = shareString {#get CMeta->u.metaGlobalInfo.linkageName#}
+-- cMetaGlobalCompileUnit :: MetaPtr -> IO MetaPtr
+-- cMetaGlobalCompileUnit = {#get CMeta->u.metaGlobalInfo.compileUnit#}
+cMetaGlobalLine :: MetaPtr -> IO Int32
+cMetaGlobalLine p = fromIntegral <$> {#get CMeta->u.metaGlobalInfo.lineNumber#} p
+cMetaGlobalType :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaGlobalType = optionalField {#get CMeta->u.metaGlobalInfo.globalType#}
+cMetaGlobalIsLocal :: MetaPtr -> IO Bool
+cMetaGlobalIsLocal p = toBool <$> {#get CMeta->u.metaGlobalInfo.isLocalToUnit#} p
+cMetaGlobalIsDefinition :: MetaPtr -> IO Bool
+cMetaGlobalIsDefinition p = toBool <$> {#get CMeta->u.metaGlobalInfo.isDefinition#} p
+cMetaLocationLine :: MetaPtr -> IO Int32
+cMetaLocationLine p = fromIntegral <$> {#get CMeta->u.metaLocationInfo.lineNumber#} p
+cMetaLocationColumn :: MetaPtr -> IO Int32
+cMetaLocationColumn p = fromIntegral <$> {#get CMeta->u.metaLocationInfo.columnNumber#} p
+cMetaLocationScope :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaLocationScope = optionalField {#get CMeta->u.metaLocationInfo.scope#}
+cMetaSubrangeLo :: MetaPtr -> IO Int64
+cMetaSubrangeLo p = fromIntegral <$> {#get CMeta->u.metaSubrangeInfo.lo#} p
+cMetaSubrangeHi :: MetaPtr -> IO Int64
+cMetaSubrangeHi p = fromIntegral <$> {#get CMeta->u.metaSubrangeInfo.hi#} p
+cMetaTemplateTypeContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTemplateTypeContext = optionalField {#get CMeta->u.metaTemplateTypeInfo.context#}
+cMetaTemplateTypeName :: InternString m => MetaPtr -> m Text
+cMetaTemplateTypeName = shareString {#get CMeta->u.metaTemplateTypeInfo.name#}
+cMetaTemplateTypeType :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTemplateTypeType = optionalField {#get CMeta->u.metaTemplateTypeInfo.type#}
+cMetaTemplateTypeLine :: MetaPtr -> IO Int32
+cMetaTemplateTypeLine p = fromIntegral <$> {#get CMeta->u.metaTemplateTypeInfo.lineNumber#} p
+cMetaTemplateTypeColumn :: MetaPtr -> IO Int32
+cMetaTemplateTypeColumn p = fromIntegral <$> {#get CMeta->u.metaTemplateTypeInfo.columnNumber#} p
+cMetaTemplateValueContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTemplateValueContext = optionalField {#get CMeta->u.metaTemplateValueInfo.context#}
+cMetaTemplateValueName :: InternString m => MetaPtr -> m Text
+cMetaTemplateValueName = shareString {#get CMeta->u.metaTemplateValueInfo.name#}
+cMetaTemplateValueType :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTemplateValueType = optionalField {#get CMeta->u.metaTemplateValueInfo.type#}
+cMetaTemplateValueValue :: MetaPtr -> IO Int64
+cMetaTemplateValueValue p = fromIntegral <$> {#get CMeta->u.metaTemplateValueInfo.value#} p
+cMetaTemplateValueLine :: MetaPtr -> IO Int32
+cMetaTemplateValueLine p = fromIntegral <$> {#get CMeta->u.metaTemplateValueInfo.lineNumber#} p
+cMetaTemplateValueColumn :: MetaPtr -> IO Int32
+cMetaTemplateValueColumn p = fromIntegral <$> {#get CMeta->u.metaTemplateValueInfo.columnNumber#} p
+cMetaVariableContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaVariableContext = optionalField {#get CMeta->u.metaVariableInfo.context#}
+cMetaVariableName :: InternString m => MetaPtr -> m Text
+cMetaVariableName = shareString {#get CMeta->u.metaVariableInfo.name#}
+-- cMetaVariableCompileUnit :: MetaPtr -> IO MetaPtr
+-- cMetaVariableCompileUnit = {#get CMeta->u.metaVariableInfo.compileUnit#}
+cMetaVariableLine :: MetaPtr -> IO Int32
+cMetaVariableLine p = fromIntegral <$> {#get CMeta->u.metaVariableInfo.lineNumber#} p
+cMetaVariableArgNumber :: MetaPtr -> IO Int32
+cMetaVariableArgNumber p = fromIntegral <$> {#get CMeta->u.metaVariableInfo.argNumber#} p
+cMetaVariableType :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaVariableType = optionalField {#get CMeta->u.metaVariableInfo.type#}
+cMetaVariableIsArtificial :: MetaPtr -> IO Bool
+cMetaVariableIsArtificial p = toBool <$> {#get CMeta->u.metaVariableInfo.isArtificial#} p
+cMetaVariableHasComplexAddress :: MetaPtr -> IO Bool
+cMetaVariableHasComplexAddress p = toBool <$> {#get CMeta->u.metaVariableInfo.hasComplexAddress #} p
+cMetaVariableAddrElements :: MetaPtr -> IO [Int64]
+cMetaVariableAddrElements p = do
+  ca <- cMetaVariableHasComplexAddress p
+  case ca of
+    True -> peekArray p {#get CMeta->u.metaVariableInfo.addrElements#} {#get CMeta->u.metaVariableInfo.numAddrElements#}
+    False -> return []
+cMetaVariableIsBlockByRefVar :: MetaPtr -> IO Bool
+cMetaVariableIsBlockByRefVar p = toBool <$> {#get CMeta->u.metaVariableInfo.isBlockByRefVar#} p
+cMetaCompileUnitLanguage :: MetaPtr -> IO DW_LANG
+cMetaCompileUnitLanguage p = dw_lang <$> {#get CMeta->u.metaCompileUnitInfo.language#} p
+cMetaCompileUnitFilename :: InternString m => MetaPtr -> m Text
+cMetaCompileUnitFilename = shareString {#get CMeta->u.metaCompileUnitInfo.filename#}
+cMetaCompileUnitDirectory :: InternString m => MetaPtr -> m Text
+cMetaCompileUnitDirectory = shareString {#get CMeta->u.metaCompileUnitInfo.directory#}
+cMetaCompileUnitProducer :: InternString m => MetaPtr -> m Text
+cMetaCompileUnitProducer = shareString {#get CMeta->u.metaCompileUnitInfo.producer#}
+cMetaCompileUnitIsMain :: MetaPtr -> IO Bool
+cMetaCompileUnitIsMain p = toBool <$> {#get CMeta->u.metaCompileUnitInfo.isMain#} p
+cMetaCompileUnitIsOptimized :: MetaPtr -> IO Bool
+cMetaCompileUnitIsOptimized p = toBool <$> {#get CMeta->u.metaCompileUnitInfo.isOptimized#} p
+cMetaCompileUnitFlags :: InternString m => MetaPtr -> m Text
+cMetaCompileUnitFlags = shareString {#get CMeta->u.metaCompileUnitInfo.flags#}
+cMetaCompileUnitRuntimeVersion :: MetaPtr -> IO Int32
+cMetaCompileUnitRuntimeVersion p = fromIntegral <$> {#get CMeta->u.metaCompileUnitInfo.runtimeVersion#} p
+cMetaCompileUnitEnumTypes :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaCompileUnitEnumTypes = optionalField {#get CMeta->u.metaCompileUnitInfo.enumTypes#}
+cMetaCompileUnitRetainedTypes :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaCompileUnitRetainedTypes = optionalField {#get CMeta->u.metaCompileUnitInfo.retainedTypes#}
+cMetaCompileUnitSubprograms :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaCompileUnitSubprograms = optionalField {#get CMeta->u.metaCompileUnitInfo.subprograms#}
+cMetaCompileUnitGlobalVariables :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaCompileUnitGlobalVariables = optionalField {#get CMeta->u.metaCompileUnitInfo.globalVariables#}
+cMetaFileFilename :: InternString m => MetaPtr -> m Text
+cMetaFileFilename = shareString {#get CMeta->u.metaFileInfo.filename#}
+cMetaFileDirectory :: InternString m => MetaPtr -> m Text
+cMetaFileDirectory = shareString {#get CMeta->u.metaFileInfo.directory#}
+-- cMetaFileCompileUnit :: MetaPtr -> IO MetaPtr
+-- cMetaFileCompileUnit = {#get CMeta->u.metaFileInfo.compileUnit#}
+cMetaLexicalBlockContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaLexicalBlockContext = optionalField {#get CMeta->u.metaLexicalBlockInfo.context#}
+cMetaLexicalBlockLine :: MetaPtr -> IO Int32
+cMetaLexicalBlockLine p = fromIntegral <$> {#get CMeta->u.metaLexicalBlockInfo.lineNumber#} p
+cMetaLexicalBlockColumn :: MetaPtr -> IO Int32
+cMetaLexicalBlockColumn p = fromIntegral <$> {#get CMeta->u.metaLexicalBlockInfo.columnNumber#} p
+cMetaNamespaceContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaNamespaceContext = optionalField {#get CMeta->u.metaNamespaceInfo.context#}
+cMetaNamespaceName :: InternString m => MetaPtr -> m Text
+cMetaNamespaceName = shareString {#get CMeta->u.metaNamespaceInfo.name#}
+-- cMetaNamespaceCompileUnit :: MetaPtr -> IO MetaPtr
+-- cMetaNamespaceCompileUnit = {#get CMeta->u.metaNamespaceInfo.compileUnit#}
+cMetaNamespaceLine :: MetaPtr -> IO Int32
+cMetaNamespaceLine p = fromIntegral <$> {#get CMeta->u.metaNamespaceInfo.lineNumber#} p
+cMetaSubprogramContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaSubprogramContext = optionalField {#get CMeta->u.metaSubprogramInfo.context#}
+cMetaSubprogramName :: InternString m => MetaPtr -> m Text
+cMetaSubprogramName = shareString {#get CMeta->u.metaSubprogramInfo.name#}
+cMetaSubprogramDisplayName :: InternString m => MetaPtr -> m Text
+cMetaSubprogramDisplayName = shareString {#get CMeta->u.metaSubprogramInfo.displayName#}
+cMetaSubprogramLinkageName :: InternString m => MetaPtr -> m Text
+cMetaSubprogramLinkageName = shareString {#get CMeta->u.metaSubprogramInfo.linkageName#}
+-- cMetaSubprogramCompileUnit :: MetaPtr -> IO MetaPtr
+-- cMetaSubprogramCompileUnit = {#get CMeta->u.metaSubprogramInfo.compileUnit#}
+cMetaSubprogramLine :: MetaPtr -> IO Int32
+cMetaSubprogramLine p = fromIntegral <$> {#get CMeta->u.metaSubprogramInfo.lineNumber#} p
+cMetaSubprogramType :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaSubprogramType = optionalField {#get CMeta->u.metaSubprogramInfo.type#}
+cMetaSubprogramIsLocal :: MetaPtr -> IO Bool
+cMetaSubprogramIsLocal p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isLocalToUnit#} p
+cMetaSubprogramIsDefinition :: MetaPtr -> IO Bool
+cMetaSubprogramIsDefinition p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isDefinition#} p
+cMetaSubprogramVirtuality :: MetaPtr -> IO DW_VIRTUALITY
+cMetaSubprogramVirtuality p = dw_virtuality <$> {#get CMeta->u.metaSubprogramInfo.virtuality#} p
+cMetaSubprogramVirtualIndex :: MetaPtr -> IO Int32
+cMetaSubprogramVirtualIndex p = fromIntegral <$> {#get CMeta->u.metaSubprogramInfo.virtualIndex#} p
+cMetaSubprogramContainingType :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaSubprogramContainingType = optionalField {#get CMeta->u.metaSubprogramInfo.containingType#}
+cMetaSubprogramIsArtificial :: MetaPtr -> IO Bool
+cMetaSubprogramIsArtificial p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isArtificial#} p
+cMetaSubprogramIsPrivate :: MetaPtr -> IO Bool
+cMetaSubprogramIsPrivate p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isPrivate#} p
+cMetaSubprogramIsProtected :: MetaPtr -> IO Bool
+cMetaSubprogramIsProtected p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isProtected#} p
+cMetaSubprogramIsExplicit :: MetaPtr -> IO Bool
+cMetaSubprogramIsExplicit p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isExplicit#} p
+cMetaSubprogramIsPrototyped :: MetaPtr -> IO Bool
+cMetaSubprogramIsPrototyped p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isPrototyped#} p
+cMetaSubprogramIsOptimized :: MetaPtr -> IO Bool
+cMetaSubprogramIsOptimized p = toBool <$> {#get CMeta->u.metaSubprogramInfo.isOptimized#} p
+cMetaTypeContext :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTypeContext = optionalField {#get CMeta->u.metaTypeInfo.context#}
+cMetaTypeName :: InternString m => MetaPtr -> m Text
+cMetaTypeName = shareString {#get CMeta->u.metaTypeInfo.name#}
+-- cMetaTypeCompileUnit :: MetaPtr -> IO (Maybe MetaPtr)
+-- cMetaTypeCompileUnit = optionalField {#get CMeta->u.metaTypeInfo.compileUnit#}
+-- cMetaTypeFile :: MetaPtr -> IO (Maybe MetaPtr)
+-- cMetaTypeFile = optionalField {#get CMeta->u.metaTypeInfo.file#}
+cMetaTypeLine :: MetaPtr -> IO Int32
+cMetaTypeLine p = fromIntegral <$> {#get CMeta->u.metaTypeInfo.lineNumber#} p
+cMetaTypeSize :: MetaPtr -> IO Int64
+cMetaTypeSize p = fromIntegral <$> {#get CMeta->u.metaTypeInfo.sizeInBits#} p
+cMetaTypeAlign :: MetaPtr -> IO Int64
+cMetaTypeAlign p = fromIntegral <$> {#get CMeta->u.metaTypeInfo.alignInBits#} p
+cMetaTypeOffset :: MetaPtr -> IO Int64
+cMetaTypeOffset p = fromIntegral <$> {#get CMeta->u.metaTypeInfo.offsetInBits#} p
+cMetaTypeFlags :: MetaPtr -> IO Int32
+cMetaTypeFlags p = fromIntegral <$> {#get CMeta->u.metaTypeInfo.flags#} p
+cMetaTypeIsPrivate :: MetaPtr -> IO Bool
+cMetaTypeIsPrivate p = toBool <$> {#get CMeta->u.metaTypeInfo.isPrivate#} p
+cMetaTypeIsProtected :: MetaPtr -> IO Bool
+cMetaTypeIsProtected p = toBool <$> {#get CMeta->u.metaTypeInfo.isProtected#} p
+cMetaTypeIsForward :: MetaPtr -> IO Bool
+cMetaTypeIsForward p = toBool <$> {#get CMeta->u.metaTypeInfo.isForward#} p
+cMetaTypeIsByRefStruct :: MetaPtr -> IO Bool
+cMetaTypeIsByRefStruct p = toBool <$> {#get CMeta->u.metaTypeInfo.isByRefStruct#} p
+cMetaTypeIsVirtual :: MetaPtr -> IO Bool
+cMetaTypeIsVirtual p = toBool <$> {#get CMeta->u.metaTypeInfo.isVirtual#} p
+cMetaTypeIsArtificial :: MetaPtr -> IO Bool
+cMetaTypeIsArtificial p = toBool <$> {#get CMeta->u.metaTypeInfo.isArtificial#} p
+cMetaTypeDirectory :: InternString m => MetaPtr -> m Text
+cMetaTypeDirectory = shareString {#get CMeta->u.metaTypeInfo.directory#}
+cMetaTypeFilename :: InternString m => MetaPtr -> m Text
+cMetaTypeFilename = shareString {#get CMeta->u.metaTypeInfo.filename#}
+cMetaTypeEncoding :: MetaPtr -> IO DW_ATE
+cMetaTypeEncoding p = dw_ate <$> {#get CMeta->u.metaTypeInfo.encoding#} p
+cMetaTypeDerivedFrom :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTypeDerivedFrom = optionalField {#get CMeta->u.metaTypeInfo.typeDerivedFrom#}
+cMetaTypeCompositeComponents :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTypeCompositeComponents = optionalField {#get CMeta->u.metaTypeInfo.typeArray#}
+cMetaTypeRuntimeLanguage :: MetaPtr -> IO Int32
+cMetaTypeRuntimeLanguage p = fromIntegral <$> {#get CMeta->u.metaTypeInfo.runTimeLang#} p
+cMetaTypeContainingType :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTypeContainingType = optionalField {#get CMeta->u.metaTypeInfo.containingType#}
+cMetaTypeTemplateParams :: MetaPtr -> IO (Maybe MetaPtr)
+cMetaTypeTemplateParams = optionalField {#get CMeta->u.metaTypeInfo.templateParams#}
+cMetaUnknownRepr :: InternString m => MetaPtr -> m Text
+cMetaUnknownRepr = shareString {#get CMeta->u.metaUnknownInfo.repr#}
+
+optionalField :: (a -> IO (Ptr b)) -> a -> IO (Maybe (Ptr b))
+optionalField accessor p = do
+  v <- accessor p
+  case v == nullPtr of
+    True -> return Nothing
+    False -> return (Just v)
+
+class MonadIO m => InternString m where
+  internString :: Text -> m Text
+  internIdentifier :: Identifier -> m Identifier
+
+-- | This helper converts C char* strings into Texts, sharing
+-- identical bytestrings on the Haskell side.  This is a simple
+-- space-saving optimization (assuming the entire cache is garbage
+-- collected)
+shareString :: InternString m => (a -> IO CString) -> a -> m Text
+shareString accessor ptr = do
+  sp <- liftIO $ accessor ptr
+  str <- case sp == nullPtr of
+    False -> liftIO $ BS.packCString sp
+    True -> return $ BS.pack ""
+  internString (decodeUtf8 str)
+
+data CGlobalInfo
+{#pointer *CGlobalInfo as GlobalInfoPtr -> CGlobalInfo #}
+cGlobalIsExternal :: GlobalInfoPtr -> IO Bool
+cGlobalIsExternal g = toBool <$> ({#get CGlobalInfo->isExternal#} g)
+cGlobalAlignment :: GlobalInfoPtr -> IO Int64
+cGlobalAlignment g = fromIntegral <$> ({#get CGlobalInfo->alignment#} g)
+cGlobalVisibility :: GlobalInfoPtr -> IO VisibilityStyle
+cGlobalVisibility g = toEnum . fromIntegral <$> ({#get CGlobalInfo->visibility#} g)
+cGlobalLinkage :: GlobalInfoPtr -> IO LinkageType
+cGlobalLinkage g = toEnum . fromIntegral <$> ({#get CGlobalInfo->linkage#} g)
+cGlobalSection :: GlobalInfoPtr -> IO (Maybe Text)
+cGlobalSection g = do
+  s <- {#get CGlobalInfo->section#} g
+  case s == nullPtr of
+    True -> return Nothing
+    False -> do
+      bs <- BS.packCString s
+      return $! Just (decodeUtf8 bs)
+cGlobalInitializer :: GlobalInfoPtr -> IO ValuePtr
+cGlobalInitializer = {#get CGlobalInfo->initializer#}
+cGlobalIsThreadLocal :: GlobalInfoPtr -> IO Bool
+cGlobalIsThreadLocal g = toBool <$> ({#get CGlobalInfo->isThreadLocal#} g)
+cGlobalAliasee :: GlobalInfoPtr -> IO ValuePtr
+cGlobalAliasee = {#get CGlobalInfo->aliasee#}
+cGlobalIsConstant :: GlobalInfoPtr -> IO Bool
+cGlobalIsConstant g = toBool <$> {#get CGlobalInfo->isConstant#} g
+
+data CFunctionInfo
+{#pointer *CFunctionInfo as FunctionInfoPtr -> CFunctionInfo #}
+cFunctionIsExternal :: FunctionInfoPtr -> IO Bool
+cFunctionIsExternal f = toBool <$> {#get CFunctionInfo->isExternal#} f
+cFunctionAlignment :: FunctionInfoPtr -> IO Int64
+cFunctionAlignment f = fromIntegral <$> {#get CFunctionInfo->alignment#} f
+cFunctionVisibility :: FunctionInfoPtr -> IO VisibilityStyle
+cFunctionVisibility f = toEnum . fromIntegral <$> {#get CFunctionInfo->visibility#} f
+cFunctionLinkage :: FunctionInfoPtr -> IO LinkageType
+cFunctionLinkage f = toEnum . fromIntegral <$> {#get CFunctionInfo->linkage#} f
+cFunctionSection :: FunctionInfoPtr -> IO (Maybe Text)
+cFunctionSection f = do
+  s <- {#get CFunctionInfo->section#} f
+  case s == nullPtr of
+    True -> return Nothing
+    False -> do
+      bs <- BS.packCString s
+      return $! Just (decodeUtf8 bs)
+cFunctionIsVarArg :: FunctionInfoPtr -> IO Bool
+cFunctionIsVarArg f = toBool <$> {#get CFunctionInfo->isVarArg#} f
+cFunctionCallingConvention :: FunctionInfoPtr -> IO CallingConvention
+cFunctionCallingConvention f = toEnum . fromIntegral <$> {#get CFunctionInfo->callingConvention#} f
+cFunctionGCName :: FunctionInfoPtr -> IO (Maybe Text)
+cFunctionGCName f = do
+  s <- {#get CFunctionInfo->gcName#} f
+  case s == nullPtr of
+    True -> return Nothing
+    False -> do
+      bs <- BS.packCString s
+      return $! Just (decodeUtf8 bs)
+cFunctionArguments :: FunctionInfoPtr -> IO [ValuePtr]
+cFunctionArguments f =
+  peekArray f {#get CFunctionInfo->arguments#} {#get CFunctionInfo->argListLen#}
+cFunctionBlocks :: FunctionInfoPtr -> IO [ValuePtr]
+cFunctionBlocks f =
+  peekArray f {#get CFunctionInfo->body#} {#get CFunctionInfo->blockListLen#}
+
+data CArgInfo
+{#pointer *CArgumentInfo as ArgInfoPtr -> CArgInfo #}
+cArgInfoHasSRet :: ArgInfoPtr -> IO Bool
+cArgInfoHasSRet a = toBool <$> ({#get CArgumentInfo->hasSRet#} a)
+cArgInfoHasByVal :: ArgInfoPtr -> IO Bool
+cArgInfoHasByVal a = toBool <$> ({#get CArgumentInfo->hasByVal#} a)
+cArgInfoHasNest :: ArgInfoPtr -> IO Bool
+cArgInfoHasNest a = toBool <$> ({#get CArgumentInfo->hasNest#} a)
+cArgInfoHasNoAlias :: ArgInfoPtr -> IO Bool
+cArgInfoHasNoAlias a = toBool <$> ({#get CArgumentInfo->hasNoAlias#} a)
+cArgInfoHasNoCapture :: ArgInfoPtr -> IO Bool
+cArgInfoHasNoCapture a = toBool <$> ({#get CArgumentInfo->hasNoCapture#} a)
+
+data CBasicBlockInfo
+{#pointer *CBasicBlockInfo as BasicBlockPtr -> CBasicBlockInfo #}
+
+cBasicBlockInstructions :: BasicBlockPtr -> IO [ValuePtr]
+cBasicBlockInstructions b =
+  peekArray b {#get CBasicBlockInfo->instructions#} {#get CBasicBlockInfo->blockLen#}
+
+data CInlineAsmInfo
+{#pointer *CInlineAsmInfo as InlineAsmInfoPtr -> CInlineAsmInfo #}
+
+cInlineAsmString :: InlineAsmInfoPtr -> IO Text
+cInlineAsmString a =
+  ({#get CInlineAsmInfo->asmString#} a) >>= makeText
+cInlineAsmConstraints :: InlineAsmInfoPtr -> IO Text
+cInlineAsmConstraints a =
+  ({#get CInlineAsmInfo->constraintString#} a) >>= makeText
+
+data CBlockAddrInfo
+{#pointer *CBlockAddrInfo as BlockAddrInfoPtr -> CBlockAddrInfo #}
+
+cBlockAddrFunc :: BlockAddrInfoPtr -> IO ValuePtr
+cBlockAddrFunc = {#get CBlockAddrInfo->func #}
+cBlockAddrBlock :: BlockAddrInfoPtr -> IO ValuePtr
+cBlockAddrBlock = {#get CBlockAddrInfo->block #}
+
+data CAggregateInfo
+{#pointer *CConstAggregate as AggregateInfoPtr -> CAggregateInfo #}
+
+cAggregateValues :: AggregateInfoPtr -> IO [ValuePtr]
+cAggregateValues a =
+  peekArray a {#get CConstAggregate->constants#} {#get CConstAggregate->numElements#}
+
+data CConstFP
+{#pointer *CConstFP as FPInfoPtr -> CConstFP #}
+cFPVal :: FPInfoPtr -> IO Double
+cFPVal f = realToFrac <$> ({#get CConstFP->val#} f)
+
+data CConstInt
+{#pointer *CConstInt as IntInfoPtr -> CConstInt #}
+cIntVal :: IntInfoPtr -> IO Integer
+cIntVal i = fromIntegral <$> ({#get CConstInt->val#} i)
+cIntHugeVal :: IntInfoPtr -> IO (Maybe Integer)
+cIntHugeVal i = do
+  s <- {#get CConstInt->hugeVal#} i
+  case s == nullPtr of
+    True -> return Nothing
+    False -> (Just . read) <$> peekCString s
+
+data CInstructionInfo
+{#pointer *CInstructionInfo as InstInfoPtr -> CInstructionInfo #}
+cInstructionOperands :: InstInfoPtr -> IO [ValuePtr]
+cInstructionOperands i =
+  peekArray i {#get CInstructionInfo->operands#} {#get CInstructionInfo->numOperands#}
+cInstructionArithFlags :: InstInfoPtr -> IO ArithFlags
+cInstructionArithFlags o = toEnum . fromIntegral <$> {#get CInstructionInfo->flags#} o
+cInstructionAlign :: InstInfoPtr -> IO Int64
+cInstructionAlign u = fromIntegral <$> {#get CInstructionInfo->align#} u
+cInstructionIsVolatile :: InstInfoPtr -> IO Bool
+cInstructionIsVolatile u = toBool <$> {#get CInstructionInfo->isVolatile#} u
+cInstructionAddrSpace :: InstInfoPtr -> IO Int
+cInstructionAddrSpace u = fromIntegral <$> {#get CInstructionInfo->addrSpace#} u
+cInstructionCmpPred :: InstInfoPtr -> IO CmpPredicate
+cInstructionCmpPred c = toEnum . fromIntegral <$> {#get CInstructionInfo->cmpPred#} c
+cInstructionInBounds :: InstInfoPtr -> IO Bool
+cInstructionInBounds g = toBool <$> {#get CInstructionInfo->inBounds#} g
+cInstructionIndices :: InstInfoPtr -> IO [Int]
+cInstructionIndices i =
+  peekArray i {#get CInstructionInfo->indices#} {#get CInstructionInfo->numIndices#}
+
+data CConstExprInfo
+{#pointer *CConstExprInfo as ConstExprPtr -> CConstExprInfo #}
+cConstExprTag :: ConstExprPtr -> IO ValueTag
+cConstExprTag e = toEnum . fromIntegral <$> {#get CConstExprInfo->instrType#} e
+cConstExprInstInfo :: ConstExprPtr -> IO InstInfoPtr
+cConstExprInstInfo = {#get CConstExprInfo->ii#}
+
+data CPHIInfo
+{#pointer *CPHIInfo as PHIInfoPtr -> CPHIInfo #}
+cPHIValues :: PHIInfoPtr -> IO [ValuePtr]
+cPHIValues p =
+  peekArray p {#get CPHIInfo->incomingValues#} {#get CPHIInfo->numIncomingValues#}
+cPHIBlocks :: PHIInfoPtr -> IO [ValuePtr]
+cPHIBlocks p =
+  peekArray p {#get CPHIInfo->valueBlocks#} {#get CPHIInfo->numIncomingValues#}
+
+data CCallInfo
+{#pointer *CCallInfo as CallInfoPtr -> CCallInfo #}
+cCallValue :: CallInfoPtr -> IO ValuePtr
+cCallValue = {#get CCallInfo->calledValue #}
+cCallArguments :: CallInfoPtr -> IO [ValuePtr]
+cCallArguments c =
+  peekArray c {#get CCallInfo->arguments#} {#get CCallInfo->argListLen#}
+cCallConvention :: CallInfoPtr -> IO CallingConvention
+cCallConvention c = toEnum . fromIntegral <$> {#get CCallInfo->callingConvention#} c
+cCallHasSRet :: CallInfoPtr -> IO Bool
+cCallHasSRet c = toBool <$> {#get CCallInfo->hasSRet#} c
+cCallIsTail :: CallInfoPtr -> IO Bool
+cCallIsTail c = toBool <$> {#get CCallInfo->isTail#} c
+cCallUnwindDest :: CallInfoPtr -> IO ValuePtr
+cCallUnwindDest = {#get CCallInfo->unwindDest#}
+cCallNormalDest :: CallInfoPtr -> IO ValuePtr
+cCallNormalDest = {#get CCallInfo->normalDest#}
+
+data CAtomicInfo
+{#pointer *CAtomicInfo as AtomicInfoPtr -> CAtomicInfo #}
+cAtomicOrdering :: AtomicInfoPtr -> IO AtomicOrdering
+cAtomicOrdering ai = toEnum . fromIntegral <$> {#get CAtomicInfo->ordering#} ai
+cAtomicScope :: AtomicInfoPtr -> IO SynchronizationScope
+cAtomicScope ai = toEnum . fromIntegral <$> {#get CAtomicInfo->scope#} ai
+cAtomicOperation :: AtomicInfoPtr -> IO AtomicOperation
+cAtomicOperation ai = toEnum . fromIntegral <$> {#get CAtomicInfo->operation#} ai
+cAtomicIsVolatile :: AtomicInfoPtr -> IO Bool
+cAtomicIsVolatile ai = toBool <$> {#get CAtomicInfo->isVolatile#} ai
+cAtomicAddressSpace :: AtomicInfoPtr -> IO Int
+cAtomicAddressSpace ai = fromIntegral <$> {#get CAtomicInfo->addrSpace#} ai
+cAtomicPointerOperand :: AtomicInfoPtr -> IO ValuePtr
+cAtomicPointerOperand = {#get CAtomicInfo->pointerOperand#}
+cAtomicValueOperand :: AtomicInfoPtr -> IO ValuePtr
+cAtomicValueOperand = {#get CAtomicInfo->valueOperand#}
+cAtomicCompareOperand :: AtomicInfoPtr -> IO ValuePtr
+cAtomicCompareOperand = {#get CAtomicInfo->compareOperand#}
+
+data CLandingPadInfo
+{#pointer *CLandingPadInfo as LandingPadInfoPtr -> CLandingPadInfo#}
+cLandingPadPersonality :: LandingPadInfoPtr -> IO ValuePtr
+cLandingPadPersonality = {#get CLandingPadInfo->personality#}
+cLandingPadIsCleanup :: LandingPadInfoPtr -> IO Bool
+cLandingPadIsCleanup li = toBool <$> {#get CLandingPadInfo->isCleanup#} li
+cLandingPadClauses :: LandingPadInfoPtr -> IO [ValuePtr]
+cLandingPadClauses li =
+  peekArray li {#get CLandingPadInfo->clauses #} {#get CLandingPadInfo->numClauses#}
+cLandingPadClauseTypes :: LandingPadInfoPtr -> IO [LandingPadClause]
+cLandingPadClauseTypes li = do
+  arr <- peekArray li {#get CLandingPadInfo->clauseTypes #} {#get CLandingPadInfo->numClauses#}
+  return $ map toEnum arr
+
+-- | Parse the named file into an FFI-friendly representation of an
+-- LLVM module.
+{#fun marshalLLVM { id `Ptr CChar', `Int',  fromBool `Bool' } -> `ModulePtr' id #}
+{#fun marshalLLVMFile { `String', fromBool `Bool' } -> `ModulePtr' id #}
+
+-- | Free all of the resources allocated by 'marshalLLVM'
+{#fun disposeCModule { id `ModulePtr' } -> `()' #}
+
+-- Helpers
+
+-- This only seems to be necessary on i386 for some reason.
+cIntConv :: (Integral a, Num b) => a -> b
+cIntConv = fromIntegral
diff --git a/src/LLVM/Internal/TypeUnification.hs b/src/LLVM/Internal/TypeUnification.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Internal/TypeUnification.hs
@@ -0,0 +1,416 @@
+{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
+{-# LANGUAGE FlexibleContexts, TemplateHaskell #-}
+-- | This module defines a function to perform unification of LLVM types.
+--
+-- The unification step is intended to eliminate duplicate struct
+-- definitions wherever possible.  Duplicate structs have .NNN
+-- suffixes after their names and are constructed by the linker when
+-- it cannot prove that types are equivalent.
+--
+-- In theory, llvm-link should do this (and it does try).  However,
+-- the implementation in llvm-link is poor and gives up on even
+-- trivial cases.  This implementation is a bit more robust and
+-- sensitive to some frontend quirks.
+--
+-- This is a low-level implementation that is run at IR translation
+-- time.  The result of 'unifyTypes' is a map from CType pointers to
+-- Type objects.  This map can be used at IR construction time to map each
+-- C type to a canonical high-level representation if at all possible.
+--
+--  * Opaque types are eliminated if there is a core of unifiable
+--    definitions of types with the same name
+--
+--  * A canonical representative is chosen for each base type name
+--
+-- Moving this analysis to very early in the translation process has
+-- two major benefits: 1) all higher-level analyses can do type-level
+-- comparisons without ad-hoc normalization steps, and 2) the knot
+-- tying process in the IR translation is simpler because types are
+-- already fully resolved.
+--
+-- TODO: This could be made more configurable for more aggressive
+-- unification (e.g., in the presence of {}* fields - this elimination is not
+-- exactly safe)
+module LLVM.Internal.TypeUnification (
+  unifyTypes
+  ) where
+
+import Control.Applicative
+import Control.Monad ( filterM, foldM, forM_, forM )
+import Control.Monad.Trans.Class
+import Control.Monad.Error.Class
+import Control.Monad.EitherK
+import Control.Unification
+import Control.Unification.IntVar
+import Data.Foldable ( Foldable )
+import Data.Traversable ( Traversable )
+import Data.Set ( Set )
+import qualified Data.Set as S
+import Data.HashMap.Strict ( HashMap )
+import qualified Data.HashMap.Strict as HM
+import Data.HashTable.IO ( BasicHashTable )
+import qualified Data.HashTable.IO as HT
+import Data.Map ( Map )
+import qualified Data.Map as M
+import Data.Maybe ( fromMaybe )
+import Data.Monoid
+import qualified Data.Text as T
+import Data.Word ( Word64 )
+import Debug.Trace.LocationTH
+import Foreign.Ptr
+import System.IO.Unsafe ( unsafePerformIO )
+
+import Data.LLVM.Types
+import LLVM.Internal.Interop
+
+-- This is adapted from one of the tests in unification-fd
+
+-- | A type of Type terms
+data T a = T String [a]
+         deriving (Show, Eq, Ord, Functor, Foldable, Traversable)
+
+instance Unifiable T where
+  zipMatch (T a xs) (T b ys) =
+    case a == b of
+      True ->
+        case pair xs ys of
+          Nothing -> Nothing
+          Just p -> Just (T a (map Right p))
+      False -> Nothing
+
+type TTerm = UTerm T IntVar
+
+-- | Build a term from a name and a list of term arguments.
+typeTerm :: String -> [TTerm] -> TTerm
+typeTerm = (UTerm .) . T
+
+unifyTypes :: [TypePtr] -> IO (BasicHashTable Word64 Type, Map Type Int)
+unifyTypes tptrs = do
+  tmap <- HT.new
+  smap <- HT.new
+
+  -- Translate all non-struct types directly into the hash table.  The
+  -- fold only accumulates struct types (including unions and classes) into
+  -- a HashMap from name to ptr.
+  --
+  -- This accumulated map is the one that will be unified over.
+  structsByName <- foldM (translateAndGroup tmap smap) mempty tptrs
+
+  -- Now, for each name in structsByName, attempt to unify all of the
+  -- types in the group.  For each type that does unify, make an entry
+  -- in tmap for its pointer to the single representative Type.  For
+  -- the rest, do a basic translation.
+  mapM_ (unifyStructTypes tmap smap) (HM.toList structsByName)
+
+  typeSizes <- HT.foldM (htToMap tmap) mempty smap
+
+  return (tmap, typeSizes)
+
+htToMap :: BasicHashTable Word64 Type
+        -> Map Type Int
+        -> (Word64, Int)
+        -> IO (Map Type Int)
+htToMap tmap a (ip, v) = do
+  Just t <- HT.lookup tmap ip
+  return $ M.insert t v a
+
+unifyStructTypes :: BasicHashTable Word64 Type
+                 -> BasicHashTable Word64 Int
+                 -> (String, [(TypePtr, Int)])
+                 -> IO ()
+unifyStructTypes tmap smap (name, allPtrs) = do
+  sizedPtrs <- filterM (isNotOpaque . fst) allPtrs
+  let ptrs = map fst sizedPtrs
+  -- All of the types reachable from the list of input types @ptrs@
+  retainedTypes <- retainedTypeSearch ptrs
+
+  -- The struct types that are reachable from the input types, grouped
+  -- by their base names.
+  namedStructs <- filterM isStruct (S.toList retainedTypes)
+  let dependencyTypes = filter (`notElem` ptrs) namedStructs
+  groupedDependencyTypes <- groupByBaseName dependencyTypes
+
+  (unifyResult, _) <- runIntBindingT $ do
+    -- Assign a logic variable to each struct type reachable from
+    -- the input types (including the input types)
+    varMap <- assignVars (HM.insert name ptrs groupedDependencyTypes)
+    -- Convert everything to terms, then start unifying groups.
+    -- The final unification gives us the answer we want.
+    primaryTerms <- mapM (toTerm varMap) ptrs
+    let dterms = map snd $ HM.toList groupedDependencyTypes
+    depTermGroups <- forM dterms $ \dptrs -> do
+      -- If a dependency is opaque, don't bother trying to unify it
+      -- since it won't have the right arity.
+      nonOpaqueDeps <- lift $ filterM isNotOpaque dptrs
+      dts <- mapM (toTerm varMap) nonOpaqueDeps
+      return dts
+    runEitherKT $ do
+      mapM_ unifies depTermGroups
+      unifies primaryTerms
+  case unifyResult of
+    Left _ ->
+      -- Make an entry in tmap for each input
+      forM_ allPtrs $ \(p, sz) -> do
+        Just name' <- cTypeName p
+        isPacked <- cTypeIsPacked p
+        mptrs <- cTypeList p
+        let t = TypeStruct (Right (T.pack name')) (map (delayedLookup tmap) mptrs) isPacked
+            ip = fromIntegral (ptrToIntPtr p)
+        HT.insert tmap ip t
+        HT.insert smap ip sz
+    Right _ ->
+      case sizedPtrs of
+        [] -> do
+          -- Make a single opaque entry for allPtrs
+          let t = TypeStruct (Right (T.pack name)) [] False
+          forM_ allPtrs $ \(p, sz) -> do
+            let ip = fromIntegral (ptrToIntPtr p)
+            HT.insert tmap ip t
+            HT.insert smap ip sz
+        (p0, _) : _ -> do
+          -- Make one type to represent all of these types that were unified
+          -- and use it as the entry for each of the input pointers.
+          mptrs <- cTypeList p0
+          isPacked <- cTypeIsPacked p0
+          let t = TypeStruct (Right (T.pack name)) (map (delayedLookup tmap) mptrs) isPacked
+          forM_ allPtrs $ \(p, sz) -> do
+            let ip = fromIntegral (ptrToIntPtr p)
+            HT.insert tmap ip t
+            HT.insert smap ip sz
+
+translateAndGroup :: BasicHashTable Word64 Type
+                  -> BasicHashTable Word64 Int
+                  -> HashMap String [(TypePtr, Int)]
+                  -> TypePtr
+                  -> IO (HashMap String [(TypePtr, Int)])
+translateAndGroup tmap sizeMap structs tptr = do
+  let ip = fromIntegral $ ptrToIntPtr tptr
+  tag <- cTypeTag tptr
+  byteSize <- cTypeSizeInBytes tptr
+  HT.insert sizeMap ip byteSize
+  case tag of
+    TYPE_STRUCT -> do
+      name <- cTypeName tptr
+      case name of
+        Just n -> return $ HM.insertWith (++) (structBaseName n) [(tptr, byteSize)] structs
+        -- Anonymous struct
+        Nothing -> do
+          isPacked <- cTypeIsPacked tptr
+          ptrs <- cTypeList tptr
+          let ts = map (delayedLookup tmap) ptrs
+              stype = TypeStruct (Left ip) ts isPacked
+          HT.insert tmap ip stype
+          return structs
+    _ -> do
+      t' <- case tag of
+        TYPE_VOID -> return TypeVoid
+        TYPE_FLOAT -> return TypeFloat
+        TYPE_DOUBLE -> return TypeDouble
+        TYPE_X86_FP80 -> return TypeX86FP80
+        TYPE_FP128 -> return TypeFP128
+        TYPE_PPC_FP128 -> return TypePPCFP128
+        TYPE_LABEL -> return TypeLabel
+        TYPE_METADATA -> return TypeMetadata
+        TYPE_X86_MMX -> return TypeX86MMX
+        TYPE_INTEGER -> do
+          sz <- cTypeSize tptr
+          return $ TypeInteger sz
+        TYPE_FUNCTION -> do
+          isVa <- cTypeIsVarArg tptr
+          rtp <- cTypeInner tptr
+          argTypePtrs <- cTypeList tptr
+
+          let rt = delayedLookup tmap rtp
+              argTs = map (delayedLookup tmap) argTypePtrs
+          return $ TypeFunction rt argTs isVa
+        TYPE_ARRAY -> do
+          sz <- cTypeSize tptr
+          itp <- cTypeInner tptr
+          let innerType = delayedLookup tmap itp
+          return $ TypeArray sz innerType
+        TYPE_VECTOR -> do
+          sz <- cTypeSize tptr
+          itp <- cTypeInner tptr
+          let innerType = delayedLookup tmap itp
+          return $ TypeVector sz innerType
+        TYPE_POINTER -> do
+          itp <- cTypeInner tptr
+          addrSpc <- cTypeAddrSpace tptr
+          let innerType = delayedLookup tmap itp
+          return $ TypePointer innerType addrSpc
+        TYPE_STRUCT -> $failure "Impossible, cannot have a struct here"
+      HT.insert tmap ip t'
+      return structs
+
+-- | Look up the Type associated with a TypePtr lazily and impurely.
+-- This relies on no entries in the hash table being inspected until
+-- everything is unified and all entries are made.
+--
+-- This is simpler, faster, and more space efficient than using real
+-- knot tying.  It is also safe here since there are never any lookups
+-- in the hash table in this algorithm - only the IR translator
+-- actually performs lookups.
+delayedLookup :: BasicHashTable Word64 Type -> TypePtr -> Type
+delayedLookup tmap ptr = unsafePerformIO $ do
+  res <- HT.lookup tmap $ fromIntegral (ptrToIntPtr ptr)
+  return $ fromMaybe errMsg res
+  where
+    errMsg = $failure ("Type lookup failure for " ++ show ptr)
+
+-- | Perform a breadth-first search to discover all types referenced
+-- by the given input type list
+retainedTypeSearch :: [TypePtr] -> IO (Set TypePtr)
+retainedTypeSearch = go mempty . S.fromList
+  where
+    go visited q = do
+      let vals = q `S.difference` visited
+      case S.null vals of
+        True -> return visited
+        False -> do
+          let visited' = visited `S.union` vals
+          q' <- foldM addValuesFrom mempty (S.toList vals)
+          go visited' q'
+
+    addValuesFrom q tp = do
+      tag <- cTypeTag tp
+      case tag of
+        TYPE_STRUCT -> do
+          ptrs <- cTypeList tp
+          return $ q `S.union` S.fromList ptrs
+        TYPE_FUNCTION -> do
+          rtp <- cTypeInner tp
+          atps <- cTypeList tp
+          return $ q `S.union` S.fromList (rtp : atps)
+        TYPE_ARRAY -> do
+          itp <- cTypeInner tp
+          return $ S.insert itp q
+        TYPE_VECTOR -> do
+          itp <- cTypeInner tp
+          return $ S.insert itp q
+        TYPE_POINTER -> do
+          itp <- cTypeInner tp
+          return $ S.insert itp q
+        _ -> return $ S.insert tp q
+
+-- | Top level term creator; this only works for named structs.
+toTerm :: Map TypePtr TTerm -> TypePtr -> IntBindingT T IO TTerm
+toTerm varMap tp = do
+  let Just svar = M.lookup tp varMap
+  Just name <- lift $ cTypeName tp
+  ptrs <- lift $ cTypeList tp
+  innerTerms <- mapM (toTerm' varMap) ptrs
+  return $ typeTerm (structBaseName name) (svar : innerTerms)
+
+-- | Inner term creator; for structs, just return the variable
+-- assigned to that Type.
+toTerm' :: Map TypePtr TTerm -> TypePtr -> IntBindingT T IO TTerm
+toTerm' varMap tp = do
+  tag <- lift $ cTypeTag tp
+  case tag of
+    TYPE_VOID -> return $ typeTerm "%primitive.void" []
+    TYPE_FLOAT -> return $ typeTerm "%primitive.float" []
+    TYPE_DOUBLE -> return $ typeTerm "%primtive.double" []
+    TYPE_X86_FP80 -> return $ typeTerm "%primitive.x86_fp80" []
+    TYPE_FP128 -> return $ typeTerm "%primitive.fp128" []
+    TYPE_PPC_FP128 -> return $ typeTerm "%primitive.ppc_fp128" []
+    TYPE_LABEL -> return $ typeTerm "%primitive.label" []
+    TYPE_METADATA -> return $ typeTerm "%primitive.metadata" []
+    TYPE_X86_MMX -> return $ typeTerm "%primitive.x86_mmx" []
+    TYPE_INTEGER -> do
+      sz <- lift $ cTypeSize tp
+      return $ typeTerm ("%primitive.i" ++ show sz) []
+    TYPE_FUNCTION -> do
+      rtp <- lift $ cTypeInner tp
+      atps <- lift $ cTypeList tp
+      innerTerms <- mapM (toTerm' varMap) (rtp : atps)
+      return $ typeTerm "%primitive.function" innerTerms
+    TYPE_ARRAY -> do
+      sz <- lift $ cTypeSize tp
+      itp <- lift $ cTypeInner tp
+      ity <- toTerm' varMap itp
+      return $ typeTerm ("%primitive.array." ++ show sz) [ity]
+    TYPE_VECTOR -> do
+      sz <- lift $ cTypeSize tp
+      itp <- lift $ cTypeInner tp
+      ity <- toTerm' varMap itp
+      return $ typeTerm ("%primitive.vector." ++ show sz) [ity]
+    TYPE_POINTER -> do
+      -- If the struct is an opaque literal ptr {}*, assign it a fresh
+      -- variable (we will allow such an opaque ref to be anything
+      -- since the frontend seems to put them in strange places).
+      itp <- lift $ cTypeInner tp
+      innerTag <- lift $ cTypeTag itp
+      case innerTag of
+        TYPE_STRUCT -> do
+          mptrs <- lift $ cTypeList itp
+          case null mptrs of
+            True -> UVar <$> freeVar
+            False -> do
+              ity <- toTerm' varMap itp
+              return $ typeTerm "*" [ity]
+        _ -> do
+          ity <- toTerm' varMap itp
+          return $ typeTerm "*" [ity]
+    TYPE_STRUCT ->
+      case M.lookup tp varMap of
+        Nothing -> do
+          mptrs <- lift $ cTypeList tp
+          innerTerms <- mapM (toTerm' varMap) mptrs
+          return $ typeTerm "%anon.struct" innerTerms
+        Just v -> return v
+
+-- | Assign fresh unification variables to every struct type in the
+-- input map.
+assignVars :: HashMap String [TypePtr] -> IntBindingT T IO (Map TypePtr TTerm)
+assignVars = foldM assignVarL mempty . HM.toList
+  where
+    assignVarL acc (_, ts) = foldM assignVar acc ts
+    assignVar acc ty = do
+      x <- freeVar
+      return $! M.insert ty (UVar x) acc
+
+-- | Take a list of types and group them by their base names (that is,
+-- the part of the name up to the trailing .NNN).
+groupByBaseName :: [TypePtr] -> IO (HashMap String [TypePtr])
+groupByBaseName = foldM addToMap mempty
+  where
+    addToMap m tp = do
+      -- All struct types that make it here are named.
+      Just name <- cTypeName tp
+      return $ HM.insertWith (++) (structBaseName name) [tp] m
+
+-- | Unify a list of terms
+unifies :: (Functor (e m), BindingMonad t v m, MonadTrans e, MonadError (UnificationFailure t v) (e m))
+           => [UTerm t v] -> e m ()
+unifies [] = return ()
+unifies [_] = return ()
+unifies (y:ys) = go ys y
+  where
+    go [] _ = return ()
+    go (x:xs) z = unify x z >>= go xs
+
+-- Helpers
+
+-- | Like zip, but only returns a result if the two input lists are
+-- the same length
+pair :: [a] -> [b] -> Maybe [(a, b)]
+pair xs ys =
+  case length xs == length ys of
+    False -> Nothing
+    True -> Just (zip xs ys)
+
+isStruct :: TypePtr -> IO Bool
+isStruct tp = do
+  tag <- cTypeTag tp
+  case tag of
+    TYPE_STRUCT -> do
+      n <- cTypeName tp
+      case n of
+        Nothing -> return False
+        Just _ -> return True
+    _ -> return False
+
+isNotOpaque :: TypePtr -> IO Bool
+isNotOpaque tp = do
+  ptrs <- cTypeList tp
+  return (not (null ptrs))
diff --git a/src/LLVM/Parse.hs b/src/LLVM/Parse.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Parse.hs
@@ -0,0 +1,1862 @@
+-- | This module converts the C form of the LLVM IR into a fully
+-- referential Haskell version of the IR.  The translation is slightly
+-- lossy around integral types in some cases, as Haskell Ints do not
+-- have the same range as C ints.  In the vast majority of cases this
+-- should not really be an issue, but it is possible to lose
+-- information.  If it is an issue it can be changed.
+--
+-- Note that this uses BasicHashTables as mappings.  Switching to
+-- LinearHashTable has less space overhead but makes performance tank.
+-- Don't be tempted.
+{-# LANGUAGE DeriveDataTypeable, RankNTypes, FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell #-}
+module LLVM.Parse (
+    -- * Types
+  ParserOptions(..),
+  PositionPrecision(..),
+  TranslationException(..),
+  -- * Helpers
+  defaultParserOptions,
+  -- * Parser
+  parseLLVM,
+  hParseLLVM,
+  parseLLVMFile
+  ) where
+
+import Control.Applicative
+import Control.DeepSeq
+import Control.Exception as E
+import Control.Monad.State.Strict
+import Data.ByteString.Char8 ( ByteString )
+import qualified Data.ByteString.Char8 as BS
+import Data.ByteString.Unsafe ( unsafeUseAsCStringLen )
+import Data.IORef
+import Data.HashTable.IO ( BasicHashTable )
+import Data.Set ( Set )
+import qualified Data.HashTable.IO as HT
+import qualified Data.Set as S
+import Data.Maybe ( catMaybes )
+import Data.Map ( Map )
+import qualified Data.Map as M
+import Data.Monoid
+import Data.Text ( Text )
+import Data.Typeable
+import qualified Data.Vector as V
+import Data.Word ( Word64 )
+import Debug.Trace.LocationTH
+import Foreign.Ptr
+import System.IO ( Handle, hSetBinaryMode )
+import System.IO.Unsafe ( unsafePerformIO )
+
+import Data.LLVM.Types
+import LLVM.Internal.Interop
+import LLVM.Internal.TypeUnification
+
+-- | Defines the level of precision of position information in the
+-- metadata.  LLVM gives very precise information, but tracking all of
+-- it can consume excessive amounts of space.  This option allows it
+-- to be selectively discarded.
+data PositionPrecision = PositionPrecise
+                         -- ^ Preserve all information from LLVM (line
+                         -- and column numbers)
+                       | PositionNone
+                         -- ^ Discard all position information
+                       deriving (Show, Eq)
+
+-- | Options controlling how 'Module's are constructed.
+data ParserOptions = ParserOptions { metaPositionPrecision :: PositionPrecision }
+                   deriving (Show, Eq)
+
+-- | Reasonable default parsing options
+defaultParserOptions :: ParserOptions
+defaultParserOptions = ParserOptions { metaPositionPrecision = PositionPrecise }
+
+data TranslationException = TooManyReturnValues
+                          | InvalidBranchInst
+                          | InvalidSwitchLayout
+                          | InvalidIndirectBranchOperands
+                          | KnotTyingFailure ValueTag
+                          | TypeKnotTyingFailure TypeTag
+                          | MetaKnotFailure
+                          | InvalidSelectArgs !Int
+                          | InvalidExtractElementInst !Int
+                          | InvalidInsertElementInst !Int
+                          | InvalidShuffleVectorInst !Int
+                          | InvalidFunctionInTranslateValue
+                          | InvalidAliasInTranslateValue
+                          | InvalidGlobalVarInTranslateValue
+                          | InvalidBinaryOp !Int
+                          | InvalidUnaryOp !Int
+                          | InvalidGEPInst !Int
+                          | InvalidExtractValueInst !Int
+                          | InvalidInsertValueInst !Int
+                          | InvalidTag String ValueTag
+                          | InvalidBlockAddressFunction Value
+                          | InvalidBlockAddressBlock Value
+                          | InvalidUnconditionalBranchTarget Value
+                          | NonConstantTag ValueTag
+                          | NonInstructionTag ValueTag
+                          | InvalidBranchTarget Value
+                          | InvalidSwitchTarget Value
+                          | InvalidResumeInst !Int
+                          | InvalidDataLayout Text String
+                          | UnparsableBitcode String
+                          | NoModule
+                          deriving (Show, Typeable)
+instance Exception TranslationException
+
+type KnotMonad = StateT KnotState IO
+data KnotState = KnotState { valueMap :: BasicHashTable Word64 Value
+                           , typeMap :: BasicHashTable Word64 Type
+                           , metaMap :: BasicHashTable Word64 Metadata
+                           , idSrc :: IORef Int
+                           , metaIdSrc :: IORef Int
+                           , result :: Maybe Module
+                           , visitedMetadata :: Set IntPtr
+                           , localId :: Int
+                           , stringCache :: BasicHashTable Text Text
+                           , identCache :: BasicHashTable Identifier Identifier
+                           }
+
+instance InternString (StateT KnotState IO) where
+  internString str = do
+    s <- get
+    let cache = stringCache s
+    v <- liftIO $ HT.lookup cache str
+    case v of
+      Just cval -> return cval
+      Nothing -> do
+        liftIO $ HT.insert cache str str
+        return str
+  internIdentifier ident = do
+    s <- get
+    let cache = identCache s
+    v <- liftIO $ HT.lookup cache ident
+    case v of
+      Just val -> return val
+      Nothing -> do
+        liftIO $ HT.insert cache ident ident
+        return ident
+
+
+emptyState :: IORef Int
+              -> IORef Int
+              -> BasicHashTable Word64 Value
+              -> BasicHashTable Word64 Metadata
+              -> BasicHashTable Word64 Type
+              -> BasicHashTable Text Text
+              -> BasicHashTable Identifier Identifier
+              -> KnotState
+emptyState r1 r2 vm mm tm sc ic =
+  KnotState { valueMap = vm
+            , typeMap = tm
+            , metaMap = mm
+            , idSrc = r1
+            , metaIdSrc = r2
+            , result = Nothing
+            , visitedMetadata = mempty
+            , localId = 0
+            , stringCache = sc
+            , identCache = ic
+            }
+
+genId :: (KnotState -> IORef Int) -> KnotMonad Int
+genId accessor = do
+  s <- get
+  let r = accessor s
+  thisId <- liftIO $ readIORef r
+  let nid = thisId + 1
+  nid `seq` return ()
+  liftIO $ writeIORef r nid
+
+  return thisId
+
+nextId :: KnotMonad Int
+nextId = genId idSrc
+
+nextMetaId :: KnotMonad Int
+nextMetaId = genId metaIdSrc
+
+-- | Parse the named LLVM file into the LLVM form of the IR (a
+-- 'Module').  In the case of an error, a descriptive string will be
+-- returned.  The input file can be either LLVM assembly or bitcode.
+parseLLVMFile :: ParserOptions -> FilePath -> IO Module
+parseLLVMFile opts filename = do
+  let includeLineNumbers = metaPositionPrecision opts == PositionPrecise
+  m <- marshalLLVMFile filename includeLineNumbers
+
+  hasError <- cModuleHasError m
+  case hasError of
+    True -> do
+      Just errMsg <- cModuleErrorMessage m
+      disposeCModule m
+      E.throwIO $ UnparsableBitcode errMsg
+    False -> translateCModule m
+
+-- | Parse LLVM IR from a Handle into a 'Module'
+hParseLLVM :: ParserOptions -> Handle -> IO Module
+hParseLLVM opts h = do
+  hSetBinaryMode h True
+  bs <- BS.hGetContents h
+  parseLLVM opts bs
+
+-- | Parse the LLVM IR (either assembly or bitcode) from a lazy ByteString
+-- into a 'Module'.
+parseLLVM :: ParserOptions -> ByteString -> IO Module
+parseLLVM opts content = do
+  let includeLineNumbers = metaPositionPrecision opts == PositionPrecise
+  unsafeUseAsCStringLen content $ \(s, len) -> do
+    m <- marshalLLVM s len includeLineNumbers
+    hasError <- cModuleHasError m
+    case hasError of
+      True -> do
+        Just errMsg <- cModuleErrorMessage m
+        disposeCModule m
+        E.throwIO $ UnparsableBitcode errMsg
+      False -> translateCModule m
+
+translateCModule :: ModulePtr -> IO Module
+translateCModule m = do
+  idref <- newIORef 1
+  mref <- newIORef 1
+
+  -- Default these tables to be slightly large to reduce resizing
+  valMap <- HT.newSized 2000
+  mmMap <- HT.newSized 2000
+  sCache <- HT.newSized 2000
+  iCache <- HT.newSized 2000
+
+  -- Do a preliminary pass over all of the types in the Module.  This
+  -- pass will unify structurally identical types (and basically
+  -- ignore opaque types).  This step should happen in llvm-link, but
+  -- that seems to miss many trivial cases.
+  --
+  -- The result of the unification step will be a map of CType -> Type
+  -- to be used in the IR translation.
+  --
+  -- Note that this up-front type translation will make the IR
+  -- translation simpler since there will be no type knot.  This also
+  -- means that
+  modTypes <- cModuleTypes m
+  (tyMap, typeSizes) <- unifyTypes modTypes
+
+  let s0 = emptyState idref mref valMap mmMap tyMap sCache iCache
+  res <- evalStateT (mfix (tieKnot m typeSizes)) s0
+  disposeCModule m
+  case result res of
+    Just r -> do
+      r `deepseq` return ()
+      return r
+    Nothing -> E.throwIO $ NoModule
+
+isExternVar :: ValuePtr -> KnotMonad Bool
+isExternVar vp = do
+  dataPtr <- liftIO $ cValueData vp
+  let dataPtr' = castPtr dataPtr
+  liftIO $ cGlobalIsExternal dataPtr'
+
+isExternFunc :: ValuePtr -> KnotMonad Bool
+isExternFunc vp = do
+  dataPtr <- liftIO $ cValueData vp
+  let dataPtr' = castPtr dataPtr
+  liftIO $ cFunctionIsExternal dataPtr'
+
+-- swiped from http://www.haskell.org/pipermail/beginners/2009-December/002882.html
+partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a],[a])
+partitionM p xs = do
+  (f,g) <- pMHelper p xs
+  return (f [], g [])
+
+pMHelper :: Monad m => (a -> m Bool) -> [a] -> m ([a] -> [a],[a] -> [a])
+pMHelper p xs = foldM help (id,id) xs
+  where
+    help (f,g) x = do
+      b <- p x
+      return (if b then (f . (x:),g) else (f,g . (x:)))
+
+tieKnot :: ModulePtr -> Map Type Int -> KnotState -> KnotMonad KnotState
+tieKnot m typeSizes finalState = do
+  modIdent <- liftIO $ cModuleIdentifier m
+  dataLayout <- liftIO $ cModuleDataLayout m
+  triple <- liftIO $ cModuleTargetTriple m
+  inlineAsm <- liftIO $ cModuleInlineAsm m
+
+  vars <- liftIO $ cModuleGlobalVariables m
+  aliases <- liftIO $ cModuleGlobalAliases m
+  funcs <- liftIO $ cModuleFunctions m
+  enumMetaPtrs <- liftIO $ cModuleEnumMetadata m
+  retainedMetaPtrs <- liftIO $ cModuleRetainedTypeMetadata m
+
+  (externVs, globalVs) <- partitionM isExternVar vars
+  (externFs, globalFs) <- partitionM isExternFunc funcs
+
+  globalVars <- mapM (translateGlobalVariable finalState) globalVs
+  externVars <- mapM (translateExternalVariable finalState) externVs
+  globalAliases <- mapM (translateAlias finalState) aliases
+  definedFuncs <- mapM (translateFunction finalState) globalFs
+  externFuncs <- mapM (translateExternalFunction finalState) externFs
+
+  enumMeta <- mapM (translateMetadata finalState) enumMetaPtrs
+  typeMeta <- mapM (translateMetadata finalState) retainedMetaPtrs
+
+  s <- get
+  tm <- liftIO $ HT.toList (typeMap s)
+  lastId <- liftIO $ readIORef (idSrc s)
+  case parseDataLayout dataLayout of
+    Left err -> throw (InvalidDataLayout dataLayout err)
+    Right dl -> do
+      let ir = Module { moduleIdentifier = modIdent
+                      , moduleDataLayoutString = dataLayout
+                      , moduleDataLayout = dl
+                      , moduleTarget = triple
+                      , moduleAssembly = Assembly inlineAsm
+                      , moduleAliases = globalAliases
+                      , moduleGlobalVariables = globalVars
+                      , moduleDefinedFunctions = definedFuncs
+                      , moduleExternalValues = externVars
+                      , moduleExternalFunctions = externFuncs
+                      , moduleEnumMetadata = enumMeta
+                      , moduleRetainedTypeMetadata = typeMeta
+                      , moduleRetainedTypes = unique $ map snd tm
+                      , moduleNextId = lastId + 1
+                      , moduleTypeSizes = \t -> M.lookup t typeSizes
+                      }
+      return s { result = Just ir }
+
+unique :: (Ord a) => [a] -> [a]
+unique = S.toList . S.fromList
+
+translateType :: TypePtr -> KnotMonad Type
+translateType tp = do
+  tm <- gets typeMap
+  let ip = fromIntegral $ ptrToIntPtr tp
+  res <- liftIO $ HT.lookup tm ip
+  case res of
+    Nothing -> $failure ("No translation for type " ++ show tp)
+    Just t -> return t
+
+recordValue :: ValuePtr -> Value -> KnotMonad ()
+recordValue vp v = do
+  s <- get
+  let key = fromIntegral $ ptrToIntPtr vp
+  liftIO $ HT.insert (valueMap s) key v
+
+translateAlias :: KnotState -> ValuePtr -> KnotMonad GlobalAlias
+translateAlias finalState vp = do
+  Just name <- cValueName vp
+  dataPtr <- liftIO $ cValueData vp
+  metaPtr <- liftIO $ cValueMetadata vp
+  let dataPtr' = castPtr dataPtr
+
+  mds <- mapM (translateMetadata finalState) metaPtr
+
+  vis <- liftIO $ cGlobalVisibility dataPtr'
+  link <- liftIO $ cGlobalLinkage dataPtr'
+  aliasee <- liftIO $ cGlobalAliasee dataPtr'
+
+  ta <- translateConstOrRef finalState aliasee
+
+  uid <- nextId
+
+  let ga = GlobalAlias { globalAliasLinkage = link
+                       , globalAliasVisibility = vis
+                       , globalAliasTarget = ta
+                       , globalAliasName = name
+                       , globalAliasMetadata = mds
+                       , globalAliasUniqueId = uid
+                       }
+
+  recordValue vp (toValue ga)
+
+  return ga
+
+translateExternalVariable :: KnotState -> ValuePtr -> KnotMonad ExternalValue
+translateExternalVariable finalState vp = do
+  Just name <- cValueName vp
+  typePtr <- liftIO $ cValueType vp
+  metaPtr <- liftIO $ cValueMetadata vp
+  tt <- translateType typePtr
+
+  mds <- mapM (translateMetadata finalState) metaPtr
+  uid <- nextId
+
+  let ev = ExternalValue { externalValueType = tt
+                         , externalValueName = name
+                         , externalValueMetadata = mds
+                         , externalValueUniqueId = uid
+                         }
+  recordValue vp (toValue ev)
+  return ev
+
+
+translateGlobalVariable :: KnotState -> ValuePtr -> KnotMonad GlobalVariable
+translateGlobalVariable finalState vp = do
+  Just name <- cValueName vp
+  typePtr <- liftIO $ cValueType vp
+  dataPtr <- liftIO $ cValueData vp
+  metaPtr <- liftIO $ cValueMetadata vp
+  tt <- translateType typePtr
+
+  mds <- mapM (translateMetadata finalState) metaPtr
+  uid <- nextId
+
+  let dataPtr' = castPtr dataPtr
+  align <- liftIO $ cGlobalAlignment dataPtr'
+  vis <- liftIO $ cGlobalVisibility dataPtr'
+  link <- liftIO $ cGlobalLinkage dataPtr'
+  section <- liftIO $ cGlobalSection dataPtr'
+  isThreadLocal <- liftIO $ cGlobalIsThreadLocal dataPtr'
+  initializer <- liftIO $ cGlobalInitializer dataPtr'
+  isConst <- liftIO $ cGlobalIsConstant dataPtr'
+
+  ti <- case initializer == nullPtr of
+    True -> return Nothing
+    False -> do
+      tv <- translateConstOrRef finalState initializer
+      return $ Just tv
+
+  let gv = GlobalVariable { globalVariableLinkage = link
+                          , globalVariableVisibility = vis
+                          , globalVariableInitializer = ti
+                          , globalVariableAlignment = align
+                          , globalVariableSection = section
+                          , globalVariableIsThreadLocal = isThreadLocal
+                          , globalVariableIsConstant = isConst
+                          , globalVariableMetadata = mds
+                          , globalVariableType = tt
+                          , globalVariableName = name
+                          , globalVariableUniqueId = uid
+                          }
+  recordValue vp (toValue gv)
+  return gv
+
+translateExternalFunction :: KnotState -> ValuePtr -> KnotMonad ExternalFunction
+translateExternalFunction finalState vp = do
+  Just name <- cValueName vp
+  typePtr <- liftIO $ cValueType vp
+  metaPtr <- liftIO $ cValueMetadata vp
+  tt <- translateType typePtr
+
+  mds <- mapM (translateMetadata finalState) metaPtr
+
+  uid <- nextId
+
+  let ef = ExternalFunction { externalFunctionType = tt
+                            , externalFunctionName = name
+                            , externalFunctionMetadata = mds
+                            , externalFunctionUniqueId = uid
+                            , externalFunctionAttrs = [] -- FIXME: Need to figure out how to find attrs
+                            }
+  recordValue vp (toValue ef)
+  return ef
+
+
+resetLocalIdCounter :: KnotMonad ()
+resetLocalIdCounter = do
+  s <- get
+  put s { localId = 0 }
+
+translateFunction :: KnotState -> ValuePtr -> KnotMonad Function
+translateFunction finalState vp = do
+  Just name <- cValueName vp
+  typePtr <- liftIO $ cValueType vp
+  dataPtr <- liftIO $ cValueData vp
+  metaPtr <- liftIO $ cValueMetadata vp
+  tt <- translateType typePtr
+
+  mds <- mapM (translateMetadata finalState) metaPtr
+
+  uid <- nextId
+
+  resetLocalIdCounter
+
+  let dataPtr' = castPtr dataPtr
+  align <- liftIO $ cFunctionAlignment dataPtr'
+  vis <- liftIO $ cFunctionVisibility dataPtr'
+  link <- liftIO $ cFunctionLinkage dataPtr'
+  section <- liftIO $ cFunctionSection dataPtr'
+  cc <- liftIO $ cFunctionCallingConvention dataPtr'
+  gcname <- liftIO $ cFunctionGCName dataPtr'
+  args <- liftIO $ cFunctionArguments dataPtr'
+  blocks <- liftIO $ cFunctionBlocks dataPtr'
+
+  f <- mfix (\finalF -> do
+                args' <- mapM (translateArgument finalState finalF) args
+                blocks' <- mapM (translateBasicBlock finalState finalF) blocks
+                let f' = Function { functionParameters = args'
+                                  , functionBodyVector = V.fromList blocks'
+                                  , functionLinkage = link
+                                  , functionVisibility = vis
+                                  , functionCC = cc
+                                  , functionRetAttrs = [] -- FIXME
+                                  , functionAttrs = [] -- FIXME
+                                  , functionSection = section
+                                  , functionAlign = align
+                                  , functionGCName = gcname
+                                  , functionType = tt
+                                  , functionName = name
+                                  , functionMetadata = mds
+                                  , functionUniqueId = uid
+                                  }
+                return f')
+
+  recordValue vp (toValue f)
+  return f
+
+translateConstant :: KnotState -> ValuePtr -> KnotMonad Constant
+translateConstant finalState vp = do
+  tag <- liftIO $ cValueTag vp
+  typePtr <- liftIO $ cValueType vp
+  dataPtr <- liftIO $ cValueData vp
+  tt <- translateType typePtr
+
+  constant <- case tag of
+    ValInlineasm -> translateInlineAsm finalState (castPtr dataPtr) tt
+    ValBlockaddress -> translateBlockAddress finalState (castPtr dataPtr) tt
+    ValConstantaggregatezero -> do
+      uid <- nextId
+      return ConstantAggregateZero { constantType = tt
+                                   , constantUniqueId = uid
+                                   }
+    ValConstantpointernull -> do
+      uid <- nextId
+      return ConstantPointerNull { constantType = tt
+                                 , constantUniqueId = uid
+                                 }
+    ValUndefvalue -> do
+      uid <- nextId
+      return UndefValue { constantType = tt
+                        , constantUniqueId = uid
+                        }
+    ValConstantarray -> translateConstantAggregate finalState ConstantArray (castPtr dataPtr) tt
+    ValConstantstruct -> translateConstantAggregate finalState ConstantStruct (castPtr dataPtr) tt
+    ValConstantvector -> translateConstantAggregate finalState ConstantVector (castPtr dataPtr) tt
+    ValConstantfp -> translateConstantFP finalState (castPtr dataPtr) tt
+    ValConstantint -> translateConstantInt finalState (castPtr dataPtr) tt
+    ValConstantexpr -> do
+      uid <- nextId
+      i <- translateConstantExpr finalState (castPtr dataPtr) tt
+      return ConstantValue { constantType = tt
+                           , constantUniqueId = uid
+                           , constantInstruction = i
+                           }
+    _ -> throw $ NonConstantTag tag
+
+  recordValue vp (toValue constant)
+
+  return constant
+
+
+-- | Most instructions don't have explicit names in LLVM - when they
+-- are printed the LLVM libraries just generate numeric names and they
+-- are never stored.  This function takes the stated name of an
+-- instruction and, if it should have a temporary name like that, we
+-- generate one using a local counter.
+computeRealName :: Maybe Identifier -> KnotMonad (Maybe Identifier)
+computeRealName name = do
+  s <- get
+  let idCtr = localId s
+  case name of
+    Just n -> return (Just n)
+    Nothing -> do
+      put s { localId = idCtr + 1 }
+      let rawAnonId = makeAnonymousLocal idCtr
+      anonId <- internIdentifier rawAnonId
+      return $! Just anonId
+
+-- | Compute the name of a call or invoke instruction.  If the call is
+-- void, it does not get a name; otherwise, it does need a
+-- sequentially-generated name.
+computeNameIfNotVoid :: Maybe Identifier -> Type -> KnotMonad (Maybe Identifier)
+computeNameIfNotVoid mid t =
+  case t of
+    TypeVoid -> return Nothing
+    _ -> computeRealName mid
+
+translateInstruction :: KnotState -> Maybe BasicBlock -> ValuePtr -> KnotMonad Instruction
+translateInstruction finalState bb vp = do
+  tag <- liftIO $ cValueTag vp
+  name <- cValueName vp
+  typePtr <- liftIO $ cValueType vp
+  dataPtr <- liftIO $ cValueData vp
+  metaPtr <- liftIO $ cValueMetadata vp
+  srcLocPtr <- liftIO $ cValueSrcLoc vp
+
+  metas <- mapM (translateMetadata finalState) metaPtr
+  mds <- case srcLocPtr == nullPtr of
+    True -> return metas
+    False -> do
+      srcLoc <- translateMetadata finalState srcLocPtr
+      return $ srcLoc : metas
+
+  tt <- translateType typePtr
+
+  inst <- case tag of
+    ValRetinst -> translateRetInst finalState (castPtr dataPtr) mds bb
+    ValBranchinst -> translateBranchInst finalState (castPtr dataPtr) mds bb
+    ValSwitchinst -> translateSwitchInst finalState (castPtr dataPtr) mds bb
+    ValIndirectbrinst -> translateIndirectBrInst finalState (castPtr dataPtr) mds bb
+    ValUnreachableinst -> do
+      uid <- nextId
+      return UnreachableInst { instructionMetadata = mds
+                             , instructionUniqueId = uid
+                             , instructionBasicBlock = bb
+                             }
+    ValInvokeinst -> translateInvokeInst finalState (castPtr dataPtr) name tt mds bb
+    ValAddinst -> translateFlaggedBinaryOp finalState AddInst (castPtr dataPtr) name tt mds bb
+    ValFaddinst -> translateFlaggedBinaryOp finalState AddInst (castPtr dataPtr) name tt mds bb
+    ValSubinst -> translateFlaggedBinaryOp finalState SubInst (castPtr dataPtr) name tt mds bb
+    ValFsubinst -> translateFlaggedBinaryOp finalState SubInst (castPtr dataPtr) name tt mds bb
+    ValMulinst ->  translateFlaggedBinaryOp finalState MulInst (castPtr dataPtr) name tt mds bb
+    ValFmulinst ->  translateFlaggedBinaryOp finalState MulInst (castPtr dataPtr) name tt mds bb
+    ValUdivinst -> translateBinaryOp finalState DivInst (castPtr dataPtr) name tt mds bb
+    ValSdivinst -> translateBinaryOp finalState DivInst (castPtr dataPtr) name tt mds bb
+    ValFdivinst -> translateBinaryOp finalState DivInst (castPtr dataPtr) name tt mds bb
+    ValUreminst -> translateBinaryOp finalState RemInst (castPtr dataPtr) name tt mds bb
+    ValSreminst -> translateBinaryOp finalState RemInst (castPtr dataPtr) name tt mds bb
+    ValFreminst -> translateBinaryOp finalState RemInst (castPtr dataPtr) name tt mds bb
+    ValShlinst -> translateBinaryOp finalState ShlInst (castPtr dataPtr) name tt mds bb
+    ValLshrinst -> translateBinaryOp finalState LshrInst (castPtr dataPtr) name tt mds bb
+    ValAshrinst -> translateBinaryOp finalState AshrInst (castPtr dataPtr) name tt mds bb
+    ValAndinst -> translateBinaryOp finalState AndInst (castPtr dataPtr) name tt mds bb
+    ValOrinst -> translateBinaryOp finalState OrInst (castPtr dataPtr) name tt mds bb
+    ValXorinst -> translateBinaryOp finalState XorInst (castPtr dataPtr) name tt mds bb
+    ValAllocainst -> translateAllocaInst finalState (castPtr dataPtr) name tt mds bb
+    ValLoadinst -> translateLoadInst finalState (castPtr dataPtr) name tt mds bb
+    ValStoreinst -> translateStoreInst finalState (castPtr dataPtr) mds bb
+    ValGetelementptrinst -> translateGEPInst finalState (castPtr dataPtr) name tt mds bb
+    ValTruncinst -> translateCastInst finalState TruncInst (castPtr dataPtr) name tt mds bb
+    ValZextinst -> translateCastInst finalState ZExtInst (castPtr dataPtr) name tt mds bb
+    ValSextinst -> translateCastInst finalState SExtInst (castPtr dataPtr) name tt mds bb
+    ValFptruncinst -> translateCastInst finalState FPTruncInst (castPtr dataPtr) name tt mds bb
+    ValFpextinst -> translateCastInst finalState FPExtInst (castPtr dataPtr) name tt mds bb
+    ValFptouiinst -> translateCastInst finalState FPToUIInst (castPtr dataPtr) name tt mds bb
+    ValFptosiinst -> translateCastInst finalState FPToSIInst (castPtr dataPtr) name tt mds bb
+    ValUitofpinst -> translateCastInst finalState UIToFPInst (castPtr dataPtr) name tt mds bb
+    ValSitofpinst -> translateCastInst finalState SIToFPInst (castPtr dataPtr) name tt mds bb
+    ValPtrtointinst -> translateCastInst finalState PtrToIntInst (castPtr dataPtr) name tt mds bb
+    ValInttoptrinst -> translateCastInst finalState IntToPtrInst (castPtr dataPtr) name tt mds bb
+    ValBitcastinst -> translateCastInst finalState BitcastInst (castPtr dataPtr) name tt mds bb
+    ValIcmpinst -> translateCmpInst finalState ICmpInst (castPtr dataPtr) name tt mds bb
+    ValFcmpinst -> translateCmpInst finalState FCmpInst (castPtr dataPtr) name tt mds bb
+    ValPhinode -> translatePhiNode finalState (castPtr dataPtr) name tt mds bb
+    ValCallinst -> translateCallInst finalState (castPtr dataPtr) name tt mds bb
+    ValSelectinst -> translateSelectInst finalState (castPtr dataPtr) name tt mds bb
+    ValVaarginst -> translateVarArgInst finalState (castPtr dataPtr) name tt mds bb
+    ValExtractelementinst -> translateExtractElementInst finalState (castPtr dataPtr) name tt mds bb
+    ValInsertelementinst -> translateInsertElementInst finalState (castPtr dataPtr) name tt mds bb
+    ValShufflevectorinst -> translateShuffleVectorInst finalState (castPtr dataPtr) name tt mds bb
+    ValExtractvalueinst -> translateExtractValueInst finalState (castPtr dataPtr) name tt mds bb
+    ValInsertvalueinst -> translateInsertValueInst finalState (castPtr dataPtr) name tt mds bb
+    ValResumeinst -> translateResumeInst finalState (castPtr dataPtr) mds bb
+    ValFenceinst -> translateFenceInst finalState (castPtr dataPtr) mds bb
+    ValAtomiccmpxchginst -> translateAtomicCmpXchgInst finalState (castPtr dataPtr) mds bb
+    ValAtomicrmwinst -> translateAtomicRMWInst finalState (castPtr dataPtr) mds bb
+    ValLandingpadinst -> translateLandingPadInst finalState (castPtr dataPtr) name tt mds bb
+    _ -> throw $ NonInstructionTag tag
+
+  recordValue vp (toValue inst)
+
+  return inst
+
+isConstant :: ValueTag -> Bool
+isConstant vt = case vt of
+  ValConstantaggregatezero -> True
+  ValConstantarray -> True
+  ValConstantfp -> True
+  ValConstantint -> True
+  ValConstantpointernull -> True
+  ValConstantstruct -> True
+  ValConstantvector -> True
+  ValUndefvalue -> True
+  ValConstantexpr -> True
+  ValBlockaddress -> True
+  ValInlineasm -> True
+  _ -> False
+
+translateConstOrRef :: KnotState -> ValuePtr -> KnotMonad Value
+translateConstOrRef finalState vp = do
+  s <- get
+  let key = fromIntegral (ptrToIntPtr vp)
+  existingVal <- liftIO $ HT.lookup (valueMap s) key
+  case existingVal of
+    Just v -> return v
+    Nothing -> do
+      tag <- liftIO $ cValueTag vp
+      case isConstant tag of
+        -- translateConstant handles making the hash table entry for
+        -- this pointer
+        True -> toValue <$> translateConstant finalState vp
+        False -> do
+          -- This cheats in the knot tying.  The map is read again
+          -- /after/ it has been filled in (since these values are not
+          -- forced until after the whole module is processed)
+          let finalRes = unsafePerformIO $ HT.lookup (valueMap s) key
+          return (maybe (throw (KnotTyingFailure tag)) id finalRes)
+
+translateArgument :: KnotState -> Function -> ValuePtr -> KnotMonad Argument
+translateArgument finalState finalF vp = do
+  tag <- liftIO $ cValueTag vp
+  Just name <- cValueName vp
+  typePtr <- liftIO $ cValueType vp
+  dataPtr <- liftIO $ cValueData vp
+  metaPtr <- liftIO $ cValueMetadata vp
+
+  mds <- mapM (translateMetadata finalState) metaPtr
+  uid <- nextId
+
+  when (tag /= ValArgument) (throw $ InvalidTag "Argument" tag)
+
+  tt <- translateType typePtr
+
+  let dataPtr' = castPtr dataPtr
+
+  hasSRet <- liftIO $ cArgInfoHasSRet dataPtr'
+  hasByVal <- liftIO $ cArgInfoHasByVal dataPtr'
+  hasNest <- liftIO $ cArgInfoHasNest dataPtr'
+  hasNoAlias <- liftIO $ cArgInfoHasNoAlias dataPtr'
+  hasNoCapture <- liftIO $ cArgInfoHasNoCapture dataPtr'
+  let attrOrNothing b att = if b then Just att else Nothing
+      atts = [ attrOrNothing hasSRet PASRet
+             , attrOrNothing hasByVal PAByVal
+             , attrOrNothing hasNest PANest
+             , attrOrNothing hasNoAlias PANoAlias
+             , attrOrNothing hasNoCapture PANoCapture
+             ]
+  let a = Argument { argumentType = tt
+                   , argumentName = name
+                   , argumentMetadata = mds
+                   , argumentUniqueId = uid
+                   , argumentParamAttrs = catMaybes atts
+                   , argumentFunction = finalF
+                   }
+  recordValue vp (toValue a)
+  return a
+
+
+translateBasicBlock :: KnotState -> Function -> ValuePtr -> KnotMonad BasicBlock
+translateBasicBlock finalState f vp = do
+  tag <- liftIO $ cValueTag vp
+  name <- cValueName vp
+  dataPtr <- liftIO $ cValueData vp
+  metaPtr <- liftIO $ cValueMetadata vp
+
+  mds <- mapM (translateMetadata finalState) metaPtr
+
+  when (tag /= ValBasicblock) (throw $ InvalidTag "BasicBlock" tag)
+
+
+  uid <- nextId
+
+  let dataPtr' = castPtr dataPtr
+  Just realName <- computeRealName name
+
+  insts <- liftIO $ cBasicBlockInstructions dataPtr'
+  -- Use mfix here to let instructions have a reference to their
+  -- enclosing basic block.  mfix is needed since the block doesn't
+  -- exist until after the instructions are translated
+  bb <- mfix (\finalBB -> do
+                 tinsts <- mapM (translateInstruction finalState (Just finalBB)) insts
+                 let block' = BasicBlock { basicBlockName = realName
+                                        , basicBlockMetadata = mds
+                                        , basicBlockUniqueId = uid
+                                        , basicBlockInstructionVector = V.fromList tinsts
+                                        , basicBlockFunction = f
+                                        }
+                 return block')
+
+  recordValue vp (toValue bb)
+  return bb
+
+translateInlineAsm :: KnotState -> InlineAsmInfoPtr -> Type -> KnotMonad Constant
+translateInlineAsm _ dataPtr tt = do
+  uid <- nextId
+  asmString <- liftIO $ cInlineAsmString dataPtr
+  constraints <- liftIO $ cInlineAsmConstraints dataPtr
+  return InlineAsm { constantType = tt
+                   , constantUniqueId = uid
+                   , inlineAsmString = asmString
+                   , inlineAsmConstraints = constraints
+                   }
+
+translateBlockAddress :: KnotState -> BlockAddrInfoPtr -> Type -> KnotMonad Constant
+translateBlockAddress finalState dataPtr tt = do
+  uid <- nextId
+  fval <- liftIO $ cBlockAddrFunc dataPtr
+  bval <- liftIO $ cBlockAddrBlock dataPtr
+  f' <- translateConstOrRef finalState fval
+  b' <- translateConstOrRef finalState bval
+  let f'' = case valueContent f' of
+        FunctionC f -> f
+        _ -> throw (InvalidBlockAddressFunction f')
+      b'' = case valueContent b' of
+        BasicBlockC b -> b
+        _ -> throw (InvalidBlockAddressBlock b')
+  return BlockAddress { constantType = tt
+                      , constantUniqueId = uid
+                      , blockAddressFunction = f''
+                      , blockAddressBlock = b''
+                      }
+
+translateConstantAggregate :: KnotState -> (Type -> UniqueId -> [Value] -> Constant)
+                              -> AggregateInfoPtr -> Type -> KnotMonad Constant
+translateConstantAggregate finalState constructor dataPtr tt = do
+  uid <- nextId
+  vals <- liftIO $ cAggregateValues dataPtr
+  vals' <- mapM (translateConstOrRef finalState) vals
+  return $ constructor tt uid vals'
+
+translateConstantFP :: KnotState -> FPInfoPtr -> Type -> KnotMonad Constant
+translateConstantFP _ dataPtr tt = do
+  uid <- nextId
+  fpval <- liftIO $ cFPVal dataPtr
+  return ConstantFP { constantType = tt
+                    , constantUniqueId = uid
+                    , constantFPValue = fpval
+                    }
+
+translateConstantInt :: KnotState -> IntInfoPtr -> Type -> KnotMonad Constant
+translateConstantInt _ dataPtr tt = do
+  uid <- nextId
+  hugeVal <- liftIO $ cIntHugeVal dataPtr
+  intval <- case hugeVal of
+    Nothing -> liftIO $ cIntVal dataPtr
+    Just hv -> return hv
+  return $ ConstantInt { constantType = tt
+                       , constantUniqueId = uid
+                       , constantIntValue = intval
+                       }
+
+translateRetInst :: KnotState -> InstInfoPtr -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateRetInst finalState dataPtr mds bb = do
+  uid <- nextId
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  rv <- case opPtrs of
+    [] -> return Nothing
+    [val] -> do
+      val' <- translateConstOrRef finalState val
+      return (Just val')
+    _ -> throw TooManyReturnValues
+  return RetInst { instructionMetadata = mds
+                 , instructionUniqueId = uid
+                 , instructionBasicBlock = bb
+                 , retInstValue = rv
+                 }
+
+-- | Note, in LLVM the operands of the Branch instruction are ordered as
+--
+-- [Condition, FalseTarget,] TrueTarget
+--
+-- This is not exactly as expected.
+translateBranchInst :: KnotState -> InstInfoPtr -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateBranchInst finalState dataPtr mds bb = do
+  uid <- nextId
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  case opPtrs of
+    [dst] -> do
+      dst' <- translateConstOrRef finalState dst
+      let dst'' = case valueContent dst' of
+            BasicBlockC b -> b
+            _ -> throw (InvalidUnconditionalBranchTarget dst')
+      return UnconditionalBranchInst { instructionMetadata = mds
+                                     , instructionUniqueId = uid
+                                     , instructionBasicBlock = bb
+                                     , unconditionalBranchTarget = dst''
+                                     }
+    [val, f, t] -> do
+      val' <- translateConstOrRef finalState val
+      fbranch <- translateConstOrRef finalState f
+      tbranch <- translateConstOrRef finalState t
+      let tbr' = case valueContent tbranch of
+            BasicBlockC b -> b
+            _ -> throw (InvalidBranchTarget tbranch)
+          fbr' = case valueContent fbranch of
+            BasicBlockC b -> b
+            _ -> throw (InvalidBranchTarget fbranch)
+      return BranchInst { instructionMetadata = mds
+                        , instructionUniqueId = uid
+                        , instructionBasicBlock = bb
+                        , branchCondition = val'
+                        , branchTrueTarget = tbr'
+                        , branchFalseTarget = fbr'
+                        }
+    _ -> throw InvalidBranchInst
+
+translateSwitchInst :: KnotState -> InstInfoPtr -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateSwitchInst finalState dataPtr mds bb = do
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  case opPtrs of
+    (swVal:defTarget:cases) -> do
+      val' <- translateConstOrRef finalState swVal
+      def' <- translateConstOrRef finalState defTarget
+      -- Process the rest of the list in pairs since that is how LLVM
+      -- stores them, but transform it into a nice list of actual
+      -- pairs
+      let tpairs acc (v1:dest:rest) = do
+            v1' <- translateConstOrRef finalState v1
+            dest' <- translateConstOrRef finalState dest
+            let dest'' = case valueContent dest' of
+                  BasicBlockC b -> b
+                  _ -> throw (InvalidSwitchTarget dest')
+            tpairs ((v1', dest''):acc) rest
+          tpairs acc [] = return $ reverse acc
+          tpairs _ _ = throw InvalidSwitchLayout
+          def'' = case valueContent def' of
+            BasicBlockC b -> b
+            _ -> throw (InvalidSwitchTarget def')
+      cases' <- tpairs [] cases
+      uid <- nextId
+      return SwitchInst { instructionMetadata = mds
+                        , instructionUniqueId = uid
+                        , instructionBasicBlock = bb
+                        , switchValue = val'
+                        , switchDefaultTarget = def''
+                        , switchCases = cases'
+                        }
+    _ -> throw InvalidSwitchLayout
+
+translateIndirectBrInst :: KnotState -> InstInfoPtr -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateIndirectBrInst finalState dataPtr mds bb = do
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  uid <- nextId
+  case opPtrs of
+    (addr:targets) -> do
+      addr' <- translateConstOrRef finalState addr
+      targets' <- mapM (translateConstOrRef finalState) targets
+      return IndirectBranchInst { instructionMetadata = mds
+                                , instructionUniqueId = uid
+                                , instructionBasicBlock = bb
+                                , indirectBranchAddress = addr'
+                                , indirectBranchTargets = map toBasicBlock targets'
+                                }
+    _ -> throw InvalidIndirectBranchOperands
+  where
+    toBasicBlock b = case valueContent b of
+      BasicBlockC b' -> b'
+      _ -> throw (InvalidBranchTarget b)
+
+
+translateInvokeInst :: KnotState -> CallInfoPtr -> Maybe Identifier -> Type
+                       -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateInvokeInst finalState dataPtr name tt mds bb = do
+  n <- computeNameIfNotVoid name tt
+  func <- liftIO $ cCallValue dataPtr
+  args <- liftIO $ cCallArguments dataPtr
+  cc <- liftIO $ cCallConvention dataPtr
+  hasSRet <- liftIO $ cCallHasSRet dataPtr
+  ndest <- liftIO $ cCallNormalDest dataPtr
+  udest <- liftIO $ cCallUnwindDest dataPtr
+
+  f' <- translateConstOrRef finalState func
+  args' <- mapM (translateConstOrRef finalState) args
+  n' <- translateConstOrRef finalState ndest
+  u' <- translateConstOrRef finalState udest
+
+  uid <- nextId
+
+  let n'' = case valueContent n' of
+        BasicBlockC b -> b
+        _ -> $failure "Expected BasicBlock for normal invoke label"
+      u'' = case valueContent u' of
+        BasicBlockC b -> b
+        _ -> $failure "Expected BasicBlock for unwind invoke label"
+
+  return InvokeInst { _instructionName = n
+                    , _instructionType = tt
+                    , instructionMetadata = mds
+                    , instructionUniqueId = uid
+                    , instructionBasicBlock = bb
+                    , invokeConvention = cc
+                    , invokeParamAttrs = [] -- FIXME
+                    , invokeFunction = f'
+                    , invokeArguments = zip args' (repeat []) -- FIXME
+                    , invokeAttrs = [] -- FIXME
+                    , invokeNormalLabel = n''
+                    , invokeUnwindLabel = u''
+                    , invokeHasSRet = hasSRet
+                    }
+
+translateFlaggedBinaryOp :: KnotState
+                            -> (Type -> Maybe Identifier -> [Metadata] -> UniqueId -> Maybe BasicBlock -> ArithFlags -> Value -> Value -> Instruction)
+                            -> InstInfoPtr -> Maybe Identifier -> Type
+                            -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateFlaggedBinaryOp finalState constructor dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  flags <- liftIO $ cInstructionArithFlags dataPtr
+
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+
+  case ops of
+    [lhs, rhs] -> return $ constructor tt n mds uid bb flags lhs rhs
+    _ -> throw $ InvalidBinaryOp (length ops)
+
+translateBinaryOp :: KnotState
+                     -> (Type -> Maybe Identifier -> [Metadata] -> UniqueId -> Maybe BasicBlock -> Value -> Value -> Instruction)
+                     -> InstInfoPtr -> Maybe Identifier -> Type
+                     -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateBinaryOp finalState constructor dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+
+  case ops of
+    [lhs, rhs] -> return $ constructor tt n mds uid bb lhs rhs
+    _ -> throw $ InvalidBinaryOp (length ops)
+
+translateAllocaInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                       -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateAllocaInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  align <- liftIO $ cInstructionAlign dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+
+  case ops of
+    [val] -> return AllocaInst { _instructionType = tt
+                               , _instructionName = n
+                               , instructionMetadata = mds
+                               , instructionUniqueId = uid
+                               , instructionBasicBlock = bb
+                               , allocaNumElements = val
+                               , allocaAlign = align
+                               }
+    _ -> throw $ InvalidUnaryOp (length ops)
+
+
+translateLoadInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                     -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateLoadInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  align <- liftIO $ cInstructionAlign dataPtr
+  vol <- liftIO $ cInstructionIsVolatile dataPtr
+  uid <- nextId
+
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+
+  case ops of
+    [addr] -> return LoadInst { _instructionType = tt
+                              , _instructionName = n
+                              , instructionMetadata = mds
+                              , instructionUniqueId = uid
+                              , instructionBasicBlock = bb
+                              , loadIsVolatile = vol
+                              , loadAddress = addr
+                              , loadAlignment = align
+                              }
+    _ -> throw $ InvalidUnaryOp (length ops)
+
+translateStoreInst :: KnotState -> InstInfoPtr -> [Metadata]
+                      -> Maybe BasicBlock -> KnotMonad Instruction
+translateStoreInst finalState dataPtr mds bb = do
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  addrSpace <- liftIO $ cInstructionAddrSpace dataPtr
+  align <- liftIO $ cInstructionAlign dataPtr
+  isVol <- liftIO $ cInstructionIsVolatile dataPtr
+
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+
+  case ops of
+    [val, ptr] -> return StoreInst { instructionMetadata = mds
+                                   , instructionUniqueId = uid
+                                   , instructionBasicBlock = bb
+                                   , storeIsVolatile = isVol
+                                   , storeValue = val
+                                   , storeAddress = ptr
+                                   , storeAlignment = align
+                                   , storeAddressSpace = addrSpace
+                                   }
+    _ -> throw $ InvalidBinaryOp (length ops)
+
+translateGEPInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                    -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateGEPInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  inBounds <- liftIO $ cInstructionInBounds dataPtr
+  addrSpace <- liftIO $ cInstructionAddrSpace dataPtr
+  uid <- nextId
+
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+
+  case ops of
+    (val:indices) -> return GetElementPtrInst { _instructionName = n
+                                              , _instructionType = tt
+                                              , instructionMetadata = mds
+                                              , instructionUniqueId = uid
+                                              , instructionBasicBlock = bb
+                                              , getElementPtrInBounds = inBounds
+                                              , getElementPtrValue = val
+                                              , getElementPtrIndices = indices
+                                              , getElementPtrAddrSpace = addrSpace
+                                              }
+    _ -> throw $ InvalidGEPInst (length ops)
+
+translateCastInst :: KnotState
+                     -> (Type -> Maybe Identifier -> [Metadata] -> UniqueId -> Maybe BasicBlock -> Value -> Instruction)
+                     -> InstInfoPtr -> Maybe Identifier -> Type
+                     -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateCastInst finalState constructor dataPtr name tt mds bb = do
+  n <- computeRealName name
+  uid <- nextId
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+
+  case ops of
+    [v] -> return $ constructor tt n mds uid bb v
+    _ -> throw $ InvalidUnaryOp (length ops)
+
+translateCmpInst :: KnotState
+                    -> (Type -> Maybe Identifier -> [Metadata] -> UniqueId -> Maybe BasicBlock -> CmpPredicate -> Value -> Value -> Instruction)
+                    -> InstInfoPtr -> Maybe Identifier -> Type -> [Metadata]
+                    -> Maybe BasicBlock -> KnotMonad Instruction
+translateCmpInst finalState constructor dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  predicate <- liftIO $ cInstructionCmpPred dataPtr
+  uid <- nextId
+
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+
+  case ops of
+    [op1, op2] -> return $ constructor tt n mds uid bb predicate op1 op2
+    _ -> throw $ InvalidBinaryOp (length ops)
+
+translatePhiNode :: KnotState -> PHIInfoPtr -> Maybe Identifier
+                    -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translatePhiNode finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  vptrs <- liftIO $ cPHIValues dataPtr
+  bptrs <- liftIO $ cPHIBlocks dataPtr
+  uid <- nextId
+
+  vals <- mapM (translateConstOrRef finalState) vptrs
+  blocks <- mapM (translateConstOrRef finalState) bptrs
+
+  return PhiNode { _instructionType = tt
+                 , _instructionName = n
+                 , instructionMetadata = mds
+                 , instructionUniqueId = uid
+                 , instructionBasicBlock = bb
+                 , phiIncomingValues = zip vals blocks
+                 }
+
+translateCallInst :: KnotState -> CallInfoPtr -> Maybe Identifier
+                     -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateCallInst finalState dataPtr name tt mds bb = do
+  n <- computeNameIfNotVoid name tt
+  vptr <- liftIO $ cCallValue dataPtr
+  aptrs <- liftIO $ cCallArguments dataPtr
+  cc <- liftIO $ cCallConvention dataPtr
+  hasSRet <- liftIO $ cCallHasSRet dataPtr
+  isTail <- liftIO $ cCallIsTail dataPtr
+  uid <- nextId
+
+  val <- translateConstOrRef finalState vptr
+  args <- mapM (translateConstOrRef finalState) aptrs
+
+  return CallInst { _instructionType = tt
+                  , _instructionName = n
+                  , instructionMetadata = mds
+                  , instructionUniqueId = uid
+                  , instructionBasicBlock = bb
+                  , callIsTail = isTail
+                  , callConvention = cc
+                  , callParamAttrs = [] -- FIXME
+                  , callFunction = val
+                  , callArguments = zip args (repeat []) -- FIXME
+                  , callAttrs = [] -- FIXME
+                  , callHasSRet = hasSRet
+                  }
+
+translateSelectInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                       -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateSelectInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+  case ops of
+    [cond, trueval, falseval] ->
+      return SelectInst { _instructionType = tt
+                        , _instructionName = n
+                        , instructionMetadata = mds
+                        , instructionUniqueId = uid
+                        , instructionBasicBlock = bb
+                        , selectCondition = cond
+                        , selectTrueValue = trueval
+                        , selectFalseValue = falseval
+                        }
+    _ -> throw $ InvalidSelectArgs (length ops)
+
+translateVarArgInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                       -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateVarArgInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+  case ops of
+    [op] -> return VaArgInst { _instructionType = tt
+                             , _instructionName = n
+                             , instructionMetadata = mds
+                             , instructionUniqueId = uid
+                             , instructionBasicBlock = bb
+                             , vaArgValue = op
+                             }
+    _ -> throw $ InvalidUnaryOp (length ops)
+
+translateExtractElementInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                               -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateExtractElementInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+  case ops of
+    [vec, idx] ->
+      return ExtractElementInst { _instructionType = tt
+                                , _instructionName = n
+                                , instructionMetadata = mds
+                                , instructionUniqueId = uid
+                                , instructionBasicBlock = bb
+                                , extractElementVector = vec
+                                , extractElementIndex = idx
+                                }
+    _ -> throw $ InvalidExtractElementInst (length ops)
+
+translateInsertElementInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                              -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateInsertElementInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+  case ops of
+    [vec, val, idx] ->
+      return InsertElementInst { _instructionType = tt
+                               , _instructionName = n
+                               , instructionMetadata = mds
+                               , instructionUniqueId = uid
+                               , instructionBasicBlock = bb
+                               , insertElementVector = vec
+                               , insertElementValue = val
+                               , insertElementIndex = idx
+                               }
+    _ -> throw $ InvalidInsertElementInst (length ops)
+
+translateShuffleVectorInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                              -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateShuffleVectorInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  uid <- nextId
+  case ops of
+    [v1, v2, vecMask] ->
+      return ShuffleVectorInst { _instructionType = tt
+                               , _instructionName = n
+                               , instructionMetadata = mds
+                               , instructionUniqueId = uid
+                               , instructionBasicBlock = bb
+                               , shuffleVectorV1 = v1
+                               , shuffleVectorV2 = v2
+                               , shuffleVectorMask = vecMask
+                               }
+    _ -> throw $ InvalidShuffleVectorInst (length ops)
+
+translateExtractValueInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                             -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateExtractValueInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  indices <- liftIO $ cInstructionIndices dataPtr
+  uid <- nextId
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  case ops of
+    [agg] -> return ExtractValueInst { _instructionType = tt
+                                     , _instructionName = n
+                                     , instructionMetadata = mds
+                                     , instructionUniqueId = uid
+                                     , instructionBasicBlock = bb
+                                     , extractValueAggregate = agg
+                                     , extractValueIndices = indices
+                                     }
+    _ -> throw $ InvalidExtractValueInst (length ops)
+
+translateInsertValueInst :: KnotState -> InstInfoPtr -> Maybe Identifier
+                            -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateInsertValueInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  indices <- liftIO $ cInstructionIndices dataPtr
+  uid <- nextId
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  case ops of
+    [agg, val] ->
+      return InsertValueInst { _instructionType = tt
+                             , _instructionName = n
+                             , instructionMetadata = mds
+                             , instructionUniqueId = uid
+                             , instructionBasicBlock = bb
+                             , insertValueAggregate = agg
+                             , insertValueValue = val
+                             , insertValueIndices = indices
+                             }
+    _ -> throw $ InvalidInsertValueInst (length ops)
+
+translateResumeInst :: KnotState -> InstInfoPtr -> [Metadata]
+                       -> Maybe BasicBlock -> KnotMonad Instruction
+translateResumeInst finalState dataPtr mds bb = do
+  uid <- nextId
+  opPtrs <- liftIO $ cInstructionOperands dataPtr
+  ops <- mapM (translateConstOrRef finalState) opPtrs
+  case ops of
+    [val] ->
+      return ResumeInst { instructionMetadata = mds
+                        , instructionUniqueId = uid
+                        , instructionBasicBlock = bb
+                        , resumeException = val
+                        }
+    _ -> throw $ InvalidResumeInst (length ops)
+
+translateFenceInst :: KnotState -> AtomicInfoPtr -> [Metadata]
+                      -> Maybe BasicBlock -> KnotMonad Instruction
+translateFenceInst _ dataPtr mds bb = do
+  uid <- nextId
+  order <- liftIO $ cAtomicOrdering dataPtr
+  scope <- liftIO $ cAtomicScope dataPtr
+  return FenceInst { instructionMetadata = mds
+                   , instructionUniqueId = uid
+                   , instructionBasicBlock = bb
+                   , fenceOrdering = order
+                   , fenceScope = scope
+                   }
+
+translateAtomicCmpXchgInst :: KnotState -> AtomicInfoPtr -> [Metadata]
+                              -> Maybe BasicBlock -> KnotMonad Instruction
+translateAtomicCmpXchgInst finalState dataPtr mds bb = do
+  uid <- nextId
+  order <- liftIO $ cAtomicOrdering dataPtr
+  scope <- liftIO $ cAtomicScope dataPtr
+  isVol <- liftIO $ cAtomicIsVolatile dataPtr
+  addrSpc <- liftIO $ cAtomicAddressSpace dataPtr
+  ptrPtr <- liftIO $ cAtomicPointerOperand dataPtr
+  cmpPtr <- liftIO $ cAtomicCompareOperand dataPtr
+  valPtr <- liftIO $ cAtomicValueOperand dataPtr
+
+  ptr <- translateConstOrRef finalState ptrPtr
+  cmp <- translateConstOrRef finalState cmpPtr
+  val <- translateConstOrRef finalState valPtr
+
+  return AtomicCmpXchgInst { instructionMetadata = mds
+                           , instructionUniqueId = uid
+                           , instructionBasicBlock = bb
+                           , atomicCmpXchgOrdering = order
+                           , atomicCmpXchgScope = scope
+                           , atomicCmpXchgIsVolatile = isVol
+                           , atomicCmpXchgAddressSpace = addrSpc
+                           , atomicCmpXchgPointer = ptr
+                           , atomicCmpXchgComparison = cmp
+                           , atomicCmpXchgNewValue = val
+                           }
+
+translateAtomicRMWInst :: KnotState -> AtomicInfoPtr -> [Metadata]
+                          -> Maybe BasicBlock -> KnotMonad Instruction
+translateAtomicRMWInst finalState dataPtr mds bb = do
+  uid <- nextId
+  order <- liftIO $ cAtomicOrdering dataPtr
+  scope <- liftIO $ cAtomicScope dataPtr
+  op <- liftIO $ cAtomicOperation dataPtr
+  isVol <- liftIO $ cAtomicIsVolatile dataPtr
+  addrSpc <- liftIO $ cAtomicAddressSpace dataPtr
+  ptrPtr <- liftIO $ cAtomicPointerOperand dataPtr
+  valPtr <- liftIO $ cAtomicValueOperand dataPtr
+
+  ptr <- translateConstOrRef finalState ptrPtr
+  val <- translateConstOrRef finalState valPtr
+
+  return AtomicRMWInst { instructionMetadata = mds
+                       , instructionUniqueId = uid
+                       , instructionBasicBlock = bb
+                       , atomicRMWOrdering = order
+                       , atomicRMWScope = scope
+                       , atomicRMWOperation = op
+                       , atomicRMWIsVolatile = isVol
+                       , atomicRMWAddressSpace = addrSpc
+                       , atomicRMWPointer = ptr
+                       , atomicRMWValue = val
+                       }
+
+translateLandingPadInst :: KnotState -> LandingPadInfoPtr -> Maybe Identifier
+                           -> Type -> [Metadata] -> Maybe BasicBlock -> KnotMonad Instruction
+translateLandingPadInst finalState dataPtr name tt mds bb = do
+  n <- computeRealName name
+  uid <- nextId
+  personPtr <- liftIO $ cLandingPadPersonality dataPtr
+  isClean <- liftIO $ cLandingPadIsCleanup dataPtr
+  clausePtrs <- liftIO $ cLandingPadClauses dataPtr
+  clauseTypes <- liftIO $ cLandingPadClauseTypes dataPtr
+
+  personality <- translateConstOrRef finalState personPtr
+  clauses <- mapM (translateConstOrRef finalState) clausePtrs
+
+  let taggedClauses = zip clauses clauseTypes
+  return LandingPadInst { _instructionType = tt
+                        , _instructionName = n
+                        , instructionMetadata = mds
+                        , instructionUniqueId = uid
+                        , instructionBasicBlock = bb
+                        , landingPadPersonality = personality
+                        , landingPadIsCleanup = isClean
+                        , landingPadClauses = taggedClauses
+                        }
+
+translateConstantExpr :: KnotState -> ConstExprPtr -> Type -> KnotMonad Instruction
+translateConstantExpr finalState dataPtr tt = do
+  let mds = []
+      bb = Nothing
+  ii <- liftIO $ cConstExprInstInfo dataPtr
+  tag <- liftIO $ cConstExprTag dataPtr
+  case tag of
+    ValAddinst -> translateFlaggedBinaryOp finalState AddInst ii Nothing tt mds bb
+    ValFaddinst -> translateFlaggedBinaryOp finalState AddInst ii Nothing tt mds bb
+    ValSubinst -> translateFlaggedBinaryOp finalState SubInst ii Nothing tt mds bb
+    ValFsubinst -> translateFlaggedBinaryOp finalState SubInst ii Nothing tt mds bb
+    ValMulinst ->  translateFlaggedBinaryOp finalState MulInst ii Nothing tt mds bb
+    ValFmulinst ->  translateFlaggedBinaryOp finalState MulInst ii Nothing tt mds bb
+    ValUdivinst -> translateBinaryOp finalState DivInst ii Nothing tt mds bb
+    ValSdivinst -> translateBinaryOp finalState DivInst ii Nothing tt mds bb
+    ValFdivinst -> translateBinaryOp finalState DivInst ii Nothing tt mds bb
+    ValUreminst -> translateBinaryOp finalState RemInst ii Nothing tt mds bb
+    ValSreminst -> translateBinaryOp finalState RemInst ii Nothing tt mds bb
+    ValFreminst -> translateBinaryOp finalState RemInst ii Nothing tt mds bb
+    ValShlinst -> translateBinaryOp finalState ShlInst ii Nothing tt mds bb
+    ValLshrinst -> translateBinaryOp finalState LshrInst ii Nothing tt mds bb
+    ValAshrinst -> translateBinaryOp finalState AshrInst ii Nothing tt mds bb
+    ValAndinst -> translateBinaryOp finalState AndInst ii Nothing tt mds bb
+    ValOrinst -> translateBinaryOp finalState OrInst ii Nothing tt mds bb
+    ValXorinst -> translateBinaryOp finalState XorInst ii Nothing tt mds bb
+    ValGetelementptrinst -> translateGEPInst finalState ii Nothing tt mds bb
+    ValTruncinst -> translateCastInst finalState TruncInst ii Nothing tt mds bb
+    ValZextinst -> translateCastInst finalState ZExtInst ii Nothing tt mds bb
+    ValSextinst -> translateCastInst finalState SExtInst ii Nothing tt mds bb
+    ValFptruncinst -> translateCastInst finalState FPTruncInst ii Nothing tt mds bb
+    ValFpextinst -> translateCastInst finalState FPExtInst ii Nothing tt mds bb
+    ValFptouiinst -> translateCastInst finalState FPToUIInst ii Nothing tt mds bb
+    ValFptosiinst -> translateCastInst finalState FPToSIInst ii Nothing tt mds bb
+    ValUitofpinst -> translateCastInst finalState UIToFPInst ii Nothing tt mds bb
+    ValSitofpinst -> translateCastInst finalState SIToFPInst ii Nothing tt mds bb
+    ValPtrtointinst -> translateCastInst finalState PtrToIntInst ii Nothing tt mds bb
+    ValInttoptrinst -> translateCastInst finalState IntToPtrInst ii Nothing tt mds bb
+    ValBitcastinst -> translateCastInst finalState BitcastInst ii Nothing tt mds bb
+    ValIcmpinst -> translateCmpInst finalState ICmpInst ii Nothing tt mds bb
+    ValFcmpinst -> translateCmpInst finalState FCmpInst ii Nothing tt mds bb
+    ValSelectinst -> translateSelectInst finalState ii Nothing tt mds bb
+    ValVaarginst -> translateVarArgInst finalState ii Nothing tt mds bb
+    ValExtractelementinst -> translateExtractElementInst finalState ii Nothing tt mds bb
+    ValInsertelementinst -> translateInsertElementInst finalState ii Nothing tt mds bb
+    ValShufflevectorinst -> translateShuffleVectorInst finalState ii Nothing tt mds bb
+    ValExtractvalueinst -> translateExtractValueInst finalState ii Nothing tt mds bb
+    ValInsertvalueinst -> translateInsertValueInst finalState ii Nothing tt mds bb
+    _ -> throw (NonInstructionTag tag)
+
+translateMetadata :: KnotState -> MetaPtr -> KnotMonad Metadata
+translateMetadata finalState mp = do
+  s <- get
+  let ip = ptrToIntPtr mp
+      key = fromIntegral ip
+  put s { visitedMetadata = S.insert ip (visitedMetadata s) }
+
+  existingVal <- liftIO $ HT.lookup (metaMap s) key
+  case existingVal of
+    Just m -> return m
+    Nothing -> translateMetadata' finalState mp
+
+translateMetadataRec :: KnotState -> MetaPtr -> KnotMonad Metadata
+translateMetadataRec finalState mp = do
+  s <- get
+  let ip = ptrToIntPtr mp
+  -- If we have already visited this metadata object, look it up in
+  -- the final state.  We record visits *before* making recursive
+  -- calls, allowing us to tie the knot by looking already-visited
+  -- nodes up in the final state.
+  --
+  -- If we haven't seen this node before, we can safely call the
+  -- outermost 'translateMetadata', which will make an entry in the
+  -- visited set and then do the translation.
+  case S.member ip (visitedMetadata s) of
+    False -> translateMetadata finalState mp
+    True -> do
+      let key = fromIntegral ip
+          finalVal = unsafePerformIO (HT.lookup (metaMap finalState) key)
+      return $ maybe (throw MetaKnotFailure) id finalVal
+
+maybeTranslateMetadataRec :: KnotState -> Maybe MetaPtr -> KnotMonad (Maybe Metadata)
+maybeTranslateMetadataRec _ Nothing = return Nothing
+maybeTranslateMetadataRec finalState (Just mp) =
+  Just <$> translateMetadataRec finalState mp
+
+metadataArrayToList :: Maybe Metadata -> [Maybe Metadata]
+metadataArrayToList (Just (MetadataList _ elts)) = elts
+metadataArrayToList Nothing = []
+metadataArrayToList _ = error "Unexpected non-array metadata"
+
+translateMetadata' :: KnotState -> MetaPtr -> KnotMonad Metadata
+translateMetadata' finalState mp = do
+  let ip = ptrToIntPtr mp
+  s <- get
+  put s { visitedMetadata = S.insert ip (visitedMetadata s) }
+  metaTag <- liftIO $ cMetaTypeTag mp
+
+  uid <- nextMetaId
+
+  md <- case metaTag of
+    MetaLocation -> do
+      line <- liftIO $ cMetaLocationLine mp
+      col <- liftIO $ cMetaLocationColumn mp
+
+      return MetaSourceLocation { metaValueUniqueId = uid
+                                , metaSourceRow = line
+                                , metaSourceCol = col
+                                , metaSourceScope = Nothing
+                                }
+    MetaDerivedtype -> do
+      ctxt <- liftIO $ cMetaTypeContext mp
+      name <- cMetaTypeName mp
+      line <- liftIO $ cMetaTypeLine mp
+      size <- liftIO $ cMetaTypeSize mp
+      align <- liftIO $ cMetaTypeAlign mp
+      off <- liftIO $ cMetaTypeOffset mp
+      parent <- liftIO $ cMetaTypeDerivedFrom mp
+
+      isArtif <- liftIO $ cMetaTypeIsArtificial mp
+      isVirt <- liftIO $ cMetaTypeIsVirtual mp
+      isForward <- liftIO $ cMetaTypeIsForward mp
+      isProt <- liftIO $ cMetaTypeIsProtected mp
+      isPriv <- liftIO $ cMetaTypeIsPrivate mp
+      dir <- cMetaTypeDirectory mp
+      file <- cMetaTypeFilename mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+      parent' <- maybeTranslateMetadataRec finalState parent
+
+      tag <- liftIO $ cMetaTag mp
+
+      return MetaDWDerivedType { metaValueUniqueId = uid
+                               , metaDerivedTypeContext = ctxt'
+                               , metaDerivedTypeName = name
+                               , metaDerivedTypeFilename = file
+                               , metaDerivedTypeDirectory = dir
+                               , metaDerivedTypeLine = line
+                               , metaDerivedTypeSize = size
+                               , metaDerivedTypeAlign = align
+                               , metaDerivedTypeOffset = off
+                               , metaDerivedTypeParent = parent'
+                               , metaDerivedTypeTag = tag
+                               , metaDerivedTypeIsArtificial = isArtif
+                               , metaDerivedTypeIsVirtual = isVirt
+                               , metaDerivedTypeIsForward = isForward
+                               , metaDerivedTypeIsProtected = isProt
+                               , metaDerivedTypeIsPrivate = isPriv
+                               }
+    MetaCompositetype -> do
+      ctxt <- liftIO $ cMetaTypeContext mp
+      name <- cMetaTypeName mp
+      line <- liftIO $ cMetaTypeLine mp
+      size <- liftIO $ cMetaTypeSize mp
+      align <- liftIO $ cMetaTypeAlign mp
+      off <- liftIO $ cMetaTypeOffset mp
+      parent <- liftIO $ cMetaTypeDerivedFrom mp
+      flags <- liftIO $ cMetaTypeFlags mp
+      members <- liftIO $ cMetaTypeCompositeComponents mp
+      rlang <- liftIO $ cMetaTypeRuntimeLanguage mp
+      ctype <- liftIO $ cMetaTypeContainingType mp
+      tparams <- liftIO $ cMetaTypeTemplateParams mp
+      isArtif <- liftIO $ cMetaTypeIsArtificial mp
+      isVirtual <- liftIO $ cMetaTypeIsVirtual mp
+      isForward <- liftIO $ cMetaTypeIsForward mp
+      isProt <- liftIO $ cMetaTypeIsProtected mp
+      isPriv <- liftIO $ cMetaTypeIsPrivate mp
+      isByRef <- liftIO $ cMetaTypeIsByRefStruct mp
+      dir <- cMetaTypeDirectory mp
+      file <- cMetaTypeFilename mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+      parent' <- maybeTranslateMetadataRec finalState parent
+      members' <- maybeTranslateMetadataRec finalState members
+      ctype' <- maybeTranslateMetadataRec finalState ctype
+      tparams' <- maybeTranslateMetadataRec finalState tparams
+
+      tag <- liftIO $ cMetaTag mp
+
+      return MetaDWCompositeType { metaValueUniqueId = uid
+                                 , metaCompositeTypeTag = tag
+                                 , metaCompositeTypeContext = ctxt'
+                                 , metaCompositeTypeName = name
+                                 , metaCompositeTypeFilename = file
+                                 , metaCompositeTypeDirectory = dir
+                                 , metaCompositeTypeLine = line
+                                 , metaCompositeTypeSize = size
+                                 , metaCompositeTypeAlign = align
+                                 , metaCompositeTypeOffset = off
+                                 , metaCompositeTypeFlags = flags
+                                 , metaCompositeTypeParent = parent'
+                                 , metaCompositeTypeMembers = members'
+                                 , metaCompositeTypeRuntime = rlang
+                                 , metaCompositeTypeContainer = ctype'
+                                 , metaCompositeTypeTemplateParams = tparams'
+                                 , metaCompositeTypeIsArtificial = isArtif
+                                 , metaCompositeTypeIsVirtual = isVirtual
+                                 , metaCompositeTypeIsForward = isForward
+                                 , metaCompositeTypeIsProtected = isProt
+                                 , metaCompositeTypeIsPrivate = isPriv
+                                 , metaCompositeTypeIsByRefStruct = isByRef
+                                 }
+    MetaBasictype -> do
+      ctxt <- liftIO $ cMetaTypeContext mp
+      name <- cMetaTypeName mp
+      line <- liftIO $ cMetaTypeLine mp
+      size <- liftIO $ cMetaTypeSize mp
+      align <- liftIO $ cMetaTypeAlign mp
+      off <- liftIO $ cMetaTypeOffset mp
+      flags <- liftIO $ cMetaTypeFlags mp
+      encoding <- liftIO $ cMetaTypeEncoding mp
+      dir <- cMetaTypeDirectory mp
+      file <- cMetaTypeFilename mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+
+      return MetaDWBaseType { metaValueUniqueId = uid
+                            , metaBaseTypeContext = ctxt'
+                            , metaBaseTypeName = name
+                            , metaBaseTypeFilename = file
+                            , metaBaseTypeDirectory = dir
+                            , metaBaseTypeLine = line
+                            , metaBaseTypeSize = size
+                            , metaBaseTypeAlign = align
+                            , metaBaseTypeOffset = off
+                            , metaBaseTypeFlags = flags
+                            , metaBaseTypeEncoding = encoding
+                            }
+    MetaVariable -> do
+      ctxt <- liftIO $ cMetaVariableContext mp
+      name <- cMetaVariableName mp
+      line <- liftIO $ cMetaVariableLine mp
+      argNo <- liftIO $ cMetaVariableArgNumber mp
+      ty <- liftIO $ cMetaVariableType mp
+      isArtif <- liftIO $ cMetaVariableIsArtificial mp
+      cplxAddr <- liftIO $ cMetaVariableAddrElements mp
+      byRef <- liftIO $ cMetaVariableIsBlockByRefVar mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+      ty' <- maybeTranslateMetadataRec finalState ty
+
+      tag <- liftIO $ cMetaTag mp
+
+      return MetaDWLocal { metaValueUniqueId = uid
+                         , metaLocalTag = tag
+                         , metaLocalContext = ctxt'
+                         , metaLocalName = name
+                         , metaLocalLine = line
+                         , metaLocalArgNo = argNo
+                         , metaLocalType = ty'
+                         , metaLocalIsArtificial = isArtif
+                         , metaLocalIsBlockByRefVar = byRef
+                         , metaLocalAddrElements = cplxAddr
+                         }
+    MetaSubprogram -> do
+      ctxt <- liftIO $ cMetaSubprogramContext mp
+      name <- cMetaSubprogramName mp
+      displayName <- cMetaSubprogramDisplayName mp
+      linkageName <- cMetaSubprogramLinkageName mp
+      line <- liftIO $ cMetaSubprogramLine mp
+      ty <- liftIO $ cMetaSubprogramType mp
+      isLocal <- liftIO $ cMetaSubprogramIsLocal mp
+      virt <- liftIO $ cMetaSubprogramVirtuality mp
+      virtIdx <- liftIO $ cMetaSubprogramVirtualIndex mp
+      baseType <- liftIO $ cMetaSubprogramContainingType mp
+      isArtif <- liftIO $ cMetaSubprogramIsArtificial mp
+      isOpt <- liftIO $ cMetaSubprogramIsOptimized mp
+      isPrivate <- liftIO $ cMetaSubprogramIsPrivate mp
+      isProtected <- liftIO $ cMetaSubprogramIsProtected mp
+      isExplicit <- liftIO $ cMetaSubprogramIsExplicit mp
+      isPrototyped <- liftIO $ cMetaSubprogramIsPrototyped mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+      ty' <- maybeTranslateMetadataRec finalState ty
+      baseType' <- maybeTranslateMetadataRec finalState baseType
+
+      return MetaDWSubprogram { metaValueUniqueId = uid
+                              , metaSubprogramContext = ctxt'
+                              , metaSubprogramName = name
+                              , metaSubprogramDisplayName = displayName
+                              , metaSubprogramLinkageName = linkageName
+                              , metaSubprogramLine = line
+                              , metaSubprogramType = ty'
+                              , metaSubprogramStatic = isLocal
+                              , metaSubprogramNotExtern = not isPrivate && not isProtected
+                              , metaSubprogramVirtuality = virt
+                              , metaSubprogramVirtIndex = virtIdx
+                              , metaSubprogramBaseType = baseType'
+                              , metaSubprogramArtificial = isArtif
+                              , metaSubprogramOptimized = isOpt
+                              , metaSubprogramIsExplicit = isExplicit
+                              , metaSubprogramIsPrototyped = isPrototyped
+                              }
+    MetaGlobalvariable -> do
+      ctxt <- liftIO $ cMetaGlobalContext mp
+      name <- cMetaGlobalName mp
+      displayName <- cMetaGlobalDisplayName mp
+      linkageName <- cMetaGlobalLinkageName mp
+      line <- liftIO $ cMetaGlobalLine mp
+      ty <- liftIO $ cMetaGlobalType mp
+      isLocal <- liftIO $ cMetaGlobalIsLocal mp
+      def <- liftIO $ cMetaGlobalIsDefinition mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+      ty' <- maybeTranslateMetadataRec finalState ty
+
+      return MetaDWVariable { metaValueUniqueId = uid
+                            , metaGlobalVarContext = ctxt'
+                            , metaGlobalVarName = name
+                            , metaGlobalVarDisplayName = displayName
+                            , metaGlobalVarLinkageName = linkageName
+                            , metaGlobalVarLine = line
+                            , metaGlobalVarType = ty'
+                            , metaGlobalVarStatic = isLocal
+                            , metaGlobalVarNotExtern = not def
+                            }
+    MetaFile -> do
+      file <- cMetaFileFilename mp
+      dir <- cMetaFileDirectory mp
+
+      return MetaDWFile { metaValueUniqueId = uid
+                        , metaFileSourceFile = file
+                        , metaFileSourceDir = dir
+                        }
+    MetaCompileunit -> do
+      lang <- liftIO $ cMetaCompileUnitLanguage mp
+      fname <- cMetaCompileUnitFilename mp
+      dir <- cMetaCompileUnitDirectory mp
+      producer <- cMetaCompileUnitProducer mp
+      isMain <- liftIO $ cMetaCompileUnitIsMain mp
+      isOpt <- liftIO $ cMetaCompileUnitIsOptimized mp
+      flags <- cMetaCompileUnitFlags mp
+      rv <- liftIO $ cMetaCompileUnitRuntimeVersion mp
+      ets <- liftIO $ cMetaCompileUnitEnumTypes mp
+      rts <- liftIO $ cMetaCompileUnitRetainedTypes mp
+      sps <- liftIO $ cMetaCompileUnitSubprograms mp
+      gvs <- liftIO $ cMetaCompileUnitGlobalVariables mp
+
+      ets' <- maybeTranslateMetadataRec finalState ets
+      rts' <- maybeTranslateMetadataRec finalState rts
+      sps' <- maybeTranslateMetadataRec finalState sps
+      gvs' <- maybeTranslateMetadataRec finalState gvs
+
+      return MetaDWCompileUnit { metaValueUniqueId = uid
+                               , metaCompileUnitLanguage = lang
+                               , metaCompileUnitSourceFile = fname
+                               , metaCompileUnitCompileDir = dir
+                               , metaCompileUnitProducer = producer
+                               , metaCompileUnitIsMain = isMain
+                               , metaCompileUnitIsOpt = isOpt
+                               , metaCompileUnitFlags = flags
+                               , metaCompileUnitVersion = rv
+                               , metaCompileUnitEnumTypes = metadataArrayToList ets'
+                               , metaCompileUnitRetainedTypes = metadataArrayToList rts'
+                               , metaCompileUnitSubprograms = metadataArrayToList sps'
+                               , metaCompileUnitGlobalVariables = metadataArrayToList gvs'
+                               }
+    MetaNamespace -> do
+      ctxt <- liftIO $ cMetaNamespaceContext mp
+      name <- cMetaNamespaceName mp
+      line <- liftIO $ cMetaNamespaceLine mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+
+      return MetaDWNamespace { metaValueUniqueId = uid
+                             , metaNamespaceContext = ctxt'
+                             , metaNamespaceName = name
+                             , metaNamespaceLine = line
+                             }
+    MetaLexicalblock -> do
+      ctxt <- liftIO $ cMetaLexicalBlockContext mp
+      line <- liftIO $ cMetaLexicalBlockLine mp
+      col <- liftIO $ cMetaLexicalBlockColumn mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+
+      return MetaDWLexicalBlock { metaValueUniqueId = uid
+                                , metaLexicalBlockRow = line
+                                , metaLexicalBlockCol = col
+                                , metaLexicalBlockContext = ctxt'
+                                }
+    MetaSubrange -> do
+      lo <- liftIO $ cMetaSubrangeLo mp
+      hi <- liftIO $ cMetaSubrangeHi mp
+      return MetaDWSubrange { metaValueUniqueId = uid
+                            , metaSubrangeLow = lo
+                            , metaSubrangeHigh = hi
+                            }
+    MetaEnumerator -> do
+      name <- cMetaEnumeratorName mp
+      val <- liftIO $ cMetaEnumeratorValue mp
+      return MetaDWEnumerator { metaValueUniqueId = uid
+                              , metaEnumeratorName = name
+                              , metaEnumeratorValue = val
+                              }
+    MetaArray -> do
+      elts <- liftIO $ cMetaArrayElts mp
+      elts' <- mapM (maybeTranslateMetadataRec finalState) elts
+
+      return $ MetadataList uid elts'
+
+    MetaTemplatetypeparameter -> do
+      ctxt <- liftIO $ cMetaTemplateTypeContext mp
+      name <- cMetaTemplateTypeName mp
+      ty <- liftIO $ cMetaTemplateTypeType mp
+      line <- liftIO $ cMetaTemplateTypeLine mp
+      col <- liftIO $ cMetaTemplateTypeColumn mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+      ty' <- maybeTranslateMetadataRec finalState ty
+
+      return MetaDWTemplateTypeParameter { metaValueUniqueId = uid
+                                         , metaTemplateTypeParameterContext = ctxt'
+                                         , metaTemplateTypeParameterType = ty'
+                                         , metaTemplateTypeParameterLine = line
+                                         , metaTemplateTypeParameterCol = col
+                                         , metaTemplateTypeParameterName = name
+                                         }
+    MetaTemplatevalueparameter -> do
+      ctxt <- liftIO $ cMetaTemplateValueContext mp
+      name <- cMetaTemplateValueName mp
+      ty <- liftIO $ cMetaTemplateValueType mp
+      val <- liftIO $ cMetaTemplateValueValue mp
+      line <- liftIO $ cMetaTemplateValueLine mp
+      col <- liftIO $ cMetaTemplateValueColumn mp
+
+      ctxt' <- maybeTranslateMetadataRec finalState ctxt
+      ty' <- maybeTranslateMetadataRec finalState ty
+
+      return MetaDWTemplateValueParameter { metaValueUniqueId = uid
+                                          , metaTemplateValueParameterContext = ctxt'
+                                          , metaTemplateValueParameterType = ty'
+                                          , metaTemplateValueParameterLine = line
+                                          , metaTemplateValueParameterCol = col
+                                          , metaTemplateValueParameterValue = val
+                                          , metaTemplateValueParameterName = name
+                                          }
+    MetaUnknown -> do
+      repr <- cMetaUnknownRepr mp
+      return $! MetadataUnknown uid repr
+
+  st <- get
+  liftIO $ HT.insert (metaMap st) (fromIntegral ip) md
+  return md
diff --git a/src/c++/marshal.cpp b/src/c++/marshal.cpp
new file mode 100644
--- /dev/null
+++ b/src/c++/marshal.cpp
@@ -0,0 +1,2673 @@
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+
+#include "marshal.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <cmath>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <tr1/unordered_map>
+
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/SourceMgr.h>
+#include <llvm/Support/system_error.h>
+
+#include <llvm/Config/llvm-config.h>
+
+#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR > 3
+  #error "LLVM 4.0 and greater are not supported"
+#endif
+
+// LLVM 3.0 does not define LLVM_VERSION_MAJOR
+#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 2
+  // LLVM 3.2 moved the debug info header and renamed TargetData
+  // to DataLayout.  LLVM 3.3 moved the DataLayout header.
+  #include <llvm/DebugInfo.h>
+  #if LLVM_VERSION_MINOR >= 3
+    #include <llvm/IR/DataLayout.h>
+  #else
+    #include <llvm/DataLayout.h>
+  #endif
+#else
+  // LLVM 3.0/3.1
+  #include <llvm/Analysis/DebugInfo.h>
+  #include <llvm/Target/TargetData.h>
+  #define DataLayout TargetData
+#endif
+
+#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 3
+  // LLVM 3.3
+  #include <llvm/IR/CallingConv.h>
+  #include <llvm/IR/DerivedTypes.h>
+  #include <llvm/IR/InlineAsm.h>
+  #include <llvm/IR/IntrinsicInst.h>
+  #include <llvm/IR/Instructions.h>
+  #include <llvm/IR/LLVMContext.h>
+  #include <llvm/IR/Module.h>
+  #include <llvm/IR/Operator.h>
+  #include <llvm/IR/Type.h>
+  #include <llvm/IRReader/IRReader.h>
+#else
+  // LLVM 3.0-3.2
+  #include <llvm/CallingConv.h>
+  #include <llvm/DerivedTypes.h>
+  #include <llvm/InlineAsm.h>
+  #include <llvm/IntrinsicInst.h>
+  #include <llvm/Instructions.h>
+  #include <llvm/LLVMContext.h>
+  #include <llvm/Module.h>
+  #include <llvm/Operator.h>
+  #include <llvm/Type.h>
+  #include <llvm/Support/IRReader.h>
+#endif
+
+using namespace llvm;
+using std::ostringstream;
+using std::string;
+using std::tr1::unordered_map;
+
+// Utility functions to hide incompatibilities between LLVM API
+// versions
+static int64_t getHiDISubrange(llvm::DISubrange &subrange) {
+#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 3
+  return subrange.getLo() + subrange.getCount();
+#else
+  return subrange.getHi();
+#endif
+}
+
+static char* getCStrdup(StringRef str) {
+  return strndup(str.data(), str.size());
+}
+
+static char* getCStrdup(std::string &str) {
+  return strdup(str.c_str());
+}
+
+static char* getCStrdup(const char *str) {
+  return strdup(str);
+}
+
+static char* getCStrdup(llvm::raw_string_ostream &os) {
+  return getCStrdup(os.str());
+}
+
+struct PrivateData {
+  LLVMContext ctxt;
+  SMDiagnostic diags;
+  OwningPtr<MemoryBuffer> buffer;
+  // Foreign callers do not need to access below this point.
+  Module* original;
+  int includeLocs;
+  DataLayout *dataLayout;
+
+  // This map is actually state only for this translation code.  Since
+  // types have pointer equality in LLVM, every type will just be
+  // translated once to a heap-allocated CType.  On the Haskell side,
+  // each CType needs to be translated once (mapping the address of
+  // the CType to the translated version).
+  unordered_map<const Type*, CType*> typeMap;
+  unordered_map<const Value*, CValue*> valueMap;
+  unordered_map<const MDNode*, CMeta*> metaMap;
+  unordered_map<const DebugLoc*, CMeta*> srcLocMap;
+};
+
+static ValueTag decodeOpcode(unsigned opcode) {
+  switch(opcode) {
+  case Instruction::Ret: return VAL_RETINST;
+  case Instruction::Br: return VAL_BRANCHINST;
+  case Instruction::Switch: return VAL_SWITCHINST;
+  case Instruction::IndirectBr: return VAL_INDIRECTBRINST;
+  case Instruction::Invoke: return VAL_INVOKEINST;
+  case Instruction::Resume: return VAL_RESUMEINST;
+  case Instruction::Unreachable: return VAL_UNREACHABLEINST;
+  case Instruction::Add: return VAL_ADDINST;
+  case Instruction::FAdd: return VAL_FADDINST;
+  case Instruction::Sub: return VAL_SUBINST;
+  case Instruction::FSub: return VAL_FSUBINST;
+  case Instruction::Mul: return VAL_MULINST;
+  case Instruction::FMul: return VAL_FMULINST;
+  case Instruction::UDiv: return VAL_UDIVINST;
+  case Instruction::SDiv: return VAL_SDIVINST;
+  case Instruction::FDiv: return VAL_FDIVINST;
+  case Instruction::URem: return VAL_UREMINST;
+  case Instruction::SRem: return VAL_SREMINST;
+  case Instruction::FRem: return VAL_FREMINST;
+  case Instruction::Shl: return VAL_SHLINST;
+  case Instruction::LShr: return VAL_LSHRINST;
+  case Instruction::AShr: return VAL_ASHRINST;
+  case Instruction::And: return VAL_ANDINST;
+  case Instruction::Or: return VAL_ORINST;
+  case Instruction::Xor: return VAL_XORINST;
+  case Instruction::Alloca: return VAL_ALLOCAINST;
+  case Instruction::Load: return VAL_LOADINST;
+  case Instruction::Store: return VAL_STOREINST;
+  case Instruction::GetElementPtr: return VAL_GETELEMENTPTRINST;
+  case Instruction::Fence: return VAL_FENCEINST;
+  case Instruction::AtomicCmpXchg: return VAL_ATOMICCMPXCHGINST;
+  case Instruction::AtomicRMW: return VAL_ATOMICRMWINST;
+  case Instruction::Trunc: return VAL_TRUNCINST;
+  case Instruction::ZExt: return VAL_ZEXTINST;
+  case Instruction::SExt: return VAL_SEXTINST;
+  case Instruction::FPToUI: return VAL_FPTOUIINST;
+  case Instruction::FPToSI: return VAL_FPTOSIINST;
+  case Instruction::UIToFP: return VAL_UITOFPINST;
+  case Instruction::SIToFP: return VAL_SITOFPINST;
+  case Instruction::FPTrunc: return VAL_FPTRUNCINST;
+  case Instruction::FPExt: return VAL_FPEXTINST;
+  case Instruction::PtrToInt: return VAL_PTRTOINTINST;
+  case Instruction::IntToPtr: return VAL_INTTOPTRINST;
+  case Instruction::BitCast: return VAL_BITCASTINST;
+  case Instruction::ICmp: return VAL_ICMPINST;
+  case Instruction::FCmp: return VAL_FCMPINST;
+  case Instruction::PHI: return VAL_PHINODE;
+  case Instruction::Call: return VAL_CALLINST;
+  case Instruction::Select: return VAL_SELECTINST;
+  case Instruction::VAArg: return VAL_VAARGINST;
+  case Instruction::ExtractElement: return VAL_EXTRACTELEMENTINST;
+  case Instruction::InsertElement: return VAL_INSERTELEMENTINST;
+  case Instruction::ShuffleVector: return VAL_SHUFFLEVECTORINST;
+  case Instruction::ExtractValue: return VAL_EXTRACTVALUEINST;
+  case Instruction::InsertValue: return VAL_INSERTVALUEINST;
+  case Instruction::LandingPad: return VAL_LANDINGPADINST;
+  }
+
+  ostringstream os;
+  os << "Unhandled instruction type in opcode translator: " << opcode;
+  throw os.str();
+}
+
+static CmpPredicate decodePredicate(CmpInst::Predicate p) {
+  switch(p) {
+  case CmpInst::FCMP_FALSE: return F_CMP_FALSE;
+  case CmpInst::FCMP_OEQ: return F_CMP_OEQ;
+  case CmpInst::FCMP_OGT: return F_CMP_OGT;
+  case CmpInst::FCMP_OGE: return F_CMP_OGE;
+  case CmpInst::FCMP_OLT: return F_CMP_OLT;
+  case CmpInst::FCMP_OLE: return F_CMP_OLE;
+  case CmpInst::FCMP_ONE: return F_CMP_ONE;
+  case CmpInst::FCMP_ORD: return F_CMP_ORD;
+  case CmpInst::FCMP_UNO: return F_CMP_UNO;
+  case CmpInst::FCMP_UEQ: return F_CMP_UEQ;
+  case CmpInst::FCMP_UGT: return F_CMP_UGT;
+  case CmpInst::FCMP_UGE: return F_CMP_UGE;
+  case CmpInst::FCMP_ULT: return F_CMP_ULT;
+  case CmpInst::FCMP_ULE: return F_CMP_ULE;
+  case CmpInst::FCMP_UNE: return F_CMP_UNE;
+  case CmpInst::FCMP_TRUE: return F_CMP_TRUE;
+  case CmpInst::ICMP_EQ: return I_CMP_EQ;
+  case CmpInst::ICMP_NE: return I_CMP_NE;
+  case CmpInst::ICMP_UGT: return I_CMP_UGT;
+  case CmpInst::ICMP_UGE: return I_CMP_UGE;
+  case CmpInst::ICMP_ULT: return I_CMP_ULT;
+  case CmpInst::ICMP_ULE: return I_CMP_ULE;
+  case CmpInst::ICMP_SGT: return I_CMP_SGT;
+  case CmpInst::ICMP_SGE: return I_CMP_SGE;
+  case CmpInst::ICMP_SLT: return I_CMP_SLT;
+  case CmpInst::ICMP_SLE: return I_CMP_SLE;
+  }
+
+  ostringstream os;
+  os << "Unhandled comparison predicate: " << p;
+  throw os.str();
+}
+
+static TypeTag decodeTypeTag(Type::TypeID t) {
+  switch(t) {
+  case Type::VoidTyID: return TYPE_VOID;
+  case Type::FloatTyID: return TYPE_FLOAT;
+  case Type::DoubleTyID: return TYPE_DOUBLE;
+  case Type::X86_FP80TyID: return TYPE_X86_FP80;
+  case Type::FP128TyID: return TYPE_FP128;
+  case Type::PPC_FP128TyID: return TYPE_PPC_FP128;
+  case Type::LabelTyID: return TYPE_LABEL;
+  case Type::MetadataTyID: return TYPE_METADATA;
+  case Type::X86_MMXTyID: return TYPE_X86_MMX;
+  case Type::IntegerTyID: return TYPE_INTEGER;
+  case Type::FunctionTyID: return TYPE_FUNCTION;
+  case Type::StructTyID: return TYPE_STRUCT;
+  case Type::ArrayTyID: return TYPE_ARRAY;
+  case Type::PointerTyID: return TYPE_POINTER;
+  case Type::VectorTyID: return TYPE_VECTOR;
+  }
+
+  ostringstream os;
+  os << "Unhandled type tag case: " << t;
+  throw os.str();
+}
+
+static LinkageType decodeLinkage(const GlobalValue *gv) {
+  switch(gv->getLinkage()) {
+  case GlobalValue::ExternalLinkage: return LTExternal;
+  case GlobalValue::AvailableExternallyLinkage: return LTAvailableExternally;
+  case GlobalValue::LinkOnceAnyLinkage: return LTLinkOnceAny;
+  case GlobalValue::LinkOnceODRLinkage: return LTLinkOnceODR;
+  case GlobalValue::WeakAnyLinkage: return LTWeakAny;
+  case GlobalValue::WeakODRLinkage: return LTWeakODR;
+  case GlobalValue::AppendingLinkage: return LTAppending;
+  case GlobalValue::InternalLinkage: return LTInternal;
+  case GlobalValue::PrivateLinkage: return LTPrivate;
+  case GlobalValue::LinkerPrivateLinkage: return LTLinkerPrivate;
+  case GlobalValue::LinkerPrivateWeakLinkage: return LTLinkerPrivateWeak;
+#if LLVM_VERSION_MINOR < 2
+  case GlobalValue::LinkerPrivateWeakDefAutoLinkage: return LTLinkerPrivateWeakDefAuto;
+#endif
+  case GlobalValue::DLLImportLinkage: return LTDLLImport;
+  case GlobalValue::DLLExportLinkage: return LTDLLExport;
+  case GlobalValue::ExternalWeakLinkage: return LTExternalWeak;
+  case GlobalValue::CommonLinkage: return LTCommon;
+  }
+
+  ostringstream os;
+  os << "Unhandled linkage type: " << gv->getLinkage();
+  throw os.str();
+}
+
+static VisibilityStyle decodeVisibility(const GlobalValue *gv) {
+  switch(gv->getVisibility()) {
+  case GlobalValue::DefaultVisibility: return VisibilityDefault;
+  case GlobalValue::HiddenVisibility: return VisibilityHidden;
+  case GlobalValue::ProtectedVisibility: return VisibilityProtected;
+  }
+
+  ostringstream os;
+  os << "Unhandled visibility style: " << gv->getVisibility();
+  throw os.str();
+}
+
+static CAtomicOrdering decodeOrdering(AtomicOrdering o) {
+  switch(o) {
+  case llvm::NotAtomic: return OrderNotAtomic;
+  case llvm::Unordered: return OrderUnordered;
+  case llvm::Monotonic: return OrderMonotonic;
+  case llvm::Acquire: return OrderAcquire;
+  case llvm::Release: return OrderRelease;
+  case llvm::AcquireRelease: return OrderAcquireRelease;
+  case llvm::SequentiallyConsistent: return OrderSequentiallyConsistent;
+  }
+
+  ostringstream os;
+  os << "Unhandled atomic ordering: " << o;
+  throw os.str();
+}
+
+static CSynchronizationScope decodeSynchScope(SynchronizationScope s) {
+  switch(s) {
+  case llvm::SingleThread: return SSSingleThread;
+  case llvm::CrossThread: return SSCrossThread;
+  }
+
+  ostringstream os;
+  os << "Unhandled synchronization scope: " << s;
+  throw os.str();
+}
+
+static AtomicOperation decodeAtomicOp(AtomicRMWInst::BinOp o) {
+  switch(o) {
+  case AtomicRMWInst::Xchg: return AOXchg;
+  case AtomicRMWInst::Add: return AOAdd;
+  case AtomicRMWInst::Sub: return AOSub;
+  case AtomicRMWInst::And: return AOAnd;
+  case AtomicRMWInst::Nand: return AONand;
+  case AtomicRMWInst::Or: return AOOr;
+  case AtomicRMWInst::Xor: return AOXor;
+  case AtomicRMWInst::Max: return AOMax;
+  case AtomicRMWInst::Min: return AOMin;
+  case AtomicRMWInst::UMax: return AOUMax;
+  case AtomicRMWInst::UMin: return AOUMin;
+  }
+
+  ostringstream os;
+  os << "Unhandled atomic operation: " << o;
+  throw os.str();
+}
+
+static CallingConvention decodeCallingConvention(CallingConv::ID cc) {
+  switch(cc) {
+  case CallingConv::C: return CC_C;
+  case CallingConv::Fast: return CC_FAST;
+  case CallingConv::Cold: return CC_COLD;
+  case CallingConv::GHC: return CC_GHC;
+  case CallingConv::X86_StdCall: return CC_X86_STDCALL;
+  case CallingConv::X86_FastCall: return CC_X86_FASTCALL;
+  case CallingConv::ARM_APCS: return CC_ARM_APCS;
+  case CallingConv::ARM_AAPCS: return CC_ARM_AAPCS;
+  case CallingConv::ARM_AAPCS_VFP: return CC_ARM_AAPCS_VFP;
+  case CallingConv::MSP430_INTR: return CC_MSP430_INTR;
+  case CallingConv::X86_ThisCall: return CC_X86_THISCALL;
+  case CallingConv::PTX_Kernel: return CC_PTX_KERNEL;
+  case CallingConv::PTX_Device: return CC_PTX_DEVICE;
+  case CallingConv::MBLAZE_INTR: return CC_MBLAZE_INTR;
+  case CallingConv::MBLAZE_SVOL: return CC_MBLAZE_SVOL;
+  }
+
+  ostringstream os;
+  os << "Unhandled calling convention: " << cc;
+  throw os.str();
+}
+
+static void disposeCType(CType *ct) {
+  free(ct->name);
+  free(ct->typeList);
+  free(ct);
+}
+
+static void disposeCMeta(CMeta *meta) {
+  switch(meta->metaTag) {
+  case META_LOCATION:
+    free(meta->u.metaLocationInfo.filename);
+    free(meta->u.metaLocationInfo.directory);
+    break;
+
+  case META_DERIVEDTYPE:
+  case META_COMPOSITETYPE:
+  case META_BASICTYPE:
+    free(meta->u.metaTypeInfo.name);
+    free(meta->u.metaTypeInfo.directory);
+    free(meta->u.metaTypeInfo.filename);
+    break;
+
+  case META_VARIABLE:
+    free(meta->u.metaVariableInfo.name);
+    break;
+
+  case META_SUBPROGRAM:
+    free(meta->u.metaSubprogramInfo.name);
+    free(meta->u.metaSubprogramInfo.displayName);
+    free(meta->u.metaSubprogramInfo.linkageName);
+    free(meta->u.metaSubprogramInfo.returnTypeName);
+    free(meta->u.metaSubprogramInfo.filename);
+    free(meta->u.metaSubprogramInfo.directory);
+    break;
+
+  case META_GLOBALVARIABLE:
+    free(meta->u.metaGlobalInfo.name);
+    free(meta->u.metaGlobalInfo.displayName);
+    free(meta->u.metaGlobalInfo.linkageName);
+    break;
+
+  case META_FILE:
+    free(meta->u.metaFileInfo.filename);
+    free(meta->u.metaFileInfo.directory);
+    break;
+
+  case META_COMPILEUNIT:
+    free(meta->u.metaCompileUnitInfo.filename);
+    free(meta->u.metaCompileUnitInfo.directory);
+    free(meta->u.metaCompileUnitInfo.producer);
+    free(meta->u.metaCompileUnitInfo.flags);
+    break;
+
+  case META_NAMESPACE:
+    free(meta->u.metaNamespaceInfo.name);
+    free(meta->u.metaNamespaceInfo.directory);
+    free(meta->u.metaNamespaceInfo.filename);
+    break;
+
+  case META_LEXICALBLOCK:
+    free(meta->u.metaLexicalBlockInfo.directory);
+    free(meta->u.metaLexicalBlockInfo.filename);
+    break;
+
+  case META_SUBRANGE:
+    break;
+
+  case META_ENUMERATOR:
+    free(meta->u.metaEnumeratorInfo.enumName);
+    break;
+
+  case META_ARRAY:
+    free(meta->u.metaArrayInfo.arrayElts);
+    break;
+
+  case META_TEMPLATETYPEPARAMETER:
+    free(meta->u.metaTemplateTypeInfo.name);
+    free(meta->u.metaTemplateTypeInfo.filename);
+    free(meta->u.metaTemplateTypeInfo.directory);
+    break;
+
+  case META_TEMPLATEVALUEPARAMETER:
+    free(meta->u.metaTemplateValueInfo.name);
+    free(meta->u.metaTemplateValueInfo.filename);
+    free(meta->u.metaTemplateValueInfo.directory);
+    break;
+
+  case META_UNKNOWN:
+    free(meta->u.metaUnknownInfo.repr);
+    break;
+  }
+
+
+  free(meta);
+}
+
+// Have to do the delete in this function since the pointer must be
+// cast to the correct type.
+static void disposeData(ValueTag t, void* data) {
+  switch(t) {
+  case VAL_ARGUMENT:
+  {
+    CArgumentInfo *ai = (CArgumentInfo*)data;
+    free(ai);
+    return;
+  }
+
+  case VAL_BASICBLOCK:
+  {
+    CBasicBlockInfo *bbi = (CBasicBlockInfo*)data;
+
+    // The actual values are deleted from the valueMap
+    free(bbi->instructions);
+
+    free(bbi);
+    return;
+  }
+
+  case VAL_INLINEASM:
+  {
+    CInlineAsmInfo *ii = (CInlineAsmInfo*)data;
+    free(ii->asmString);
+    free(ii->constraintString);
+    free(ii);
+    return;
+  }
+
+  case VAL_ALIAS:
+  case VAL_GLOBALVARIABLE:
+  {
+    CGlobalInfo *gi = (CGlobalInfo*)data;
+
+    free(gi->section);
+
+    free(gi);
+    return;
+  }
+
+  case VAL_FUNCTION:
+  {
+    CFunctionInfo *fi = (CFunctionInfo*)data;
+
+    free(fi->section);
+    free(fi->gcName);
+
+    free(fi->arguments);
+    free(fi->body);
+
+    free(fi);
+    return;
+  }
+
+  case VAL_UNREACHABLEINST:
+  {
+    // No data
+    return;
+  }
+
+  case VAL_INVOKEINST:
+  case VAL_CALLINST:
+  {
+    CCallInfo *ci = (CCallInfo*)data;
+
+    free(ci->arguments);
+    free(ci);
+    return;
+  }
+
+  case VAL_PHINODE:
+  {
+    CPHIInfo *pi = (CPHIInfo*)data;
+    free(pi->incomingValues);
+    free(pi->valueBlocks);
+    free(pi);
+    return;
+  }
+
+  case VAL_FENCEINST:
+  case VAL_ATOMICCMPXCHGINST:
+  case VAL_ATOMICRMWINST:
+  {
+    CAtomicInfo *ai = (CAtomicInfo*)data;
+    free(ai);
+    return;
+  }
+
+  case VAL_LANDINGPADINST:
+  {
+    CLandingPadInfo *li = (CLandingPadInfo*)data;
+    free(li->clauses);
+    free(li->clauseTypes);
+    return;
+  }
+
+  case VAL_RESUMEINST:
+  case VAL_RETINST:
+  case VAL_BRANCHINST:
+  case VAL_SWITCHINST:
+  case VAL_INDIRECTBRINST:
+  case VAL_GETELEMENTPTRINST:
+  case VAL_STOREINST:
+  case VAL_ALLOCAINST:
+  case VAL_LOADINST:
+  case VAL_ADDINST:
+  case VAL_FADDINST:
+  case VAL_SUBINST:
+  case VAL_FSUBINST:
+  case VAL_MULINST:
+  case VAL_FMULINST:
+  case VAL_UDIVINST:
+  case VAL_SDIVINST:
+  case VAL_FDIVINST:
+  case VAL_UREMINST:
+  case VAL_SREMINST:
+  case VAL_FREMINST:
+  case VAL_SHLINST:
+  case VAL_LSHRINST:
+  case VAL_ASHRINST:
+  case VAL_ANDINST:
+  case VAL_ORINST:
+  case VAL_XORINST:
+  case VAL_TRUNCINST:
+  case VAL_ZEXTINST:
+  case VAL_SEXTINST:
+  case VAL_FPTOUIINST:
+  case VAL_FPTOSIINST:
+  case VAL_UITOFPINST:
+  case VAL_SITOFPINST:
+  case VAL_FPTRUNCINST:
+  case VAL_FPEXTINST:
+  case VAL_PTRTOINTINST:
+  case VAL_INTTOPTRINST:
+  case VAL_BITCASTINST:
+  case VAL_ICMPINST:
+  case VAL_FCMPINST:
+  case VAL_VAARGINST:
+  case VAL_SELECTINST:
+  case VAL_EXTRACTELEMENTINST:
+  case VAL_INSERTELEMENTINST:
+  case VAL_SHUFFLEVECTORINST:
+  case VAL_EXTRACTVALUEINST:
+  case VAL_INSERTVALUEINST:
+  {
+    CInstructionInfo *ii = (CInstructionInfo*)data;
+    free(ii->operands);
+    free(ii->indices);
+    free(ii);
+    return;
+  }
+
+  case VAL_BLOCKADDRESS:
+  {
+    CBlockAddrInfo *bi = (CBlockAddrInfo*)data;
+    free(bi);
+    return;
+  }
+
+  case VAL_CONSTANTINT:
+  {
+    CConstInt *d = (CConstInt*)data;
+    free(d->hugeVal);
+    free(d);
+    return;
+  }
+
+  case VAL_CONSTANTFP:
+  {
+    CConstFP *d = (CConstFP*)data;
+    free(d);
+    return;
+  }
+
+  case VAL_CONSTANTPOINTERNULL:
+  case VAL_CONSTANTAGGREGATEZERO:
+  case VAL_UNDEFVALUE:
+  {
+    // No data
+    return;
+  }
+
+  case VAL_CONSTANTSTRUCT:
+  case VAL_CONSTANTVECTOR:
+  case VAL_CONSTANTARRAY:
+  {
+    CConstAggregate *c = (CConstAggregate*)data;
+    free(c->constants);
+    free(c);
+    return;
+  }
+
+  case VAL_CONSTANTEXPR:
+  {
+    CConstExprInfo *ce = (CConstExprInfo*)data;
+    free(ce->ii->operands);
+    free(ce->ii->indices);
+    free(ce->ii);
+    free(ce);
+    return;
+  }
+
+  }
+
+  ostringstream os;
+  os << "Unhandled cleanup case for value tag: " << t;
+  throw os.str();
+}
+
+static void disposeCValue(CValue *v) {
+  // Do not dispose the type - that is taken care of in bulk in the
+  // CModule disposal.  Same for MD.
+  free(v->name);
+  free(v->md);
+
+  disposeData(v->valueTag, v->data);
+
+  free(v);
+}
+
+static MetaTag extractMetaTag(const MDNode *md) {
+  DIDescriptor desc(md);
+  // Ranked roughly by frequency.
+  if(desc.isLexicalBlock()) return META_LEXICALBLOCK;
+  // This variant of lexical block has an extra file argument that is
+  // not currently translated.  This might be used for code inserted
+  // by the preprocessor from headers?
+  if(desc.isLexicalBlockFile()) return META_LEXICALBLOCK;
+  if(desc.isVariable()) return META_VARIABLE;
+  if(desc.isSubprogram()) return META_SUBPROGRAM;
+  if(desc.isGlobalVariable()) return META_GLOBALVARIABLE;
+  if(desc.isCompositeType()) return META_COMPOSITETYPE;
+  if(desc.isDerivedType()) return META_DERIVEDTYPE;
+  if(desc.isBasicType()) return META_BASICTYPE;
+  if(desc.isFile()) return META_FILE;
+  if(desc.isCompileUnit()) return META_COMPILEUNIT;
+  if(desc.isNameSpace()) return META_NAMESPACE;
+  if(desc.isSubrange()) return META_SUBRANGE;
+  if(desc.isEnumerator()) return META_ENUMERATOR;
+  if(desc.isTemplateTypeParameter()) return META_TEMPLATETYPEPARAMETER;
+  if(desc.isTemplateValueParameter()) return META_TEMPLATEVALUEPARAMETER;
+
+  DILocation loc(md);
+  if(loc.Verify()) return META_LOCATION;
+
+  // Otherwise we have no idea what to do with this.  One type of odd
+  // metadata is the inline assembly srcloc metadata, which has a
+  // strange format.  Right now we don't bother to translate this.  It
+  // could probably be done if required... we don't know what it
+  // really is at this stage, though, so it might need to be
+  // serialized generically as an MDNode
+  return META_UNKNOWN;
+}
+
+static CValue* translateConstant(CModule *m, const Constant *c);
+static CValue* translateValue(CModule *m, const Value *v);
+static CValue* translateBasicBlock(CModule *m, const BasicBlock *bb);
+static CMeta* translateMetadata(CModule *m, const MDNode *md);
+static CMeta* translateMetadataArray(CModule *m, const MDNode *md);
+
+static void makeMetaSrcLocation(CModule *m, const DebugLoc &loc, CMeta *meta) {
+  meta->u.metaLocationInfo.lineNumber = loc.getLine();
+  meta->u.metaLocationInfo.columnNumber = loc.getCol();
+}
+
+static void makeMetaLocation(CModule *m, const MDNode *md, CMeta *meta) {
+  DILocation loc(md);
+  meta->u.metaLocationInfo.lineNumber = loc.getLineNumber();
+  meta->u.metaLocationInfo.columnNumber = loc.getColumnNumber();
+}
+
+static void makeMetaDerivedType(CModule *m, const MDNode *md, CMeta *meta) {
+  DIDerivedType dt(md);
+  meta->u.metaTypeInfo.context = translateMetadata(m, dt.getContext());
+  meta->u.metaTypeInfo.name = getCStrdup(dt.getName());
+  meta->u.metaTypeInfo.lineNumber = dt.getLineNumber();
+  meta->u.metaTypeInfo.sizeInBits = dt.getSizeInBits();
+  meta->u.metaTypeInfo.alignInBits = dt.getAlignInBits();
+  meta->u.metaTypeInfo.offsetInBits = dt.getOffsetInBits();
+  meta->u.metaTypeInfo.flags = dt.getFlags();
+  meta->u.metaTypeInfo.isPrivate = dt.isPrivate();
+  meta->u.metaTypeInfo.isProtected = dt.isProtected();
+  meta->u.metaTypeInfo.isForward = dt.isForwardDecl();
+  meta->u.metaTypeInfo.isByRefStruct = dt.isBlockByrefStruct();
+  meta->u.metaTypeInfo.isVirtual = dt.isVirtual();
+  meta->u.metaTypeInfo.isArtificial = dt.isArtificial();
+  meta->u.metaTypeInfo.directory = getCStrdup(dt.getDirectory());
+  meta->u.metaTypeInfo.filename = getCStrdup(dt.getFilename());
+
+  meta->u.metaTypeInfo.typeDerivedFrom = translateMetadata(m, dt.getTypeDerivedFrom());
+  meta->u.metaTypeInfo.originalTypeSize = dt.getOriginalTypeSize();
+}
+
+static void makeMetaCompositeType(CModule *m, const MDNode *md, CMeta *meta) {
+  DICompositeType dt(md);
+  meta->u.metaTypeInfo.context = translateMetadata(m, dt.getContext());
+  meta->u.metaTypeInfo.name = getCStrdup(dt.getName());
+  meta->u.metaTypeInfo.lineNumber = dt.getLineNumber();
+  meta->u.metaTypeInfo.sizeInBits = dt.getSizeInBits();
+  meta->u.metaTypeInfo.alignInBits = dt.getAlignInBits();
+  meta->u.metaTypeInfo.offsetInBits = dt.getOffsetInBits();
+  meta->u.metaTypeInfo.flags = dt.getFlags();
+  meta->u.metaTypeInfo.isPrivate = dt.isPrivate();
+  meta->u.metaTypeInfo.isProtected = dt.isProtected();
+  meta->u.metaTypeInfo.isForward = dt.isForwardDecl();
+  meta->u.metaTypeInfo.isByRefStruct = dt.isBlockByrefStruct();
+  meta->u.metaTypeInfo.isVirtual = dt.isVirtual();
+  meta->u.metaTypeInfo.isArtificial = dt.isArtificial();
+  meta->u.metaTypeInfo.directory = getCStrdup(dt.getDirectory());
+  meta->u.metaTypeInfo.filename = getCStrdup(dt.getFilename());
+
+  meta->u.metaTypeInfo.typeDerivedFrom = translateMetadata(m, dt.getTypeDerivedFrom());
+  meta->u.metaTypeInfo.originalTypeSize = dt.getOriginalTypeSize();
+
+  meta->u.metaTypeInfo.typeArray = translateMetadataArray(m, dt.getTypeArray());
+  meta->u.metaTypeInfo.runTimeLang = dt.getRunTimeLang();
+  meta->u.metaTypeInfo.containingType = translateMetadata(m, dt.getContainingType());
+  meta->u.metaTypeInfo.templateParams = translateMetadata(m, dt.getTemplateParams());
+}
+
+static void makeMetaBasicType(CModule *m, const MDNode *md, CMeta *meta) {
+  DIBasicType dt(md);
+  meta->u.metaTypeInfo.context = translateMetadata(m, dt.getContext());
+  meta->u.metaTypeInfo.name = getCStrdup(dt.getName());
+  meta->u.metaTypeInfo.lineNumber = dt.getLineNumber();
+  meta->u.metaTypeInfo.sizeInBits = dt.getSizeInBits();
+  meta->u.metaTypeInfo.alignInBits = dt.getAlignInBits();
+  meta->u.metaTypeInfo.offsetInBits = dt.getOffsetInBits();
+  meta->u.metaTypeInfo.flags = dt.getFlags();
+  meta->u.metaTypeInfo.isPrivate = dt.isPrivate();
+  meta->u.metaTypeInfo.isProtected = dt.isProtected();
+  meta->u.metaTypeInfo.isForward = dt.isForwardDecl();
+  meta->u.metaTypeInfo.isByRefStruct = dt.isBlockByrefStruct();
+  meta->u.metaTypeInfo.isVirtual = dt.isVirtual();
+  meta->u.metaTypeInfo.isArtificial = dt.isArtificial();
+  meta->u.metaTypeInfo.directory = getCStrdup(dt.getDirectory());
+  meta->u.metaTypeInfo.filename = getCStrdup(dt.getFilename());
+
+  meta->u.metaTypeInfo.encoding = dt.getEncoding();
+}
+
+static void makeMetaVariable(CModule *m, const MDNode *md, CMeta *meta) {
+  DIVariable dv(md);
+  meta->u.metaVariableInfo.context = translateMetadata(m, dv.getContext());
+  meta->u.metaVariableInfo.name = getCStrdup(dv.getName());
+  meta->u.metaVariableInfo.lineNumber = dv.getLineNumber();
+  meta->u.metaVariableInfo.argNumber = dv.getArgNumber();
+  meta->u.metaVariableInfo.type = translateMetadata(m, dv.getType());
+  meta->u.metaVariableInfo.isArtificial = dv.isArtificial();
+  meta->u.metaVariableInfo.hasComplexAddress = dv.hasComplexAddress();
+  meta->u.metaVariableInfo.numAddrElements = dv.getNumAddrElements();
+  if(meta->u.metaVariableInfo.numAddrElements > 0) {
+    meta->u.metaVariableInfo.addrElements =
+      (uint64_t*)calloc(meta->u.metaVariableInfo.numAddrElements, sizeof(uint64_t));
+
+    for(unsigned int i = 0; i < meta->u.metaVariableInfo.numAddrElements; ++i) {
+      meta->u.metaVariableInfo.addrElements[i] = dv.getAddrElement(i);
+    }
+  }
+
+  meta->u.metaVariableInfo.isBlockByRefVar = dv.isBlockByrefVariable();
+}
+
+static void makeMetaSubprogram(CModule *m, const MDNode *md, CMeta *meta) {
+  DISubprogram ds(md);
+  meta->u.metaSubprogramInfo.context = translateMetadata(m, ds.getContext());
+  meta->u.metaSubprogramInfo.name = getCStrdup(ds.getName());
+  meta->u.metaSubprogramInfo.displayName = getCStrdup(ds.getDisplayName());
+  meta->u.metaSubprogramInfo.linkageName = getCStrdup(ds.getLinkageName());
+  meta->u.metaSubprogramInfo.lineNumber = ds.getLineNumber();
+  meta->u.metaSubprogramInfo.type = translateMetadata(m, ds.getType());
+  meta->u.metaSubprogramInfo.returnTypeName = getCStrdup(ds.getReturnTypeName());
+  meta->u.metaSubprogramInfo.isLocalToUnit = ds.isLocalToUnit();
+  meta->u.metaSubprogramInfo.isDefinition = ds.isDefinition();
+  meta->u.metaSubprogramInfo.virtuality = ds.getVirtuality();
+  meta->u.metaSubprogramInfo.virtualIndex = ds.getVirtualIndex();
+  meta->u.metaSubprogramInfo.containingType = translateMetadata(m, ds.getContainingType());
+  meta->u.metaSubprogramInfo.isArtificial = ds.isArtificial();
+  meta->u.metaSubprogramInfo.isPrivate = ds.isPrivate();
+  meta->u.metaSubprogramInfo.isProtected = ds.isProtected();
+  meta->u.metaSubprogramInfo.isExplicit = ds.isExplicit();
+  meta->u.metaSubprogramInfo.isPrototyped = ds.isPrototyped();
+  meta->u.metaSubprogramInfo.isOptimized = ds.isOptimized();
+  meta->u.metaSubprogramInfo.filename = getCStrdup(ds.getFilename());
+  meta->u.metaSubprogramInfo.directory = getCStrdup(ds.getDirectory());
+  const Value *func = ds.getFunction();
+  if(func)
+    meta->u.metaSubprogramInfo.function = translateValue(m, func);
+}
+
+static void makeMetaGlobalVariable(CModule *m, const MDNode *md, CMeta *meta) {
+  DIGlobalVariable dg(md);
+  meta->u.metaGlobalInfo.context = translateMetadata(m, dg.getContext());
+  meta->u.metaGlobalInfo.name = getCStrdup(dg.getName());
+  meta->u.metaGlobalInfo.displayName = getCStrdup(dg.getDisplayName());
+  meta->u.metaGlobalInfo.linkageName = getCStrdup(dg.getLinkageName());
+  meta->u.metaGlobalInfo.lineNumber = dg.getLineNumber();
+  meta->u.metaGlobalInfo.globalType = translateMetadata(m, dg.getType());
+  meta->u.metaGlobalInfo.isLocalToUnit = dg.isLocalToUnit();
+  meta->u.metaGlobalInfo.isDefinition = dg.isDefinition();
+  const Value *global = dg.getConstant();
+  if(global)
+    meta->u.metaGlobalInfo.global = translateValue(m, global);
+}
+
+static void makeMetaFile(CModule *m, const MDNode *md, CMeta *meta) {
+  DIFile df(md);
+  meta->u.metaFileInfo.filename = getCStrdup(df.getFilename());
+  meta->u.metaFileInfo.directory = getCStrdup(df.getDirectory());
+}
+
+static void makeMetaCompileUnit(CModule *m, const MDNode *md, CMeta *meta) {
+  DICompileUnit dc(md);
+  meta->u.metaCompileUnitInfo.language = dc.getLanguage();
+  meta->u.metaCompileUnitInfo.filename = getCStrdup(dc.getFilename());
+  meta->u.metaCompileUnitInfo.directory = getCStrdup(dc.getDirectory());
+  meta->u.metaCompileUnitInfo.producer = getCStrdup(dc.getProducer());
+#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 3
+#else
+  meta->u.metaCompileUnitInfo.isMain = dc.isMain();
+#endif
+  meta->u.metaCompileUnitInfo.isOptimized = dc.isOptimized();
+  meta->u.metaCompileUnitInfo.flags = getCStrdup(dc.getFlags());
+  meta->u.metaCompileUnitInfo.runtimeVersion = dc.getRunTimeVersion();
+  meta->u.metaCompileUnitInfo.enumTypes = translateMetadata(m, dc.getEnumTypes());
+  meta->u.metaCompileUnitInfo.retainedTypes = translateMetadata(m, dc.getRetainedTypes());
+  meta->u.metaCompileUnitInfo.subprograms = translateMetadata(m, dc.getSubprograms());
+  meta->u.metaCompileUnitInfo.globalVariables = translateMetadata(m, dc.getGlobalVariables());
+}
+
+static void makeMetaNamespace(CModule *m, const MDNode *md, CMeta *meta) {
+  DINameSpace dn(md);
+  meta->u.metaNamespaceInfo.context = translateMetadata(m, dn.getContext());
+  meta->u.metaNamespaceInfo.name = getCStrdup(dn.getName());
+  meta->u.metaNamespaceInfo.directory = getCStrdup(dn.getDirectory());
+  meta->u.metaNamespaceInfo.filename = getCStrdup(dn.getFilename());
+  meta->u.metaNamespaceInfo.lineNumber = dn.getLineNumber();
+}
+
+static void makeMetaLexicalBlock(CModule *m, const MDNode *md, CMeta *meta) {
+  DILexicalBlock dl(md);
+  meta->u.metaLexicalBlockInfo.context = translateMetadata(m, dl.getContext());
+  meta->u.metaLexicalBlockInfo.lineNumber = dl.getLineNumber();
+  meta->u.metaLexicalBlockInfo.columnNumber = dl.getColumnNumber();
+  meta->u.metaLexicalBlockInfo.directory = getCStrdup(dl.getDirectory());
+  meta->u.metaLexicalBlockInfo.filename = getCStrdup(dl.getFilename());
+}
+
+static void makeMetaSubrange(CModule *, const MDNode *md, CMeta *meta) {
+  DISubrange ds(md);
+  meta->u.metaSubrangeInfo.lo = ds.getLo();
+  meta->u.metaSubrangeInfo.hi = getHiDISubrange(ds);
+}
+
+static void makeMetaEnumerator(CModule *, const MDNode *md, CMeta *meta) {
+  DIEnumerator de(md);
+  meta->u.metaEnumeratorInfo.enumName = getCStrdup(de.getName());
+  meta->u.metaEnumeratorInfo.enumValue = de.getEnumValue();
+}
+
+static void makeMetaArray(CModule *m, const MDNode *md, CMeta *meta) {
+  DIArray da(md);
+  meta->u.metaArrayInfo.arrayLen = da.getNumElements();
+  if(meta->u.metaArrayInfo.arrayLen == 0) return;
+
+  meta->u.metaArrayInfo.arrayElts =
+    (CMeta**)calloc(meta->u.metaArrayInfo.arrayLen, sizeof(CMeta*));
+  for(int i = 0; i < meta->u.metaArrayInfo.arrayLen; ++i) {
+    meta->u.metaArrayInfo.arrayElts[i] = translateMetadata(m, da.getElement(i));
+  }
+}
+
+static void makeMetaTemplateTypeParameter(CModule *m, const MDNode *md, CMeta *meta) {
+  DITemplateTypeParameter dt(md);
+  meta->u.metaTemplateTypeInfo.context = translateMetadata(m, dt.getContext());
+  meta->u.metaTemplateTypeInfo.name = getCStrdup(dt.getName());
+  meta->u.metaTemplateTypeInfo.type = translateMetadata(m, dt.getType());
+  meta->u.metaTemplateTypeInfo.filename = getCStrdup(dt.getFilename());
+  meta->u.metaTemplateTypeInfo.directory = getCStrdup(dt.getDirectory());
+  meta->u.metaTemplateTypeInfo.lineNumber = dt.getLineNumber();
+  meta->u.metaTemplateTypeInfo.columnNumber = dt.getColumnNumber();
+}
+
+static void makeMetaTemplateValueParameter(CModule *m, const MDNode *md, CMeta *meta) {
+  DITemplateValueParameter dt(md);
+  meta->u.metaTemplateValueInfo.context = translateMetadata(m, dt.getContext());
+  meta->u.metaTemplateValueInfo.name = getCStrdup(dt.getName());
+  meta->u.metaTemplateValueInfo.type = translateMetadata(m, dt.getType());
+  meta->u.metaTemplateValueInfo.value = dt.getValue();
+  meta->u.metaTemplateValueInfo.filename = getCStrdup(dt.getFilename());
+  meta->u.metaTemplateValueInfo.directory = getCStrdup(dt.getDirectory());
+  meta->u.metaTemplateValueInfo.lineNumber = dt.getLineNumber();
+  meta->u.metaTemplateValueInfo.columnNumber = dt.getColumnNumber();
+}
+
+// Treat source locations specially; keeping them in the general case
+// was causing crashes that I never managed to track down.
+static CMeta* translateSrcLoc(CModule *m, const DebugLoc& loc) {
+  if(loc.isUnknown()) return NULL;
+
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const DebugLoc*,CMeta*>::const_iterator it = pd->srcLocMap.find(&loc);
+  if(it != pd->srcLocMap.end()) {
+    return it->second;
+  }
+  CMeta *meta = (CMeta*)calloc(1, sizeof(CMeta));
+  pd->srcLocMap[&loc] = meta;
+  meta->metaTag = META_LOCATION;
+  // There is no DWARF tag for these source locations.  Just use -1
+  // and be sure not to try to convert it to a DWARF tag later.
+  meta->tag = -1;
+
+  makeMetaSrcLocation(m, loc, meta);
+
+  return meta;
+}
+
+static CMeta* translateMetadata(CModule *m, const MDNode *md) {
+  // I expect some metadata fields to be empty (e.g., templateParams).
+  // Just propagate nulls.
+  if(md == NULL) return NULL;
+
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const MDNode*,CMeta*>::const_iterator it = pd->metaMap.find(md);
+  if(it != pd->metaMap.end()) {
+    return it->second;
+  }
+  CMeta *meta = (CMeta*)calloc(1, sizeof(CMeta));
+  pd->metaMap[md] = meta;
+  meta->metaTag = extractMetaTag(md);
+  DIDescriptor desc(md);
+  meta->tag = desc.getTag();
+
+  switch(meta->metaTag) {
+  case META_LOCATION: makeMetaLocation(m, md, meta); break;
+  case META_DERIVEDTYPE: makeMetaDerivedType(m, md, meta); break;
+  case META_COMPOSITETYPE: makeMetaCompositeType(m, md, meta); break;
+  case META_BASICTYPE: makeMetaBasicType(m, md, meta); break;
+  case META_VARIABLE: makeMetaVariable(m, md, meta); break;
+  case META_SUBPROGRAM: makeMetaSubprogram(m, md, meta); break;
+  case META_GLOBALVARIABLE: makeMetaGlobalVariable(m, md, meta); break;
+  case META_COMPILEUNIT: makeMetaCompileUnit(m, md, meta); break;
+  case META_NAMESPACE: makeMetaNamespace(m, md, meta); break;
+  case META_LEXICALBLOCK: makeMetaLexicalBlock(m, md, meta); break;
+  case META_SUBRANGE: makeMetaSubrange(m, md, meta); break;
+  case META_ENUMERATOR: makeMetaEnumerator(m, md, meta); break;
+//  case META_ARRAY: makeMetaArray(m, md, meta); break;
+  case META_TEMPLATETYPEPARAMETER: makeMetaTemplateTypeParameter(m, md, meta); break;
+  case META_TEMPLATEVALUEPARAMETER: makeMetaTemplateValueParameter(m, md, meta); break;
+  case META_UNKNOWN:
+  {
+    // Just dump unknown metadata to a string... it might be more
+    // appropriate to make a generic MDNode, but that is low priority.
+    string msg;
+    raw_string_ostream os(msg);
+    os << "Unhandled metadata node type: ";
+    md->print(os);
+
+    meta->u.metaUnknownInfo.repr = getCStrdup(os);
+    break;
+  }
+  }
+  return meta;
+}
+
+static CMeta* translateMetadataArray(CModule *m, const MDNode *md) {
+  // I expect some metadata fields to be empty (e.g., templateParams).
+  // Just propagate nulls.
+  if(md == NULL) return NULL;
+
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const MDNode*,CMeta*>::const_iterator it = pd->metaMap.find(md);
+  if(it != pd->metaMap.end()) {
+    return it->second;
+  }
+  CMeta *meta = (CMeta*)calloc(1, sizeof(CMeta));
+  pd->metaMap[md] = meta;
+  meta->metaTag = META_ARRAY;
+  meta->tag = 0;
+
+  makeMetaArray(m, md, meta);
+
+  return meta;
+}
+
+// The Type parameter would be const, except
+// DataLayout::getTypeSizeInBits() is not const for some reason.
+static CType* translateType(CModule *m, Type *t) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Type*,CType*>::const_iterator it = pd->typeMap.find(t);
+  if(it != pd->typeMap.end())
+    return it->second;
+
+  CType *ret = (CType*)calloc(1, sizeof(CType));
+  ret->typeTag = decodeTypeTag(t->getTypeID());
+  ret->sizeInBytes = 0;
+  if(t->isSized())
+    ret->sizeInBytes = std::ceil(pd->dataLayout->getTypeSizeInBits(t) / 8.0);
+
+  // Need to put this in the table before making any recursive calls,
+  // otherwise it might never terminate.
+  pd->typeMap[t] = ret;
+
+  switch(ret->typeTag) {
+    // Primitives don't require any work
+  case TYPE_VOID:
+  case TYPE_FLOAT:
+  case TYPE_DOUBLE:
+  case TYPE_X86_FP80:
+  case TYPE_FP128:
+  case TYPE_PPC_FP128:
+  case TYPE_LABEL:
+  case TYPE_METADATA:
+  case TYPE_X86_MMX:
+    break;
+
+  case TYPE_INTEGER:
+    ret->size = t->getPrimitiveSizeInBits();
+    break;
+
+  case TYPE_FUNCTION:
+  {
+    const FunctionType *ft = dyn_cast<const FunctionType>(t);
+    ret->isVarArg = ft->isVarArg();
+    ret->innerType = translateType(m, ft->getReturnType());
+    ret->typeListLen = ft->getNumParams();
+    ret->typeList = (CType**)calloc(ret->typeListLen, sizeof(CType*));
+    for(int i = 0; i < ret->typeListLen; ++i) {
+      ret->typeList[i] = translateType(m, ft->getParamType(i));
+    }
+
+    break;
+  }
+
+  case TYPE_STRUCT:
+  {
+    const StructType *st = dyn_cast<const StructType>(t);
+    if(st->hasName())
+      ret->name = getCStrdup(st->getName());
+    else
+      ret->name = NULL;
+
+    ret->isPacked = st->isPacked();
+    ret->typeListLen = st->getNumElements();
+    ret->typeList = (CType**)calloc(ret->typeListLen, sizeof(CType*));
+    for(int i = 0; i < ret->typeListLen; ++i) {
+      ret->typeList[i] = translateType(m, st->getElementType(i));
+    }
+    break;
+  }
+
+  case TYPE_ARRAY:
+  {
+    const ArrayType *at = dyn_cast<const ArrayType>(t);
+    ret->size = at->getNumElements();
+    ret->innerType = translateType(m, at->getElementType());
+    break;
+  }
+
+  case TYPE_POINTER:
+  {
+    const PointerType *pt = dyn_cast<const PointerType>(t);
+    ret->innerType = translateType(m, pt->getElementType());
+    ret->addrSpace = pt->getAddressSpace();
+    break;
+  }
+
+  case TYPE_VECTOR:
+  {
+    const VectorType *vt = dyn_cast<const VectorType>(t);
+    ret->size = vt->getNumElements();
+    ret->innerType = translateType(m, vt->getElementType());
+    break;
+  }
+  }
+
+  return ret;
+}
+
+static CValue* translateGlobalAlias(CModule *m, const GlobalAlias *ga) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Value*, CValue*>::iterator it = pd->valueMap.find(ga);
+  if(it != pd->valueMap.end())
+    return it->second;
+
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[ga] = v;
+
+  v->valueTag = VAL_ALIAS;
+  v->valueType = translateType(m, ga->getType());
+  v->name = getCStrdup(ga->getName());
+
+  CGlobalInfo *gi = (CGlobalInfo*)calloc(1, sizeof(CGlobalInfo));
+  v->data = (void*)gi;
+
+  gi->isExternal = ga->isDeclaration();
+  gi->alignment = ga->getAlignment();
+  gi->visibility = decodeVisibility(ga);
+  gi->linkage = decodeLinkage(ga);
+  if(ga->hasSection())
+    gi->section = getCStrdup(ga->getSection());
+
+  gi->aliasee = translateConstant(m, ga->getAliasee());
+
+  return v;
+}
+
+static CValue* translateArgument(CModule *m, const Argument *a) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  // Arguments are translated before instructions, so we don't really
+  // need to check to see if the argument exists already (it won't).
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[a] = v;
+
+  v->valueTag = VAL_ARGUMENT;
+  v->valueType = translateType(m, a->getType());
+  v->name = getCStrdup(a->getName());
+
+  // Metadata will be attached as instructions are processed (calls to
+  // the Debug intrinsics)
+
+  CArgumentInfo *ai = (CArgumentInfo*)calloc(1, sizeof(CArgumentInfo));
+  v->data = (void*)ai;
+
+  ai->hasSRet = a->hasStructRetAttr();
+  ai->hasByVal = a->hasByValAttr();
+  ai->hasNest = a->hasNestAttr();
+  ai->hasNoAlias = a->hasNoAliasAttr();
+  ai->hasNoCapture = a->hasNoCaptureAttr();
+
+  return v;
+}
+
+static void buildRetInst(CModule *m, CValue *v, const ReturnInst *ri) {
+  v->valueTag = VAL_RETINST;
+  v->valueType = translateType(m, ri->getType());
+  // Never has a name
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  if(Value* rv = ri->getReturnValue())
+  {
+    ii->numOperands = 1;
+    ii->operands = (CValue**)calloc(1, sizeof(CValue*));
+    ii->operands[0] = translateValue(m, rv);
+  }
+
+  // Otherwise, the data fields default to 0 as intended
+}
+
+static void buildSimpleInst(CModule *m, CValue *v, ValueTag t, const Instruction *inst) {
+  v->valueTag = t;
+  v->valueType = translateType(m, inst->getType());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  ii->numOperands = inst->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+
+  for(size_t i = 0; i < inst->getNumOperands(); ++i) {
+    ii->operands[i] = translateValue(m, inst->getOperand(i));
+  }
+}
+
+static void buildBinaryInst(CModule *m, CValue *v, ValueTag t, const Instruction *inst) {
+  const BinaryOperator *bi = dyn_cast<const BinaryOperator>(inst);
+  assert(bi);
+
+  v->valueTag = t;
+  v->valueType = translateType(m, bi->getType());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  ii->numOperands = inst->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, inst->getOperand(i));
+  }
+
+  ii->flags = ArithNone;
+  // If the operator isn't *really* an overflowing binary operator,
+  // calling hasNoUnsignedWrap causes an assertion failure.  Guard
+  // against leaky abstractions here.
+  if(isa<const OverflowingBinaryOperator>(bi))
+  {
+    if(bi->hasNoUnsignedWrap() && bi->hasNoSignedWrap())
+      ii->flags = ArithBoth;
+    else if(bi->hasNoUnsignedWrap())
+      ii->flags = ArithNUW;
+    else if(bi->hasNoSignedWrap())
+      ii->flags = ArithNSW;
+  }
+}
+
+static void buildInvokeInst(CModule *m, CValue *v, const InvokeInst *ii) {
+  v->valueTag = VAL_INVOKEINST;
+  v->valueType = translateType(m, ii->getType());
+  if(ii->hasName())
+    v->name = getCStrdup(ii->getName());
+
+  CCallInfo *ci = (CCallInfo*)calloc(1, sizeof(CCallInfo));
+  v->data = (void*)ci;
+
+  ci->calledValue = translateValue(m, ii->getCalledValue());
+  ci->callingConvention = decodeCallingConvention(ii->getCallingConv());
+  ci->hasSRet = ii->hasStructRetAttr();
+  ci->normalDest = translateBasicBlock(m, ii->getNormalDest());
+  ci->unwindDest = translateBasicBlock(m, ii->getUnwindDest());
+  ci->argListLen = ii->getNumArgOperands();
+  ci->arguments = (CValue**)calloc(ci->argListLen, sizeof(CValue*));
+
+  for(unsigned i = 0; i < ii->getNumArgOperands(); ++i) {
+    ci->arguments[i] = translateValue(m, ii->getArgOperand(i));
+  }
+}
+
+static bool buildCallInst(CModule *m, CValue *v, const CallInst *ii) {
+
+  /*
+    I wanted to use the Intrinsics directly here, but it didn't seem
+    to work.  I didn't look into the matter too closely, but these
+    instructions insisted that they were simply calls and I didn't
+    know how to convert them to intrinsics.
+   */
+
+  if(ii->getCalledValue()->getName().str() == "llvm.dbg.declare") {
+    CValue *addr = NULL;
+    if(const MDNode *addrWrapper = dyn_cast<const MDNode>(ii->getArgOperand(0))) {
+      const Value* realAddr = addrWrapper->getOperand(0);
+      // If the alloca was completely eliminated, this debug
+      // information can't be attached to anything as far as I can
+      // tell.
+      if(realAddr == NULL || dyn_cast<const ConstantPointerNull>(realAddr))
+        return false;
+
+      addr = translateValue(m, realAddr);
+    }
+    CMeta *md = NULL;
+    if(const MDNode *variableVal = dyn_cast<const MDNode>(ii->getArgOperand(1))) {
+      md = translateMetadata(m, variableVal);
+    }
+
+    if(!md) return false;
+
+    // CValue *addr = translateValue(m, di->getAddress());
+    // CMeta *md = translateMetadata(m, di->getVariable());
+
+    // It should be the case that there should be exactly one of these
+    // per alloca, and allocas should not have location info of their
+    // own.
+    if(addr->md) {
+      return false;
+    } // throw "Address of MD already has metadata";
+
+    addr->numMetadata = 1;
+    addr->md = (CMeta**)calloc(1, sizeof(CMeta*));
+    addr->md[0] = md;
+
+    return false;
+  }
+
+  if(ii->getCalledValue()->getName().str() == "llvm.dbg.value") {
+    // In this case, we could see llvm.dbg.value "calls" for updates
+    // to parameters.  We should only attach the *first* one we
+    // encounter, which will be the one describing parameters or
+    // locals.  This is an important case when the bitcode has been
+    // run through the mem2reg optimization pass and most allocas are
+    // eliminated.  I don't care about when the value of a variable
+    // changes (that is apparent from the instruction stream).  I
+    // could be convinced to change the behavior here if there is a
+    // good use case.
+
+    CValue *val = NULL;
+    if(const MDNode *valWrapper = dyn_cast<const MDNode>(ii->getArgOperand(0))) {
+      const Value *realAddr = valWrapper->getOperand(0);
+      if(realAddr == NULL || dyn_cast<const ConstantPointerNull>(realAddr))
+        return false;
+
+      val = translateValue(m, realAddr);
+    }
+
+    if(val->numMetadata == 0) {
+      CMeta *md = NULL;
+      if(const MDNode *variable = dyn_cast<const MDNode>(ii->getArgOperand(2))) {
+        md = translateMetadata(m, variable);
+      }
+
+      if(!md) return false;
+
+      val->numMetadata = 1;
+      val->md = (CMeta**)calloc(1, sizeof(CMeta*));
+      val->md[0] = md;
+    }
+
+    return false;
+  }
+
+  v->valueTag = VAL_CALLINST;
+  v->valueType = translateType(m, ii->getType());
+  if(ii->hasName())
+    v->name = getCStrdup(ii->getName());
+
+  CCallInfo *ci = (CCallInfo*)calloc(1, sizeof(CCallInfo));
+  v->data = (void*)ci;
+
+  ci->calledValue = translateValue(m, ii->getCalledValue());
+  ci->callingConvention = decodeCallingConvention(ii->getCallingConv());
+  ci->hasSRet = ii->hasStructRetAttr();
+  ci->isTail = ii->isTailCall();
+  ci->argListLen = ii->getNumArgOperands();
+  ci->arguments = (CValue**)calloc(ci->argListLen, sizeof(CValue*));
+
+  for(unsigned i = 0; i < ii->getNumArgOperands(); ++i) {
+    ci->arguments[i] = translateValue(m, ii->getArgOperand(i));
+  }
+
+  return true;
+}
+
+static void buildAllocaInst(CModule *m, CValue *v, const AllocaInst *ai) {
+  v->valueTag = VAL_ALLOCAINST;
+  v->valueType = translateType(m, ai->getType());
+  if(ai->hasName())
+    v->name = getCStrdup(ai->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  ii->numOperands = ai->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, ai->getOperand(i));
+  }
+
+  ii->align = ai->getAlignment();
+}
+
+static void buildLoadInst(CModule *m, CValue *v, const LoadInst *li) {
+  v->valueTag = VAL_LOADINST;
+  v->valueType = translateType(m, li->getType());
+  if(li->hasName())
+    v->name = getCStrdup(li->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  ii->numOperands = li->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, li->getOperand(i));
+  }
+
+  ii->isVolatile = li->isVolatile();
+  ii->align = li->getAlignment();
+  ii->addrSpace = li->getPointerAddressSpace();
+}
+
+static void buildStoreInst(CModule *m, CValue *v, const StoreInst *si) {
+  v->valueTag = VAL_STOREINST;
+  v->valueType = translateType(m, si->getType());
+  if(si->hasName())
+    v->name = getCStrdup(si->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+
+  ii->numOperands = si->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, si->getOperand(i));
+  }
+
+  ii->addrSpace = si->getPointerAddressSpace();
+  ii->align = si->getAlignment();
+  ii->isVolatile = si->isVolatile();
+}
+
+static void buildGEPInst(CModule *m, CValue *v, const GetElementPtrInst *gi) {
+  v->valueTag = VAL_GETELEMENTPTRINST;
+  v->valueType = translateType(m, gi->getType());
+  if(gi->hasName())
+    v->name = getCStrdup(gi->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+
+  ii->numOperands = gi->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, gi->getOperand(i));
+  }
+
+  ii->inBounds = gi->isInBounds();
+  ii->addrSpace = gi->getPointerAddressSpace();
+}
+
+static void buildCastInst(CModule *m, CValue *v, ValueTag t, const Instruction *inst) {
+  const CastInst *ci = dyn_cast<const CastInst>(inst);
+  v->valueTag = t;
+  v->valueType = translateType(m, ci->getType());
+  if(ci->hasName())
+    v->name = getCStrdup(ci->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+
+  ii->numOperands = ci->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, ci->getOperand(i));
+  }
+}
+
+static void buildCmpInst(CModule *m, CValue *v, ValueTag t, const Instruction *inst) {
+  const CmpInst *ci = dyn_cast<const CmpInst>(inst);
+  v->valueTag = t;
+  v->valueType = translateType(m, ci->getType());
+  if(ci->hasName())
+    v->name = getCStrdup(ci->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  ii->numOperands = ci->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, ci->getOperand(i));
+  }
+
+  ii->cmpPred = decodePredicate(ci->getPredicate());
+}
+
+static void buildPHINode(CModule *m, CValue *v, const PHINode* n) {
+  v->valueTag = VAL_PHINODE;
+  v->valueType = translateType(m, n->getType());
+  if(n->hasName())
+    v->name = getCStrdup(n->getName());
+
+  CPHIInfo *pi = (CPHIInfo*)calloc(1, sizeof(CPHIInfo));
+  v->data = (void*)pi;
+
+  pi->numIncomingValues = n->getNumIncomingValues();
+  pi->incomingValues = (CValue**)calloc(pi->numIncomingValues, sizeof(CValue*));
+  pi->valueBlocks = (CValue**)calloc(pi->numIncomingValues, sizeof(CValue*));
+
+  for(int i = 0; i < pi->numIncomingValues; ++i) {
+    pi->incomingValues[i] = translateValue(m, n->getIncomingValue(i));
+    pi->valueBlocks[i] = translateValue(m, n->getIncomingBlock(i));
+  }
+}
+
+static void buildAtomicRMWInst(CModule *m, CValue *v, const AtomicRMWInst *I) {
+  v->valueTag = VAL_ATOMICRMWINST;
+  v->valueType = translateType(m, I->getType());
+  // Should not have a name
+
+  CAtomicInfo *ai = (CAtomicInfo*)calloc(1, sizeof(CAtomicInfo));
+  v->data = (void*)ai;
+
+  ai->ordering = decodeOrdering(I->getOrdering());
+  ai->scope = decodeSynchScope(I->getSynchScope());
+  ai->operation = decodeAtomicOp(I->getOperation());
+  ai->isVolatile = I->isVolatile();
+  ai->addrSpace = I->getPointerAddressSpace();
+  ai->pointerOperand = translateValue(m, I->getPointerOperand());
+  ai->valueOperand = translateValue(m, I->getValOperand());
+}
+
+static void buildAtomicCmpXchgInst(CModule *m, CValue *v, const AtomicCmpXchgInst *I) {
+  v->valueTag = VAL_ATOMICCMPXCHGINST;
+  v->valueType = translateType(m, I->getType());
+  // Should not have a name
+
+  CAtomicInfo *ai = (CAtomicInfo*)calloc(1, sizeof(CAtomicInfo));
+  v->data = (void*)ai;
+
+  ai->ordering = decodeOrdering(I->getOrdering());
+  ai->scope = decodeSynchScope(I->getSynchScope());
+  ai->isVolatile = I->isVolatile();
+  ai->addrSpace = I->getPointerAddressSpace();
+  ai->pointerOperand = translateValue(m, I->getPointerOperand());
+  ai->compareOperand = translateValue(m, I->getCompareOperand());
+  ai->valueOperand = translateValue(m, I->getNewValOperand());
+}
+
+static void buildFenceInst(CModule *m, CValue *v, const FenceInst *I) {
+  v->valueTag = VAL_FENCEINST;
+  v->valueType = translateType(m, I->getType());
+  // Should not have a name
+
+  CAtomicInfo *ai = (CAtomicInfo*)calloc(1, sizeof(CAtomicInfo));
+  v->data = (void*)ai;
+
+  ai->ordering = decodeOrdering(I->getOrdering());
+  ai->scope = decodeSynchScope(I->getSynchScope());
+}
+
+static void buildVAArgInst(CModule *m, CValue *v, const VAArgInst *vi) {
+  v->valueTag = VAL_VAARGINST;
+  v->valueType = translateType(m, vi->getType());
+  if(vi->hasName())
+    v->name = getCStrdup(vi->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  ii->numOperands = vi->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, vi->getOperand(i));
+  }
+}
+
+static void buildLandingPadInst(CModule *m, CValue *v, const LandingPadInst *li) {
+  v->valueTag = VAL_LANDINGPADINST;
+  v->valueType = translateType(m, li->getType());
+
+  if(li->hasName())
+    v->name = getCStrdup(li->getName());
+
+  CLandingPadInfo *ii = (CLandingPadInfo*)calloc(1, sizeof(CLandingPadInfo));
+  v->data = (void*)ii;
+
+  ii->personality = translateValue(m, li->getPersonalityFn());
+  ii->isCleanup = li->isCleanup();
+  ii->numClauses = li->getNumClauses();
+  ii->clauses = (CValue**)calloc(ii->numClauses, sizeof(CValue*));
+  ii->clauseTypes = (LandingPadClause*)calloc(ii->numClauses, sizeof(LandingPadClause));
+
+  for(int i = 0; i < ii->numClauses; ++i) {
+    ii->clauses[i] = translateValue(m, li->getClause(i));
+    ii->clauseTypes[i] = li->isCatch(i) ? LPCatch : LPFilter;
+  }
+}
+
+static void buildExtractValueInst(CModule *m, CValue *v, const ExtractValueInst *ei) {
+  v->valueTag = VAL_EXTRACTVALUEINST;
+  v->valueType = translateType(m, ei->getType());
+  if(ei->hasName())
+    v->name = getCStrdup(ei->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+
+  ii->numOperands = ei->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, ei->getOperand(i));
+  }
+
+  ii->numIndices = ei->getNumIndices();
+  ii->indices = (int*)calloc(ii->numIndices, sizeof(int));
+
+  std::copy(ei->idx_begin(), ei->idx_end(), ii->indices);
+}
+
+static void buildInsertValueInst(CModule *m, CValue *v, const InsertValueInst *ei) {
+  v->valueTag = VAL_INSERTVALUEINST;
+  v->valueType = translateType(m, ei->getType());
+  if(ei->hasName())
+    v->name = getCStrdup(ei->getName());
+
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ii;
+
+  ii->numOperands = ei->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+  for(int i = 0; i < ii->numOperands; ++i) {
+    ii->operands[i] = translateValue(m, ei->getOperand(i));
+  }
+
+  ii->numIndices = ei->getNumIndices();
+  ii->indices = (int*)calloc(ii->numIndices, sizeof(int));
+
+  std::copy(ei->idx_begin(), ei->idx_end(), ii->indices);
+}
+
+namespace {
+  class TinyVector : public SmallVectorImpl<std::pair<unsigned, MDNode*> > {
+  public:
+    TinyVector(unsigned int i)
+    :SmallVectorImpl<std::pair<unsigned, MDNode*> >(i)
+    {
+    }
+  };
+}
+
+static CValue* translateInstruction(CModule *m, const Instruction *i) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Value*, CValue*>::iterator it = pd->valueMap.find(i);
+  if(it != pd->valueMap.end())
+    return it->second;
+
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[i] = v;
+
+  TinyVector md(0);
+  i->getAllMetadataOtherThanDebugLoc(md);
+
+  v->numMetadata = md.size();
+  v->md = (CMeta**)calloc(v->numMetadata, sizeof(CMeta*));
+  for(int ix = 0; ix < v->numMetadata; ++ix) {
+    v->md[ix] = translateMetadata(m, md[ix].second);
+  }
+  if(pd->includeLocs)
+    v->srcLoc = translateSrcLoc(m, i->getDebugLoc());
+
+  switch(i->getOpcode()) {
+    // Terminator instructions
+  case Instruction::Ret:
+    buildRetInst(m, v, dyn_cast<const ReturnInst>(i));
+    break;
+  case Instruction::Br:
+    buildSimpleInst(m, v, VAL_BRANCHINST, i);
+    break;
+  case Instruction::Switch:
+    buildSimpleInst(m, v, VAL_SWITCHINST, i);
+    break;
+  case Instruction::IndirectBr:
+    buildSimpleInst(m, v, VAL_INDIRECTBRINST, i);
+    break;
+  case Instruction::Invoke:
+    buildInvokeInst(m, v, dyn_cast<const InvokeInst>(i));
+    break;
+  case Instruction::Unreachable:
+    buildSimpleInst(m, v, VAL_UNREACHABLEINST, i);
+    break;
+
+    // Binary instructions
+  case Instruction::Add:
+    buildBinaryInst(m, v, VAL_ADDINST, i);
+    break;
+  case Instruction::FAdd:
+    buildBinaryInst(m, v, VAL_FADDINST, i);
+    break;
+  case Instruction::Sub:
+    buildBinaryInst(m, v, VAL_SUBINST, i);
+    break;
+  case Instruction::FSub:
+    buildBinaryInst(m, v, VAL_FSUBINST, i);
+    break;
+  case Instruction::Mul:
+    buildBinaryInst(m, v, VAL_MULINST, i);
+    break;
+  case Instruction::FMul:
+    buildBinaryInst(m, v, VAL_FMULINST, i);
+    break;
+  case Instruction::UDiv:
+    buildBinaryInst(m, v, VAL_UDIVINST, i);
+    break;
+  case Instruction::SDiv:
+    buildBinaryInst(m, v, VAL_SDIVINST, i);
+    break;
+  case Instruction::FDiv:
+    buildBinaryInst(m, v, VAL_FDIVINST, i);
+    break;
+  case Instruction::URem:
+    buildBinaryInst(m, v, VAL_UREMINST, i);
+    break;
+  case Instruction::SRem:
+    buildBinaryInst(m, v, VAL_SREMINST, i);
+    break;
+  case Instruction::FRem:
+    buildBinaryInst(m, v, VAL_FREMINST, i);
+    break;
+  case Instruction::Shl:
+    buildBinaryInst(m, v, VAL_SHLINST, i);
+    break;
+  case Instruction::LShr:
+    buildBinaryInst(m, v, VAL_LSHRINST, i);
+    break;
+  case Instruction::AShr:
+    buildBinaryInst(m, v, VAL_ASHRINST, i);
+    break;
+  case Instruction::And:
+    buildBinaryInst(m, v, VAL_ANDINST, i);
+    break;
+  case Instruction::Or:
+    buildBinaryInst(m, v, VAL_ORINST, i);
+    break;
+  case Instruction::Xor:
+    buildBinaryInst(m, v, VAL_XORINST, i);
+    break;
+
+    // Memory operations
+  case Instruction::Alloca:
+    buildAllocaInst(m, v, dyn_cast<const AllocaInst>(i));
+    break;
+
+  case Instruction::Load:
+    buildLoadInst(m, v, dyn_cast<const LoadInst>(i));
+    break;
+
+  case Instruction::Store:
+    buildStoreInst(m, v, dyn_cast<const StoreInst>(i));
+    break;
+
+  case Instruction::GetElementPtr:
+    buildGEPInst(m, v, dyn_cast<const GetElementPtrInst>(i));
+    break;
+
+  case Instruction::Fence:
+    buildFenceInst(m, v, dyn_cast<const FenceInst>(i));
+    break;
+
+  case Instruction::AtomicRMW:
+    buildAtomicRMWInst(m, v, dyn_cast<const AtomicRMWInst>(i));
+    break;
+
+  case Instruction::AtomicCmpXchg:
+    buildAtomicCmpXchgInst(m, v, dyn_cast<const AtomicCmpXchgInst>(i));
+    break;
+
+    // Casts
+  case Instruction::Trunc:
+    buildCastInst(m, v, VAL_TRUNCINST, i);
+    break;
+
+  case Instruction::ZExt:
+    buildCastInst(m, v, VAL_ZEXTINST, i);
+    break;
+
+  case Instruction::SExt:
+    buildCastInst(m, v, VAL_SEXTINST, i);
+    break;
+
+  case Instruction::FPToUI:
+    buildCastInst(m, v, VAL_FPTOUIINST, i);
+    break;
+
+  case Instruction::FPToSI:
+    buildCastInst(m, v, VAL_FPTOSIINST, i);
+    break;
+
+  case Instruction::UIToFP:
+    buildCastInst(m, v, VAL_UITOFPINST, i);
+    break;
+
+  case Instruction::SIToFP:
+    buildCastInst(m, v, VAL_SITOFPINST, i);
+    break;
+
+  case Instruction::FPTrunc:
+    buildCastInst(m, v, VAL_FPTRUNCINST, i);
+    break;
+
+  case Instruction::FPExt:
+    buildCastInst(m, v, VAL_FPEXTINST, i);
+    break;
+
+  case Instruction::PtrToInt:
+    buildCastInst(m, v, VAL_PTRTOINTINST, i);
+    break;
+
+  case Instruction::IntToPtr:
+    buildCastInst(m, v, VAL_INTTOPTRINST, i);
+    break;
+
+  case Instruction::BitCast:
+    buildCastInst(m, v, VAL_BITCASTINST, i);
+    break;
+
+    // Other instructions
+  case Instruction::ICmp:
+    buildCmpInst(m, v, VAL_ICMPINST, i);
+    break;
+
+  case Instruction::FCmp:
+    buildCmpInst(m, v, VAL_FCMPINST, i);
+    break;
+
+  case Instruction::PHI:
+    buildPHINode(m, v, dyn_cast<const PHINode>(i));
+    break;
+
+  case Instruction::Call:
+    // If this is a call to llvm.dbg.*, return NULL and delete what we
+    // made so far.  We don't want these in the instruction stream
+    // (the builder will attach the debug information to the relevant
+    // entities)
+    if(!buildCallInst(m, v, dyn_cast<const CallInst>(i))) {
+      pd->valueMap.erase(i);
+      free(v);
+      return NULL;
+    }
+    break;
+
+  case Instruction::Select:
+    buildSimpleInst(m, v, VAL_SELECTINST, i);
+    break;
+
+  case Instruction::Resume:
+    buildSimpleInst(m, v, VAL_RESUMEINST, i);
+    break;
+
+  case Instruction::VAArg:
+    buildVAArgInst(m, v, dyn_cast<const VAArgInst>(i));
+    break;
+
+  case Instruction::ExtractElement:
+    buildSimpleInst(m, v, VAL_EXTRACTELEMENTINST, i);
+    break;
+
+  case Instruction::InsertElement:
+    buildSimpleInst(m, v, VAL_INSERTELEMENTINST, i);
+    break;
+
+  case Instruction::ShuffleVector:
+    buildSimpleInst(m, v, VAL_SHUFFLEVECTORINST, i);
+    break;
+
+  case Instruction::ExtractValue:
+    buildExtractValueInst(m, v, dyn_cast<const ExtractValueInst>(i));
+    break;
+
+  case Instruction::InsertValue:
+    buildInsertValueInst(m, v, dyn_cast<const InsertValueInst>(i));
+    break;
+
+  case Instruction::LandingPad:
+    buildLandingPadInst(m, v, dyn_cast<const LandingPadInst>(i));
+    break;
+
+  default:
+  {
+    ostringstream os;
+    os << "Unhandled instruction type: " << i->getOpcode();
+    throw os.str();
+  }
+  }
+
+  return v;
+}
+
+static CValue* translateBasicBlock(CModule *m, const BasicBlock *bb) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Value*, CValue*>::iterator it = pd->valueMap.find(bb);
+  if(it != pd->valueMap.end())
+    return it->second;
+
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[bb] = v;
+
+  v->valueTag = VAL_BASICBLOCK;
+  v->valueType = translateType(m, bb->getType());
+  if(bb->hasName())
+    v->name = getCStrdup(bb->getName());
+
+  // No metadata for these
+
+  CBasicBlockInfo* bbi = (CBasicBlockInfo*)calloc(1, sizeof(CBasicBlockInfo));
+  v->data = (void*)bbi;
+
+  bbi->blockLen = bb->size();
+  bbi->instructions = (CValue**)calloc(bbi->blockLen, sizeof(CValue*));
+
+  int idx = 0;
+  for(BasicBlock::const_iterator it = bb->begin(),
+        ed = bb->end(); it != ed; ++it)
+  {
+    CValue *tr = translateInstruction(m, &*it);
+    if(!tr) {
+      // This was a metadata call, so do not insert it into the
+      // instruction stream
+      --bbi->blockLen;
+      continue;
+    }
+
+    bbi->instructions[idx++] = tr;
+  }
+
+  return v;
+}
+
+static CValue* translateFunction(CModule *m, const Function *f) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Value*, CValue*>::iterator it = pd->valueMap.find(f);
+  if(it != pd->valueMap.end())
+    return it->second;
+
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[f] = v;
+
+  v->valueTag = VAL_FUNCTION;
+  v->valueType = translateType(m, f->getFunctionType());
+  v->name = getCStrdup(f->getName());
+
+  CFunctionInfo *fi = (CFunctionInfo*)calloc(1, sizeof(CFunctionInfo));
+  v->data = (void*)fi;
+
+  if(f->hasSection())
+    fi->section = getCStrdup(f->getSection());
+
+  fi->visibility = decodeVisibility(f);
+  fi->linkage = decodeLinkage(f);
+  fi->isExternal = f->isDeclaration();
+  fi->callingConvention = decodeCallingConvention(f->getCallingConv());
+  fi->isVarArg = f->isVarArg();
+  if(f->hasGC())
+    fi->gcName = getCStrdup(f->getGC());
+
+  fi->argListLen = f->arg_size();
+  fi->arguments = (CValue**)calloc(fi->argListLen, sizeof(CValue*));
+  int idx = 0;
+  for(Function::const_arg_iterator it = f->arg_begin(),
+        ed = f->arg_end(); it != ed; ++it)
+  {
+    fi->arguments[idx++] = translateArgument(m, &*it);
+  }
+
+  fi->blockListLen = f->size();
+  fi->body = (CValue**)calloc(fi->blockListLen, sizeof(CValue*));
+  idx = 0;
+  for(Function::const_iterator it = f->begin(),
+        ed = f->end(); it != ed; ++it)
+  {
+    fi->body[idx++] = translateBasicBlock(m, &*it);
+  }
+
+  return v;
+}
+
+static CValue* translateGlobalVariable(CModule *m, const GlobalVariable *gv) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Value*, CValue*>::iterator it = pd->valueMap.find(gv);
+  if(it != pd->valueMap.end())
+    return it->second;
+
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[gv] = v;
+
+  v->valueTag = VAL_GLOBALVARIABLE;
+  v->valueType = translateType(m, gv->getType());
+  if(gv->hasName())
+    v->name = getCStrdup(gv->getName());
+
+  CGlobalInfo *gi = (CGlobalInfo*)calloc(1, sizeof(CGlobalInfo));
+  v->data = (void*)gi;
+
+  if(gv->hasSection())
+    gi->section = getCStrdup(gv->getSection());
+
+  gi->visibility = decodeVisibility(gv);
+  gi->linkage = decodeLinkage(gv);
+  gi->isExternal = gv->isDeclaration();
+  gi->isThreadLocal = gv->isThreadLocal();
+  gi->isConstant = gv->isConstant();
+
+  if(gv->hasInitializer())
+    gi->initializer = translateConstant(m, gv->getInitializer());
+
+  return v;
+}
+
+static CValue* translateInlineAsm(CModule *m, const InlineAsm* a) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[a] = v;
+
+  v->valueTag = VAL_INLINEASM;
+  v->valueType = translateType(m, a->getType());
+  if(a->hasName())
+    v->name = getCStrdup(a->getName());
+
+  CInlineAsmInfo *ii = (CInlineAsmInfo*)calloc(1, sizeof(CInlineAsmInfo));
+  v->data = (void*)ii;
+
+  ii->asmString = getCStrdup(a->getAsmString());
+  ii->constraintString = getCStrdup(a->getConstraintString());
+
+  return v;
+}
+
+static CValue* translateGlobalValue(CModule *m, const GlobalValue *gv) {
+  if(const Function *f = dyn_cast<const Function>(gv)) {
+    return translateFunction(m, f);
+  }
+
+  if(const GlobalVariable *v = dyn_cast<const GlobalVariable>(gv)) {
+    return translateGlobalVariable(m, v);
+  }
+
+  if(const GlobalAlias *a = dyn_cast<const GlobalAlias>(gv)) {
+    return translateGlobalAlias(m, a);
+  }
+
+  string msg;
+  raw_string_ostream os(msg);
+  os << "Non-global constant: ";
+  gv->print(os);
+  throw os.str();
+}
+
+static CValue* translateEmptyConstant(CModule *m, ValueTag t, const Constant *p) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[p] = v;
+
+  v->valueTag = t;
+  v->valueType = translateType(m, p->getType());
+
+  // No data or metadata
+
+  return v;
+}
+
+static CValue* translateConstantInt(CModule *m, const ConstantInt* i) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[i] = v;
+
+  v->valueTag = VAL_CONSTANTINT;
+  v->valueType = translateType(m, i->getType());
+
+  // No name
+
+  CConstInt *d = (CConstInt*)calloc(1, sizeof(CConstInt));
+  v->data = (void*)d;
+
+  const APInt& apint = i->getValue();
+  d->hugeVal = NULL;
+  if(apint.getMinSignedBits() <= 64)
+    d->val = i->getSExtValue();
+  else
+    d->hugeVal = getCStrdup(apint.toString(10, true));
+  return v;
+}
+
+static CValue* translateConstantFP(CModule *m, const ConstantFP *fp) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[fp] = v;
+
+  v->valueTag = VAL_CONSTANTFP;
+  v->valueType = translateType(m, fp->getType());
+
+  // No name
+
+  CConstFP *d = (CConstFP*)calloc(1, sizeof(CConstFP));
+  v->data = (void*)d;
+
+  APFloat apf = fp->getValueAPF();
+  bool b;
+  apf.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &b);
+  d->val = apf.convertToDouble();
+
+  return v;
+}
+
+static CValue* translateBlockAddress(CModule *m, const BlockAddress *ba) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[ba] = v;
+
+  v->valueTag = VAL_BLOCKADDRESS;
+  v->valueType = translateType(m, ba->getType());
+  if(ba->hasName())
+    v->name = getCStrdup(ba->getName());
+
+  CBlockAddrInfo *i = (CBlockAddrInfo*)calloc(1, sizeof(CBlockAddrInfo));
+  v->data = (void*)i;
+
+  i->func = translateValue(m, ba->getFunction());
+  i->block = translateValue(m, ba->getBasicBlock());
+
+  return v;
+}
+
+static CValue* translateConstantAggregate(CModule *m, ValueTag t, const Constant *ca) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[ca] = v;
+
+  v->valueTag = t;
+  v->valueType = translateType(m, ca->getType());
+  if(ca->hasName())
+    v->name = getCStrdup(ca->getName());
+
+  CConstAggregate *a = (CConstAggregate*)calloc(1, sizeof(CConstAggregate));
+  v->data = (void*)a;
+
+  a->numElements = ca->getNumOperands();
+  a->constants = (CValue**)calloc(a->numElements, sizeof(CValue*));
+
+  int idx = 0;
+  for(User::const_op_iterator it = ca->op_begin(),
+        ed = ca->op_end(); it != ed; ++it)
+  {
+    a->constants[idx++] = translateValue(m, it->get());
+  }
+
+  return v;
+}
+
+#if defined(LLVM_VERSION_MAJOR)
+static CValue* translateConstantData(CModule *m, const ConstantDataSequential *cd) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[cd] = v;
+
+  v->valueTag = VAL_CONSTANTARRAY;
+  v->valueType = translateType(m, cd->getType());
+  if(cd->hasName())
+    v->name = getCStrdup(cd->getName());
+
+  CConstAggregate *a = (CConstAggregate*)calloc(1, sizeof(CConstAggregate));
+  v->data = (void*)a;
+
+  a->numElements = cd->getNumElements();
+  a->constants = (CValue**)calloc(a->numElements, sizeof(CValue*));
+
+  for(int idx = 0; idx < a->numElements; ++idx) {
+    a->constants[idx] = translateConstant(m, cd->getElementAsConstant(idx));
+  }
+
+  return v;
+}
+#endif // LLVM_VERSION_MAJOR
+
+static CValue* translateConstantExpr(CModule *m, const ConstantExpr *ce) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  CValue *v = (CValue*)calloc(1, sizeof(CValue));
+  pd->valueMap[ce] = v;
+
+  v->valueTag = VAL_CONSTANTEXPR;
+  v->valueType = translateType(m, ce->getType());
+  if(ce->hasName())
+    v->name = getCStrdup(ce->getName());
+
+  CConstExprInfo *ci = (CConstExprInfo*)calloc(1, sizeof(CConstExprInfo));
+  CInstructionInfo *ii = (CInstructionInfo*)calloc(1, sizeof(CInstructionInfo));
+  v->data = (void*)ci;
+  ci->ii = ii;
+
+  ci->instrType = decodeOpcode(ce->getOpcode());
+  ii->numOperands = ce->getNumOperands();
+  ii->operands = (CValue**)calloc(ii->numOperands, sizeof(CValue*));
+
+  int idx = 0;
+  for(User::const_op_iterator it = ce->op_begin(),
+        ed = ce->op_end(); it != ed; ++it)
+  {
+    ii->operands[idx++] = translateValue(m, it->get());
+  }
+
+  if(ce->isCompare()) {
+    ii->cmpPred = decodePredicate((CmpInst::Predicate)ce->getPredicate());
+  }
+  else if(ce->hasIndices()) {
+    ii->numIndices = ce->getIndices().size();
+    ii->indices = (int*)calloc(ii->numIndices, sizeof(int));
+    std::copy(ce->getIndices().begin(), ce->getIndices().end(), ii->indices);
+  }
+
+  return v;
+}
+
+static CValue* translateConstant(CModule *m, const Constant *c) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Value*, CValue*>::iterator it = pd->valueMap.find(c);
+  if(it != pd->valueMap.end())
+    return it->second;
+
+  // Order these in order of frequency
+  if(const ConstantInt *ci = dyn_cast<const ConstantInt>(c)) {
+    return translateConstantInt(m, ci);
+  }
+
+  if(const ConstantPointerNull *pn = dyn_cast<const ConstantPointerNull>(c)) {
+    return translateEmptyConstant(m, VAL_CONSTANTPOINTERNULL, pn);
+  }
+
+  if(const ConstantExpr *ce = dyn_cast<const ConstantExpr>(c)) {
+    return translateConstantExpr(m, ce);
+  }
+
+  if(const GlobalValue *gv = dyn_cast<const GlobalValue>(c)) {
+    return translateGlobalValue(m, gv);
+  }
+
+  if(const ConstantArray *ca = dyn_cast<const ConstantArray>(c)) {
+    return translateConstantAggregate(m, VAL_CONSTANTARRAY, ca);
+  }
+#if defined(LLVM_VERSION_MAJOR)
+  // The ConstantDataSequential type was introduced with LLVM 3.1 (3.0
+  // did not define LLVM_VERSION_*)
+  if(const ConstantDataSequential *cd = dyn_cast<const ConstantDataSequential>(c)) {
+    return translateConstantData(m, cd);
+  }
+#endif
+  if(const ConstantVector *cv = dyn_cast<const ConstantVector>(c)) {
+    return translateConstantAggregate(m, VAL_CONSTANTVECTOR, cv);
+  }
+
+  if(const ConstantStruct *cs = dyn_cast<const ConstantStruct>(c)) {
+    return translateConstantAggregate(m, VAL_CONSTANTSTRUCT, cs);
+  }
+
+  if(const ConstantFP *fp = dyn_cast<const ConstantFP>(c)) {
+    return translateConstantFP(m, fp);
+  }
+
+  if(const ConstantAggregateZero *az = dyn_cast<const ConstantAggregateZero>(c)) {
+    return translateEmptyConstant(m, VAL_CONSTANTAGGREGATEZERO, az);
+  }
+
+  if(const UndefValue *uv = dyn_cast<const UndefValue>(c)) {
+    return translateEmptyConstant(m, VAL_UNDEFVALUE, uv);
+  }
+
+  if(const BlockAddress *ba = dyn_cast<const BlockAddress>(c)) {
+    return translateBlockAddress(m, ba);
+  }
+
+
+  string msg;
+  raw_string_ostream os(msg);
+  os << "Unhandled constant type: ";
+  c->print(os);
+  throw os.str();
+}
+
+static CValue* translateValue(CModule *m, const Value *v) {
+  PrivateData *pd = (PrivateData*)m->privateData;
+  unordered_map<const Value*, CValue*>::iterator it = pd->valueMap.find(v);
+  if(it != pd->valueMap.end())
+    return it->second;
+
+  // This order is pretty reasonable since constants will be the most
+  // frequent un-cached values.
+  if(const Constant *c = dyn_cast<const Constant>(v)) {
+    return translateConstant(m, c);
+  }
+
+  if(const Instruction *i = dyn_cast<const Instruction>(v)) {
+    return translateInstruction(m, i);
+  }
+
+  if(const BasicBlock *bb = dyn_cast<const BasicBlock>(v)) {
+    return translateBasicBlock(m, bb);
+  }
+
+  if(const InlineAsm *a = dyn_cast<const InlineAsm>(v)) {
+    return translateInlineAsm(m, a);
+  }
+
+  if(dyn_cast<const Argument>(v)) {
+    string msg = "Un-cached Argument passed to translateValue";
+    throw msg;
+  }
+
+  string msg;
+  raw_string_ostream os(msg);
+  os << "Unhandled value type: ";
+  v->print(os);
+  throw os.str();
+}
+
+static void decodeAndAttachSubprogram(CModule *m, DISubprogram sp) {
+  if(sp.getFunction() == NULL)
+    return;
+
+  CMeta *md = translateMetadata(m, sp);
+  if(!md)
+    throw "No translation for subprogram metadata";
+
+  int currentCapacity = md->u.metaSubprogramInfo.function->metaCapacity;
+  int metaCount = md->u.metaSubprogramInfo.function->numMetadata;
+  if(metaCount == 0) {
+    currentCapacity = 10;
+    md->u.metaSubprogramInfo.function->metaCapacity = currentCapacity;
+    md->u.metaSubprogramInfo.function->md =
+      (CMeta**)calloc(currentCapacity, sizeof(CMeta*));
+  }
+  else if(metaCount == currentCapacity - 1) {
+    int newCapacity = 2 * currentCapacity;
+    CMeta **newMeta = (CMeta**)calloc(newCapacity, sizeof(CMeta*));
+    memcpy(newMeta, md->u.metaSubprogramInfo.function->md, currentCapacity * sizeof(CMeta*));
+    free(md->u.metaSubprogramInfo.function->md);
+    md->u.metaSubprogramInfo.function->md = newMeta;
+    md->u.metaSubprogramInfo.function->metaCapacity = newCapacity;
+  }
+
+  md->u.metaSubprogramInfo.function->md[metaCount] = md;
+  md->u.metaSubprogramInfo.function->numMetadata++;
+}
+
+static void attachFunctionMetadata(CModule *m, Module *M) {
+  // dragonegg format
+  if(NamedMDNode *sp = M->getNamedMetadata("llvm.dbg.sp")) {
+    for(unsigned int i = 0; i < sp->getNumOperands(); ++i) {
+      DISubprogram dsp(sp->getOperand(i));
+      decodeAndAttachSubprogram(m, dsp);
+    }
+  }
+  // clang format
+  else if(NamedMDNode *cu = M->getNamedMetadata("llvm.dbg.cu")) {
+    for(unsigned int i = 0; i < cu->getNumOperands(); ++i) {
+      DIDescriptor cudesc(cu->getOperand(i));
+      if(!cudesc.isCompileUnit())
+        throw "llvm.dbg.cu contains a something that isn't a CompileUnit";
+      DICompileUnit dicu(cu->getOperand(i));
+      DIArray sps = dicu.getSubprograms();
+      for(unsigned int j = 0; j < sps.getNumElements(); ++j) {
+        DIDescriptor spdesc = sps.getElement(j);
+        // It looks like there can be NULL entries in subprogram
+        // lists.  Just ignore them.  Debug info is best-effort so
+        // this should be fine.
+        if(!spdesc.isSubprogram()) {
+          continue;
+        }
+
+        DISubprogram dsp(spdesc);
+        decodeAndAttachSubprogram(m, dsp);
+      }
+    }
+  }
+}
+
+static void attachGlobalMetadata(CModule *m, Module *M) {
+  NamedMDNode *gv = M->getNamedMetadata("llvm.dbg.gv");
+  // No debug information
+  if(!gv) return;
+
+  for(unsigned int i = 0; i < gv->getNumOperands(); ++i) {
+    CMeta *md = translateMetadata(m, gv->getOperand(i));
+    if(md->metaTag != META_GLOBALVARIABLE) {
+      throw "Non-global in llvm.dbg.gv";
+    }
+
+    if(md->u.metaGlobalInfo.global == NULL)
+      continue;
+
+    int currentCapacity = md->u.metaGlobalInfo.global->metaCapacity;
+    int metaCount = md->u.metaGlobalInfo.global->numMetadata;
+    if(metaCount == 0) {
+      currentCapacity = 10;
+      md->u.metaGlobalInfo.global->metaCapacity = currentCapacity;
+      md->u.metaGlobalInfo.global->md = (CMeta**)calloc(currentCapacity, sizeof(CMeta*));
+    }
+    else if(metaCount == currentCapacity - 1) {
+      int newCapacity = 2 * currentCapacity;
+      CMeta **newMeta = (CMeta**)calloc(newCapacity, sizeof(CMeta*));
+      memcpy(newMeta, md->u.metaGlobalInfo.global->md, currentCapacity * sizeof(CMeta*));
+      free(md->u.metaGlobalInfo.global->md);
+      md->u.metaGlobalInfo.global->md = newMeta;
+      md->u.metaGlobalInfo.global->metaCapacity = newCapacity;
+    }
+
+    md->u.metaGlobalInfo.global->md[metaCount] = md;
+    md->u.metaGlobalInfo.global->numMetadata++;
+  }
+}
+
+static void attachEnumMetadata(CModule *m, Module *M) {
+  // First, try to deal with the old method used by dragonegg 3.0
+  NamedMDNode *enums = M->getNamedMetadata("llvm.dbg.enum");
+  std::set<CMeta*> enumMeta;
+
+  if(enums) {
+    for(unsigned int i = 0; i < enums->getNumOperands(); ++i) {
+      CMeta *md = translateMetadata(m, enums->getOperand(i));
+      if(md)
+        enumMeta.insert(md);
+    }
+
+    m->enumMetadata = (CMeta**)calloc(enumMeta.size(), sizeof(CMeta*));
+    m->numEnumMetadata = enumMeta.size();
+    std::copy(enumMeta.begin(), enumMeta.end(), m->enumMetadata);
+    return;
+  }
+
+  // Otherwise, try the newer format used by clang (and hopefully
+  // newer dragoneggs).
+  NamedMDNode *compUnits = M->getNamedMetadata("llvm.dbg.cu");
+  if(compUnits) {
+    for(unsigned int i = 0; i < compUnits->getNumOperands(); ++i) {
+      DICompileUnit CU(compUnits->getOperand(i));
+      DIArray unitEnums(CU.getEnumTypes());
+      for(unsigned int e = 0; e < unitEnums.getNumElements(); ++e) {
+        CMeta *md = translateMetadata(m, unitEnums.getElement(e));
+        if(md)
+          enumMeta.insert(md);
+      }
+    }
+
+    m->enumMetadata = (CMeta**)calloc(enumMeta.size(), sizeof(CMeta*));
+    m->numEnumMetadata = enumMeta.size();
+    std::copy(enumMeta.begin(), enumMeta.end(), m->enumMetadata);
+    return;
+  }
+}
+
+static void attachRetainedTypeMetadata(CModule *m, Module *M) {
+  // This information is not present in dragonegg, so we just use the
+  // new clang style.
+  NamedMDNode *compUnits = M->getNamedMetadata("llvm.dbg.cu");
+  if(!compUnits) return;
+  std::set<CMeta*> typeMeta;
+
+  for(unsigned int i = 0; i < compUnits->getNumOperands(); ++i) {
+    DICompileUnit CU(compUnits->getOperand(i));
+    DIArray unitTypes(CU.getRetainedTypes());
+    for(unsigned int t = 0; t < unitTypes.getNumElements(); ++t) {
+      CMeta *md = translateMetadata(m, unitTypes.getElement(t));
+      if(md)
+        typeMeta.insert(md);
+    }
+  }
+
+  m->retainedTypeMetadata = (CMeta**)calloc(typeMeta.size(), sizeof(CMeta*));
+  m->numRetainedTypes = typeMeta.size();
+  std::copy(typeMeta.begin(), typeMeta.end(), m->retainedTypeMetadata);
+}
+
+static CModule* marshal(CModule * module) {
+  PrivateData *pd = (PrivateData*)module->privateData;
+  Module *m = pd->original;
+
+  module->moduleIdentifier = getCStrdup(m->getModuleIdentifier());
+  module->moduleDataLayout = getCStrdup(m->getDataLayout());
+  module->targetTriple = getCStrdup(m->getTargetTriple());
+  module->moduleInlineAsm = getCStrdup(m->getModuleInlineAsm());
+
+
+  try
+  {
+    std::vector<CValue*> globalVariables;
+    for(Module::const_global_iterator it = m->global_begin(),
+          ed = m->global_end(); it != ed; ++it)
+    {
+      const GlobalVariable *globalVar = dyn_cast<const GlobalVariable>(&*it);
+      if(!globalVar) throw "Not a global";
+
+      CValue *gv = translateGlobalVariable(module, globalVar);
+      globalVariables.push_back(gv);
+    }
+
+    module->numGlobalVariables = globalVariables.size();
+    module->globalVariables = (CValue**)calloc(module->numGlobalVariables, sizeof(CValue*));
+    std::copy(globalVariables.begin(), globalVariables.end(), module->globalVariables);
+
+
+    std::vector<CValue*> functions;
+    for(Module::const_iterator it = m->begin(),
+          ed = m->end(); it != ed; ++it)
+    {
+      const Function *func = dyn_cast<const Function>(&*it);
+      if(!func) throw "Not a function";
+
+      CValue *f = translateFunction(module, func);
+      functions.push_back(f);
+    }
+
+    module->numFunctions = functions.size();
+    module->functions = (CValue**)calloc(module->numFunctions, sizeof(CValue*));
+    std::copy(functions.begin(), functions.end(), module->functions);
+
+
+    std::vector<CValue*> globalAliases;
+    for(Module::const_alias_iterator it = m->alias_begin(),
+          ed = m->alias_end(); it != ed; ++it)
+    {
+      const GlobalAlias *globalAlias = dyn_cast<const GlobalAlias>(&*it);
+      if(!globalAlias) throw "Not a global alias";
+
+      CValue *ga = translateGlobalAlias(module, globalAlias);
+      globalAliases.push_back(ga);
+    }
+
+    module->numGlobalAliases = globalAliases.size();
+    module->globalAliases = (CValue**)calloc(module->numGlobalAliases, sizeof(CValue*));
+    std::copy(globalAliases.begin(), globalAliases.end(), module->globalAliases);
+
+    std::vector<CType*> typeVec;
+    for(unordered_map<const Type*, CType*>::const_iterator it = pd->typeMap.begin(),
+          ed = pd->typeMap.end(); it != ed; ++it)
+    {
+      typeVec.push_back(it->second);
+    }
+    module->numTypes = typeVec.size();
+    module->types = (CType**)calloc(module->numTypes, sizeof(CType*));
+
+    std::copy(typeVec.begin(), typeVec.end(), module->types);
+
+    // Now process the global metadata to attach metadata to global
+    // variables and functions.
+    attachFunctionMetadata(module, m);
+    attachGlobalMetadata(module, m);
+    attachEnumMetadata(module, m);
+    attachRetainedTypeMetadata(module, m);
+  }
+  catch(const string &msg) {
+    module->hasError = 1;
+    module->errMsg = getCStrdup(msg);
+  }
+  catch(const char *msg) {
+    module->hasError = 1;
+    module->errMsg = getCStrdup(msg);
+  }
+  catch(...) {
+    module->hasError = 1;
+    module->errMsg = getCStrdup("Unknown error");
+  }
+
+  return module;
+}
+
+extern "C" {
+
+  /*!
+    Free all of the resources allocated by the exposed module,
+    including the underlying C++ LLVM Module.
+   */
+  void disposeCModule(CModule *m) {
+    free(m->errMsg);
+    free(m->moduleIdentifier);
+    free(m->moduleDataLayout);
+    free(m->targetTriple);
+    free(m->moduleInlineAsm);
+
+    // The actual variables are deleted with disposeCValue from the
+    // valueMap.
+    free(m->globalVariables);
+    free(m->globalAliases);
+    free(m->functions);
+    free(m->enumMetadata);
+    free(m->retainedTypeMetadata);
+
+    PrivateData *pd = (PrivateData*)m->privateData;
+
+    for(unordered_map<const Type*,CType*>::iterator it = pd->typeMap.begin(),
+          ed = pd->typeMap.end(); it != ed; ++it)
+    {
+      disposeCType(it->second);
+    }
+
+    for(unordered_map<const Value*,CValue*>::iterator it = pd->valueMap.begin(),
+          ed = pd->valueMap.end(); it != ed; ++it)
+    {
+      disposeCValue(it->second);
+    }
+
+    for(unordered_map<const MDNode*,CMeta*>::iterator it = pd->metaMap.begin(),
+          ed = pd->metaMap.end(); it != ed; ++it)
+    {
+      disposeCMeta(it->second);
+    }
+
+    for(unordered_map<const DebugLoc*,CMeta*>::iterator it = pd->srcLocMap.begin(),
+          ed = pd->srcLocMap.end(); it != ed; ++it)
+    {
+      disposeCMeta(it->second);
+    }
+
+
+    // These are actually allocated with new
+    delete pd->dataLayout;
+    delete pd->original;
+    delete pd;
+
+    free(m);
+  }
+
+  CModule* marshalLLVMFile(const char * filename, int includeLocs) {
+    CModule *module = (CModule*)calloc(1, sizeof(CModule));
+    PrivateData *pd = new PrivateData;
+    module->privateData = (void*)pd;
+
+    Module *m = ParseIRFile(filename, pd->diags, pd->ctxt);
+    pd->dataLayout = new DataLayout(m);
+
+    if(m == NULL) {
+      module->hasError = 1;
+      module->errMsg = getCStrdup(pd->diags.getMessage());
+      return module;
+    }
+
+    pd->original = m;
+    pd->includeLocs = includeLocs;
+
+    return marshal(module);
+  }
+
+  CModule* marshalLLVM(const char * buffer, int bufLen, int includeLocs) {
+    CModule *module = (CModule*)calloc(1, sizeof(CModule));
+    PrivateData *pd = new PrivateData;
+    module->privateData = (void*)pd;
+
+    StringRef bref(buffer, bufLen);
+    pd->buffer.reset(MemoryBuffer::getMemBuffer(bref, "", false));
+
+    if(pd->buffer.get() == NULL){
+      module->hasError = 1;
+      module->errMsg = getCStrdup("Could not create memory buffer");
+      return module;
+    }
+
+    Module *m = ParseIR(pd->buffer.get(), pd->diags, pd->ctxt);
+
+    if(m == NULL) {
+      module->hasError = 1;
+      module->errMsg = getCStrdup(pd->diags.getMessage());
+      return module;
+    }
+
+    pd->original = m;
+    pd->includeLocs = includeLocs;
+
+    return marshal(module);
+  }
+}
diff --git a/src/c++/marshal.h b/src/c++/marshal.h
new file mode 100644
--- /dev/null
+++ b/src/c++/marshal.h
@@ -0,0 +1,441 @@
+#include <stdint.h>
+#include <llvm-base-enums.h>
+
+typedef struct CValue_t CValue;
+typedef struct CMeta_t CMeta;
+typedef struct CType_t CType;
+
+struct CType_t {
+  TypeTag typeTag;
+  // For TypeInt, lengths of TypeArray and TypeVector
+  unsigned long long size;
+
+  // For TypeFunction
+  int isVarArg;
+
+  // For structs
+  int isPacked;
+
+  // For TypeFunction, TypeStruct
+  CType** typeList;
+  int typeListLen;
+
+  // For FunctionType returnType, TypePointer, TypeNamed, and
+  // TypeArray and TypeVector
+  CType* innerType;
+
+  // Only for TypeNamed
+  char *name;
+
+  // For TypePointer
+  int addrSpace;
+
+  // For all types
+  int sizeInBytes;
+};
+
+typedef struct {
+  int arrayLen;
+  CMeta **arrayElts;
+} MetaArrayInfo;
+
+typedef struct {
+  char *enumName;
+  uint64_t enumValue;
+} MetaEnumeratorInfo;
+
+typedef struct {
+  CMeta *context;
+  char *name;
+  char *displayName;
+  char *linkageName;
+  // CMeta *compileUnit;
+  unsigned lineNumber;
+  CMeta *globalType;
+  int isLocalToUnit;
+  int isDefinition;
+  CValue *global;
+} MetaGlobalInfo;
+
+typedef struct {
+  unsigned lineNumber;
+  unsigned columnNumber;
+  CMeta *scope;
+  CMeta *origLocation;
+  char *filename;
+  char *directory;
+} MetaLocationInfo;
+
+typedef struct {
+  int64_t lo;
+  int64_t hi;
+} MetaSubrangeInfo;
+
+typedef struct {
+  CMeta *context;
+  char *name;
+  CMeta *type;
+  char *filename;
+  char *directory;
+  unsigned lineNumber;
+  unsigned columnNumber;
+} MetaTemplateTypeInfo;
+
+typedef struct {
+  CMeta *context;
+  char *name;
+  CMeta *type;
+  uint64_t value;
+  char *filename;
+  char *directory;
+  unsigned lineNumber;
+  unsigned columnNumber;
+} MetaTemplateValueInfo;
+
+typedef struct {
+  CMeta *context;
+  char *name;
+  // CMeta *compileUnit;
+  unsigned lineNumber;
+  unsigned argNumber;
+  CMeta *type;
+  int isArtificial;
+  int hasComplexAddress;
+  unsigned numAddrElements;
+  uint64_t *addrElements;
+  int isBlockByRefVar;
+} MetaVariableInfo;
+
+typedef struct {
+  unsigned language;
+  char *filename;
+  char *directory;
+  char *producer;
+  int isMain;
+  int isOptimized;
+  char *flags;
+  unsigned runtimeVersion;
+  CMeta *enumTypes;
+  CMeta *retainedTypes;
+  CMeta *subprograms;
+  CMeta *globalVariables;
+} MetaCompileUnitInfo;
+
+typedef struct {
+  char *filename;
+  char *directory;
+  // CMeta *compileUnit;
+} MetaFileInfo;
+
+typedef struct {
+  CMeta *context;
+  unsigned lineNumber;
+  unsigned columnNumber;
+  char *directory;
+  char *filename;
+} MetaLexicalBlockInfo;
+
+typedef struct {
+  CMeta *context;
+  char *name;
+  char *directory;
+  char *filename;
+  // CMeta *compileUnit;
+  unsigned lineNumber;
+} MetaNamespaceInfo;
+
+typedef struct {
+  CMeta *context;
+  char *name;
+  char *displayName;
+  char *linkageName;
+  // CMeta *compileUnit;
+  unsigned lineNumber;
+  CMeta *type;
+  char *returnTypeName;
+  int isLocalToUnit;
+  int isDefinition;
+  unsigned virtuality;
+  unsigned virtualIndex;
+  CMeta *containingType;
+  int isArtificial;
+  int isPrivate;
+  int isProtected;
+  int isExplicit;
+  int isPrototyped;
+  int isOptimized;
+  char *filename;
+  char *directory;
+  CValue *function;
+  // This is only available in LLVM 3.0+
+  // CMeta *templateParams;
+} MetaSubprogramInfo;
+
+typedef struct {
+  CMeta *context;
+  char *name;
+  // CMeta *compileUnit;
+  // CMeta *file;
+  unsigned lineNumber;
+  uint64_t sizeInBits;
+  uint64_t alignInBits;
+  uint64_t offsetInBits;
+  unsigned flags;
+  int isPrivate;
+  int isProtected;
+  int isForward;
+  int isByRefStruct;
+  int isVirtual;
+  int isArtificial;
+  char *directory;
+  char *filename;
+
+  // Basic type
+  unsigned encoding;
+
+  // Derived and Composite Types
+  CMeta *typeDerivedFrom;
+  uint64_t originalTypeSize;
+
+  // Composite Type
+  CMeta *typeArray;
+  unsigned runTimeLang;
+  CMeta *containingType;
+  CMeta *templateParams;
+} MetaTypeInfo;
+
+typedef struct {
+  char *repr;
+} MetaUnknownInfo;
+
+struct CMeta_t {
+  MetaTag metaTag;
+  unsigned int tag;
+  union {
+    MetaArrayInfo metaArrayInfo;
+    MetaEnumeratorInfo metaEnumeratorInfo;
+    MetaGlobalInfo metaGlobalInfo;
+    MetaLocationInfo metaLocationInfo;
+    MetaSubrangeInfo metaSubrangeInfo;
+    MetaTemplateTypeInfo metaTemplateTypeInfo;
+    MetaTemplateValueInfo metaTemplateValueInfo;
+    MetaVariableInfo metaVariableInfo;
+    MetaCompileUnitInfo metaCompileUnitInfo;
+    MetaFileInfo metaFileInfo;
+    MetaLexicalBlockInfo metaLexicalBlockInfo;
+    MetaNamespaceInfo metaNamespaceInfo;
+    MetaSubprogramInfo metaSubprogramInfo;
+    MetaTypeInfo metaTypeInfo;
+    MetaUnknownInfo metaUnknownInfo;
+  } u;
+};
+
+typedef struct {
+  int hasSRet;
+  int hasByVal;
+  int hasNest;
+  int hasNoAlias;
+  int hasNoCapture;
+} CArgumentInfo;
+
+typedef struct {
+  CValue **instructions;
+  int blockLen;
+} CBasicBlockInfo;
+
+typedef struct {
+  int isExternal; // Declaration
+  int alignment;
+  VisibilityStyle visibility;
+  LinkageType linkage;
+  char *section;
+
+  CallingConvention callingConvention;
+  int isVarArg;
+  char *gcName;
+  CValue **arguments;
+  int argListLen;
+  CValue **body;
+  int blockListLen;
+  // FIXME: Add attributes
+} CFunctionInfo;
+
+typedef struct {
+  int isExternal; // Declaration
+  int alignment;
+  VisibilityStyle visibility;
+  LinkageType linkage;
+  char *section;
+
+  // Only for global vars
+  CValue *initializer;
+  int isThreadLocal;
+  int isConstant;
+
+  // Only for global aliases
+  CValue *aliasee;
+} CGlobalInfo;
+
+typedef struct {
+  CValue **operands;
+  int numOperands;
+
+  // Value insts
+  int *indices;
+  int numIndices;
+
+  // Comparisons
+  CmpPredicate cmpPred;
+
+  // Binary operators
+  ArithFlags flags;
+
+  // Misc
+  int align;
+  int addrSpace;
+
+  // Load/Store
+  int isVolatile;
+
+  // GEP
+  int inBounds;
+} CInstructionInfo;
+
+typedef struct {
+  CAtomicOrdering ordering;
+  CSynchronizationScope scope;
+  AtomicOperation operation;
+  int isVolatile;
+  int addrSpace;
+
+  // cmpxchg, atomicrwm
+  CValue *pointerOperand;
+  // cmpxchg, atomicrwm
+  CValue *valueOperand;
+  // cmpxchg
+  CValue *compareOperand;
+} CAtomicInfo;
+
+typedef struct {
+  CValue **incomingValues;
+  CValue **valueBlocks;
+  int numIncomingValues;
+} CPHIInfo;
+
+typedef struct {
+  CValue *personality;
+  int isCleanup;
+  int numClauses;
+  CValue **clauses;
+  LandingPadClause *clauseTypes;
+} CLandingPadInfo;
+
+// Also for invoke
+typedef struct {
+  CValue *calledValue;
+  CValue **arguments;
+  int argListLen;
+  CallingConvention callingConvention;
+  int hasSRet;
+  int isTail;
+
+  // FIXME: Add attributes
+
+  // Invoke only
+  CValue *normalDest;
+  CValue *unwindDest;
+} CCallInfo;
+
+typedef struct {
+  char *asmString;
+  char *constraintString;
+} CInlineAsmInfo;
+
+typedef struct {
+  CValue *func;
+  CValue *block;
+} CBlockAddrInfo;
+
+// This is lossy but good enough for all practical purposes.
+typedef struct {
+  long long int val;
+  char* hugeVal;
+} CConstInt;
+
+typedef struct {
+  double val;
+} CConstFP;
+
+typedef struct {
+  CValue **constants;
+  int numElements;
+} CConstAggregate;
+
+typedef struct {
+  CInstructionInfo *ii;
+  ValueTag instrType;
+} CConstExprInfo;
+
+struct CValue_t {
+  ValueTag valueTag;
+  CType *valueType;
+  char *name;
+  CMeta **md;
+  CMeta *srcLoc;
+  int numMetadata;
+  int metaCapacity;
+
+  void *data;
+};
+
+typedef struct {
+  char *moduleIdentifier;
+  char *moduleDataLayout;
+  char *targetTriple;
+  int littleEndian;
+  int pointerSize;
+  char *moduleInlineAsm;
+
+  CValue **globalVariables;
+  int numGlobalVariables;
+  CValue **globalAliases;
+  int numGlobalAliases;
+  CValue **functions;
+  int numFunctions;
+
+  CType **types;
+  int numTypes;
+
+  CMeta **enumMetadata;
+  int numEnumMetadata;
+
+  CMeta **retainedTypeMetadata;
+  int numRetainedTypes;
+
+  int hasError;
+  char *errMsg;
+
+  void *privateData;
+} CModule;
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+  #if defined(__GNUC__)
+    #define DLL_PUBLIC __attribute__((dllexport))
+  #else
+    #define DLL_PUBLIC __declspec(dllexport)
+  #endif
+#else
+  #if __GNUC__ >= 4
+    #define DLL_PUBLIC __attribute__((visibility("default")))
+  #endif
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+  DLL_PUBLIC void disposeCModule(CModule *m);
+  DLL_PUBLIC CModule* marshalLLVM(const char *buffer, int bufLen, int includeLocs);
+  DLL_PUBLIC CModule* marshalLLVMFile(const char *filename, int includeLocs);
+#if defined(__cplusplus)
+}
+#endif
