diff --git a/CHANGES b/CHANGES
new file mode 100644
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,6 @@
+0.5 
+- support LLVM 3.5 syntax
+- renamed to hLLVM
+0.1
+- support LLVM 3.1 syntax
+- Hoopl based implementation :mem2reg, dce, dominator 
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2011-2015 Ning Wang (email@ningwang.org)
+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 the Ning Wang nor the
+      names of its 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 NING WANG 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,38 @@
+hLLVM -- A Haskell Library for analyzing and transforming LLVM assembly codes
+
+
+Goal: 
+==========================================
+- Provide functionalities for performaning analysis and transformation of LLVM codes in pure Haskell
+
+
+
+Build:
+==============
+From hLLVM toplevel directory
+
+  cabal configure
+
+  cabal build
+
+The test driver 'llvm-test' is generated at dist/build/llvm-test
+
+Test:
+==============
+## test LLVM assembly parser
+dist/build/llvm-test/llvm-test parse -i test/test1.ll -o out.ll
+
+## test mem2reg pass
+dist/build/llvm-test/llvm-test pass -s=mem2reg -f=10000 -i test/test1.ll -o out.ll
+
+
+## test dce pass
+dist/build/llvm-test/llvm-test pass -s=dce -f=10000 -i test/test1.ll -o out.ll
+
+
+## test mem2reg and dce passes
+dist/build/llvm-test/llvm-test pass -s=mem2reg -s=dce -f=1000 -i test/test1.ll -o out.ll
+
+
+## run tests in batch (llvm-test needs to be available in the executable search paths)
+test/runLlvmTest.sh [parse|ast2ir|ir2ast] <directory of llvm-3.5 test cases>
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+import Distribution.Simple
+main = defaultMain
+
+
diff --git a/TODO b/TODO
new file mode 100644
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+- hoopl will remove all unresearchable code, however, blockaddress might refer to some removed code labels. We need to write a pass to update all blockaddress that still refer to removed code labels to undef
+
+- constant folding
diff --git a/hLLVM.cabal b/hLLVM.cabal
new file mode 100644
--- /dev/null
+++ b/hLLVM.cabal
@@ -0,0 +1,135 @@
+name:  hLLVM
+version: 0.5.0.0
+license: BSD3
+license-file: LICENSE
+author: Ning Wang <email@ningwang.org>
+maintainer: Ning Wang <email@ningwang.org>
+build-Type: Simple
+cabal-Version: >= 1.10
+stability: 0.5
+synopsis: A library for processing LLVM assembly codes
+category: Compilers/Interpreters
+description:  A pure Haskell library for analyzing and transforming LLVM assembly codes. 
+              It includes:
+              1) a parser to parse LLVM code in its text form
+              2) an internal IR that can be feed into Hoopl
+              3) a set of utility functions to convert LLVM AST to and from the internal IR 
+              4) a set of utility functions to query the IR
+
+extra-source-files:  README.md, LICENSE, CHANGES, TODO
+
+source-repository head
+  type:     git
+  location: https://github.com/mlite/hLLVM.git
+
+
+
+flag debug {
+  description: Enable debug support
+  default:     False
+}
+
+flag testcoverage {
+  description: Enable test coverage report
+  default: False
+}
+
+library {
+  default-language:  Haskell2010
+  build-depends:     base >= 3 && < 5,
+                     containers,
+                     array,
+                     bytestring,
+                     mtl,
+                     filepath,
+                     directory,
+                     hooplext == 3.10.0.2,
+                     parsec >=3.1.2 && <3.2,
+                     cmdargs >=0.10 && <0.11,
+                     transformers >= 0.3.0.0,
+                     pretty >= 1.1.1.1,
+                     data-dword == 0.3,
+                     template-haskell >= 2.9.0.0
+  hs-source-dirs:    src
+  exposed-modules:   Llvm.Data.Ast,
+                     Llvm.Data.Type,
+                     Llvm.Data.CoreIr,
+                     Llvm.Data.Ir,
+                     Llvm.Data.IrType,
+                     Llvm.Data.Shared,
+                     Llvm.Data.Shared.AtomicEntity,
+                     Llvm.Data.Shared.SimpleConst,
+                     Llvm.Data.Shared.DataLayout,
+                     Llvm.Data.Shared.Util,
+                     Llvm.Data.Conversion,
+                     Llvm.Data.Conversion.AstSimplification,
+                     Llvm.Data.Conversion.AstIrConversion,
+                     Llvm.Data.Conversion.AstScanner,
+                     Llvm.Data.Conversion.IrAstConversion,
+                     Llvm.Data.Conversion.TypeConversion,
+                     Llvm.Data.Conversion.LabelMapM,
+                     Llvm.Util.Mapping,
+                     Llvm.Util.Monadic,
+                     Llvm.Query.TypeConstValue,
+                     Llvm.Query.Qerror,
+                     Llvm.Query.Conversion,
+                     Llvm.Query.IrCxt,
+                     Llvm.Query.TypeDef,
+                     Llvm.Syntax.Printer.Common,
+                     Llvm.Syntax.Printer.SharedEntityPrint,
+                     Llvm.Syntax.Printer.IrPrint,
+                     Llvm.Syntax.Printer.LlvmPrint,
+                     Llvm.Syntax.Parser.Basic,
+                     Llvm.Syntax.Parser.Block,
+                     Llvm.Syntax.Parser.Const,
+                     Llvm.Syntax.Parser.DataLayout,
+                     Llvm.Syntax.Parser.Instruction,
+                     Llvm.Syntax.Parser.Module,
+                     Llvm.Syntax.Parser.Rhs,
+                     Llvm.Syntax.Parser.Type,
+                     Llvm.Pass.Dominator,
+                     Llvm.Pass.Liveness,
+                     Llvm.Pass.Mem2Reg,
+                     Llvm.Pass.NormalGraph,
+                     Llvm.Pass.Optimizer,
+                     Llvm.Pass.PassManager,
+                     Llvm.Pass.PhiFixUp,
+                     Llvm.Pass.Rewriter,
+                     Llvm.Pass.Uda,
+                     Llvm.Pass.PassTester,
+                     ParserTester
+  if flag(debug) {
+     if !os(windows) {
+        cc-options: -DDEBUG
+     } else {
+        cc-options: -DNDEBUG
+    }
+  } 
+  if flag(testcoverage) {
+    ghc-options: 
+  }
+  other-extensions: CPP
+}
+
+executable llvm-test
+  default-language:  Haskell2010
+  main-is:           LlvmTest.hs
+  hs-source-dirs:    src
+  build-depends:     base >= 3 && < 5,
+                     containers,
+                     array,
+                     bytestring,
+                     mtl,
+                     filepath,
+                     directory,
+                     template-haskell >= 2.9.0.0,
+                     hooplext == 3.10.0.2,
+                     parsec >=3.1.2 && <3.2,
+                     cmdargs >=0.10 && <0.11,
+                     transformers >= 0.3.0.0,
+                     pretty >= 1.1.1.1,
+                     data-dword == 0.3
+  if flag(testcoverage) {
+    ghc-options:
+  }
+
diff --git a/src/Llvm/Data/Ast.hs b/src/Llvm/Data/Ast.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Ast.hs
@@ -0,0 +1,357 @@
+{-# LANGUAGE GADTs #-}
+module Llvm.Data.Ast
+       ( module Llvm.Data.Ast
+       , module Llvm.Data.Shared
+       , module Llvm.Data.Type
+       ) where
+
+import Llvm.Data.Shared
+import Llvm.Data.Type
+import qualified Data.Map as M
+import Data.Word (Word32)
+
+
+-- | quotation does not change a label value
+-- | it's still unclear when a quoted verion is used
+-- | we keep the original format to make llvm-as happy
+data LabelId = LabelString String -- Lstring
+             | LabelDqString String -- Lstring -- a string enclosed by double quotes
+             | LabelNumber Word32 -- Int
+             | LabelDqNumber Word32 -- Int -- a number enclosed by double quotes
+             deriving (Eq,Ord,Show)
+
+data BlockLabel = ExplicitBlockLabel LabelId
+                | ImplicitBlockLabel (String, Int, Int)
+                deriving (Eq, Ord, Show)
+
+data PercentLabel = PercentLabel LabelId deriving (Eq, Ord, Show)
+data TargetLabel = TargetLabel PercentLabel deriving (Eq,Ord,Show)
+
+data IbinOp = Add | Sub | Mul | Udiv
+            | Sdiv | Urem | Srem
+            | Shl | Lshr | Ashr | And | Or | Xor
+            deriving (Eq,Ord,Show)
+
+ibinOpMap :: M.Map IbinOp String
+ibinOpMap = M.fromList [(Add, "add"), (Sub, "sub"), (Mul, "mul")
+                       ,(Udiv, "udiv"), (Sdiv, "sdiv")
+                       ,(Urem, "urem"), (Srem, "srem")
+                       ,(Shl, "shl"), (Lshr, "lshr"), (Ashr, "ashr")
+                       ,(And, "and"), (Or, "or"), (Xor, "xor")
+                       ]
+
+data FbinOp = Fadd | Fsub | Fmul | Fdiv | Frem
+            deriving (Eq,Ord,Show)
+
+fbinOpMap :: M.Map FbinOp String
+fbinOpMap = M.fromList [(Fadd, "fadd"), (Fsub, "fsub"), (Fmul, "fmul"), (Fdiv, "fdiv"), (Frem, "frem")]
+
+data TrapFlag = Nuw | Nsw | Exact deriving (Eq,Ord,Show)
+
+trapFlagMap :: M.Map TrapFlag String
+trapFlagMap = M.fromList [(Nuw, "nuw"), (Nsw, "nsw"), (Exact, "exact")]
+
+-- | Binary Operations <http://llvm.org/releases/3.0/docs/LangRef.html#binaryops>
+data IbinExpr v = IbinExpr IbinOp [TrapFlag] Type v v deriving (Eq,Ord,Show)
+data FbinExpr v = FbinExpr FbinOp FastMathFlags Type v v deriving (Eq,Ord,Show)
+data BinExpr v = Ie (IbinExpr v)
+               | Fe (FbinExpr v)
+               deriving (Eq, Ord, Show)
+data GetElementPtr v = GetElementPtr (IsOrIsNot InBounds) (Pointer (Typed v)) [Typed v] deriving (Eq,Ord,Show)
+data Select v = Select (Typed v) (Typed v) (Typed v) deriving (Eq,Ord,Show)
+data Icmp v = Icmp IcmpOp Type v v deriving (Eq,Ord,Show)
+data Fcmp v = Fcmp FcmpOp Type v v deriving (Eq,Ord,Show)
+
+
+-- | Vector Operations <http://llvm.org/releases/3.0/docs/LangRef.html#vectorops>
+data ExtractElement v = ExtractElement (Typed v) (Typed v) deriving (Eq,Ord,Show)
+data InsertElement v = InsertElement (Typed v) (Typed v) (Typed v) deriving (Eq,Ord,Show)
+data ShuffleVector v = ShuffleVector (Typed v) (Typed v) (Typed v) deriving (Eq,Ord,Show)
+
+-- | Aggregate Operations <http://llvm.org/releases/3.0/docs/LangRef.html#aggregateops>
+data ExtractValue v = ExtractValue (Typed v) [Word32] deriving (Eq,Ord,Show)
+data InsertValue v = InsertValue (Typed v) (Typed v) [Word32] deriving (Eq,Ord,Show)
+
+-- | Conversion Operations <http://llvm.org/releases/3.0/docs/LangRef.html#convertops>
+data Conversion v = Conversion ConvertOp (Typed v) Type deriving (Eq,Ord,Show)
+
+data ConvertOp = Trunc | Zext | Sext | FpTrunc | FpExt | FpToUi
+               | FpToSi | UiToFp | SiToFp | PtrToInt | IntToPtr
+               | Bitcast | AddrSpaceCast
+               deriving (Eq,Ord,Show)
+
+convertOpMap :: M.Map ConvertOp String
+convertOpMap = M.fromList [(Trunc, "trunc"), (Zext, "zext"), (Sext, "sext")
+                          ,(FpTrunc, "fptrunc"), (FpExt, "fpext"), (FpToUi, "fptoui")
+                          ,(FpToSi, "fptosi"), (UiToFp, "uitofp"), (SiToFp, "sitofp")
+                          ,(PtrToInt, "ptrtoint"), (IntToPtr, "inttoptr"), (Bitcast, "bitcast")
+                          ,(AddrSpaceCast, "addrspacecast")]
+
+-- | Complex Constants <http://llvm.org/releases/3.0/docs/LangRef.html#complexconstants>
+data ComplexConstant = Cstruct Packing [TypedConstOrNull]
+                     | Carray [TypedConstOrNull]
+                     | Cvector [TypedConstOrNull]
+                       deriving (Eq,Ord,Show)
+
+-- | Constants <http://llvm.org/releases/3.5.0/docs/LangRef.html#constant-expressions>
+data Const = C_simple SimpleConstant
+           | C_complex ComplexConstant
+           | C_localId LocalId
+           | C_labelId LabelId
+           -- | Addresses of Basic Block <http://llvm.org/releases/3.0/docs/LangRef.html#blockaddress>
+           | C_blockAddress GlobalId PercentLabel
+           | C_binexp (BinExpr Const)
+           | C_conv (Conversion Const)
+           | C_gep (GetElementPtr Const)
+           | C_select (Select Const)
+           | C_icmp (Icmp Const)
+           | C_fcmp (Fcmp Const)
+           | C_shufflevector (ShuffleVector Const)
+           | C_extractvalue (ExtractValue Const)
+           | C_insertvalue (InsertValue Const)
+           | C_extractelement (ExtractElement Const)
+           | C_insertelement (InsertElement Const)
+           | C_null
+           deriving (Eq,Ord,Show)
+
+data Prefix = Prefix (TypedConstOrNull) deriving (Eq, Ord, Show)
+data Prologue = Prologue (TypedConstOrNull) deriving (Eq, Ord, Show)
+
+data MdVar = MdVar String deriving (Eq,Ord,Show)
+data MdNode = MdNode String deriving (Eq,Ord,Show)
+data MetaConst = McStruct [MetaKindedConst]
+               | McString DqString
+               | McMn MdNode
+               | McMv MdVar
+               | McRef LocalId
+               | McSimple Const
+               deriving (Eq,Ord,Show)
+
+data MetaKindedConst = MetaKindedConst MetaKind MetaConst
+                     | UnmetaKindedNull
+                     deriving (Eq, Ord, Show)
+
+data GetResult = GetResult (Typed Value) String deriving (Eq, Ord, Show)
+
+
+data Expr = EgEp (GetElementPtr Value)
+          | EiC (Icmp Value)
+          | EfC (Fcmp Value)
+          | Eb (BinExpr Value)
+          | Ec (Conversion Value)
+          | Es (Select Value)
+          deriving (Eq,Ord,Show)
+
+-- | Memory Access and Addressing Operations <http://llvm.org/releases/3.5.0/docs/LangRef.html#memory-access-and-addressing-operations>
+data MemOp = Alloca (IsOrIsNot InAllocaAttr) Type (Maybe (Typed Value)) (Maybe Alignment)
+           | Load (IsOrIsNot Volatile) (Pointer (Typed Value)) (Maybe Alignment) (Maybe Nontemporal) (Maybe InvariantLoad) (Maybe Nonnull)
+           | LoadAtomic Atomicity (IsOrIsNot Volatile) (Pointer (Typed Value)) (Maybe Alignment)
+           | Store (IsOrIsNot Volatile) (Typed Value) (Pointer (Typed Value)) (Maybe Alignment) (Maybe Nontemporal)
+           | StoreAtomic Atomicity (IsOrIsNot Volatile) (Typed Value) (Pointer (Typed Value)) (Maybe Alignment)
+           | Fence (IsOrIsNot SingleThread) AtomicMemoryOrdering
+           | CmpXchg (IsOrIsNot Weak) (IsOrIsNot Volatile) (Pointer (Typed Value)) (Typed Value) (Typed Value)
+             (IsOrIsNot SingleThread) AtomicMemoryOrdering AtomicMemoryOrdering
+           | AtomicRmw (IsOrIsNot Volatile) AtomicOp (Pointer (Typed Value)) (Typed Value)
+             (IsOrIsNot SingleThread) AtomicMemoryOrdering deriving (Eq,Ord,Show)
+
+data Pointer v = Pointer v deriving (Eq, Ord, Show)
+
+instance Functor Pointer where
+  fmap f (Pointer x) = Pointer (f x)
+
+data FunName = FunNameGlobal GlobalOrLocalId
+             | FunNameString String
+               deriving (Eq,Ord,Show)
+
+data CallSite = CsFun (Maybe CallConv) [ParamAttr] Type FunName [ActualParam] [FunAttr]
+              | CsAsm Type (Maybe SideEffect) (Maybe AlignStack) AsmDialect DqString DqString [ActualParam] [FunAttr]
+              | CsConversion [ParamAttr] Type (Conversion Const) [ActualParam] [FunAttr]
+              deriving (Eq,Ord,Show)
+
+data Clause = Catch (Typed Value)
+            | Filter TypedConstOrNull
+            | Cco (Conversion Value)
+            deriving (Eq,Ord,Show)
+
+data TypedConstOrNull = TypedConst (Typed Const)
+                      | UntypedNull
+                      deriving (Eq, Ord, Show)
+
+data PersFn = PersFnId GlobalOrLocalId
+            | PersFnCast (Conversion GlobalOrLocalId)
+            | PersFnUndef
+            | PersFnNull
+            | PersFnConst Const
+            deriving (Eq, Ord, Show)
+
+
+data Rhs = RmO MemOp
+         | Re Expr
+         | Call TailCall CallSite
+         | ReE (ExtractElement Value)
+         | RiE (InsertElement Value)
+         | RsV (ShuffleVector Value)
+         | ReV (ExtractValue Value)
+         | RiV (InsertValue Value)
+         | RvA VaArg
+         | RlP LandingPad
+         deriving (Eq,Ord,Show)
+
+data VaArg = VaArg (Typed Value) Type deriving (Eq, Ord, Show)
+
+data LandingPad = LandingPad Type Type PersFn (Maybe Cleanup) [Clause] deriving (Eq, Ord, Show)
+
+data Dbg = Dbg MdVar MetaConst deriving (Eq,Show)
+
+data PhiInst = PhiInst (Maybe LocalId) Type
+               [(Value, PercentLabel)] deriving (Eq,Show)
+
+data PhiInstWithDbg = PhiInstWithDbg PhiInst [Dbg]
+                      deriving (Eq, Show)
+
+data ComputingInst = ComputingInst (Maybe LocalId) Rhs
+                     deriving (Eq,Show)
+                              
+data ComputingInstWithDbg = ComputingInstWithDbg ComputingInst [Dbg]
+                          | ComputingInstWithComment String
+                            deriving (Eq,Show)
+
+-- | Terminator Instructions <http://llvm.org/releases/3.0/docs/LangRef.html#terminators>
+data TerminatorInst =
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_ret>
+    RetVoid
+    | Return [(Typed Value)]
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_br>
+    | Br TargetLabel
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_br>
+    | Cbr Value TargetLabel TargetLabel
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_switch>
+    | Switch (Typed Value) TargetLabel [((Typed Value), TargetLabel)]
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_indirectbr>
+    | IndirectBr (Typed Value) [TargetLabel]
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_invoke>
+    | Invoke (Maybe LocalId) CallSite TargetLabel TargetLabel
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_unwind>
+    | Unwind
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_resume>
+    | Resume (Typed Value)
+    -- | <http://llvm.org/releases/3.0/docs/LangRef.html#i_unreachable>
+    | Unreachable
+      deriving (Eq,Show)
+
+data TerminatorInstWithDbg = TerminatorInstWithDbg TerminatorInst [Dbg]
+                             deriving (Eq,Show)
+
+data ActualParam = ActualParamData Type [ParamAttr] (Maybe Alignment) Value [ParamAttr]
+                 | ActualParamMeta MetaKindedConst
+                 deriving (Eq,Ord,Show)
+
+data Value = Val_local LocalId
+           | Val_const Const
+           deriving (Eq,Ord,Show)
+                    
+data Typed v = Typed Type v deriving (Eq, Ord, Show)
+
+data Aliasee = AtV (Typed Value)
+             | Ac (Conversion Const)
+             | AgEp (GetElementPtr Const)
+             deriving (Eq,Show)
+
+data FunctionPrototype = FunctionPrototype
+                         (Maybe Linkage)
+                         (Maybe Visibility)
+                         (Maybe DllStorageClass)
+                         (Maybe CallConv)
+                         [ParamAttr]
+                         Type
+                         GlobalId
+                         FormalParamList
+                         (Maybe AddrNaming)
+                         [FunAttr]
+                         (Maybe Section)
+                         (Maybe Comdat)
+                         (Maybe Alignment)
+                         (Maybe Gc)
+                         (Maybe Prefix)
+                         (Maybe Prologue)
+                       deriving (Eq,Ord,Show)
+
+
+data Toplevel = ToplevelTriple TlTriple
+              | ToplevelDataLayout TlDataLayout
+              | ToplevelAlias TlAlias
+              | ToplevelDbgInit TlDbgInit
+              | ToplevelStandaloneMd TlStandaloneMd
+              | ToplevelNamedMd TlNamedMd
+              | ToplevelDeclare TlDeclare
+              | ToplevelDefine TlDefine
+              | ToplevelGlobal TlGlobal
+              | ToplevelTypeDef TlTypeDef
+              | ToplevelDepLibs TlDepLibs
+              | ToplevelUnamedType TlUnamedType
+              | ToplevelModuleAsm TlModuleAsm
+              | ToplevelAttribute TlAttribute
+              | ToplevelComdat TlComdat
+              deriving (Eq,Show)
+
+
+data TlTriple = TlTriple TargetTriple deriving (Eq, Show)
+
+data TlDataLayout = TlDataLayout DataLayout deriving (Eq, Show)
+
+data TlAlias = TlAlias GlobalId (Maybe Visibility) (Maybe DllStorageClass) (Maybe ThreadLocalStorage)
+               AddrNaming (Maybe Linkage) Aliasee deriving (Eq, Show)
+
+data TlDbgInit = TlDbgInit String Word32 deriving (Eq, Show)
+
+data TlStandaloneMd = TlStandaloneMd String MetaKindedConst deriving (Eq, Show)
+
+data TlNamedMd = TlNamedMd MdVar [MdNode] deriving (Eq, Show)
+
+data TlDeclare = TlDeclare FunctionPrototype deriving (Eq, Show)
+
+data TlDefine = TlDefine FunctionPrototype [Block] deriving (Eq, Show)
+
+data TlGlobal = TlGlobal (Maybe GlobalId)
+                (Maybe Linkage)
+                (Maybe Visibility)
+                (Maybe DllStorageClass)
+                (Maybe ThreadLocalStorage)
+                AddrNaming
+                (Maybe AddrSpace)
+                (IsOrIsNot ExternallyInitialized)
+                GlobalType
+                Type
+                (Maybe Const)
+                (Maybe Section)
+                (Maybe Comdat)
+                (Maybe Alignment)
+              deriving (Eq, Show)
+
+data TlTypeDef = TlTypeDef LocalId Type deriving (Eq, Show)
+
+data TlDepLibs = TlDepLibs [DqString] deriving (Eq, Show)
+
+data TlUnamedType = TlUnamedType Word32 Type deriving (Eq, Show)
+
+data TlModuleAsm = TlModuleAsm DqString deriving (Eq, Show)
+
+data TlAttribute = TlAttribute Word32 [FunAttr] deriving (Eq, Show)
+
+data TlComdat = TlComdat DollarId SelectionKind deriving (Eq, Show)
+
+data Block = Block BlockLabel [PhiInstWithDbg] [ComputingInstWithDbg] TerminatorInstWithDbg deriving (Eq,Show)
+
+blockLabel :: Block -> BlockLabel
+blockLabel (Block v _ _ _) = v
+
+data Module = Module [Toplevel] deriving (Eq,Show)
+
+
+dataLayoutOfModule :: Module -> DataLayoutInfo
+dataLayoutOfModule (Module tl) = let [ToplevelDataLayout (TlDataLayout dl)] =
+                                       filter (\x -> case x of
+                                                  ToplevelDataLayout _ -> True
+                                                  _ -> False
+                                              ) tl
+                                 in getDataLayoutInfo dl
diff --git a/src/Llvm/Data/Conversion.hs b/src/Llvm/Data/Conversion.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Conversion.hs
@@ -0,0 +1,11 @@
+module Llvm.Data.Conversion
+       (module Llvm.Data.Conversion.AstSimplification
+       ,module Llvm.Data.Conversion.AstIrConversion
+       ,module Llvm.Data.Conversion.IrAstConversion
+       ,module Llvm.Data.Conversion.LabelMapM
+       ) where
+
+import Llvm.Data.Conversion.AstSimplification
+import Llvm.Data.Conversion.AstIrConversion
+import Llvm.Data.Conversion.IrAstConversion
+import Llvm.Data.Conversion.LabelMapM (IdLabelMap(..),a2h,invertMap)
diff --git a/src/Llvm/Data/Conversion/AstIrConversion.hs b/src/Llvm/Data/Conversion/AstIrConversion.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Conversion/AstIrConversion.hs
@@ -0,0 +1,1492 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Llvm.Data.Conversion.AstIrConversion(astToIr) where
+
+#define FLC  (I.FileLoc $(I.srcLoc))
+
+import qualified Compiler.Hoopl as H
+import qualified Control.Monad as Md
+import qualified Data.Map as M
+import qualified Llvm.Data.Ast as A
+import qualified Llvm.Data.Ir as I
+import Llvm.Data.Conversion.LabelMapM
+import Llvm.Util.Monadic (maybeM, pairM)
+import Llvm.Data.Conversion.TypeConversion
+import Llvm.Data.Conversion.AstScanner (typeDefOfModule)
+import Data.Maybe (fromJust)
+
+type MM = LabelMapM H.SimpleUniqueMonad
+
+{- Ast to Ir conversion -}
+-- the real differences between Ast and Ir
+-- 1. Ir uses Unique values as labels while Ast can use any strings as labels
+-- 2. All unreachable code are removed in Ir
+
+isTvector :: MP -> A.Type -> Bool
+isTvector mp t = let (ta::I.Utype) = tconvert mp t
+                 in case ta of
+                   (I.UtypeVectorI _) -> True
+                   (I.UtypeVectorF _) -> True
+                   (I.UtypeVectorP _) -> True
+                   _ -> False
+
+getElemPtrIsTvector :: MP -> A.GetElementPtr v -> Bool
+getElemPtrIsTvector mp (A.GetElementPtr n (A.Pointer (A.Typed t _)) l) = isTvector mp t
+
+conversionIsTvector :: MP -> A.Conversion v -> Bool
+conversionIsTvector mp (A.Conversion _ _ dt) = isTvector mp dt
+
+convert_LabelId :: A.LabelId -> MM H.Label 
+convert_LabelId = labelFor
+
+
+convert_PercentLabel :: A.PercentLabel -> MM H.Label 
+convert_PercentLabel (A.PercentLabel l) = convert_LabelId l
+
+convert_TargetLabel :: A.TargetLabel -> MM H.Label 
+convert_TargetLabel (A.TargetLabel tl) = convert_PercentLabel tl 
+
+convert_BlockLabel :: A.BlockLabel -> MM H.Label
+convert_BlockLabel (A.ImplicitBlockLabel p) = error $ "ImplicitBlockLabel @" ++ show p ++ " should be normalized away in AstSimplification, and should not be leaked to Ast2Ir."
+convert_BlockLabel (A.ExplicitBlockLabel b) = convert_LabelId b 
+
+
+convert_ComplexConstant :: A.ComplexConstant -> (MM I.Const)
+convert_ComplexConstant (A.Cstruct b fs) = Md.liftM (I.C_struct b) (mapM convert_TypedConstOrNUll fs)
+convert_ComplexConstant (A.Cvector fs) = Md.liftM I.C_vector (mapM convert_TypedConstOrNUll fs)
+convert_ComplexConstant (A.Carray fs) = Md.liftM I.C_array (mapM convert_TypedConstOrNUll fs)
+
+
+data Binexp s v where {
+  Add :: (Maybe I.NoWrap) -> I.Type s I.I -> v -> v -> Binexp s v;
+  Sub :: (Maybe I.NoWrap) -> I.Type s I.I -> v -> v -> Binexp s v;
+  Mul :: (Maybe I.NoWrap) -> I.Type s I.I -> v -> v -> Binexp s v;
+  Udiv :: (Maybe I.Exact) -> I.Type s I.I -> v -> v -> Binexp s v;
+  Sdiv :: (Maybe I.Exact) -> I.Type s I.I -> v -> v -> Binexp s v;
+  Urem :: I.Type s I.I -> v -> v -> Binexp s v;
+  Srem :: I.Type s I.I -> v -> v -> Binexp s v;
+  Shl :: (Maybe I.NoWrap) -> I.Type s I.I -> v -> v -> Binexp s v;
+  Lshr :: (Maybe I.Exact) -> I.Type s I.I -> v -> v -> Binexp s v;
+  Ashr :: (Maybe I.Exact) -> I.Type s I.I -> v -> v -> Binexp s v;
+  And :: I.Type s I.I -> v -> v -> Binexp s v;
+  Or :: I.Type s I.I -> v -> v -> Binexp s v;
+  Xor :: I.Type s I.I -> v -> v -> Binexp s v;
+  } deriving (Eq, Ord, Show)
+
+data FBinexp s v where {
+  Fadd :: I.FastMathFlags -> I.Type s I.F -> v -> v -> FBinexp s v;
+  Fsub :: I.FastMathFlags -> I.Type s I.F -> v -> v -> FBinexp s v;
+  Fmul :: I.FastMathFlags -> I.Type s I.F -> v -> v -> FBinexp s v;
+  Fdiv :: I.FastMathFlags -> I.Type s I.F -> v -> v -> FBinexp s v;
+  Frem :: I.FastMathFlags -> I.Type s I.F -> v -> v -> FBinexp s v;
+  } deriving (Eq, Ord, Show)
+
+
+
+convert_to_Binexp :: (u -> MM v) -> A.IbinExpr u -> MM (Binexp I.ScalarB v)
+convert_to_Binexp cvt (A.IbinExpr op cs t u1 u2) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; let ta::I.Type I.ScalarB I.I = I.dcast FLC $ ((tconvert mp t)::I.Utype)
+     ; return (convert_IbinOp op cs ta u1a u2a)
+     }
+  where convert_IbinOp :: A.IbinOp -> [A.TrapFlag] -> I.Type I.ScalarB I.I -> v -> v -> Binexp I.ScalarB v
+        convert_IbinOp op cs = case op of
+          A.Add -> Add (getnowrap cs)
+          A.Sub -> Sub (getnowrap cs)
+          A.Mul -> Mul (getnowrap cs)
+          A.Udiv -> Udiv (getexact cs)
+          A.Sdiv -> Sdiv (getexact cs)
+          A.Shl -> Shl (getnowrap cs)
+          A.Lshr -> Lshr (getexact cs)
+          A.Ashr -> Ashr (getexact cs)
+          A.Urem -> Urem
+          A.Srem -> Srem
+          A.And -> And
+          A.Or -> Or
+          A.Xor -> Xor
+
+convert_to_Binexp_V :: (u -> MM v) -> A.IbinExpr u -> MM (Binexp I.VectorB v)
+convert_to_Binexp_V cvt (A.IbinExpr op cs t u1 u2) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; let ta::I.Type I.VectorB I.I = I.dcast FLC $ ((tconvert mp t)::I.Utype)
+     ; return (convert_IbinOp op cs ta u1a u2a)
+     }
+  where convert_IbinOp :: A.IbinOp -> [A.TrapFlag] -> I.Type I.VectorB I.I -> v -> v -> Binexp I.VectorB v
+        convert_IbinOp op cs = case op of
+          A.Add -> Add (getnowrap cs)
+          A.Sub -> Sub (getnowrap cs)
+          A.Mul -> Mul (getnowrap cs)
+          A.Udiv -> Udiv (getexact cs)
+          A.Sdiv -> Sdiv (getexact cs)
+          A.Shl -> Shl (getnowrap cs)
+          A.Lshr -> Lshr (getexact cs)
+          A.Ashr -> Ashr (getexact cs)
+          A.Urem -> Urem
+          A.Srem -> Srem
+          A.And -> And
+          A.Or -> Or
+          A.Xor -> Xor
+
+
+getnowrap :: [A.TrapFlag] -> Maybe I.NoWrap
+getnowrap x = case x of
+  [A.Nsw] -> Just I.Nsw
+  [A.Nuw] -> Just I.Nuw
+  [A.Nsw,A.Nuw] -> Just I.Nsuw
+  [A.Nuw,A.Nsw] -> Just I.Nsuw
+  [] -> Nothing
+  _ -> error ("irrefutable error1 " ++ show x)
+
+getexact :: [A.TrapFlag] -> Maybe I.Exact
+getexact x = case x of
+  [A.Exact] -> Just I.Exact
+  [] -> Nothing
+  _ -> error "irrefutable error2"
+
+
+convert_to_FBinexp :: (u -> MM v) -> A.FbinExpr u -> (MM (FBinexp I.ScalarB v))
+convert_to_FBinexp cvt (A.FbinExpr op cs t u1 u2) = 
+    do { mp <- typeDefs
+       ; u1a <- cvt u1
+       ; u2a <- cvt u2
+       ; let ta::I.Type I.ScalarB I.F = I.dcast FLC $ ((tconvert mp t)::I.Utype)
+       ; return ((convertFop op) cs ta u1a u2a)
+       }
+    where
+      convertFop o = case o of
+        A.Fadd -> Fadd
+        A.Fsub -> Fsub
+        A.Fmul -> Fmul
+        A.Fdiv -> Fdiv
+        A.Frem -> Frem
+
+
+convert_to_FBinexp_V :: (u -> MM v) -> A.FbinExpr u -> (MM (FBinexp I.VectorB v))
+convert_to_FBinexp_V cvt (A.FbinExpr op cs t u1 u2) = 
+    do { mp <- typeDefs
+       ; u1a <- cvt u1
+       ; u2a <- cvt u2
+       ; let ta::I.Type I.VectorB I.F = I.dcast FLC $ ((tconvert mp t)::I.Utype)
+       ; return ((convertFop op) cs ta u1a u2a)
+       }
+    where
+      convertFop o = case o of
+        A.Fadd -> Fadd
+        A.Fsub -> Fsub
+        A.Fmul -> Fmul
+        A.Fdiv -> Fdiv
+        A.Frem -> Frem
+
+
+convert_to_Conversion :: (u -> MM v) -> A.Conversion u -> (MM (I.Conversion I.ScalarB v))
+convert_to_Conversion cvt  (A.Conversion op (A.Typed t u) dt) = 
+    do { mp <- typeDefs
+       ; u1 <- cvt u 
+       ; let (t1::I.Utype) = tconvert mp t
+             (dt1::I.Utype) = tconvert mp dt
+             newOp = case op of
+               A.Trunc -> let (t2::I.Type I.ScalarB I.I) = I.dcast FLC t1
+                              (dt2::I.Type I.ScalarB I.I) = I.dcast FLC dt1
+                          in I.Trunc (I.T t2 u1) dt2
+               A.Zext -> let (t2::I.Type I.ScalarB I.I) = I.dcast FLC t1
+                             (dt2::I.Type I.ScalarB I.I) = I.dcast FLC dt1
+                         in I.Zext (I.T t2 u1) dt2 
+               A.Sext -> let (t2::I.Type I.ScalarB I.I) = I.dcast FLC t1
+                             (dt2::I.Type I.ScalarB I.I) = I.dcast FLC dt1
+                         in I.Sext (I.T t2 u1) dt2 
+               A.FpTrunc -> let (t2::I.Type I.ScalarB I.F) = I.dcast FLC t1
+                                (dt2::I.Type I.ScalarB I.F) = I.dcast FLC dt1
+                            in I.FpTrunc (I.T t2 u1) dt2 
+               A.FpExt -> let (t2::I.Type I.ScalarB I.F) = I.dcast FLC t1
+                              (dt2::I.Type I.ScalarB I.F) = I.dcast FLC dt1
+                          in I.FpExt (I.T t2 u1) dt2 
+               A.FpToUi -> let (t2::I.Type I.ScalarB I.F) = I.dcast FLC t1
+                               (dt2::I.Type I.ScalarB I.I) = I.dcast FLC dt1
+                           in I.FpToUi (I.T t2 u1) dt2 
+               A.FpToSi -> let (t2::I.Type I.ScalarB I.F) = I.dcast FLC t1
+                               (dt2::I.Type I.ScalarB I.I) = I.dcast FLC dt1
+                           in I.FpToSi (I.T t2 u1) dt2 
+               A.UiToFp -> let (t2::I.Type I.ScalarB I.I) = I.dcast FLC t1
+                               (dt2::I.Type I.ScalarB I.F) = I.dcast FLC dt1
+                           in I.UiToFp (I.T t2 u1) dt2 
+               A.SiToFp -> let (t2::I.Type I.ScalarB I.I) = I.dcast FLC t1
+                               (dt2::I.Type I.ScalarB I.F) = I.dcast FLC dt1
+                           in I.SiToFp (I.T t2 u1) dt2 
+               A.PtrToInt -> let (t2::I.Type I.ScalarB I.P) = I.dcast FLC t1
+                                 (dt2::I.Type I.ScalarB I.I) = I.dcast FLC dt1
+                             in I.PtrToInt (I.T t2 u1) dt2 
+               A.IntToPtr -> let (t2::I.Type I.ScalarB I.I) = I.dcast FLC t1
+                                 (dt2::I.Type I.ScalarB I.P) = I.dcast FLC dt1
+                             in I.IntToPtr (I.T t2 u1) dt2 
+               A.Bitcast -> let (t2::I.Dtype) = I.dcast FLC t1
+                                (dt2::I.Dtype) = I.dcast FLC dt1
+                            in I.Bitcast (I.T t2 u1) dt2 
+               A.AddrSpaceCast -> let (t2::I.Type I.ScalarB I.P) = I.dcast FLC t1
+                                      (dt2::I.Type I.ScalarB I.P) = I.dcast FLC dt1
+                                  in I.AddrSpaceCast (I.T t2 u1) dt2 
+       ; return newOp
+       }
+
+convert_to_Conversion_V :: (u -> MM v) -> A.Conversion u -> (MM (I.Conversion I.VectorB v))
+convert_to_Conversion_V cvt  (A.Conversion op (A.Typed t u) dt) = 
+    do { mp <- typeDefs
+       ; u1 <- cvt u 
+       ; let (t1::I.Utype) = tconvert mp t
+             (dt1::I.Utype) = tconvert mp dt
+             newOp = case op of
+               A.Trunc -> let (t2::I.Type I.VectorB I.I) = I.dcast FLC t1
+                              (dt2::I.Type I.VectorB I.I) = I.dcast FLC dt1
+                          in I.Trunc (I.T t2 u1) dt2
+               A.Zext -> let (t2::I.Type I.VectorB I.I) = I.dcast FLC t1
+                             (dt2::I.Type I.VectorB I.I) = I.dcast FLC dt1
+                         in I.Zext (I.T t2 u1) dt2 
+               A.Sext -> let (t2::I.Type I.VectorB I.I) = I.dcast FLC t1
+                             (dt2::I.Type I.VectorB I.I) = I.dcast FLC dt1
+                         in I.Sext (I.T t2 u1) dt2 
+               A.FpTrunc -> let (t2::I.Type I.VectorB I.F) = I.dcast FLC t1
+                                (dt2::I.Type I.VectorB I.F) = I.dcast FLC dt1
+                            in I.FpTrunc (I.T t2 u1) dt2 
+               A.FpExt -> let (t2::I.Type I.VectorB I.F) = I.dcast FLC t1
+                              (dt2::I.Type I.VectorB I.F) = I.dcast FLC dt1
+                          in I.FpExt (I.T t2 u1) dt2 
+               A.FpToUi -> let (t2::I.Type I.VectorB I.F) = I.dcast FLC t1
+                               (dt2::I.Type I.VectorB I.I) = I.dcast FLC dt1
+                           in I.FpToUi (I.T t2 u1) dt2 
+               A.FpToSi -> let (t2::I.Type I.VectorB I.F) = I.dcast FLC t1
+                               (dt2::I.Type I.VectorB I.I) = I.dcast FLC dt1
+                           in I.FpToSi (I.T t2 u1) dt2 
+               A.UiToFp -> let (t2::I.Type I.VectorB I.I) = I.dcast FLC t1
+                               (dt2::I.Type I.VectorB I.F) = I.dcast FLC dt1
+                           in I.UiToFp (I.T t2 u1) dt2 
+               A.SiToFp -> let (t2::I.Type I.VectorB I.I) = I.dcast FLC t1
+                               (dt2::I.Type I.VectorB I.F) = I.dcast FLC dt1
+                           in I.SiToFp (I.T t2 u1) dt2 
+               A.PtrToInt -> let (t2::I.Type I.VectorB I.P) = I.dcast FLC t1
+                                 (dt2::I.Type I.VectorB I.I) = I.dcast FLC dt1
+                             in I.PtrToInt (I.T t2 u1) dt2 
+               A.IntToPtr -> let (t2::I.Type I.VectorB I.I) = I.dcast FLC t1
+                                 (dt2::I.Type I.VectorB I.P) = I.dcast FLC dt1
+                             in I.IntToPtr (I.T t2 u1) dt2 
+               A.Bitcast -> let (t2::I.Dtype) = I.dcast FLC t1
+                                (dt2::I.Dtype) = I.dcast FLC dt1
+                            in I.Bitcast (I.T t2 u1) dt2 
+               A.AddrSpaceCast -> let (t2::I.Type I.VectorB I.P) = I.dcast FLC t1
+                                      (dt2::I.Type I.VectorB I.P) = I.dcast FLC dt1
+                                  in I.AddrSpaceCast (I.T t2 u1) dt2 
+       ; return newOp
+       }
+
+
+convert_to_GetElementPtr :: (u -> MM v) -> A.GetElementPtr u -> (MM (I.GetElementPtr I.ScalarB v))
+convert_to_GetElementPtr cvt (A.GetElementPtr b (A.Pointer (A.Typed t u)) us) = 
+  do { mp <- typeDefs
+     ; ua <- cvt u
+     ; let (ta::I.Type I.ScalarB I.P) = I.dcast FLC ((tconvert mp t)::I.Utype)
+     ; usa <- mapM convert_Tv_Tint us
+     ; return $ I.GetElementPtr b (I.T ta ua) usa
+     }
+  where
+    convert_Tv_Tint (A.Typed t v) = do { mp <- typeDefs
+                                       ; va <- cvt v
+                                       ; let (ta::I.Type I.ScalarB I.I) = I.dcast FLC ((tconvert mp t)::I.Utype)
+                                       ; return $ I.T ta va
+                                       }
+
+
+convert_to_GetElementPtr_V :: (u -> MM v) -> A.GetElementPtr u -> (MM (I.GetElementPtr I.VectorB v))
+convert_to_GetElementPtr_V cvt (A.GetElementPtr b (A.Pointer (A.Typed t u)) us) = 
+  do { mp <- typeDefs
+     ; ua <- cvt u
+     ; let (ta::I.Type I.VectorB I.P) = I.dcast FLC ((tconvert mp t)::I.Utype)
+     ; usa <- mapM (convert_Tv_Tint) us
+     ; return $ I.GetElementPtr b (I.T ta ua) usa
+     }
+  where
+    convert_Tv_Tint (A.Typed te v) = do { mp <- typeDefs
+                                        ; va <- cvt v
+                                        ; let (ta::I.Utype) = tconvert mp te
+                                        ; return $ I.T (I.dcast FLC ta) va
+                                        }
+
+
+cast_to_EitherScalarOrVectorI :: I.FileLoc -> I.T I.Utype v -> 
+                                 Either (I.T (I.Type I.ScalarB I.I) v) (I.T (I.Type I.VectorB I.I) v)
+cast_to_EitherScalarOrVectorI flc (I.T t v) = case t of
+  I.UtypeScalarI e -> Left $ I.T e v
+  I.UtypeVectorI e -> Right $ I.T e v
+  _ -> error "$$$$"
+  
+  
+convert_to_Select_I :: (u -> MM v) -> A.Select u -> (MM (I.Select I.ScalarB I.I v))
+convert_to_Select_I cvt (A.Select (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.ScalarB I.I) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.I) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.ScalarB I.I) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return $ I.Select (Left (I.T t1a u1a)) (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+convert_to_Select_VI :: (u -> MM v) -> A.Select u -> (MM (I.Select I.VectorB I.I v))
+convert_to_Select_VI cvt (A.Select (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let t1a = cast_to_EitherScalarOrVectorI FLC (I.T ((tconvert mp t1)::I.Utype) u1a)
+           (t2a::I.Type I.VectorB I.I) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.VectorB I.I) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return $ I.Select t1a (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+convert_to_Select_F :: (u -> MM v) -> A.Select u -> (MM (I.Select I.ScalarB I.F v))
+convert_to_Select_F cvt (A.Select (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.ScalarB I.I) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.F) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.ScalarB I.F) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return $ I.Select (Left (I.T t1a u1a)) (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+convert_to_Select_VF :: (u -> MM v) -> A.Select u -> (MM (I.Select I.VectorB I.F v))
+convert_to_Select_VF cvt (A.Select (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let t1a = cast_to_EitherScalarOrVectorI FLC (I.T ((tconvert mp t1)::I.Utype) u1a)
+           (t2a::I.Type I.VectorB I.F) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.VectorB I.F) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return $ I.Select t1a (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+convert_to_Select_P :: (u -> MM v) -> A.Select u -> (MM (I.Select I.ScalarB I.P v))
+convert_to_Select_P cvt (A.Select (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.ScalarB I.I) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.P) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.ScalarB I.P) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return $ I.Select (Left (I.T t1a u1a)) (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+
+convert_to_Select_VP :: (u -> MM v) -> A.Select u -> (MM (I.Select I.VectorB I.P v))
+convert_to_Select_VP cvt (A.Select (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let t1a = cast_to_EitherScalarOrVectorI FLC (I.T ((tconvert mp t1)::I.Utype) u1a)
+           (t2a::I.Type I.VectorB I.P) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.VectorB I.P) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return $ I.Select t1a (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+
+convert_to_Select_Record :: (u -> MM v) -> A.Select u -> (MM (I.Select I.FirstClassB I.D v))
+convert_to_Select_Record cvt (A.Select (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.ScalarB I.I) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.FirstClassB I.D) = I.squeeze FLC (I.dcast FLC ((tconvert mp t2)::I.Utype))
+           (t3a::I.Type I.FirstClassB I.D) = I.squeeze FLC (I.dcast FLC ((tconvert mp t3)::I.Utype))
+     ; return $ I.Select (Left (I.T t1a u1a)) (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+
+convert_to_Icmp :: (u -> MM v) -> A.Icmp u -> MM (I.Icmp I.ScalarB v)
+convert_to_Icmp cvt (A.Icmp op t u1 u2) = 
+  do { mp <- typeDefs
+     ; let (t1::I.IntOrPtrType I.ScalarB) = I.dcast FLC ((tconvert mp t)::I.Utype)
+     ; u1a <- cvt u1 
+     ; u2a <- cvt u2
+     ; return (I.Icmp op t1 u1a u2a)
+     }
+
+convert_to_Icmp_V :: (u -> MM v) -> A.Icmp u -> MM (I.Icmp I.VectorB v)
+convert_to_Icmp_V cvt (A.Icmp op t u1 u2) = 
+  do { mp <- typeDefs
+     ; let (t1::I.IntOrPtrType I.VectorB) = I.dcast FLC ((tconvert mp t)::I.Utype)
+     ; u1a <- cvt u1 
+     ; u2a <- cvt u2
+     ; return (I.Icmp op t1 u1a u2a)
+     }
+
+convert_to_Fcmp :: (u -> MM v) -> A.Fcmp u -> MM (I.Fcmp I.ScalarB v)
+convert_to_Fcmp cvt (A.Fcmp op t u1 u2) = 
+  do { mp <- typeDefs
+     ; let (t1::I.Type I.ScalarB I.F) = I.dcast FLC ((tconvert mp t)::I.Utype)
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; return (I.Fcmp op t1 u1a u2a)
+     }
+
+convert_to_Fcmp_V :: (u -> MM v) -> A.Fcmp u -> MM (I.Fcmp I.VectorB v)
+convert_to_Fcmp_V cvt (A.Fcmp op t u1 u2) = 
+  do { mp <- typeDefs
+     ; let (t1::I.Type I.VectorB I.F) = I.dcast FLC ((tconvert mp t)::I.Utype)
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; return (I.Fcmp op t1 u1a u2a)
+     }
+
+convert_to_ShuffleVector_I :: (u -> MM v) -> A.ShuffleVector u -> MM (I.ShuffleVector I.I v)
+convert_to_ShuffleVector_I cvt (A.ShuffleVector (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) =
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.VectorB I.I) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.VectorB I.I) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.VectorB I.I) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return (I.ShuffleVector (I.T t1a u1a) (I.T t2a u2a) (I.T t3a u3a))
+     }
+
+convert_to_ShuffleVector_F :: (u -> MM v) -> A.ShuffleVector u -> MM (I.ShuffleVector I.F v)
+convert_to_ShuffleVector_F cvt (A.ShuffleVector (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) =
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.VectorB I.F) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.VectorB I.F) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.VectorB I.I) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return (I.ShuffleVector (I.T t1a u1a) (I.T t2a u2a) (I.T t3a u3a))
+     }
+
+convert_to_ShuffleVector_P :: (u -> MM v) -> A.ShuffleVector u -> MM (I.ShuffleVector I.P v)
+convert_to_ShuffleVector_P cvt (A.ShuffleVector (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) =
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.VectorB I.P) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.VectorB I.P) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.VectorB I.I) = I.dcast FLC ((tconvert mp t3)::I.Utype)
+     ; return (I.ShuffleVector (I.T t1a u1a) (I.T t2a u2a) (I.T t3a u3a))
+     }
+
+convert_to_ExtractValue :: (u -> MM v) -> A.ExtractValue u -> MM (I.ExtractValue v)
+convert_to_ExtractValue cvt (A.ExtractValue (A.Typed t u) s) = 
+  do { mp <- typeDefs
+     ; let (ta::I.Type I.RecordB I.D) = I.dcast FLC ((tconvert mp t)::I.Utype)
+     ; ua <- cvt u 
+     ; return (I.ExtractValue (I.T ta ua) s)
+     }
+
+convert_to_InsertValue :: (u -> MM v) -> A.InsertValue u -> MM (I.InsertValue v)
+convert_to_InsertValue cvt (A.InsertValue (A.Typed t1 u1) (A.Typed t2 u2) s) = 
+  do { mp <- typeDefs
+     ; let (t1a::I.Type I.RecordB I.D) = I.dcast FLC ((tconvert mp t1)::I.Utype)
+           (t2a::I.Dtype) = I.dcast FLC ((tconvert mp t2)::I.Utype)
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; return $ I.InsertValue (I.T t1a u1a) (I.T t2a u2a) s
+     }
+
+convert_to_ExtractElement_I :: (u -> MM v) -> A.ExtractElement u -> MM (I.ExtractElement I.I v)
+convert_to_ExtractElement_I cvt (A.ExtractElement (A.Typed t1 u1) (A.Typed t2 u2)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; let (t1a::I.Type I.VectorB I.I) = I.dcast FLC $ ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.I) = I.dcast FLC $ ((tconvert mp t2)::I.Utype)
+     ; return $ I.ExtractElement (I.T t1a u1a) (I.T t2a u2a)
+     }
+
+convert_to_ExtractElement_F :: (u -> MM v) -> A.ExtractElement u -> MM (I.ExtractElement I.F v)
+convert_to_ExtractElement_F cvt (A.ExtractElement (A.Typed t1 u1) (A.Typed t2 u2)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; let (t1a::I.Type I.VectorB I.F) = I.dcast FLC $ ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.I) = I.dcast FLC $ ((tconvert mp t2)::I.Utype)
+     ; return $ I.ExtractElement (I.T t1a u1a) (I.T t2a u2a)
+     }
+
+convert_to_ExtractElement_P :: (u -> MM v) -> A.ExtractElement u -> MM (I.ExtractElement I.P v)
+convert_to_ExtractElement_P cvt (A.ExtractElement (A.Typed t1 u1) (A.Typed t2 u2)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; let (t1a::I.Type I.VectorB I.P) = I.dcast FLC $ ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.I) = I.dcast FLC $ ((tconvert mp t2)::I.Utype)
+     ; return $ I.ExtractElement (I.T t1a u1a) (I.T t2a u2a)
+     }
+
+convert_to_InsertElement_I :: (u -> MM v) -> A.InsertElement u ->  MM (I.InsertElement I.I v)
+convert_to_InsertElement_I cvt (A.InsertElement (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.VectorB I.I) = I.dcast FLC $ ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.I) = I.dcast FLC $ ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.ScalarB I.I) = I.dcast FLC $ ((tconvert mp t3)::I.Utype)
+     ; return $ I.InsertElement (I.T t1a u1a) (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+convert_to_InsertElement_F :: (u -> MM v) -> A.InsertElement u ->  MM (I.InsertElement I.F v)
+convert_to_InsertElement_F cvt (A.InsertElement (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.VectorB I.F) = I.dcast FLC $ ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.F) = I.dcast FLC $ ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.ScalarB I.I) = I.dcast FLC $ ((tconvert mp t3)::I.Utype)
+     ; return $ I.InsertElement (I.T t1a u1a) (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+convert_to_InsertElement_P :: (u -> MM v) -> A.InsertElement u ->  MM (I.InsertElement I.P v)
+convert_to_InsertElement_P cvt (A.InsertElement (A.Typed t1 u1) (A.Typed t2 u2) (A.Typed t3 u3)) = 
+  do { mp <- typeDefs
+     ; u1a <- cvt u1
+     ; u2a <- cvt u2
+     ; u3a <- cvt u3
+     ; let (t1a::I.Type I.VectorB I.P) = I.dcast FLC $ ((tconvert mp t1)::I.Utype)
+           (t2a::I.Type I.ScalarB I.P) = I.dcast FLC $ ((tconvert mp t2)::I.Utype)
+           (t3a::I.Type I.ScalarB I.I) = I.dcast FLC $ ((tconvert mp t3)::I.Utype)
+     ; return $ I.InsertElement (I.T t1a u1a) (I.T t2a u2a) (I.T t3a u3a)
+     }
+
+
+convert_SimpleConst :: A.SimpleConstant -> I.Const
+convert_SimpleConst x = case x of
+  A.CpInt s -> I.C_int s
+  A.CpUhexInt s -> I.C_uhex_int s
+  A.CpShexInt s -> I.C_shex_int s
+  A.CpFloat s -> I.C_float s
+  A.CpNull -> I.C_null
+  A.CpUndef -> I.C_undef
+  A.CpTrue -> I.C_true
+  A.CpFalse -> I.C_false
+  A.CpZeroInitializer -> I.C_zeroinitializer
+  A.CpGlobalAddr s -> I.C_globalAddr s
+  A.CpStr s -> I.C_str s
+  A.CpBconst s -> convert_Bconst s
+  
+convert_Bconst :: A.BinaryConstant -> I.Const  
+convert_Bconst x = case x of
+  A.BconstUint8 s -> I.C_u8 s
+  A.BconstUint16 s -> I.C_u16 s
+  A.BconstUint32 s -> I.C_u32 s
+  A.BconstUint64 s -> I.C_u64 s
+  A.BconstUint96 s -> I.C_u96 s
+  A.BconstUint128 s -> I.C_u128 s
+  A.BconstInt8 s -> I.C_s8 s
+  A.BconstInt16 s -> I.C_s16 s
+  A.BconstInt32 s -> I.C_s32 s
+  A.BconstInt64 s -> I.C_s64 s
+  A.BconstInt96 s -> I.C_s96 s
+  A.BconstInt128 s -> I.C_s128 s
+
+convert_Const :: A.Const -> MM I.Const
+convert_Const x = 
+  let cvt = convert_Const
+  in case x of
+    A.C_simple a -> return $ convert_SimpleConst a
+    A.C_complex a -> convert_ComplexConstant a
+    A.C_localId a -> return $ I.C_localId a
+    A.C_labelId a -> Md.liftM I.C_labelId (convert_LabelId a)
+    A.C_blockAddress g a -> do { a' <- convert_PercentLabel a
+                              ; return $ I.C_block g a'
+                              }
+    A.C_binexp (A.Ie a@(A.IbinExpr _ _ t _ _)) -> 
+      do { mp <- typeDefs
+         ; if isTvector mp t then
+             do { x <- convert_to_Binexp_V cvt a 
+                ; let y = case x of
+                        Add n ta v1a v2a -> I.C_add_V n ta v1a v2a
+                        Sub n ta v1a v2a -> I.C_sub_V n ta v1a v2a
+                        Mul n ta v1a v2a -> I.C_mul_V n ta v1a v2a
+                        Udiv n ta v1a v2a -> I.C_udiv_V n ta v1a v2a
+                        Sdiv n ta v1a v2a -> I.C_sdiv_V n ta v1a v2a
+                        Urem ta v1a v2a -> I.C_urem_V ta v1a v2a
+                        Srem ta v1a v2a -> I.C_srem_V ta v1a v2a
+                        Shl n ta v1a v2a -> I.C_shl_V n ta v1a v2a
+                        Lshr n ta v1a v2a -> I.C_lshr_V n ta v1a v2a
+                        Ashr n ta v1a v2a -> I.C_ashr_V n ta v1a v2a
+                        And ta v1a v2a -> I.C_and_V ta v1a v2a
+                        Or ta v1a v2a -> I.C_or_V ta v1a v2a
+                        Xor ta v1a v2a -> I.C_xor_V ta v1a v2a
+                ; return y 
+                }
+           else
+             do { x <- convert_to_Binexp cvt a 
+                ; let y = case x of
+                        Add n ta v1a v2a -> I.C_add n ta v1a v2a
+                        Sub n ta v1a v2a -> I.C_sub n ta v1a v2a
+                        Mul n ta v1a v2a -> I.C_mul n ta v1a v2a
+                        Udiv n ta v1a v2a -> I.C_udiv n ta v1a v2a
+                        Sdiv n ta v1a v2a -> I.C_sdiv n ta v1a v2a
+                        Urem ta v1a v2a -> I.C_urem ta v1a v2a
+                        Srem ta v1a v2a -> I.C_srem ta v1a v2a
+                        Shl n ta v1a v2a -> I.C_shl n ta v1a v2a
+                        Lshr n ta v1a v2a -> I.C_lshr n ta v1a v2a
+                        Ashr n ta v1a v2a -> I.C_ashr n ta v1a v2a
+                        And ta v1a v2a -> I.C_and ta v1a v2a
+                        Or ta v1a v2a -> I.C_or ta v1a v2a
+                        Xor ta v1a v2a -> I.C_xor ta v1a v2a
+                ; return y 
+                }
+         }
+    A.C_binexp (A.Fe a@(A.FbinExpr _ _ t _ _)) -> 
+      do { mp <- typeDefs
+         ; if isTvector mp t then
+             do { x <- convert_to_FBinexp_V cvt a
+                ; let y = case x of
+                        Fadd n ta v1a v2a -> I.C_fadd_V n ta v1a v2a
+                        Fsub n ta v1a v2a -> I.C_fsub_V n ta v1a v2a
+                        Fmul n ta v1a v2a -> I.C_fmul_V n ta v1a v2a
+                        Fdiv n ta v1a v2a -> I.C_fdiv_V n ta v1a v2a
+                        Frem n ta v1a v2a -> I.C_frem_V n ta v1a v2a
+                ; return y 
+                }
+           else
+             do { x <- convert_to_FBinexp cvt a
+                ; let y = case x of
+                        Fadd n ta v1a v2a -> I.C_fadd n ta v1a v2a
+                        Fsub n ta v1a v2a -> I.C_fsub n ta v1a v2a
+                        Fmul n ta v1a v2a -> I.C_fmul n ta v1a v2a
+                        Fdiv n ta v1a v2a -> I.C_fdiv n ta v1a v2a
+                        Frem n ta v1a v2a -> I.C_frem n ta v1a v2a
+                ; return y 
+                }
+         }
+    A.C_conv a ->
+      do { mp <- typeDefs
+         ; if conversionIsTvector mp a then
+             do { x <- convert_to_Conversion_V cvt a
+                ; let y = case x of
+                        I.Trunc tv dt -> I.C_trunc_V tv dt
+                        I.Zext tv dt -> I.C_zext_V tv dt
+                        I.Sext tv dt -> I.C_sext_V tv dt
+                        I.FpTrunc tv dt -> I.C_fptrunc_V tv dt
+                        I.FpExt tv dt -> I.C_fpext_V tv dt
+                        I.FpToUi tv dt -> I.C_fptoui_V tv dt
+                        I.FpToSi tv dt -> I.C_fptosi_V tv dt
+                        I.UiToFp tv dt -> I.C_uitofp_V tv dt
+                        I.SiToFp tv dt -> I.C_sitofp_V tv dt
+                        I.PtrToInt tv dt -> I.C_ptrtoint_V tv dt
+                        I.IntToPtr tv dt -> I.C_inttoptr_V tv dt
+                        I.Bitcast tv dt -> I.C_bitcast tv dt
+                        I.AddrSpaceCast tv dt -> I.C_addrspacecast_V tv dt 
+                ; return y
+                }
+           else
+             do { x <- convert_to_Conversion cvt a
+                ; let y = case x of
+                        I.Trunc tv dt -> I.C_trunc tv dt
+                        I.Zext tv dt -> I.C_zext tv dt
+                        I.Sext tv dt -> I.C_sext tv dt
+                        I.FpTrunc tv dt -> I.C_fptrunc tv dt
+                        I.FpExt tv dt -> I.C_fpext tv dt
+                        I.FpToUi tv dt -> I.C_fptoui tv dt
+                        I.FpToSi tv dt -> I.C_fptosi tv dt
+                        I.UiToFp tv dt -> I.C_uitofp tv dt
+                        I.SiToFp tv dt -> I.C_sitofp tv dt
+                        I.PtrToInt tv dt -> I.C_ptrtoint tv dt
+                        I.IntToPtr tv dt -> I.C_inttoptr tv dt
+                        I.Bitcast tv dt -> I.C_bitcast tv dt
+                        I.AddrSpaceCast tv dt -> I.C_addrspacecast tv dt 
+                ; return y
+                }
+         }
+    A.C_gep a -> 
+      do { mp <- typeDefs
+         ; if getElemPtrIsTvector mp a then 
+             do { (I.GetElementPtr b t idx) <- convert_to_GetElementPtr_V convert_Const a
+                ; return $ I.C_getelementptr_V b t idx
+                }
+           else 
+             do { (I.GetElementPtr b t idx) <- convert_to_GetElementPtr convert_Const a
+                ; return $ I.C_getelementptr b t idx
+                }
+         }
+    A.C_select a@(A.Select _ (A.Typed t _) _) -> 
+      do { mp <- typeDefs
+         ; case matchType mp t of
+           Tk_VectorI -> Md.liftM I.C_select_VI (convert_to_Select_VI cvt a)
+           Tk_ScalarI -> Md.liftM I.C_select_I (convert_to_Select_I cvt a)
+           Tk_VectorF -> Md.liftM I.C_select_VF (convert_to_Select_VF cvt a)
+           Tk_ScalarF -> Md.liftM I.C_select_F (convert_to_Select_F cvt a)
+           Tk_VectorP -> Md.liftM I.C_select_VP (convert_to_Select_VP cvt a)
+           Tk_ScalarP -> Md.liftM I.C_select_P (convert_to_Select_P cvt a)
+           Tk_RecordD -> do { (I.Select (Left cnd) t f) <- convert_to_Select_Record cvt a 
+                            ; return $ I.C_select_First cnd t f
+                            }
+         }
+    A.C_icmp a@(A.Icmp _ t _ _) -> 
+      do { mp <- typeDefs
+         ; if isTvector mp t then Md.liftM I.C_icmp_V (convert_to_Icmp_V cvt a)
+           else Md.liftM I.C_icmp (convert_to_Icmp cvt a)
+         }
+    A.C_fcmp a@(A.Fcmp _ t _ _) -> 
+      do { mp <- typeDefs
+         ; if isTvector mp t then Md.liftM I.C_fcmp_V (convert_to_Fcmp_V cvt a)
+           else Md.liftM I.C_fcmp (convert_to_Fcmp cvt a)
+         }
+    A.C_shufflevector a@(A.ShuffleVector (A.Typed t _) _ _) -> 
+      do { mp <- typeDefs
+         ; case matchType mp t of
+           Tk_VectorI -> Md.liftM I.C_shufflevector_I (convert_to_ShuffleVector_I cvt a)
+           Tk_VectorF -> Md.liftM I.C_shufflevector_F (convert_to_ShuffleVector_F cvt a)
+           Tk_VectorP -> Md.liftM I.C_shufflevector_P (convert_to_ShuffleVector_P cvt a)
+         }
+    A.C_extractvalue a -> Md.liftM I.C_extractvalue (convert_to_ExtractValue cvt a)
+    A.C_insertvalue a -> Md.liftM I.C_insertvalue (convert_to_InsertValue cvt a)
+    A.C_extractelement a@(A.ExtractElement (A.Typed t _) _) -> 
+      do { mp <- typeDefs
+         ; case matchType mp t of
+           Tk_VectorI -> Md.liftM I.C_extractelement_I (convert_to_ExtractElement_I cvt a)
+           Tk_VectorF -> Md.liftM I.C_extractelement_F (convert_to_ExtractElement_F cvt a)
+           Tk_VectorP -> Md.liftM I.C_extractelement_P (convert_to_ExtractElement_P cvt a)
+         }
+    A.C_insertelement a@(A.InsertElement (A.Typed t _) _ _) -> 
+      do { mp <- typeDefs
+         ; case matchType mp t of
+           Tk_VectorI -> Md.liftM I.C_insertelement_I (convert_to_InsertElement_I cvt a)
+           Tk_VectorF -> Md.liftM I.C_insertelement_F (convert_to_InsertElement_F cvt a)
+           Tk_VectorP -> Md.liftM I.C_insertelement_P (convert_to_InsertElement_P cvt a)
+         }
+        
+convert_MdVar :: A.MdVar -> (MM I.MdVar)
+convert_MdVar (A.MdVar s) = return $ I.MdVar s
+
+convert_MdNode :: A.MdNode -> (MM I.MdNode)
+convert_MdNode (A.MdNode s) = return $ I.MdNode s
+
+convert_MetaConst :: A.MetaConst -> (MM I.MetaConst)
+convert_MetaConst (A.McStruct c) = Md.liftM I.McStruct (mapM convert_MetaKindedConst c)
+convert_MetaConst (A.McString s) = return $ I.McString s
+convert_MetaConst (A.McMn n) = Md.liftM I.McMn (convert_MdNode n)
+convert_MetaConst (A.McMv n) = Md.liftM I.McMv (convert_MdVar n)
+convert_MetaConst (A.McRef i) = return $ I.McRef i
+convert_MetaConst (A.McSimple sc) = Md.liftM I.McSimple (convert_Const sc)
+
+convert_MetaKindedConst :: A.MetaKindedConst -> MM I.MetaKindedConst
+convert_MetaKindedConst x = 
+  do { mp <- typeDefs
+     ; case x of
+       (A.MetaKindedConst mk mc) -> Md.liftM (I.MetaKindedConst (tconvert mp mk)) (convert_MetaConst mc)
+       A.UnmetaKindedNull -> return I.UnmetaKindedNull
+     }
+
+
+
+convert_FunName :: A.FunName -> (MM I.FunName)
+convert_FunName (A.FunNameGlobal g) = return $ I.FunNameGlobal g
+convert_FunName (A.FunNameString s) = return $ I.FunNameString s
+
+convert_Value :: A.Value -> (MM I.Value)
+convert_Value (A.Val_local a) = return $ I.Val_ssa a
+convert_Value (A.Val_const a) = Md.liftM I.Val_const (convert_Const a)
+
+convert_to_CallSite :: A.CallSite -> MM (Bool, I.CallSite)
+convert_to_CallSite x = case x of
+  (A.CsFun cc pa t fn aps fa) ->
+    do { mp <- typeDefs
+       ; let ert = A.splitCallReturnType t
+             erta = eitherRet mp ert
+       ; fna <- convert_FunName fn
+       ; apsa <- mapM convert_ActualParam aps
+       ; return (fst ert == A.Tvoid, I.CsFun cc pa erta fna apsa fa)
+       }
+  (A.CsAsm t dia b1 b2 qs1 qs2 as fa) ->
+    do { mp <- typeDefs
+       ; let ert = A.splitCallReturnType t
+             erta = eitherRet mp ert
+       ; asa <- mapM convert_ActualParam as
+       ; return (fst ert == A.Tvoid, I.CsAsm erta dia b1 b2 qs1 qs2 asa fa)
+       }
+  (A.CsConversion pa t cv as fa) ->
+    do { mp <- typeDefs
+       ; let ert = A.splitCallReturnType t
+             erta = eitherRet mp ert
+       ; asa <- mapM convert_ActualParam as
+       ; if isTvector mp t then 
+           do { cva <- convert_to_Conversion_V convert_Const cv
+              ; return (fst ert == A.Tvoid, I.CsConversionV pa erta cva asa fa)
+              }
+         else
+           do { cva <- convert_to_Conversion convert_Const cv
+              ; return (fst ert == A.Tvoid, I.CsConversion pa erta cva asa fa)
+              }
+       }
+  where eitherRet :: MP -> (A.Type, Maybe (A.Type, A.AddrSpace)) -> I.CallSiteType
+        eitherRet mp (rt, ft) = case ft of
+            Just (fta,as) -> I.CallSiteFun (I.dcast FLC ((tconvert mp fta)::I.Utype)) (tconvert mp as)
+            Nothing -> I.CallSiteRet $ I.dcast FLC ((tconvert mp rt)::I.Utype)
+
+convert_Clause :: A.Clause -> MM I.Clause
+convert_Clause x = case x of 
+  (A.Catch (A.Typed t v)) -> do { mp <- typeDefs
+                                ; let (ti::I.Dtype) = I.dcast FLC ((tconvert mp t)::I.Utype)
+                                ; vi <- convert_Value v
+                                ; return $ I.Catch (I.T ti vi)
+                                }
+  (A.Filter tc) -> Md.liftM I.Filter (convert_TypedConstOrNUll tc)
+  (A.Cco tc) ->  
+    do { mp <- typeDefs
+       ; if conversionIsTvector mp tc then Md.liftM I.CcoV (convert_to_Conversion_V convert_Value tc)
+         else Md.liftM I.CcoS (convert_to_Conversion convert_Value tc)
+       }
+
+
+convert_GlobalOrLocalId :: A.GlobalOrLocalId -> (MM I.GlobalOrLocalId)
+convert_GlobalOrLocalId = return
+
+convert_PersFn :: A.PersFn -> MM I.PersFn
+convert_PersFn (A.PersFnId s) = return $ I.PersFnId s
+convert_PersFn (A.PersFnCast c) = 
+  do { mp <- typeDefs
+     ; if conversionIsTvector mp c then Md.liftM I.PersFnCastV (convert_to_Conversion_V convert_GlobalOrLocalId c)
+       else Md.liftM I.PersFnCastS (convert_to_Conversion convert_GlobalOrLocalId c)
+     }
+convert_PersFn (A.PersFnUndef) = return $ I.PersFnUndef
+convert_PersFn (A.PersFnNull) = return $ I.PersFnNull
+convert_PersFn (A.PersFnConst c) = Md.liftM I.PersFnConst (convert_Const c)
+
+
+convert_Expr_CInst :: (Maybe A.LocalId, A.Expr) -> (MM I.CInst)
+convert_Expr_CInst (Just lhs, A.EgEp c) = 
+  do { mp <- typeDefs
+     ; if getElemPtrIsTvector mp c then 
+         do { (I.GetElementPtr b t idx) <- convert_to_GetElementPtr_V convert_Value c
+            ; return $ I.I_getelementptr_V b t idx lhs
+            }
+       else 
+         do { (I.GetElementPtr b t idx) <- convert_to_GetElementPtr convert_Value c
+            ; return $ I.I_getelementptr b t idx lhs
+            }
+     }
+convert_Expr_CInst (Just lhs, A.EiC a@(A.Icmp _ t _ _)) = 
+  do { mp <- typeDefs
+     ; if isTvector mp t then 
+         do { (I.Icmp op ta v1a v2a) <- convert_to_Icmp_V convert_Value a
+            ; return $ I.I_icmp_V op ta v1a v2a lhs
+            }
+       else 
+         do { (I.Icmp op ta v1a v2a) <- convert_to_Icmp convert_Value a
+            ; return $ I.I_icmp op ta v1a v2a lhs
+            }
+     }
+convert_Expr_CInst (Just lhs, A.EfC a@(A.Fcmp _ t _ _)) = 
+  do { mp <- typeDefs
+     ; if isTvector mp t then 
+         do { (I.Fcmp op ta v1a v2a) <- convert_to_Fcmp_V convert_Value a
+            ; return $ I.I_fcmp_V op ta v1a v2a lhs
+            }
+       else 
+         do { (I.Fcmp op ta v1a v2a) <- convert_to_Fcmp convert_Value a
+            ; return $ I.I_fcmp op ta v1a v2a lhs
+            }
+     }
+convert_Expr_CInst (Just lhs, A.Eb (A.Ie a@(A.IbinExpr _ _ t _ _))) = 
+  do { mp <- typeDefs
+     ; if not $ isTvector mp t then 
+         do { x <- convert_to_Binexp convert_Value a 
+            ; let y = case x of
+                    Add n ta v1a v2a -> I.I_add n ta v1a v2a lhs
+                    Sub n ta v1a v2a -> I.I_sub n ta v1a v2a lhs 
+                    Mul n ta v1a v2a -> I.I_mul n ta v1a v2a lhs
+                    Udiv n ta v1a v2a -> I.I_udiv n ta v1a v2a lhs
+                    Sdiv n ta v1a v2a -> I.I_sdiv n ta v1a v2a lhs
+                    Urem ta v1a v2a -> I.I_urem ta v1a v2a lhs
+                    Srem ta v1a v2a -> I.I_srem ta v1a v2a lhs
+                    Shl n ta v1a v2a -> I.I_shl n ta v1a v2a lhs
+                    Lshr n ta v1a v2a -> I.I_lshr n ta v1a v2a lhs
+                    Ashr n ta v1a v2a -> I.I_ashr n ta v1a v2a lhs
+                    And ta v1a v2a -> I.I_and ta v1a v2a lhs
+                    Or ta v1a v2a -> I.I_or ta v1a v2a lhs
+                    Xor ta v1a v2a -> I.I_xor ta v1a v2a lhs
+            ; return y 
+            }
+       else 
+         do { x <- convert_to_Binexp_V convert_Value a 
+            ; let y = case x of
+                    Add n ta v1a v2a -> I.I_add_V n ta v1a v2a lhs
+                    Sub n ta v1a v2a -> I.I_sub_V n ta v1a v2a lhs
+                    Mul n ta v1a v2a -> I.I_mul_V n ta v1a v2a lhs
+                    Udiv n ta v1a v2a -> I.I_udiv_V n ta v1a v2a lhs
+                    Sdiv n ta v1a v2a -> I.I_sdiv_V n ta v1a v2a lhs
+                    Urem ta v1a v2a -> I.I_urem_V ta v1a v2a lhs
+                    Srem ta v1a v2a -> I.I_srem_V ta v1a v2a lhs
+                    Shl n ta v1a v2a -> I.I_shl_V n ta v1a v2a lhs
+                    Lshr n ta v1a v2a -> I.I_lshr_V n ta v1a v2a lhs
+                    Ashr n ta v1a v2a -> I.I_ashr_V n ta v1a v2a lhs
+                    And ta v1a v2a -> I.I_and_V ta v1a v2a lhs
+                    Or ta v1a v2a -> I.I_or_V ta v1a v2a lhs
+                    Xor ta v1a v2a -> I.I_xor_V ta v1a v2a lhs
+            ; return y 
+            }
+     }
+convert_Expr_CInst (Just lhs, A.Eb (A.Fe a@(A.FbinExpr _ _ t _ _))) = 
+  do { mp <- typeDefs
+     ; if not $ isTvector mp t then 
+       do { x <- convert_to_FBinexp convert_Value a
+          ; let y = case x of
+                  Fadd n ta v1a v2a -> I.I_fadd n ta v1a v2a lhs
+                  Fsub n ta v1a v2a -> I.I_fsub n ta v1a v2a lhs
+                  Fmul n ta v1a v2a -> I.I_fmul n ta v1a v2a lhs
+                  Fdiv n ta v1a v2a -> I.I_fdiv n ta v1a v2a lhs
+                  Frem n ta v1a v2a -> I.I_frem n ta v1a v2a lhs
+          ; return y 
+          }
+     else
+       do { x <- convert_to_FBinexp_V convert_Value a
+          ; let y = case x of
+                  Fadd n ta v1a v2a -> I.I_fadd_V n ta v1a v2a lhs
+                  Fsub n ta v1a v2a -> I.I_fsub_V n ta v1a v2a lhs
+                  Fmul n ta v1a v2a -> I.I_fmul_V n ta v1a v2a lhs
+                  Fdiv n ta v1a v2a -> I.I_fdiv_V n ta v1a v2a lhs
+                  Frem n ta v1a v2a -> I.I_frem_V n ta v1a v2a lhs
+          ; return y
+          }
+   }
+convert_Expr_CInst (Just lhs, A.Ec a) =  
+  do { mp <- typeDefs
+     ; if not $ conversionIsTvector mp a then 
+         do { x <- convert_to_Conversion convert_Value a
+            ; let y = case x of
+                   I.Trunc tv dt -> I.I_trunc tv dt lhs
+                   I.Zext tv dt -> I.I_zext tv dt lhs
+                   I.Sext tv dt -> I.I_sext tv dt lhs
+                   I.FpTrunc tv dt -> I.I_fptrunc tv dt lhs
+                   I.FpExt tv dt -> I.I_fpext tv dt lhs
+                   I.FpToUi tv dt -> I.I_fptoui tv dt lhs
+                   I.FpToSi tv dt -> I.I_fptosi tv dt lhs
+                   I.UiToFp tv dt -> I.I_uitofp tv dt lhs
+                   I.SiToFp tv dt -> I.I_sitofp tv dt lhs
+                   I.PtrToInt tv dt -> I.I_ptrtoint tv dt lhs
+                   I.IntToPtr tv dt -> I.I_inttoptr tv dt lhs
+                   I.Bitcast tv@(I.T st v) dt -> case (st, dt) of
+                     (I.DtypeScalarP sta, I.DtypeScalarP dta) -> I.I_bitcast (I.T sta v) dta lhs
+                     (_,_) -> I.I_bitcast_D tv dt lhs
+                   I.AddrSpaceCast tv dt -> I.I_addrspacecast tv dt lhs
+           ; return y 
+           }
+       else 
+         do { x <- convert_to_Conversion_V convert_Value a
+            ; let y = case x of
+                   I.Trunc tv dt -> I.I_trunc_V tv dt lhs
+                   I.Zext tv dt -> I.I_zext_V tv dt lhs
+                   I.Sext tv dt -> I.I_sext_V tv dt lhs
+                   I.FpTrunc tv dt -> I.I_fptrunc_V tv dt lhs
+                   I.FpExt tv dt -> I.I_fpext_V tv dt lhs
+                   I.FpToUi tv dt -> I.I_fptoui_V tv dt lhs
+                   I.FpToSi tv dt -> I.I_fptosi_V tv dt lhs
+                   I.UiToFp tv dt -> I.I_uitofp_V tv dt lhs
+                   I.SiToFp tv dt -> I.I_sitofp_V tv dt lhs
+                   I.PtrToInt tv dt -> I.I_ptrtoint_V tv dt lhs
+                   I.IntToPtr tv dt -> I.I_inttoptr_V tv dt lhs
+                   I.Bitcast tv@(I.T st v) dt -> case (st, dt) of
+                     (I.DtypeScalarP sta, I.DtypeScalarP dta) -> I.I_bitcast (I.T sta v) dta lhs
+                     (_,_) -> I.I_bitcast_D tv dt lhs
+                   I.AddrSpaceCast tv dt -> I.I_addrspacecast_V tv dt lhs
+           ; return y
+           }
+     }
+convert_Expr_CInst (Just lhs, A.Es a@(A.Select _ (A.Typed t _) _)) = 
+  do { mp <- typeDefs
+     ; case matchType mp t of
+       Tk_ScalarI -> do { (I.Select (Left cnd) t f) <- convert_to_Select_I convert_Value a
+                        ; return $ I.I_select_I cnd t f lhs
+                        }
+       Tk_ScalarF -> do { (I.Select (Left cnd) t f) <- convert_to_Select_F convert_Value a
+                        ; return $ I.I_select_F cnd t f lhs
+                        }
+       Tk_ScalarP -> do { (I.Select (Left cnd) t f) <- convert_to_Select_P convert_Value a
+                        ; return $ I.I_select_P cnd t f lhs
+                        }
+       Tk_RecordD -> do { (I.Select (Left cnd) t f) <- convert_to_Select_Record convert_Value a
+                        ; return $ I.I_select_First cnd t f lhs
+                        }
+       Tk_VectorI -> do { (I.Select cnd t f) <- convert_to_Select_VI convert_Value a
+                        ; return $ I.I_select_VI cnd t f lhs
+                        }
+       Tk_VectorF -> do { (I.Select cnd t f) <- convert_to_Select_VF convert_Value a
+                        ; return $ I.I_select_VF cnd t f lhs
+                        }
+       Tk_VectorP -> do { (I.Select cnd t f) <- convert_to_Select_VP convert_Value a
+                        ; return $ I.I_select_VP cnd t f lhs
+                        }
+     }
+
+
+convert_MemOp :: (Maybe A.LocalId, A.MemOp) -> (MM I.CInst)
+convert_MemOp (mlhs, c) = case (mlhs, c) of
+  (Just lhs, A.Alloca mar t mtv ma) -> 
+    do { mp <- typeDefs
+       ; ti <- convert_Type_Dtype FLC t
+       ; mtvi <- maybeM (convert_to_TypedValue_SI FLC) mtv
+       ; return (I.I_alloca mar ti mtvi ma lhs)
+       }
+  (Just lhs, A.Load atom (A.Pointer tv) aa nonterm inv nonul) -> 
+    do { tvi <- convert_to_TypedAddrValue FLC tv
+       ; return (I.I_load atom tvi aa nonterm inv nonul lhs)
+       }
+  (Just lhs, A.LoadAtomic  at v (A.Pointer tv) aa) -> 
+    do { tvi <- convert_to_TypedAddrValue FLC tv
+       ; return (I.I_loadatomic at v tvi aa lhs)
+       }
+  (Nothing, A.Store atom tv1 (A.Pointer tv2) aa nt) -> 
+    do { tv1a <- convert_to_DtypedValue tv1
+       ; tv2a <- convert_to_TypedAddrValue FLC tv2
+       ; return $ I.I_store atom tv1a tv2a aa nt
+       }
+  (Nothing, A.StoreAtomic atom v tv1 (A.Pointer tv2) aa) -> 
+    do { tv1a <- convert_to_DtypedValue tv1
+       ; tv2a <- convert_to_TypedAddrValue FLC tv2
+       ; return $ I.I_storeatomic atom v tv1a tv2a aa
+       }
+  (Nothing, A.Fence  b fo) -> return $ I.I_fence b fo
+  (Just lhs, A.CmpXchg wk b1 (A.Pointer tv1) tv2@(A.Typed t2 _) tv3 b2 mf ff) -> 
+    do { mp <- typeDefs
+       ; tv1a <- convert_to_TypedAddrValue FLC tv1
+       ; case matchType mp t2 of
+         Tk_ScalarI -> do { tv2a <- convert_to_TypedValue_SI FLC tv2
+                          ; tv3a <- convert_to_TypedValue_SI FLC tv3
+                          ; return $ I.I_cmpxchg_I wk b1 tv1a tv2a tv3a b2 mf ff lhs
+                          }
+         Tk_ScalarF -> do { tv2a <- convert_to_TypedValue_SF FLC tv2
+                          ; tv3a <- convert_to_TypedValue_SF FLC tv3
+                          ; return $ I.I_cmpxchg_F wk b1 tv1a tv2a tv3a b2 mf ff lhs
+                          }
+         Tk_ScalarP -> do { tv2a <- convert_to_TypedValue_SP FLC tv2
+                          ; tv3a <- convert_to_TypedValue_SP FLC tv3
+                          ; return $ I.I_cmpxchg_P wk b1 tv1a tv2a tv3a b2 mf ff lhs
+                          }
+       }
+  (Just lhs, A.AtomicRmw b1 op (A.Pointer tv1) tv2 b2 mf) -> 
+    do { tv1a <- convert_to_TypedAddrValue FLC tv1
+       ; tv2a <- convert_to_TypedValue_SI FLC tv2
+       ; return $ I.I_atomicrmw b1 op tv1a tv2a b2 mf lhs
+       }
+  (_,_) -> error $ "AstIrConversion:irrefutable lhs:" ++ show mlhs ++ " rhs:" ++ show c
+
+convert_to_DtypedValue :: A.Typed A.Value -> MM (I.T I.Dtype I.Value)
+convert_to_DtypedValue (A.Typed t v) = do { mp <- typeDefs
+                                          ; let (ti::I.Dtype) = I.dcast FLC ((tconvert mp t)::I.Utype)
+                                          ; vi <- convert_Value v 
+                                          ; return $ I.T ti vi
+                                          }
+                                              
+convert_to_DtypedConst :: A.Typed A.Const -> MM (I.T I.Dtype I.Const)
+convert_to_DtypedConst (A.Typed t v) = do { mp <- typeDefs
+                                          ; let (ti::I.Dtype) = I.dcast FLC ((tconvert mp t)::I.Utype)
+                                          ; vi <- convert_Const v 
+                                          ; return $ I.T ti vi
+                                          }
+
+
+convert_to_TypedValue_SI :: I.FileLoc -> A.Typed A.Value -> MM (I.T (I.Type I.ScalarB I.I) I.Value)
+convert_to_TypedValue_SI lc (A.Typed t v) = do { mp <- typeDefs
+                                               ; let (ti::I.Type I.ScalarB I.I) = I.dcast lc ((tconvert mp t)::I.Utype)
+                                               ; vi <- convert_Value v
+                                               ; return $ I.T ti vi
+                                               }
+
+convert_to_TypedValue_SF :: I.FileLoc -> A.Typed A.Value -> MM (I.T (I.Type I.ScalarB I.F) I.Value)
+convert_to_TypedValue_SF lc (A.Typed t v) = do { mp <- typeDefs
+                                               ; let (ti::I.Type I.ScalarB I.F) = I.dcast lc ((tconvert mp t)::I.Utype)
+                                               ; vi <- convert_Value v
+                                               ; return $ I.T ti vi
+                                               }
+
+convert_to_TypedValue_SP :: I.FileLoc -> A.Typed A.Value -> MM (I.T (I.Type I.ScalarB I.P) I.Value)
+convert_to_TypedValue_SP lc (A.Typed t v) = do { mp <- typeDefs
+                                               ; let (ti::I.Type I.ScalarB I.P) = I.dcast lc ((tconvert mp t)::I.Utype)
+                                               ; vi <- convert_Value v
+                                               ; return $ I.T ti vi
+                                               }
+
+convert_to_TypedAddrValue :: I.FileLoc -> A.Typed A.Value -> MM (I.T (I.Type I.ScalarB I.P) I.Value)
+convert_to_TypedAddrValue lc (A.Typed t v) = do { mp <- typeDefs
+                                                ; let (ti::I.Type I.ScalarB I.P) = I.dcast lc ((tconvert mp t)::I.Utype)
+                                                ; vi <- convert_Value v
+                                                ; return $ I.T ti vi
+                                                }
+
+convert_Type_Dtype :: I.FileLoc -> A.Type -> MM I.Dtype
+convert_Type_Dtype lc t = do { mp <- typeDefs
+                             ; return $ I.dcast lc ((tconvert mp t)::I.Utype)
+                             }
+
+
+convert_Rhs :: (Maybe A.LocalId, A.Rhs) -> MM I.CInst
+convert_Rhs (mlhs, A.RmO c) = convert_MemOp (mlhs, c)
+convert_Rhs (mlhs, A.Re e) = convert_Expr_CInst (mlhs, e)
+convert_Rhs (lhs, A.Call b cs) = 
+  do { (isvoid,csi) <- convert_to_CallSite cs
+     ; case csi of 
+       I.CsFun _ _ _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "llvm.dbg.declare"))) paramList _ -> return $ I.I_llvm_dbg_declare paramList
+       I.CsFun _ _ _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "llvm.dbg.value"))) paramList _ -> return $ I.I_llvm_dbg_value paramList
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "llvm.va_start"))) 
+         [I.ActualParamData t1 [] Nothing v []] [] | isvoid -> return $ I.I_va_start (I.T (I.dcast FLC t1) v)
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "llvm.va_end")))
+         [I.ActualParamData t1 [] Nothing v []] [] | isvoid -> return $ I.I_va_end (I.T (I.dcast FLC t1) v)
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum nm)))
+         [I.ActualParamData t1 [] Nothing v1 [] -- dest
+         ,I.ActualParamData t2 [] Nothing v2 [] -- src
+         ,I.ActualParamData t3 [] Nothing v3 [] -- len
+         ,I.ActualParamData t4 [] Nothing v4 [] -- align
+         ,I.ActualParamData t5 [] Nothing v5 [] -- volatile          
+         ] [] | isvoid && (nm == "llvm.memcpy.p0i8.p0i8.i32" || nm == "llvm.memcpy.p0i8.p0i8.i64") 
+                -> let mod = case nm of
+                         "llvm.memcpy.p0i8.p0i8.i32" -> I.MemLenI32
+                         "llvm.memcpy.p0i8.p0i8.i64" -> I.MemLenI64                         
+                   in return $ I.I_llvm_memcpy mod
+                      (I.T (I.dcast FLC t1) v1)
+                      (I.T (I.dcast FLC t2) v2)
+                      (I.T (I.dcast FLC t3) v3)
+                      (I.T (I.dcast FLC t4) v4)
+                      (I.T (I.dcast FLC t5) v5)
+                      {-
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "_dts_dbaseOf"))) 
+         [I.ActualParamData t1 [] Nothing v []] [] -> return $ I.I_dbaseOf (I.T (I.dcast FLC t1) v) (fromJust lhs)
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "_dts_dsizeOf"))) 
+         [I.ActualParamData t1 [] Nothing v []] [] -> return $ I.I_dsizeOf (I.T (I.dcast FLC t1) v) (fromJust lhs)
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "_dts_inspect_va_start_offset"))) 
+         [] _ -> return $ I.I_inspect_va_start_offset (fromJust lhs)
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "_dts_inspect_va_start_mbase"))) 
+         [] _ -> return $ I.I_inspect_va_start_mbase (fromJust lhs)
+       I.CsFun Nothing [] _ (I.FunNameGlobal (I.GolG (I.GlobalIdAlphaNum "_dts_inspect_va_start_msize"))) 
+         [] _ -> return $ I.I_inspect_va_start_msize (fromJust lhs)                  
+                      -}
+       I.CsFun cc pa cstype fn ap fa -> return $ I.I_call_fun b cc pa cstype fn ap fa lhs
+       _ -> return $ I.I_call_other b csi lhs
+     }
+convert_Rhs (Just lhs, A.RvA (A.VaArg tv t)) = 
+  do { tvi <- convert_to_DtypedValue tv
+     ; ti <- convert_Type_Dtype FLC t
+     ; return $ I.I_va_arg tvi ti lhs
+     }
+convert_Rhs (Just lhs, A.RlP (A.LandingPad t1 t2 pf b cs)) = 
+  do { pfi <- convert_PersFn pf
+     ; csi <- mapM convert_Clause cs
+     ; t1i <- convert_Type_Dtype FLC t1
+     ; t2i <- convert_Type_Dtype FLC t2
+     ; return $ I.I_landingpad t1i t2i pfi b csi lhs
+     }
+convert_Rhs (Just lhs, A.ReE a@(A.ExtractElement (A.Typed t1 _) _)) = 
+  do { mp <- typeDefs
+     ; case matchType mp t1 of
+       Tk_VectorI -> do { (I.ExtractElement vec idx) <- convert_to_ExtractElement_I convert_Value a
+                        ; return $ I.I_extractelement_I vec idx lhs
+                        }
+       Tk_VectorF -> do { (I.ExtractElement vec idx) <- convert_to_ExtractElement_F convert_Value a
+                        ; return $ I.I_extractelement_F vec idx lhs
+                        }
+       Tk_VectorP -> do { (I.ExtractElement vec idx) <- convert_to_ExtractElement_P convert_Value a
+                        ; return $ I.I_extractelement_P vec idx lhs
+                        }
+     }
+convert_Rhs (Just lhs, A.RiE a@(A.InsertElement (A.Typed t1 _) _ _)) = 
+  do { mp <- typeDefs
+     ; case matchType mp t1 of
+       Tk_VectorI -> do { (I.InsertElement vec val idx) <- convert_to_InsertElement_I convert_Value a
+                        ; return $ I.I_insertelement_I vec val idx lhs
+                        }
+       Tk_VectorF -> do { (I.InsertElement vec val idx) <- convert_to_InsertElement_F convert_Value a
+                        ; return $ I.I_insertelement_F vec val idx lhs
+                        }
+       Tk_VectorP -> do { (I.InsertElement vec val idx) <- convert_to_InsertElement_P convert_Value a
+                        ; return $ I.I_insertelement_P vec val idx lhs
+                        }
+     }
+convert_Rhs (Just lhs, A.RsV a@(A.ShuffleVector (A.Typed t _) _ _)) = 
+  do { mp <- typeDefs
+     ; case matchType mp t of
+       Tk_VectorI -> do { (I.ShuffleVector tv1a tv2a tv3a) <- convert_to_ShuffleVector_I convert_Value a
+                        ; return $ I.I_shufflevector_I tv1a tv2a tv3a lhs
+                        }
+       Tk_VectorF -> do { (I.ShuffleVector tv1a tv2a tv3a) <- convert_to_ShuffleVector_F convert_Value a
+                        ; return $ I.I_shufflevector_F tv1a tv2a tv3a lhs
+                        }
+       Tk_VectorP -> do { (I.ShuffleVector tv1a tv2a tv3a) <- convert_to_ShuffleVector_P convert_Value a
+                        ; return $ I.I_shufflevector_P tv1a tv2a tv3a lhs
+                        }
+     }
+convert_Rhs (Just lhs, A.ReV a) = 
+  do { (I.ExtractValue blocka idxa) <- convert_to_ExtractValue convert_Value a
+     ; return $ I.I_extractvalue blocka idxa lhs
+     }
+convert_Rhs (Just lhs, A.RiV a) = 
+  do { (I.InsertValue blocka va idxa) <- convert_to_InsertValue convert_Value a
+     ; return $ I.I_insertvalue blocka va idxa lhs
+     }
+convert_Rhs (lhs,rhs) =  error $ "AstIrConversion:irrefutable error lhs:" ++ show lhs ++ " rhs:" ++ show rhs
+
+
+convert_ActualParam :: A.ActualParam -> MM I.ActualParam
+convert_ActualParam x = case x of
+  (A.ActualParamData t pa1 ma v pa2) ->
+    do { mp <- typeDefs
+       ; let (ta::I.Utype) = tconvert mp t
+       ; va <- convert_Value v
+       ; case ta of
+         I.UtypeLabelX lbl -> return $ I.ActualParamLabel lbl pa1 ma va pa2
+         _ -> return $ I.ActualParamData (I.dcast FLC ta) pa1 ma va pa2
+       }
+  (A.ActualParamMeta mc) -> Md.liftM I.ActualParamMeta (convert_MetaKindedConst mc)
+
+convert_Aliasee :: A.Aliasee -> (MM I.Aliasee)
+convert_Aliasee (A.AtV (A.Typed t v)) = do { mp <- typeDefs
+                                           ; va <- convert_Value v
+                                           ; let (ta::I.Dtype) = I.dcast FLC ((tconvert mp t)::I.Utype)
+                                           ; return $ I.AtV (I.T ta va)
+                                           }
+convert_Aliasee (A.Ac c@(A.Conversion _ _ dt)) = 
+  do { mp <- typeDefs
+     ; if isTvector mp dt then Md.liftM I.AcV (convert_to_Conversion_V convert_Const c)
+       else Md.liftM I.Ac (convert_to_Conversion convert_Const c)
+     }
+convert_Aliasee (A.AgEp a) = 
+  do { mp <- typeDefs
+     ; if getElemPtrIsTvector mp a then Md.liftM I.AgepV (convert_to_GetElementPtr_V convert_Const a)
+       else Md.liftM I.Agep (convert_to_GetElementPtr convert_Const a)
+     }
+
+convert_Prefix :: A.Prefix -> (MM I.Prefix)
+convert_Prefix (A.Prefix n) = Md.liftM I.Prefix (convert_TypedConstOrNUll n)
+
+convert_Prologue :: A.Prologue -> (MM I.Prologue)
+convert_Prologue (A.Prologue n) = Md.liftM I.Prologue (convert_TypedConstOrNUll n)
+
+convert_TypedConstOrNUll :: A.TypedConstOrNull -> MM I.TypedConstOrNull
+convert_TypedConstOrNUll x = case x of
+  A.TypedConst (A.Typed t v) -> do { mp <- typeDefs
+                                   ; vi <- convert_Const v
+                                   ; let (ti::I.Dtype) = I.dcast FLC ((tconvert mp t)::I.Utype)
+                                   ; return (I.TypedConst (I.T ti vi))
+                                   }
+  A.UntypedNull -> return I.UntypedNull
+
+convert_FunctionPrototype :: A.FunctionPrototype -> (MM I.FunctionPrototype)
+convert_FunctionPrototype  (A.FunctionPrototype f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f10a f11 f12 f13 f14) =
+  do { mp <- typeDefs
+     ; let (f5a::I.Rtype) = I.dcast FLC ((tconvert mp f5)::I.Utype)
+     ; f13a <- maybeM convert_Prefix f13
+     ; f14a <- maybeM convert_Prologue f14
+     ; return $ I.FunctionPrototype f0 f1 f2 f3 f4 f5a f6 (tconvert mp f7) f8 f9 f10 f10a f11 f12 f13a f14a
+     }
+
+convert_PhiInst :: A.PhiInst -> MM I.PhiInst
+convert_PhiInst phi@(A.PhiInst mg t branches) = 
+  do { mp <- typeDefs
+     ; branchesa <- mapM (pairM convert_Value convert_PercentLabel) branches             
+     ; let (ta::I.Utype) = tconvert mp t
+     ; let (tab::I.Ftype) = case ta of 
+             I.UtypeRecordD e -> I.dcast FLC (I.squeeze FLC e)
+             _ -> I.dcast FLC ta 
+     ; case mg of 
+       Just lhs -> return $ I.PhiInst lhs tab (fmap (\x -> (fst x, snd x)) branchesa)
+       Nothing -> I.errorLoc FLC $ "unused phi" ++ show phi
+     }
+
+convert_CInst :: A.ComputingInst -> (MM I.CInst)
+convert_CInst (A.ComputingInst mg rhs) = convert_Rhs (mg, rhs) 
+
+convert_TerminatorInst :: A.TerminatorInst -> (MM I.TerminatorInst)
+convert_TerminatorInst (A.RetVoid) = return I.RetVoid
+convert_TerminatorInst (A.Return tvs) = Md.liftM I.Return (mapM convert_to_DtypedValue tvs)
+convert_TerminatorInst (A.Br t) = Md.liftM I.Br (convert_TargetLabel t)
+convert_TerminatorInst (A.Cbr cnd t f) = Md.liftM3 I.Cbr (convert_Value cnd) (convert_TargetLabel t) (convert_TargetLabel f)
+convert_TerminatorInst (A.IndirectBr cnd bs) = 
+  Md.liftM2 I.IndirectBr (convert_to_TypedAddrValue FLC cnd) (mapM convert_TargetLabel bs)
+convert_TerminatorInst (A.Switch cnd d cases) = 
+  Md.liftM3 I.Switch (convert_to_TypedValue_SI FLC cnd) 
+  (convert_TargetLabel d) (mapM (pairM (convert_to_TypedValue_SI FLC) convert_TargetLabel) cases)
+convert_TerminatorInst (A.Invoke mg cs t f) = 
+  do { (isvoid, csa) <- convert_to_CallSite cs
+     ; ta <- convert_TargetLabel t
+     ; fa <- convert_TargetLabel f
+     ; if isvoid then return $ I.InvokeCmd csa ta fa
+       else return $ I.Invoke csa ta fa mg
+     }
+convert_TerminatorInst (A.Resume tv) = Md.liftM I.Resume (convert_to_DtypedValue tv)
+convert_TerminatorInst A.Unreachable = return I.Unreachable
+convert_TerminatorInst A.Unwind = return I.Unwind
+
+convert_Dbg :: A.Dbg -> (MM I.Dbg)
+convert_Dbg (A.Dbg mv mc) = Md.liftM2 I.Dbg (convert_MdVar mv) (convert_MetaConst mc)
+
+convert_PhiInstWithDbg :: A.PhiInstWithDbg -> (MM I.PhiInstWithDbg)
+convert_PhiInstWithDbg (A.PhiInstWithDbg ins dbgs) = Md.liftM2 I.PhiInstWithDbg (convert_PhiInst ins) (mapM convert_Dbg dbgs)
+
+convert_CInstWithDbg :: A.ComputingInstWithDbg -> (MM I.CInstWithDbg)
+convert_CInstWithDbg (A.ComputingInstWithDbg ins dbgs) = Md.liftM2 I.CInstWithDbg (convert_CInst ins) (mapM convert_Dbg dbgs)
+    
+convert_TerminatorInstWithDbg :: A.TerminatorInstWithDbg -> (MM I.TerminatorInstWithDbg)
+convert_TerminatorInstWithDbg (A.TerminatorInstWithDbg term dbgs) = 
+  Md.liftM2 I.TerminatorInstWithDbg (convert_TerminatorInst term) (mapM convert_Dbg dbgs)
+
+
+toSingleNodeGraph :: A.Block -> MM (H.Graph (I.Node a) H.C H.C)
+-- toSingleNodeGraph b | trace ("toSingleNodeGraph " ++ toLlvm b) False = undefined
+toSingleNodeGraph (A.Block f  phi ms l) =
+  do { f'  <- toFirst f
+     ; phi' <- mapM toPhi phi
+     ; ms' <- mapM toMid ms
+     ; l'  <- toLast l
+     ; return $ H.mkFirst f' H.<*> H.mkMiddles phi' H.<*> H.mkMiddles ms' H.<*> H.mkLast l'
+     }
+
+toFirst :: A.BlockLabel -> MM (I.Node a H.C H.O)
+toFirst x = Md.liftM I.Nlabel (convert_BlockLabel x)
+
+toPhi :: A.PhiInstWithDbg -> MM (I.Node a H.O H.O)
+toPhi phi = Md.liftM I.Pinst (convert_PhiInstWithDbg phi)
+
+toMid :: A.ComputingInstWithDbg -> MM (I.Node a H.O H.O)
+toMid inst = Md.liftM I.Cinst (convert_CInstWithDbg inst)
+
+toLast :: A.TerminatorInstWithDbg -> MM (I.Node a H.O H.C)
+toLast inst = Md.liftM I.Tinst (convert_TerminatorInstWithDbg inst)
+
+-- | the head must be the entry block
+getEntryAndAlist :: [A.Block] -> MM (H.Label, [A.LabelId])
+getEntryAndAlist [] = error "Parsed procedures should not be empty"
+getEntryAndAlist bs =
+  do { l <- convert_BlockLabel $ A.blockLabel $ head bs
+     ; let ord = map (\b -> case A.blockLabel b of
+                         A.ImplicitBlockLabel p -> error $ "irrefutable implicitblock " 
+                                                   ++ show p ++ " should be normalized in AstSimplify" 
+                         A.ExplicitBlockLabel x -> x 
+                     ) bs
+     ; return (l, ord)
+     }
+
+toGraph :: [A.Block] -> MM (H.Graph (I.Node a) H.C H.C)
+toGraph bs =
+  {-
+    It's more likely that only reachable blocks are pulled out and used to create
+    a graph, the unreachable blocks are left.
+  -}
+  do { g <- foldl (Md.liftM2 (H.|*><*|)) (return H.emptyClosedGraph) (map toSingleNodeGraph bs)
+     ; getBody g
+     }
+
+getBody :: forall n. H.Graph n H.C H.C -> MM (H.Graph n H.C H.C)
+getBody graph = LabelMapM f
+  where f m = return (m, graph)
+
+
+blockToGraph :: A.FunctionPrototype -> [A.Block] -> MM (H.Label, H.Graph (I.Node a) H.C H.C)
+blockToGraph fn blocks =
+  do { (entry, labels) <- getEntryAndAlist blocks
+     ; body <- toGraph blocks 
+     ; return (entry, body)
+     }
+  
+convert_TlTriple :: A.TlTriple -> (MM I.TlTriple)
+convert_TlTriple (A.TlTriple x) = return (I.TlTriple x)
+  
+convert_TlDataLayout :: A.TlDataLayout -> (MM I.TlDataLayout)
+convert_TlDataLayout (A.TlDataLayout x) = return (I.TlDataLayout x)
+
+
+convert_TlAlias :: A.TlAlias -> (MM I.TlAlias)
+convert_TlAlias (A.TlAlias  g v dll tlm na l a) = convert_Aliasee a >>= return . (I.TlAlias g v dll tlm na l)
+
+convert_TlDbgInit :: A.TlDbgInit -> (MM I.TlDbgInit)
+convert_TlDbgInit (A.TlDbgInit s i) = return (I.TlDbgInit s i)
+  
+convert_TlStandaloneMd :: A.TlStandaloneMd -> (MM I.TlStandaloneMd)
+convert_TlStandaloneMd (A.TlStandaloneMd s tv) = convert_MetaKindedConst tv >>= return . (I.TlStandaloneMd s)
+  
+                                                 
+convert_TlNamedMd :: A.TlNamedMd -> (MM I.TlNamedMd)
+convert_TlNamedMd (A.TlNamedMd m ns) = do { ma <- convert_MdVar m
+                                          ; nsa <- mapM convert_MdNode ns
+                                          ; return $ I.TlNamedMd ma nsa
+                                          }
+                               
+convert_TlDeclare :: A.TlDeclare -> (MM I.TlDeclare)
+convert_TlDeclare (A.TlDeclare f) = convert_FunctionPrototype f >>= return . I.TlDeclare
+  
+convert_TlDefine :: A.TlDefine -> (MM (I.TlDefine a))
+convert_TlDefine  (A.TlDefine f b) = do { fa <- convert_FunctionPrototype f
+                                        ; (e, g) <- blockToGraph f b
+                                        ; return $ I.TlDefine fa e g
+                                        }
+
+convert_TlGlobal :: A.TlGlobal -> (MM I.TlGlobal)
+convert_TlGlobal (A.TlGlobal a1 a2 a3 a4 a5 a6 a7 a8 a8a a9 a10 a11 a12 a13) =
+  do { mp <- typeDefs
+     ; let (a9a::I.Utype) = tconvert mp a9
+     ; a10a <- maybeM convert_Const a10
+     ; case a9a of 
+       I.UtypeOpaqueD _ -> return $ I.TlGlobalOpaque a1 a2 a3 a4 a5 a6 (fmap (tconvert mp) a7) 
+                           a8 a8a (I.dcast FLC a9a) a10a a11 a12 a13
+       _ -> return $ I.TlGlobalDtype a1 a2 a3 a4 a5 a6 (fmap (tconvert mp) a7) 
+            a8 a8a (I.dcast FLC a9a) a10a a11 a12 a13
+     }
+  
+convert_TlTypeDef :: A.TlTypeDef -> (MM I.TlTypeDef)
+convert_TlTypeDef (A.TlTypeDef lid t) = 
+  do { mp <- typeDefs
+     ; let (ta::I.Utype) = tconvert mp t
+     ; case ta of
+       I.UtypeFunX _ -> return (I.TlFunTypeDef lid (I.dcast FLC ta))
+       I.UtypeOpaqueD _-> return (I.TlOpqTypeDef lid (I.dcast FLC ta))
+       _ -> return (I.TlDatTypeDef lid (I.dcast FLC ((tconvert mp t)::I.Utype)))
+     }
+  
+convert_TlDepLibs :: A.TlDepLibs -> (MM I.TlDepLibs)
+convert_TlDepLibs (A.TlDepLibs s) = return (I.TlDepLibs s)
+  
+convert_TlUnamedType :: A.TlUnamedType -> (MM I.TlUnamedType)
+convert_TlUnamedType (A.TlUnamedType i t) = do { mp <- typeDefs
+                                               ; let (ta::I.Dtype) = I.dcast FLC ((tconvert mp t)::I.Utype)
+                                               ; return (I.TlUnamedType i ta)
+                                               }
+  
+convert_TlModuleAsm :: A.TlModuleAsm -> (MM I.TlModuleAsm)
+convert_TlModuleAsm (A.TlModuleAsm s) = return (I.TlModuleAsm s)
+
+convert_TlAttribute :: A.TlAttribute -> (MM I.TlAttribute)
+convert_TlAttribute (A.TlAttribute n l) = return (I.TlAttribute n l)
+  
+convert_TlComdat :: A.TlComdat -> (MM I.TlComdat)
+convert_TlComdat (A.TlComdat l s) = return (I.TlComdat l s)
+                                                 
+
+toplevel2Ir :: A.Toplevel -> MM (I.Toplevel a)
+toplevel2Ir (A.ToplevelTriple q) = Md.liftM I.ToplevelTriple (convert_TlTriple q)
+toplevel2Ir (A.ToplevelDataLayout q) = Md.liftM I.ToplevelDataLayout (convert_TlDataLayout q)
+toplevel2Ir (A.ToplevelAlias q) = Md.liftM I.ToplevelAlias (convert_TlAlias q)
+toplevel2Ir (A.ToplevelDbgInit s) = Md.liftM I.ToplevelDbgInit (convert_TlDbgInit s)
+toplevel2Ir (A.ToplevelStandaloneMd s) = Md.liftM I.ToplevelStandaloneMd (convert_TlStandaloneMd s)
+toplevel2Ir (A.ToplevelNamedMd m) = Md.liftM I.ToplevelNamedMd (convert_TlNamedMd m)
+toplevel2Ir (A.ToplevelDeclare f) = Md.liftM I.ToplevelDeclare (convert_TlDeclare f)
+toplevel2Ir (A.ToplevelDefine f) = Md.liftM I.ToplevelDefine (convert_TlDefine f)
+toplevel2Ir (A.ToplevelGlobal g) = Md.liftM I.ToplevelGlobal (convert_TlGlobal g)
+toplevel2Ir (A.ToplevelTypeDef t) = Md.liftM I.ToplevelTypeDef (convert_TlTypeDef t)
+toplevel2Ir (A.ToplevelDepLibs qs) = Md.liftM I.ToplevelDepLibs (convert_TlDepLibs qs)
+toplevel2Ir (A.ToplevelUnamedType i) = Md.liftM I.ToplevelUnamedType (convert_TlUnamedType i)
+toplevel2Ir (A.ToplevelModuleAsm q) = Md.liftM I.ToplevelModuleAsm (convert_TlModuleAsm q)
+toplevel2Ir (A.ToplevelAttribute n) = Md.liftM I.ToplevelAttribute (convert_TlAttribute n)
+toplevel2Ir (A.ToplevelComdat l) = Md.liftM I.ToplevelComdat (convert_TlComdat l)
+
+astToIr :: A.Module -> H.SimpleUniqueMonad (IdLabelMap, I.Module a)
+astToIr m@(A.Module ts) = let td = M.fromList $ typeDefOfModule m
+                          in runLabelMapM (emptyIdLabelMap td) $ Md.liftM I.Module (mapM toplevel2Ir ts)
diff --git a/src/Llvm/Data/Conversion/AstScanner.hs b/src/Llvm/Data/Conversion/AstScanner.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Conversion/AstScanner.hs
@@ -0,0 +1,14 @@
+module Llvm.Data.Conversion.AstScanner where
+
+import Llvm.Data.Ast
+
+typeDefOfModule :: Module -> [(LocalId, Type)]
+typeDefOfModule (Module tl) = 
+  let tl0 = filter (\x -> case x of
+                       ToplevelTypeDef _ -> True
+                       _ -> False
+                   ) tl
+  in fmap (\(ToplevelTypeDef (TlTypeDef lid ty)) -> (lid,ty)) tl0
+     
+     
+     
diff --git a/src/Llvm/Data/Conversion/AstSimplification.hs b/src/Llvm/Data/Conversion/AstSimplification.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Conversion/AstSimplification.hs
@@ -0,0 +1,750 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE RecordWildCards #-}
+module Llvm.Data.Conversion.AstSimplification (simplify) where
+
+import Llvm.Data.Ast
+import qualified Data.Map as M
+import qualified Data.Set as St
+import qualified Control.Monad.State as S
+import qualified Control.Monad.Reader as R
+import Data.Maybe
+import Llvm.Util.Monadic (maybeM)
+import Debug.Trace
+import Data.Word (Word32)
+
+{-
+  Assign explicit names to all implicit variables  
+  Assign explicit labels to all implicit labels
+-}
+data MyState = MyState { _cnt :: Word32 -- Integer
+                       , _renaming :: String
+                       , _implicitLabelNums :: St.Set Word32 -- Integer
+                       , _explicitLabelNums :: St.Set Word32 -- Integer
+                       , _explicitLabelDqNums :: St.Set Word32 -- Integer                         
+                       } 
+               
+type MS = S.State MyState
+
+data LabelNumbers = LabelNumbers { implicitNumbers :: St.Set Word32 -- Integer
+                                 , explicitNumbers :: St.Set Word32 -- Integer
+                                 , explicitDqNumbers :: St.Set Word32 -- Integer
+                                 } deriving (Eq, Ord, Show)
+                                            
+idPrefix :: String
+idPrefix = "_hsllvm_implicit_ID"
+
+implicitLbPrefix :: String
+implicitLbPrefix = "_hsllvm_implicit_L"
+
+explicitLbPrefix :: String
+explicitLbPrefix = "_hsllvm_explicit_L"
+
+------------------------------------------------------------------------
+-- iteration 1
+------------------------------------------------------------------------
+iter1 :: [Toplevel] -> ([Toplevel], M.Map GlobalId LabelNumbers)
+iter1 l = let (l1, m1) = unzip $ fmap rnToplevel1 l
+          in (l1, foldl M.union M.empty m1)
+
+rnToplevel1 :: Toplevel -> (Toplevel, M.Map GlobalId LabelNumbers)
+rnToplevel1 (ToplevelDefine (TlDefine fp bs)) = 
+  let ((fp2, bs2), mys) = S.runState (do { fpa <- rnDefFunctionPrototype fp
+                                         ; bsa <- S.mapM rnBlock bs
+                                         ; return (fpa, bsa)
+                                         }
+                                     ) (MyState 0 (show fp) St.empty St.empty St.empty)
+      labelNumbers = LabelNumbers (_implicitLabelNums mys) (_explicitLabelNums mys) (_explicitLabelDqNums mys)
+  in ((ToplevelDefine (TlDefine fp2 bs2)), M.insert (getGlobalId fp) labelNumbers M.empty)
+rnToplevel1 x = (x, M.empty)
+
+
+getGlobalId :: FunctionPrototype -> GlobalId
+getGlobalId (FunctionPrototype _ _ _ _ _ _ fhName _ _ _ _ _ _ _ _ _) = fhName 
+
+rnDefFunctionPrototype :: FunctionPrototype -> MS FunctionPrototype
+rnDefFunctionPrototype fpt@(FunctionPrototype v0 v1 v2 v3 v4 v5 v6 fhParams v8 v9 v10 v11 v12 v13 fhPrefix fhPrologue) = 
+  do { fp' <- rnDefFormalParamList fhParams
+     ; prefix' <- rnPrefix fhPrefix
+     ; prologue' <- rnPrologue fhPrologue 
+     ; return $ FunctionPrototype v0 v1 v2 v3 v4 v5 v6 fp' v8 v9 v10 v11 v12 v13  prefix' prologue'
+     }
+  
+  
+  
+rnDefFormalParamList :: FormalParamList -> MS FormalParamList  
+rnDefFormalParamList (FormalParamList fps b fa) = do { fps' <- mapM rnDefFormalParam fps
+                                                     ; return $ FormalParamList fps' b fa
+                                                     }
+                                               
+rnDefFormalParam :: FormalParam -> MS FormalParam
+rnDefFormalParam x = case x of
+  (FormalParamData t pas1 align pid pas2) -> 
+    do { pid' <- rnDefFparam pid
+       ; return $ FormalParamData (normalType t) pas1 align pid' pas2
+       }
+  (FormalParamMeta e pid) -> 
+    do { pid1 <- rnDefFparam pid
+       ; e1 <- rnMetaKind e
+       ; return $ FormalParamMeta e1 pid1
+       }
+
+rnDefFparam :: Fparam -> MS Fparam 
+rnDefFparam (FimplicitParam) =
+  do { x <- getNext
+     ; S.liftM FexplicitParam (rnDefLocalId (LocalIdNum x))
+     }
+rnDefFparam (FexplicitParam x) = S.liftM FexplicitParam (rnDefLocalId x)
+  
+rnLabelId :: LabelId -> MS LabelId
+rnLabelId x = return x
+
+
+
+getNext :: MS Word32 -- Integer
+getNext = do { MyState{..} <- S.get
+             ; S.modify (\s@MyState {..} -> s { _cnt = _cnt + 1})
+             ; return _cnt
+             }
+
+getFp :: MS String
+getFp = do { MyState{..} <- S.get
+           ; return _renaming
+           }
+
+rnDefLabel :: BlockLabel -> MS BlockLabel
+rnDefLabel bl = case bl of
+  ImplicitBlockLabel _ -> do { i <- getNext
+                             ; S.modify (\s@MyState{..} ->  s { _implicitLabelNums  = St.insert i _implicitLabelNums })
+                             ; ia <- return $ LabelString (implicitLbPrefix ++ show i)
+                             ; return $ ExplicitBlockLabel ia
+                             }
+  ExplicitBlockLabel i -> S.liftM ExplicitBlockLabel (recordLabelNumber i)
+  where 
+    recordLabelNumber :: LabelId -> MS LabelId
+    recordLabelNumber (LabelNumber i) = S.modify (\s@MyState {..} -> s { _explicitLabelNums = St.insert i _explicitLabelNums }) >> return (LabelString (explicitLbPrefix ++ show i))
+    recordLabelNumber x@(LabelDqNumber i) = S.modify (\s@MyState {..} -> s { _explicitLabelDqNums = St.insert i _explicitLabelDqNums }) >> return x
+    recordLabelNumber x = return x
+
+rnBlock :: Block -> MS Block
+rnBlock (Block lbl phi comp term) = do { lbl' <- rnDefLabel lbl
+                                       ; phi' <- mapM rnPhiInstWithDbg phi
+                                       ; comp' <- mapM rnComputingInstWithDbg comp
+                                       ; term' <- rnTerminatorInstWithDbg term
+                                       ; return (Block lbl' phi' comp' term')
+                                       }
+
+
+rnDefLocalId :: LocalId -> MS LocalId
+#ifdef DEBUG
+rnDefLocalId l | trace ("rnDefLocalId " ++ (show l)) False = undefined
+#endif
+rnDefLocalId (LocalIdNum i) = S.liftM (LocalIdAlphaNum) (return (idPrefix ++ show i))
+rnDefLocalId x = return x
+
+
+rnLocalId :: LocalId -> MS LocalId
+rnLocalId (LocalIdNum i) = S.liftM (LocalIdAlphaNum) (return (idPrefix ++ show i))
+rnLocalId x = return x  
+
+
+rnLhs :: LocalId -> MS LocalId
+rnLhs localId = checkImpCount localId >> rnDefLocalId localId
+
+rnPhiInstWithDbg :: PhiInstWithDbg -> MS PhiInstWithDbg
+rnPhiInstWithDbg (PhiInstWithDbg ins dbgs) = S.liftM (\x -> PhiInstWithDbg x dbgs) (rnPhi ins)
+
+rnPhi :: PhiInst -> MS PhiInst
+rnPhi (PhiInst lhs t ins) = do { lhs' <- maybeM rnLhs lhs
+                               ; lhs'' <- getLhs True lhs'
+                               ; ins' <- S.mapM g ins
+                               ; return $ PhiInst lhs'' t ins'
+                               }
+  where g (v, p) = do { v' <- rnValue v
+                      ; p' <- rnPercentLabel p
+                      ; return (v', p')
+                      }
+
+
+rnComputingInstWithDbg :: ComputingInstWithDbg -> MS ComputingInstWithDbg
+rnComputingInstWithDbg (ComputingInstWithDbg c l) = S.liftM (\x -> ComputingInstWithDbg x l) 
+                                                    (rnComputingInst c)
+
+rnComputingInst :: ComputingInst -> MS ComputingInst
+#ifdef DEBUG
+rnComputingInst x | trace ("rnComputingInst " ++ show (x)) False = undefined
+#endif
+rnComputingInst (ComputingInst lhs rhs) = do { lhs' <- maybeM rnLhs lhs
+                                             ; (b, rhs') <- rnRhs rhs
+                                             ; lhs'' <- getLhs b lhs'
+                                             ; return (ComputingInst lhs'' rhs')
+                                             }
+
+getLhs :: Bool -> Maybe LocalId -> MS (Maybe LocalId)
+getLhs False x = return x
+getLhs True (Just x) = return $ Just x
+getLhs True Nothing = do { m <- getNext
+                         ; m' <- rnLocalId (LocalIdNum m)
+                         ; return $ Just m'
+                         }
+
+rnGlobalOrLocalId :: GlobalOrLocalId -> MS GlobalOrLocalId
+rnGlobalOrLocalId (GolL l) = S.liftM GolL (rnLocalId l)
+rnGlobalOrLocalId x = return x
+
+rnValue :: Value -> MS Value
+rnValue (Val_local x) = S.liftM Val_local (rnLocalId x)
+rnValue (Val_const x) = S.liftM Val_const (rnConst x)
+
+rnTypedValue :: Typed Value -> MS (Typed Value)
+rnTypedValue (Typed t v) = S.liftM (Typed $ normalType t) (rnValue v)
+
+normalType :: Type -> Type
+normalType (Tpointer et as) = Tpointer (normalType et) (normAddrSpace as)  
+normalType (Tstruct pk l) = Tstruct pk (fmap normalType l)
+normalType (Tarray n e) = Tarray n (normalType e)
+normalType x = x
+  
+normAddrSpace :: AddrSpace -> AddrSpace  
+normAddrSpace (AddrSpace 0) = AddrSpaceUnspecified
+normAddrSpace x = x
+
+checkImpCount :: LocalId -> MS ()
+checkImpCount x@(LocalIdNum i) = 
+  do { m <- getNext
+     ; if (i == m) then return ()
+       else do { y <- getFp
+               ; error ("AstSimplify:expect " ++ (show m) ++ " and but found " ++ (show x) ++ " in " ++ y)
+               }
+     }
+checkImpCount _ = return ()                
+                                         
+rnRhs :: Rhs -> MS (Bool, Rhs)
+rnRhs lhs = case lhs of
+              RmO x -> S.liftM (\(b,x) -> (b, RmO x)) (rnMemOp x)
+              Re x -> S.liftM (\x -> (True, Re x)) (rnExpr x)
+              Call b cs -> S.liftM (\(bb, x) -> (bb, Call b x)) (rnCallSite cs)
+              ReE e -> S.liftM (\x -> (True, ReE x)) (rnExtractElem rnTypedValue e)
+              RiE e -> S.liftM (\x -> (True, RiE x)) (rnInsertElem rnTypedValue e)
+              RsV e -> S.liftM (\x -> (True, RsV x)) (rnShuffleVector rnTypedValue e)
+              ReV e -> S.liftM (\x -> (True, ReV x)) (rnExtractValue rnTypedValue e)
+              RiV e -> S.liftM (\x -> (True, RiV x)) (rnInsertValue rnTypedValue e)
+              RvA (VaArg tv t) -> S.liftM (\x -> (True, RvA $ VaArg x t)) (rnTypedValue tv)
+              RlP (LandingPad rt ft ix cl c) -> return (True, lhs)
+              
+rnMemOp :: MemOp -> MS (Bool, MemOp)
+rnMemOp (Alloca m t tv a) = do { tv' <- maybeM rnTypedValue tv
+                               ; return (True, Alloca m t tv' a)
+                               }
+rnMemOp (Load a tp ma nt inv nl) = S.liftM (\x -> (True, Load a x ma nt inv nl)) (rnPointer rnTypedValue tp)
+rnMemOp (LoadAtomic at a tp ma) = S.liftM (\x -> (True, LoadAtomic at a x ma)) (rnPointer rnTypedValue tp)
+rnMemOp (Store a tv tp ma nt) = S.liftM2 (\x y -> (False, Store a x y ma nt))
+                                (rnTypedValue tv) (rnPointer rnTypedValue tp)
+rnMemOp (StoreAtomic at a tv tp ma) = S.liftM2 (\x y -> (False, StoreAtomic at a x y ma))
+                                      (rnTypedValue tv) (rnPointer rnTypedValue tp)
+rnMemOp (Fence b f) = return (False, Fence b f)
+rnMemOp (CmpXchg wk b1 tp tv1 tv2 b2 mf ff) = 
+  S.liftM3 (\x y z -> (True, CmpXchg wk b1 x y z b2 mf ff))
+  (rnPointer rnTypedValue tp)
+  (rnTypedValue tv1)
+  (rnTypedValue tv2)
+rnMemOp (AtomicRmw b1 ao tp tv b2 mf) = 
+  S.liftM2 (\x y -> (True, AtomicRmw b1 ao x y b2 mf))
+  (rnPointer rnTypedValue tp)
+  (rnTypedValue tv)
+
+rnPointer :: (a -> MS a) -> Pointer a -> MS (Pointer a)
+rnPointer f (Pointer v) = S.liftM Pointer (f v) 
+
+rnExpr :: Expr -> MS Expr
+rnExpr (EgEp e) = S.liftM EgEp (rnGetElemPtr rnTypedValue e)
+rnExpr (EiC e) = S.liftM EiC (rnIcmp rnValue e)
+rnExpr (EfC e) = S.liftM EfC (rnFcmp rnValue e)
+rnExpr (Eb e) = S.liftM Eb (rnBinExpr rnValue e)
+rnExpr (Ec e) = S.liftM Ec (rnConversion rnTypedValue e)
+rnExpr (Es e) = S.liftM Es (rnSelect rnTypedValue e)
+
+
+rnGetElemPtr :: (Typed v -> MS (Typed v)) -> GetElementPtr v -> MS (GetElementPtr v)
+rnGetElemPtr fv (GetElementPtr b v vs) = do { v' <- rnPointer fv v
+                                            ; vs' <- mapM fv vs
+                                            ; return $ GetElementPtr b v' vs'
+                                            }
+
+
+rnIcmp :: (a -> MS a) -> Icmp a -> MS (Icmp a)
+rnIcmp f (Icmp o t v1 v2) = S.liftM2 (Icmp o t) (f v1) (f v2)
+
+rnFcmp :: (a -> MS a) -> Fcmp a -> MS (Fcmp a)
+rnFcmp f (Fcmp o t v1 v2) = S.liftM2 (Fcmp o t) (f v1) (f v2)
+
+rnIbinExpr :: (a -> MS a) -> IbinExpr a -> MS (IbinExpr a)
+rnIbinExpr f (IbinExpr o tf t v1 v2) = S.liftM2 (IbinExpr o tf t) (f v1) (f v2)
+
+rnFbinExpr :: (a -> MS a) -> FbinExpr a -> MS (FbinExpr a)
+rnFbinExpr f (FbinExpr o tf t v1 v2) = S.liftM2 (FbinExpr o tf t) (f v1) (f v2)
+
+rnBinExpr :: (a -> MS a) -> BinExpr a -> MS (BinExpr a)
+rnBinExpr f (Ie x) = S.liftM Ie (rnIbinExpr f x)
+rnBinExpr f (Fe x) = S.liftM Fe (rnFbinExpr f x)
+
+rnConversion :: (Typed a -> MS (Typed a)) -> Conversion a -> MS (Conversion a)
+rnConversion f (Conversion o v t) = S.liftM (\x -> Conversion o x t) (f v)
+
+rnSelect :: (Typed a -> MS (Typed a)) -> Select a -> MS (Select a)
+rnSelect f (Select v1 v2 v3) = S.liftM3 Select (f v1) (f v2) (f v3)
+
+
+rnFunName :: FunName -> MS FunName
+rnFunName (FunNameGlobal g) = S.liftM FunNameGlobal (rnGlobalOrLocalId g)
+rnFunName x = return x
+  
+
+rnCallSite :: CallSite -> MS (Bool, CallSite)
+rnCallSite (CsFun c pa t fn aps fas) = 
+  do { fna <- rnFunName fn
+     ; x <- mapM rnActualParam aps
+     ; let (rt, _) = splitCallReturnType t
+     ; return (not (rt == Tvoid), CsFun c pa t fna x fas)
+     }
+rnCallSite (CsAsm t dia b1 b2 qs1 qs2 aps fas) = 
+  do { apsa <- mapM rnActualParam aps
+     ; let (rt, _) = splitCallReturnType t
+     ; return (not (rt == Tvoid),  CsAsm t dia b1 b2 qs1 qs2 apsa fas)
+     }
+rnCallSite (CsConversion pas t c aps fas) = 
+  do { apsa <- mapM rnActualParam aps
+     ; let (rt, _) = splitCallReturnType t
+     ; return (not (rt == Tvoid), CsConversion pas t c apsa fas)
+     }
+
+rnActualParam :: ActualParam -> MS ActualParam
+rnActualParam (ActualParamData t ps ma v pa) = S.liftM (\x -> ActualParamData t ps ma x pa) (rnValue v)
+rnActualParam (ActualParamMeta mc) = S.liftM ActualParamMeta (rnMetaKindedConst mc)
+                                        
+
+rnExtractElem :: (Typed a -> MS (Typed a)) -> ExtractElement a -> MS (ExtractElement a)
+rnExtractElem f (ExtractElement v1 v2) = S.liftM2 ExtractElement (f v1) (f v2)
+
+rnInsertElem :: (Typed a -> MS (Typed a)) -> InsertElement a -> MS (InsertElement a)
+rnInsertElem f (InsertElement v1 v2 v3) = S.liftM3 InsertElement (f v1) (f v2) (f v3)
+
+rnShuffleVector :: (Typed a -> MS (Typed a)) -> ShuffleVector a -> MS (ShuffleVector a)
+rnShuffleVector f (ShuffleVector v1 v2 v3) = S.liftM3 ShuffleVector (f v1) (f v2) (f v3)
+
+
+rnExtractValue :: (Typed a -> MS (Typed a)) -> ExtractValue a -> MS (ExtractValue a)
+rnExtractValue f (ExtractValue v s) = S.liftM (\x -> ExtractValue x s) (f v)
+
+
+rnInsertValue :: (Typed a -> MS (Typed a)) -> InsertValue a -> MS (InsertValue a)
+rnInsertValue f (InsertValue v1 v2 s) = S.liftM2 (\x y -> InsertValue x y s)
+                                        (f v1) (f v2)
+                                        
+  
+rnTerminatorInstWithDbg :: TerminatorInstWithDbg -> MS TerminatorInstWithDbg
+rnTerminatorInstWithDbg (TerminatorInstWithDbg t ds) = S.liftM (\x -> TerminatorInstWithDbg x ds) (rnTerminatorInst t)
+
+
+rnTerminatorInst :: TerminatorInst -> MS TerminatorInst
+rnTerminatorInst (Return ls) = S.liftM Return (mapM rnTypedValue ls)
+rnTerminatorInst (Br l) = S.liftM Br (rnTargetLabel l)
+rnTerminatorInst (Cbr v tl fl) = S.liftM3 Cbr (rnValue v) (rnTargetLabel tl) (rnTargetLabel fl)
+rnTerminatorInst (Switch t d cases) = S.liftM3 Switch (rnTypedValue t) (rnTargetLabel d) 
+                                      (mapM (\(x,y) -> S.liftM2 (,)
+                                                       (rnTypedValue x)
+                                                       (rnTargetLabel y)) cases)
+
+rnTerminatorInst (IndirectBr tv ls) = S.liftM2 IndirectBr
+                                      (rnTypedValue tv) (mapM rnTargetLabel ls)
+                                      
+rnTerminatorInst (Invoke lhsOpt callSite tl fl) = do { lhsOpt' <- (maybeM rnLhs lhsOpt)
+                                                     ; (b, cs) <- (rnCallSite callSite)
+                                                     ; lhsOpt'' <- getLhs b lhsOpt'
+                                                     ; tl' <- (rnTargetLabel tl)
+                                                     ; fl' <- (rnTargetLabel fl)
+                                                     ; return $ Invoke lhsOpt'' cs tl' fl'
+                                                     }
+rnTerminatorInst (Resume tv) = S.liftM Resume (rnTypedValue tv)                                                  
+rnTerminatorInst x = return x
+
+
+rnPercentLabel :: PercentLabel -> MS PercentLabel
+rnPercentLabel (PercentLabel x) = S.liftM PercentLabel (rnLabelId x)
+
+rnTargetLabel :: TargetLabel -> MS TargetLabel
+rnTargetLabel (TargetLabel x) = S.liftM TargetLabel (rnPercentLabel x)
+
+
+rnMetaConst :: MetaConst -> MS MetaConst
+rnMetaConst (McRef l) = S.liftM McRef (rnLocalId l)
+rnMetaConst (McStruct c) = S.liftM McStruct (S.mapM (mapMetaKindedConst rnMetaConst) c)
+rnMetaConst mc@(McSimple sc) = return mc
+rnMetaConst x = return x
+ 
+rnMetaKind :: MetaKind -> MS MetaKind                
+rnMetaKind mk = return mk
+
+rnMetaKind2 :: MetaKind -> RD MetaKind
+rnMetaKind2 mk = return mk
+
+rnMetaKindedConst :: MetaKindedConst -> MS MetaKindedConst
+rnMetaKindedConst x = case x of
+  (MetaKindedConst mk mc) -> S.liftM (MetaKindedConst mk) (rnMetaConst mc)
+  UnmetaKindedNull -> return UnmetaKindedNull
+
+mapMetaKindedConst :: Monad m => (MetaConst -> m MetaConst) -> MetaKindedConst -> m MetaKindedConst
+mapMetaKindedConst f x = case x of
+  (MetaKindedConst mk mc) -> S.liftM (MetaKindedConst mk) (f mc)
+  UnmetaKindedNull -> return UnmetaKindedNull
+
+rnConst :: Const -> MS Const
+rnConst (C_complex x) = S.liftM C_complex (rnComplexConstant x)
+rnConst (C_localId x) = S.liftM C_localId (rnLocalId x)
+rnConst (C_labelId l) = S.liftM C_labelId (rnLabelId l)
+rnConst (C_blockAddress g l) = S.liftM (C_blockAddress g) (rnPercentLabel l)
+rnConst (C_binexp bexpr) = S.liftM C_binexp (rnBinExpr rnConst bexpr)
+rnConst (C_conv convert) = S.liftM C_conv (rnConversion rnTypedConst convert)
+rnConst (C_gep getelm) = S.liftM C_gep (rnGetElemPtr rnTypedConst getelm)
+rnConst (C_select select) = S.liftM C_select (rnSelect rnTypedConst select)
+rnConst (C_icmp icmp) = S.liftM C_icmp (rnIcmp rnConst icmp)
+rnConst (C_fcmp fcmp) = S.liftM C_fcmp (rnFcmp rnConst fcmp)
+rnConst (C_shufflevector shuffle) = S.liftM C_shufflevector (rnShuffleVector rnTypedConst shuffle)
+rnConst (C_extractvalue extract) = S.liftM C_extractvalue (rnExtractValue rnTypedConst extract)
+rnConst (C_insertvalue insert) = S.liftM C_insertvalue (rnInsertValue rnTypedConst insert)
+rnConst (C_extractelement extract) = S.liftM C_extractelement (rnExtractElem rnTypedConst extract)
+rnConst (C_insertelement insert) = S.liftM C_insertelement (rnInsertElem rnTypedConst insert)
+rnConst x = return x
+
+rnComplexConstant :: ComplexConstant -> MS ComplexConstant
+rnComplexConstant (Cstruct b l) = S.liftM (Cstruct b) (S.mapM (mapTypedConstOrNull rnTypedConst) l)
+rnComplexConstant (Carray l) = S.liftM Carray (S.mapM (mapTypedConstOrNull rnTypedConst) l)
+rnComplexConstant (Cvector l) = S.liftM Cvector (S.mapM (mapTypedConstOrNull rnTypedConst) l)
+
+rnTypedConst :: Typed Const -> MS (Typed Const)                                  
+rnTypedConst (Typed t c) = S.liftM (Typed t) (rnConst c)
+
+rnPrefix :: Maybe Prefix -> MS (Maybe Prefix)
+rnPrefix (Just (Prefix n)) = S.liftM (Just . Prefix) (mapTypedConstOrNull rnTypedConst n)
+rnPrefix _ = return Nothing
+
+rnPrologue :: Maybe Prologue -> MS (Maybe Prologue)
+rnPrologue (Just (Prologue n)) = S.liftM (Just . Prologue) (mapTypedConstOrNull rnTypedConst n)
+rnPrologue _ = return Nothing
+
+
+
+------------------------------------------------------------------------
+-- iteration 2
+------------------------------------------------------------------------
+type RD a = R.Reader (GlobalId, (M.Map GlobalId LabelNumbers)) a
+
+iter2 :: M.Map GlobalId LabelNumbers -> [Toplevel] -> [Toplevel]
+#ifdef DEBUG
+iter2 m tl | trace ("iter2 " ++ show m) False = undefined
+#endif
+iter2 m tl = fmap (rnToplevel2 m) tl
+  
+rnToplevel2 :: M.Map GlobalId LabelNumbers -> Toplevel -> Toplevel
+rnToplevel2 m (ToplevelGlobal (TlGlobal v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 const v12 v13 v14)) = 
+  R.runReader (do { x <- maybe (return Nothing) (\x -> R.liftM Just (rnConst2 x)) const
+                  ; return (ToplevelGlobal (TlGlobal v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 const v12 v13 v14))
+                  }) (GlobalIdNum 0, m)
+rnToplevel2 m (ToplevelDefine (TlDefine fp@(FunctionPrototype _ _ _ _ _ _ fhName _ _ _ _ _ _ _ _ _) bs)) = 
+  let (fp2, bs2) = R.runReader (do { fp' <- rnDefFunctionPrototype2 fp
+                                   ; bs' <- S.mapM rnBlock2 bs
+                                   ; return (fp', bs')
+                                   }) (fhName, m) -- 
+  in (ToplevelDefine (TlDefine fp2 bs2))
+rnToplevel2 _ x = x
+
+
+rnBlock2 :: Block -> RD Block
+rnBlock2 (Block lbl phi comp term) = do { phi' <- mapM rnPhiInstWithDbg2 phi
+                                        ; comp' <- mapM rnComputingInstWithDbg2 comp
+                                        ; term' <- rnTerminatorInstWithDbg2 term
+                                        ; return (Block lbl phi' comp' term')
+                                        }
+
+
+rnPhiInstWithDbg2 :: PhiInstWithDbg -> RD PhiInstWithDbg
+rnPhiInstWithDbg2 (PhiInstWithDbg ins dbgs) = S.liftM (\x -> PhiInstWithDbg x dbgs) (rnPhi2 ins)
+
+rnPhi2 :: PhiInst -> RD PhiInst
+rnPhi2 (PhiInst lhs t ins) = do { ins' <- S.mapM g ins
+                                ; return $ PhiInst lhs t ins'
+                                }
+  where g (v, p) = do { v' <- rnValue2 v
+                      ; p' <- rnMyPercentLabel2 p
+                      ; return (v', p')
+                      }
+
+rnComputingInstWithDbg2 :: ComputingInstWithDbg -> RD ComputingInstWithDbg
+rnComputingInstWithDbg2 (ComputingInstWithDbg c l) = 
+  R.liftM (\x -> ComputingInstWithDbg x l) (rnComputingInst2 c)
+
+rnComputingInst2 :: ComputingInst -> RD ComputingInst
+#ifdef DEBUG
+rnComputingInst2 x | trace ("rnComputingInst2 " ++ show (x)) False = undefined
+#endif
+rnComputingInst2 (ComputingInst lhs rhs) = do { rhsa <- rnRhs2 rhs
+                                              ; return (ComputingInst lhs rhsa)
+                                              }
+
+
+rnRhs2 :: Rhs -> RD Rhs
+rnRhs2 lhs = case lhs of
+  RmO x -> S.liftM RmO (rnMemOp2 x)
+  Re x -> S.liftM Re (rnExpr2 x)
+  Call b cs -> S.liftM (Call b) (rnCallSite2 cs)
+  ReE e -> S.liftM ReE (rnExtractElem2 rnTypedValue2 e)
+  RiE e -> S.liftM RiE (rnInsertElem2 rnTypedValue2 e)
+  RsV e -> S.liftM RsV (rnShuffleVector2 rnTypedValue2 e)
+  ReV e -> S.liftM ReV (rnExtractValue2 rnTypedValue2 e)
+  RiV e -> S.liftM RiV (rnInsertValue2 rnTypedValue2 e)
+  RvA (VaArg tv t) -> S.liftM (\x -> RvA $ VaArg x t) (rnTypedValue2 tv)
+  RlP (LandingPad rt ft ix cl c) -> return lhs
+
+
+rnMemOp2 :: MemOp -> RD MemOp
+rnMemOp2 (Alloca m t tv a) = do { tv' <- maybeM rnTypedValue2 tv
+                                ; return (Alloca m t tv' a)
+                                }
+rnMemOp2 (Load a tp ma nt inv nl) = S.liftM (\x -> (Load a x ma nt inv nl)) (rnPointer2 rnTypedValue2 tp)
+rnMemOp2 (LoadAtomic at a tp ma) = S.liftM (\x -> (LoadAtomic at a x ma)) (rnPointer2 rnTypedValue2 tp)
+rnMemOp2 (Store a tv tp ma nt) = S.liftM2 (\x y -> (Store a x y ma nt))
+                                 (rnTypedValue2 tv) (rnPointer2 rnTypedValue2 tp)
+rnMemOp2 (StoreAtomic at a tv tp ma) = S.liftM2 (\x y -> (StoreAtomic at a x y ma))
+                                       (rnTypedValue2 tv) (rnPointer2 rnTypedValue2 tp)
+rnMemOp2 (Fence b f) = return (Fence b f)
+rnMemOp2 (CmpXchg wk b1 tp tv1 tv2 b2 mf ff) = 
+  S.liftM3 (\x y z -> CmpXchg wk b1 x y z b2 mf ff)
+  (rnPointer2 rnTypedValue2 tp)
+  (rnTypedValue2 tv1)
+  (rnTypedValue2 tv2)
+rnMemOp2 (AtomicRmw b1 ao tp tv b2 mf) = 
+  S.liftM2 (\x y -> AtomicRmw b1 ao x y b2 mf)
+  (rnPointer2 rnTypedValue2 tp)
+  (rnTypedValue2 tv)
+
+rnCallSite2 :: CallSite -> RD CallSite
+rnCallSite2 (CsFun c pa t fn aps fas) = 
+  do { x <- mapM rnActualParam2 aps
+     ; return (CsFun c pa t fn x fas)
+     }
+rnCallSite2 (CsAsm t dia b1 b2 qs1 qs2 aps fas) = 
+  do { apsa <- mapM rnActualParam2 aps
+     ; return (CsAsm t dia b1 b2 qs1 qs2 apsa fas)
+     }
+rnCallSite2 (CsConversion pas t c aps fas) = 
+  do { apsa <- mapM rnActualParam2 aps
+     ; return (CsConversion pas t c apsa fas)
+     }
+  
+rnActualParam2 :: ActualParam -> RD ActualParam
+rnActualParam2 (ActualParamData t ps ma v pa) = S.liftM (\x -> ActualParamData t ps ma x pa) (rnValue2 v)
+rnActualParam2 (ActualParamMeta mc) = S.liftM ActualParamMeta (rnMetaKindedConst2 mc)
+                                        
+  
+
+rnTerminatorInstWithDbg2 :: TerminatorInstWithDbg -> RD TerminatorInstWithDbg
+rnTerminatorInstWithDbg2 (TerminatorInstWithDbg t ds) = 
+  S.liftM (\x -> TerminatorInstWithDbg x ds) (rnTerminatorInst2 t)
+  
+  
+rnTerminatorInst2 :: TerminatorInst -> RD TerminatorInst
+rnTerminatorInst2 x = case x of
+  Return ls -> S.liftM Return (mapM rnTypedValue2 ls)
+  Br l -> S.liftM Br (rnTargetLabel2 l)
+  Cbr v tl fl -> S.liftM3 Cbr (rnValue2 v) (rnTargetLabel2 tl) (rnTargetLabel2 fl)
+  Switch t d cases -> S.liftM3 Switch (rnTypedValue2 t) (rnTargetLabel2 d) 
+                      (mapM (\(x,y) -> S.liftM2 (,)
+                                       (rnTypedValue2 x)
+                                       (rnTargetLabel2 y)) cases)
+  IndirectBr tv ls -> S.liftM2 IndirectBr
+                      (rnTypedValue2 tv) (mapM rnTargetLabel2 ls)
+  Invoke lhsOpt callSite tl fl -> do { cs <- (rnCallSite2 callSite)
+                                     ; tla <- (rnTargetLabel2 tl)
+                                     ; fla <- (rnTargetLabel2 fl)
+                                     ; return $ Invoke lhsOpt cs tla fla
+                                     }
+  Resume tv -> S.liftM Resume (rnTypedValue2 tv)
+  _ -> return x  
+
+rnTargetLabel2 :: TargetLabel -> RD TargetLabel
+rnTargetLabel2 (TargetLabel x) = S.liftM TargetLabel (rnMyPercentLabel2 x)
+
+rnDefFunctionPrototype2 :: FunctionPrototype -> RD FunctionPrototype
+rnDefFunctionPrototype2 fpt = return fpt
+
+
+rnConst2 :: Const -> RD Const
+rnConst2 (C_complex x) = S.liftM C_complex (rnComplexConstant2 x)
+rnConst2 (C_localId x) = S.liftM C_localId (rnLocalId2 x)
+rnConst2 (C_labelId l) = do { rd <- R.ask
+                            ; S.liftM C_labelId (rnLabelId2 (fst rd) l)
+                            }
+rnConst2 (C_blockAddress g l) = S.liftM (C_blockAddress g) (rnPercentLabel2 g l)
+rnConst2 (C_binexp bexpr) = S.liftM C_binexp (rnBinExpr2 rnConst2 bexpr)
+rnConst2 (C_conv convert) = S.liftM C_conv (rnConversion2 rnTypedConst2 convert)
+rnConst2 (C_gep getelm) = S.liftM C_gep (rnGetElemPtr2 rnTypedConst2 getelm)
+rnConst2 (C_select select) = S.liftM C_select (rnSelect2 rnTypedConst2 select)
+rnConst2 (C_icmp icmp) = S.liftM C_icmp (rnIcmp2 rnConst2 icmp)
+rnConst2 (C_fcmp fcmp) = S.liftM C_fcmp (rnFcmp2 rnConst2 fcmp)
+rnConst2 (C_shufflevector shuffle) = S.liftM C_shufflevector (rnShuffleVector2 rnTypedConst2 shuffle)
+rnConst2 (C_extractvalue extract) = S.liftM C_extractvalue (rnExtractValue2 rnTypedConst2 extract)
+rnConst2 (C_insertvalue insert) = S.liftM C_insertvalue (rnInsertValue2 rnTypedConst2 insert)
+rnConst2 (C_extractelement extract) = S.liftM C_extractelement (rnExtractElem2 rnTypedConst2 extract)
+rnConst2 (C_insertelement insert) = S.liftM C_insertelement (rnInsertElem2 rnTypedConst2 insert)
+rnConst2 x = return x
+
+
+
+rnComplexConstant2 :: ComplexConstant -> RD ComplexConstant
+rnComplexConstant2 (Cstruct b l) = S.liftM (Cstruct b) (S.mapM (mapTypedConstOrNull rnTypedConst2) l)
+rnComplexConstant2 (Carray l) = S.liftM Carray (S.mapM (mapTypedConstOrNull rnTypedConst2) l)
+rnComplexConstant2 (Cvector l) = S.liftM Cvector (S.mapM (mapTypedConstOrNull rnTypedConst2) l)
+                                  
+rnTypedConst2 :: Typed Const -> RD (Typed Const)                                  
+rnTypedConst2 (Typed t c) = S.liftM (Typed t) (rnConst2 c)
+
+mapTypedConstOrNull :: Monad m => (Typed Const -> m (Typed Const)) -> TypedConstOrNull -> m TypedConstOrNull
+mapTypedConstOrNull f (TypedConst tc) = S.liftM TypedConst (f tc)
+mapTypedConstOrNull f UntypedNull = return UntypedNull
+
+rnMetaConst2 :: MetaConst -> RD MetaConst
+rnMetaConst2 (McRef l) = R.liftM McRef (rnLocalId2 l)
+rnMetaConst2 (McStruct l) = R.liftM McStruct (S.mapM (mapMetaKindedConst rnMetaConst2) l) -- Const (rnConst2 c)
+rnMetaConst2 (McSimple sc) = return $ McSimple sc
+rnMetaConst2 x = return x
+
+rnMetaKindedConst2 :: MetaKindedConst -> RD MetaKindedConst
+rnMetaKindedConst2 x = case x of
+  (MetaKindedConst mk mc) -> R.liftM (MetaKindedConst mk) (rnMetaConst2 mc)
+  UnmetaKindedNull -> return UnmetaKindedNull  
+
+rnPercentLabel2 :: GlobalId -> PercentLabel -> RD PercentLabel
+rnPercentLabel2 g (PercentLabel x) = R.liftM PercentLabel (rnLabelId2 g x)
+
+rnMyPercentLabel2 :: PercentLabel -> RD PercentLabel 
+rnMyPercentLabel2 x = do { r <- R.ask
+                         ; rnPercentLabel2 (fst r) x
+                         }
+
+rnLabelId2 :: GlobalId -> LabelId -> RD LabelId
+rnLabelId2 g l = case l of
+  LabelNumber i -> do { b <- isImplicitNum g i
+                      ; if b then return $ LabelString (implicitLbPrefix ++ show i)
+                        else do { c <- isExplicitNum g i
+                                ; if c then return $ LabelString (explicitLbPrefix ++ show i)
+                                  else do { d <- isExplicitDqNum g i     
+                                          ; if d then return $ LabelDqNumber i
+                                            else error ("what happend??? " ++ show l)
+                                          }
+                                }
+                      }
+  LabelDqNumber i -> do { b <- isExplicitDqNum g i
+                        ; if b then return l
+                          else do { c <- isExplicitNum g i     
+                                  ; if c then return $ LabelString (explicitLbPrefix ++ show i)
+                                    else do { x <- R.ask
+                                            ; error ("what happend??? " ++ show l ++ " " ++ show x)
+                                            }
+                                  }
+                        }
+  _ -> return l
+
+isImplicitNum :: GlobalId -> Word32 {-Integer-} -> RD Bool
+isImplicitNum g i = do { (_,r) <- R.ask
+                       ; case M.lookup g r of
+                         Nothing -> return False
+                         Just st -> return $ St.member i (implicitNumbers st) 
+                       }
+                    
+isExplicitNum :: GlobalId -> Word32 {-Integer-} -> RD Bool
+isExplicitNum g i = do { (_,r) <- R.ask
+                       ; case M.lookup g r of
+                         Nothing -> return False
+                         Just st -> return $ St.member i (explicitNumbers st) 
+                       }
+
+isExplicitDqNum :: GlobalId -> Word32 {-Integer-} -> RD Bool
+isExplicitDqNum g i = do { (_,r) <- R.ask
+                         ; case M.lookup g r of
+                           Nothing -> return False
+                           Just st -> return $ St.member i (explicitDqNumbers st) 
+                         }
+
+rnPointer2 :: (a -> RD a) -> Pointer a -> RD (Pointer a)
+rnPointer2 f (Pointer v) = S.liftM Pointer (f v)
+
+rnExpr2 :: Expr -> RD Expr
+rnExpr2 (EgEp e) = S.liftM EgEp (rnGetElemPtr2 rnTypedValue2 e)
+rnExpr2 (EiC e) = S.liftM EiC (rnIcmp2 rnValue2 e)
+rnExpr2 (EfC e) = S.liftM EfC (rnFcmp2 rnValue2 e)
+rnExpr2 (Eb e) = S.liftM Eb (rnBinExpr2 rnValue2 e)
+rnExpr2 (Ec e) = S.liftM Ec (rnConversion2 rnTypedValue2 e)
+rnExpr2 (Es e) = S.liftM Es (rnSelect2 rnTypedValue2 e)
+
+
+rnGetElemPtr2 :: (Typed v -> RD (Typed v)) -> GetElementPtr v -> RD (GetElementPtr v)
+rnGetElemPtr2 fv (GetElementPtr b v vs) = do { v' <- rnPointer2 fv v
+                                             ; vs' <- mapM fv vs
+                                             ; return $ GetElementPtr b v' vs'
+                                             }
+
+rnIcmp2 :: (a -> RD a) -> Icmp a -> RD (Icmp a)
+rnIcmp2 f (Icmp o t v1 v2) = S.liftM2 (Icmp o t) (f v1) (f v2)
+
+rnFcmp2 :: (a -> RD a) -> Fcmp a -> RD (Fcmp a)
+rnFcmp2 f (Fcmp o t v1 v2) = S.liftM2 (Fcmp o t) (f v1) (f v2)
+
+rnIbinExpr2 :: (a -> RD a) -> IbinExpr a -> RD (IbinExpr a)
+rnIbinExpr2 f (IbinExpr o tf t v1 v2) = S.liftM2 (IbinExpr o tf t) (f v1) (f v2)
+
+rnFbinExpr2 :: (a -> RD a) -> FbinExpr a -> RD (FbinExpr a)
+rnFbinExpr2 f (FbinExpr o tf t v1 v2) = S.liftM2 (FbinExpr o tf t) (f v1) (f v2)
+
+rnBinExpr2 :: (a -> RD a) -> BinExpr a -> RD (BinExpr a)
+rnBinExpr2 f (Ie x) = S.liftM Ie (rnIbinExpr2 f x)
+rnBinExpr2 f (Fe x) = S.liftM Fe (rnFbinExpr2 f x)
+
+rnConversion2 :: (Typed a -> RD (Typed a)) -> Conversion a -> RD (Conversion a)
+rnConversion2 f (Conversion o v t) = S.liftM (\x -> Conversion o x t) (f v)
+
+rnSelect2 :: (Typed a -> RD (Typed a)) -> Select a -> RD (Select a)
+rnSelect2 f (Select v1 v2 v3) = S.liftM3 Select (f v1) (f v2) (f v3)
+
+rnValue2 :: Value -> RD Value
+rnValue2 (Val_local x) = S.liftM Val_local (rnLocalId2 x)
+rnValue2 (Val_const x) = S.liftM Val_const (rnConst2 x)
+
+
+rnTypedValue2 :: Typed Value -> RD (Typed Value)
+rnTypedValue2 (Typed t v) = S.liftM (Typed t) (rnValue2 v)
+
+rnLocalId2 :: LocalId -> RD LocalId
+rnLocalId2 x = return x;
+
+rnExtractElem2 :: (Typed a -> RD (Typed a)) -> ExtractElement a -> RD (ExtractElement a)
+rnExtractElem2 f (ExtractElement v1 v2) = S.liftM2 ExtractElement (f v1) (f v2)
+
+rnInsertElem2 :: (Typed a -> RD (Typed a)) -> InsertElement a -> RD (InsertElement a)
+rnInsertElem2 f (InsertElement v1 v2 v3) = S.liftM3 InsertElement (f v1) (f v2) (f v3)
+
+rnShuffleVector2 :: (Typed a -> RD (Typed a)) -> ShuffleVector a -> RD (ShuffleVector a)
+rnShuffleVector2 f (ShuffleVector v1 v2 v3) = S.liftM3 ShuffleVector (f v1) (f v2) (f v3)
+
+
+rnExtractValue2 :: (Typed a -> RD (Typed a)) -> ExtractValue a -> RD (ExtractValue a)
+rnExtractValue2 f (ExtractValue v s) = S.liftM (\x -> ExtractValue x s) (f v)
+
+
+rnInsertValue2 :: (Typed a -> RD (Typed a)) -> InsertValue a -> RD (InsertValue a)
+rnInsertValue2 f (InsertValue v1 v2 s) = S.liftM2 (\x y -> InsertValue x y s)
+                                         (f v1) (f v2)
+
+
+simplify :: Module -> Module
+simplify (Module ml) = let (sl, ml1) = iter1 ml
+                       in Module (iter2 ml1 sl)
diff --git a/src/Llvm/Data/Conversion/IrAstConversion.hs b/src/Llvm/Data/Conversion/IrAstConversion.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Conversion/IrAstConversion.hs
@@ -0,0 +1,1171 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Llvm.Data.Conversion.IrAstConversion(irToAst) where
+
+#define FLC  (I.FileLoc $(I.srcLoc))
+
+import qualified Compiler.Hoopl as H
+import qualified Control.Monad as Md
+import qualified Data.Map as M
+import qualified Llvm.Data.Ast as A
+import qualified Llvm.Data.Ir as I
+import Llvm.Util.Monadic (maybeM, pairM)
+import Llvm.Data.Conversion.TypeConversion
+import Control.Monad.Reader
+
+class Conversion l1 l2 | l1 -> l2 where
+  convert :: l1 -> l2
+
+type Rm = Reader (M.Map H.Label A.LabelId)
+
+instance Conversion a (Rm b) => Conversion (Maybe a) (Rm (Maybe b)) where
+  convert (Just x) = Md.liftM Just (convert x)
+  convert Nothing = return Nothing
+
+instance (Conversion a (Rm c), Conversion b (Rm c)) => Conversion (Either a b) (Rm c) where
+  convert (Left x) = (convert x)
+  convert (Right x) = (convert x)
+
+{- Ir to Ast conversion -} 
+instance Conversion H.Label (Rm A.LabelId) where
+  convert l = do { r <- ask
+                 ; case M.lookup l r of 
+                   Just l0 -> return l0
+                   Nothing -> return $  A.LabelDqString $ "_hoopl_label_" ++ show l 
+                 }
+
+convert_to_PercentLabel :: H.Label -> Rm A.PercentLabel
+convert_to_PercentLabel l = Md.liftM A.PercentLabel (convert l)
+
+convert_to_TargetLabel :: H.Label -> Rm A.TargetLabel
+convert_to_TargetLabel l = Md.liftM (A.TargetLabel . A.PercentLabel) (convert l)
+
+convert_to_BlockLabel :: H.Label -> Rm A.BlockLabel
+convert_to_BlockLabel l = Md.liftM A.ExplicitBlockLabel (convert l)
+    
+cnowrap :: Maybe I.NoWrap -> [A.TrapFlag]
+cnowrap = maybe [] (\x -> case x of
+                       I.Nsw -> [A.Nsw]
+                       I.Nuw -> [A.Nuw]
+                       I.Nsuw -> [A.Nsw, A.Nuw]
+                   )
+cexact :: Maybe a -> [A.TrapFlag]          
+cexact = maybe [] (\_ -> [A.Exact])
+
+
+instance Conversion v1 (Rm v2) => Conversion (I.Conversion I.ScalarB v1) (Rm (A.Conversion v2)) where
+  convert x = let (op, t1, u, dt1) = case x of
+                    I.Trunc (I.T t0 u0) dt0 -> (A.Trunc, tconvert () t0, u0, tconvert () dt0) 
+                    I.Zext (I.T t0 u0) dt0 -> (A.Zext, tconvert () t0, u0, tconvert () dt0)
+                    I.Sext (I.T t0 u0) dt0 -> (A.Sext, tconvert () t0, u0, tconvert () dt0)
+                    I.FpTrunc (I.T t0 u0) dt0 -> (A.FpTrunc, tconvert () t0, u0, tconvert () dt0)
+                    I.FpExt (I.T t0 u0) dt0 -> (A.FpExt, tconvert () t0, u0, tconvert () dt0)
+                    I.FpToUi (I.T t0 u0) dt0 -> (A.FpToUi, tconvert () t0, u0, tconvert () dt0)
+                    I.FpToSi (I.T t0 u0) dt0 -> (A.FpToSi, tconvert () t0, u0, tconvert () dt0)
+                    I.UiToFp (I.T t0 u0) dt0 -> (A.UiToFp, tconvert () t0, u0, tconvert () dt0)
+                    I.SiToFp (I.T t0 u0) dt0 -> (A.SiToFp, tconvert () t0, u0, tconvert () dt0)
+                    I.PtrToInt (I.T t0 u0) dt0 -> (A.PtrToInt, tconvert () t0, u0, tconvert () dt0)
+                    I.IntToPtr (I.T t0 u0) dt0 -> (A.IntToPtr, tconvert () t0, u0, tconvert () dt0)
+                    I.Bitcast (I.T t0 u0) dt0 -> (A.Bitcast, tconvert () t0, u0, tconvert () dt0)
+                    I.AddrSpaceCast (I.T t0 u0) dt0 -> (A.AddrSpaceCast, tconvert () t0, u0, tconvert () dt0)
+              in do { u1 <- convert u
+                    ; return $ A.Conversion op (A.Typed t1 u1) dt1
+                    }
+
+instance Conversion v1 (Rm v2) => Conversion (I.Conversion I.VectorB v1) (Rm (A.Conversion v2)) where
+  convert x = let (op, t1, u, dt1) = case x of
+                    I.Trunc (I.T t0 u0) dt0 -> (A.Trunc, tconvert () t0, u0, tconvert () dt0) 
+                    I.Zext (I.T t0 u0) dt0 -> (A.Zext, tconvert () t0, u0, tconvert () dt0)
+                    I.Sext (I.T t0 u0) dt0 -> (A.Sext, tconvert () t0, u0, tconvert () dt0)
+                    I.FpTrunc (I.T t0 u0) dt0 -> (A.FpTrunc, tconvert () t0, u0, tconvert () dt0)
+                    I.FpExt (I.T t0 u0) dt0 -> (A.FpExt, tconvert () t0, u0, tconvert () dt0)
+                    I.FpToUi (I.T t0 u0) dt0 -> (A.FpToUi, tconvert () t0, u0, tconvert () dt0)
+                    I.FpToSi (I.T t0 u0) dt0 -> (A.FpToSi, tconvert () t0, u0, tconvert () dt0)
+                    I.UiToFp (I.T t0 u0) dt0 -> (A.UiToFp, tconvert () t0, u0, tconvert () dt0)
+                    I.SiToFp (I.T t0 u0) dt0 -> (A.SiToFp, tconvert () t0, u0, tconvert () dt0)
+                    I.PtrToInt (I.T t0 u0) dt0 -> (A.PtrToInt, tconvert () t0, u0, tconvert () dt0)
+                    I.IntToPtr (I.T t0 u0) dt0 -> (A.IntToPtr, tconvert () t0, u0, tconvert () dt0)
+                    I.Bitcast (I.T t0 u0) dt0 -> (A.Bitcast, tconvert () t0, u0, tconvert () dt0)
+                    I.AddrSpaceCast (I.T t0 u0) dt0 -> (A.AddrSpaceCast, tconvert () t0, u0, tconvert () dt0)
+              in do { u1 <- convert u
+                    ; return $ A.Conversion op (A.Typed t1 u1) dt1
+                    }
+                 
+mkConversion :: (A.ConvertOp, A.Type, I.Const, A.Type) -> Rm A.Const
+mkConversion (op, t1, u, dt1) = do { u1 <- convert u
+                                   ; return $ A.C_conv $ A.Conversion op (A.Typed t1 u1) dt1                                   
+                                   }
+
+instance (Conversion v1 (Rm v2)) => Conversion (I.GetElementPtr I.ScalarB v1) (Rm (A.GetElementPtr v2)) where
+  convert (I.GetElementPtr b u us) = do { ua <- convert u
+                                        ; usa <- mapM convert us
+                                        ; return $ A.GetElementPtr b (A.Pointer ua) usa
+                                        }
+          
+instance (Conversion v1 (Rm v2)) => Conversion (I.GetElementPtr I.VectorB v1) (Rm (A.GetElementPtr v2)) where
+  convert (I.GetElementPtr b u us) = do { ua <- convert u
+                                        ; usa <- mapM convert us
+                                        ; return $ A.GetElementPtr b (A.Pointer ua) usa
+                                        }                                     
+
+instance Conversion v1 (Rm v2) => Conversion (I.T I.ScalarType v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T I.Dtype v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.ScalarB I.I) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.ScalarB I.F) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.ScalarB I.P) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.VectorB I.I) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.VectorB I.F) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.VectorB I.P) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.RecordB I.D) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.CodeFunB I.X) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.CodeLabelB I.X) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance Conversion v1 (Rm v2) => Conversion (I.T (I.Type I.FirstClassB I.D) v1) (Rm (A.Typed v2)) where
+  convert (I.T t v) = Md.liftM (A.Typed $ tconvert () t) (convert v)
+
+instance (Conversion v1 (Rm v2)) => Conversion (I.Select I.ScalarB I.I v1) (Rm (A.Select v2)) where
+  convert (I.Select u1 u2 u3) = Md.liftM3 A.Select (convert u1) (convert u2) (convert u3)
+
+instance (Conversion v1 (Rm v2)) => Conversion (I.Select I.ScalarB I.F v1) (Rm (A.Select v2)) where
+  convert (I.Select u1 u2 u3) = Md.liftM3 A.Select (convert u1) (convert u2) (convert u3)
+
+instance (Conversion v1 (Rm v2)) => Conversion (I.Select I.ScalarB I.P v1) (Rm (A.Select v2)) where
+  convert (I.Select u1 u2 u3) = Md.liftM3 A.Select (convert u1) (convert u2) (convert u3)
+
+instance (Conversion v1 (Rm v2)) => Conversion (I.Select I.VectorB I.I v1) (Rm (A.Select v2)) where
+  convert (I.Select u1 u2 u3) = Md.liftM3 A.Select (convert u1) (convert u2) (convert u3)
+
+instance (Conversion v1 (Rm v2)) => Conversion (I.Select I.VectorB I.F v1) (Rm (A.Select v2)) where
+  convert (I.Select u1 u2 u3) = Md.liftM3 A.Select (convert u1) (convert u2) (convert u3)
+
+instance (Conversion v1 (Rm v2)) => Conversion (I.Select I.VectorB I.P v1) (Rm (A.Select v2)) where
+  convert (I.Select u1 u2 u3) = Md.liftM3 A.Select (convert u1) (convert u2) (convert u3)
+
+instance Conversion v1 (Rm v2) => Conversion (I.Icmp I.ScalarB v1) (Rm (A.Icmp v2)) where
+  convert (I.Icmp op t u1 u2) = Md.liftM2 (A.Icmp op (tconvert () t)) (convert u1) (convert u2)
+
+instance Conversion v1 (Rm v2) => Conversion (I.Icmp I.VectorB v1) (Rm (A.Icmp v2)) where
+  convert (I.Icmp op t u1 u2) = Md.liftM2 (A.Icmp op (tconvert () t)) (convert u1) (convert u2)
+
+instance Conversion v1 (Rm v2) => Conversion (I.Fcmp I.ScalarB v1) (Rm (A.Fcmp v2)) where
+  convert (I.Fcmp op t u1 u2) = Md.liftM2 (A.Fcmp op (tconvert () t)) (convert u1) (convert u2)
+
+instance Conversion v1 (Rm v2) => Conversion (I.Fcmp I.VectorB v1) (Rm (A.Fcmp v2)) where
+  convert (I.Fcmp op t u1 u2) = Md.liftM2 (A.Fcmp op (tconvert () t)) (convert u1) (convert u2)
+
+instance Conversion v1 (Rm v2) => Conversion (I.ShuffleVector I.I v1) (Rm (A.ShuffleVector v2)) where
+  convert (I.ShuffleVector u1 u2 u3) = Md.liftM3 A.ShuffleVector (convert u1) (convert u2) (convert u3)
+
+instance Conversion v1 (Rm v2) => Conversion (I.ShuffleVector I.F v1) (Rm (A.ShuffleVector v2)) where
+  convert (I.ShuffleVector u1 u2 u3) = Md.liftM3 A.ShuffleVector (convert u1) (convert u2) (convert u3)
+
+instance Conversion v1 (Rm v2) => Conversion (I.ShuffleVector I.P v1) (Rm (A.ShuffleVector v2)) where
+  convert (I.ShuffleVector u1 u2 u3) = Md.liftM3 A.ShuffleVector (convert u1) (convert u2) (convert u3)
+
+instance Conversion v1 (Rm v2) => Conversion (I.ExtractValue v1) (Rm (A.ExtractValue v2)) where
+  convert (I.ExtractValue u s) = convert u >>= \u' -> return $ A.ExtractValue u' s
+
+instance Conversion v1 (Rm v2) => Conversion (I.InsertValue v1) (Rm (A.InsertValue v2)) where
+  convert (I.InsertValue u1 u2 s) = do { u1' <- convert u1
+                                       ; u2' <- convert u2
+                                       ; return $ A.InsertValue u1' u2' s
+                                       }
+
+instance Conversion v1 (Rm v2) => Conversion (I.ExtractElement I.I v1) (Rm (A.ExtractElement v2)) where
+  convert (I.ExtractElement u1 u2) = Md.liftM2 A.ExtractElement (convert u1) (convert u2)
+
+instance Conversion v1 (Rm v2) => Conversion (I.ExtractElement I.F v1) (Rm (A.ExtractElement v2)) where
+  convert (I.ExtractElement u1 u2) = Md.liftM2 A.ExtractElement (convert u1) (convert u2)
+
+instance Conversion v1 (Rm v2) => Conversion (I.ExtractElement I.P v1) (Rm (A.ExtractElement v2)) where
+  convert (I.ExtractElement u1 u2) = Md.liftM2 A.ExtractElement (convert u1) (convert u2)
+
+
+instance Conversion v1 (Rm v2) => Conversion (I.InsertElement I.I v1) (Rm (A.InsertElement v2)) where
+  convert (I.InsertElement u1 u2 u3) = Md.liftM3 A.InsertElement (convert u1) (convert u2) (convert u3)
+
+instance Conversion v1 (Rm v2) => Conversion (I.InsertElement I.F v1) (Rm (A.InsertElement v2)) where
+  convert (I.InsertElement u1 u2 u3) = Md.liftM3 A.InsertElement (convert u1) (convert u2) (convert u3)
+
+instance Conversion v1 (Rm v2) => Conversion (I.InsertElement I.P v1) (Rm (A.InsertElement v2)) where
+  convert (I.InsertElement u1 u2 u3) = Md.liftM3 A.InsertElement (convert u1) (convert u2) (convert u3)
+
+
+
+
+
+instance Conversion I.Const (Rm A.Const) where
+  convert x = case x of
+    I.C_int s -> return $ A.C_simple $ A.CpInt s 
+    I.C_uhex_int s -> return $ A.C_simple $ A.CpUhexInt s
+    I.C_shex_int s -> return $ A.C_simple $ A.CpShexInt s 
+    I.C_float s -> return $ A.C_simple $ A.CpFloat s
+    I.C_null -> return $ A.C_simple $ A.CpNull
+    I.C_undef -> return $ A.C_simple $ A.CpUndef
+    I.C_true -> return $ A.C_simple $ A.CpTrue
+    I.C_false -> return $ A.C_simple $ A.CpFalse
+    I.C_zeroinitializer -> return $ A.C_simple $ A.CpZeroInitializer
+    I.C_globalAddr s -> return $ A.C_simple $ A.CpGlobalAddr s
+    I.C_str s -> return $ A.C_simple $ A.CpStr s
+    I.C_u8 s -> return $ A.C_simple $ A.CpBconst $ A.BconstUint8 s
+    I.C_u16 s -> return $ A.C_simple $ A.CpBconst $ A.BconstUint16 s
+    I.C_u32 s -> return $ A.C_simple $ A.CpBconst $ A.BconstUint32 s 
+    I.C_u64 s -> return $ A.C_simple $ A.CpBconst $ A.BconstUint64 s
+    I.C_u96 s -> return $ A.C_simple $ A.CpBconst $ A.BconstUint96 s 
+    I.C_u128 s -> return $ A.C_simple $ A.CpBconst $ A.BconstUint128 s 
+    I.C_s8 s ->  return $ A.C_simple $ A.CpBconst $ A.BconstInt8 s 
+    I.C_s16 s -> return $ A.C_simple $ A.CpBconst $ A.BconstInt16 s
+    I.C_s32 s -> return $ A.C_simple $ A.CpBconst $ A.BconstInt32 s 
+    I.C_s64 s -> return $ A.C_simple $ A.CpBconst $ A.BconstInt64 s 
+    I.C_s96 s -> return $ A.C_simple $ A.CpBconst $ A.BconstInt96 s 
+    I.C_s128 s -> return $ A.C_simple $ A.CpBconst $ A.BconstInt128 s 
+
+
+    (I.C_struct b fs) -> Md.liftM (A.C_complex . (A.Cstruct b)) (mapM convert fs)
+    (I.C_vector fs) -> Md.liftM (A.C_complex . A.Cvector) (mapM convert fs)
+    (I.C_array fs) -> Md.liftM (A.C_complex . A.Carray) (mapM convert fs)
+    (I.C_vectorN n fs) -> do { v <- convert fs
+                             ; return  (A.C_complex $ A.Cvector $ (fmap (\_ -> v) [1..n]))
+                             }
+    (I.C_arrayN n fs) -> do { v <- convert fs
+                            ; return (A.C_complex $ A.Carray $ (fmap (\_ -> v) [1..n]))
+                            }
+    I.C_localId a -> return $ A.C_localId a
+    I.C_labelId a -> Md.liftM A.C_labelId (convert a)
+    I.C_block g a -> do { a' <- convert_to_PercentLabel a
+                        ; return $ A.C_blockAddress g a'
+                        }
+    I.C_add nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) 
+                          (Md.liftM2 (A.IbinExpr A.Add (cnowrap nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_sub nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                          (Md.liftM2 (A.IbinExpr A.Sub (cnowrap nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_mul nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                          (Md.liftM2 (A.IbinExpr A.Mul (cnowrap nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_udiv nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                           (Md.liftM2 (A.IbinExpr A.Udiv (cexact nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_sdiv nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                           (Md.liftM2 (A.IbinExpr A.Sdiv (cexact nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_urem t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                        (Md.liftM2 (A.IbinExpr A.Urem [] (tconvert () t)) (convert u1) (convert u2))
+    I.C_srem t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                        (Md.liftM2 (A.IbinExpr A.Srem [] (tconvert () t)) (convert u1) (convert u2))
+    I.C_shl nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                          (Md.liftM2 (A.IbinExpr A.Shl (cnowrap nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_lshr nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                           (Md.liftM2 (A.IbinExpr A.Lshr (cexact nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_ashr nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                           (Md.liftM2 (A.IbinExpr A.Ashr (cexact nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_and t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                       (Md.liftM2 (A.IbinExpr A.And [] (tconvert () t)) (convert u1) (convert u2))
+    I.C_or t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                      (Md.liftM2 (A.IbinExpr A.Or [] (tconvert () t)) (convert u1) (convert u2))
+    I.C_xor t u1 u2 -> Md.liftM (A.C_binexp . A.Ie)
+                       (Md.liftM2 (A.IbinExpr A.Xor [] (tconvert () t)) (convert u1) (convert u2))
+
+
+    I.C_add_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) (Md.liftM2 (A.IbinExpr A.Add (cnowrap nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_sub_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) (Md.liftM2 (A.IbinExpr A.Sub (cnowrap nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_mul_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) (Md.liftM2 (A.IbinExpr A.Mul (cnowrap nw) (tconvert () t)) (convert u1) (convert u2))
+    I.C_udiv_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Udiv (cexact nw) (tconvert () t)) (convert u1) (convert u2)
+    I.C_sdiv_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Sdiv (cexact nw) (tconvert () t)) (convert u1) (convert u2)
+    I.C_urem_V t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Urem [] (tconvert () t)) (convert u1) (convert u2)
+    I.C_srem_V t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Srem [] (tconvert () t)) (convert u1) (convert u2)
+    I.C_shl_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Shl (cnowrap nw) (tconvert () t)) (convert u1) (convert u2)
+    I.C_lshr_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Lshr (cexact nw) (tconvert () t)) (convert u1) (convert u2)
+    I.C_ashr_V nw t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Ashr (cexact nw) (tconvert () t)) (convert u1) (convert u2)
+    I.C_and_V t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.And [] (tconvert () t)) (convert u1) (convert u2)
+    I.C_or_V t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Or [] (tconvert () t)) (convert u1) (convert u2)
+    I.C_xor_V t u1 u2 -> Md.liftM (A.C_binexp . A.Ie) $ Md.liftM2 (A.IbinExpr A.Xor [] (tconvert () t)) (convert u1) (convert u2)
+
+    I.C_fadd fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fadd fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_fsub fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fsub fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_fmul fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fmul fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_fdiv fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fdiv fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_frem fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Frem fg (tconvert () t)) (convert u1) (convert u2)
+
+    I.C_fadd_V fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fadd fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_fsub_V fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fsub fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_fmul_V fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fmul fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_fdiv_V fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Fdiv fg (tconvert () t)) (convert u1) (convert u2)
+    I.C_frem_V fg t u1 u2 -> Md.liftM (A.C_binexp . A.Fe) $ Md.liftM2 (A.FbinExpr A.Frem fg (tconvert () t)) (convert u1) (convert u2)
+
+    I.C_trunc (I.T t0 u0) dt0 -> mkConversion (A.Trunc, tconvert () t0, u0, tconvert () dt0) 
+    I.C_zext (I.T t0 u0) dt0 -> mkConversion (A.Zext, tconvert () t0, u0, tconvert () dt0)
+    I.C_sext (I.T t0 u0) dt0 -> mkConversion (A.Sext, tconvert () t0, u0, tconvert () dt0)
+    I.C_fptrunc (I.T t0 u0) dt0 -> mkConversion (A.FpTrunc, tconvert () t0, u0, tconvert () dt0)
+    I.C_fpext (I.T t0 u0) dt0 -> mkConversion (A.FpExt, tconvert () t0, u0, tconvert () dt0)
+    I.C_fptoui (I.T t0 u0) dt0 -> mkConversion (A.FpToUi, tconvert () t0, u0, tconvert () dt0)
+    I.C_fptosi (I.T t0 u0) dt0 -> mkConversion (A.FpToSi, tconvert () t0, u0, tconvert () dt0)
+    I.C_uitofp (I.T t0 u0) dt0 -> mkConversion (A.UiToFp, tconvert () t0, u0, tconvert () dt0)
+    I.C_sitofp (I.T t0 u0) dt0 -> mkConversion (A.SiToFp, tconvert () t0, u0, tconvert () dt0)
+    I.C_ptrtoint (I.T t0 u0) dt0 -> mkConversion (A.PtrToInt, tconvert () t0, u0, tconvert () dt0)
+    I.C_inttoptr (I.T t0 u0) dt0 -> mkConversion (A.IntToPtr, tconvert () t0, u0, tconvert () dt0)
+    I.C_addrspacecast (I.T t0 u0) dt0 -> mkConversion (A.AddrSpaceCast, tconvert () t0, u0, tconvert () dt0)
+
+    I.C_bitcast (I.T t0 u0) dt0 -> mkConversion (A.Bitcast, tconvert () t0, u0, tconvert () dt0)
+    
+    I.C_trunc_V (I.T t0 u0) dt0 -> mkConversion (A.Trunc, tconvert () t0, u0, tconvert () dt0) 
+    I.C_zext_V (I.T t0 u0) dt0 -> mkConversion (A.Zext, tconvert () t0, u0, tconvert () dt0)
+    I.C_sext_V (I.T t0 u0) dt0 -> mkConversion (A.Sext, tconvert () t0, u0, tconvert () dt0)
+    I.C_fptrunc_V (I.T t0 u0) dt0 -> mkConversion (A.FpTrunc, tconvert () t0, u0, tconvert () dt0)
+    I.C_fpext_V (I.T t0 u0) dt0 -> mkConversion (A.FpExt, tconvert () t0, u0, tconvert () dt0)
+    I.C_fptoui_V (I.T t0 u0) dt0 -> mkConversion (A.FpToUi, tconvert () t0, u0, tconvert () dt0)
+    I.C_fptosi_V (I.T t0 u0) dt0 -> mkConversion (A.FpToSi, tconvert () t0, u0, tconvert () dt0)
+    I.C_uitofp_V (I.T t0 u0) dt0 -> mkConversion (A.UiToFp, tconvert () t0, u0, tconvert () dt0)
+    I.C_sitofp_V (I.T t0 u0) dt0 -> mkConversion (A.SiToFp, tconvert () t0, u0, tconvert () dt0)
+    I.C_ptrtoint_V (I.T t0 u0) dt0 -> mkConversion (A.PtrToInt, tconvert () t0, u0, tconvert () dt0)
+    I.C_inttoptr_V (I.T t0 u0) dt0 -> mkConversion (A.IntToPtr, tconvert () t0, u0, tconvert () dt0)
+    I.C_addrspacecast_V (I.T t0 u0) dt0 -> mkConversion (A.AddrSpaceCast, tconvert () t0, u0, tconvert () dt0)
+
+    I.C_getelementptr b u us -> do { ua <- convert u
+                                   ; usa <- mapM convert us
+                                   ; return $ A.C_gep $ A.GetElementPtr b (A.Pointer ua) usa
+                                   }
+
+    I.C_getelementptr_V b u us -> do { ua <- convert u
+                                     ; usa <- mapM convert us
+                                     ; return $ A.C_gep $ A.GetElementPtr b (A.Pointer ua) usa
+                                     }
+    I.C_select_I a -> Md.liftM A.C_select (convert a)
+    I.C_select_F a -> Md.liftM A.C_select (convert a)
+    I.C_select_P a -> Md.liftM A.C_select (convert a)
+    I.C_select_First cnd t f -> do { cnda <- convert cnd 
+                                   ; ta <- convert t
+                                   ; fa <- convert f
+                                   ; return $ A.C_select (A.Select cnda ta fa)
+                                   }
+    I.C_select_VI a -> Md.liftM A.C_select (convert a)
+    I.C_select_VF a -> Md.liftM A.C_select (convert a)
+    I.C_select_VP a -> Md.liftM A.C_select (convert a)
+    I.C_icmp a -> Md.liftM A.C_icmp (convert a)
+    I.C_icmp_V a -> Md.liftM A.C_icmp (convert a)
+    I.C_fcmp a -> Md.liftM A.C_fcmp (convert a)
+    I.C_fcmp_V a -> Md.liftM A.C_fcmp (convert a)
+    I.C_shufflevector_I a -> Md.liftM A.C_shufflevector (convert a)
+    I.C_shufflevector_F a -> Md.liftM A.C_shufflevector (convert a)
+    I.C_shufflevector_P a -> Md.liftM A.C_shufflevector (convert a)
+    I.C_extractvalue a -> Md.liftM A.C_extractvalue (convert a)
+    I.C_insertvalue a -> Md.liftM A.C_insertvalue (convert a)
+    I.C_extractelement_I a -> Md.liftM A.C_extractelement (convert a)
+    I.C_extractelement_F a -> Md.liftM A.C_extractelement (convert a)
+    I.C_extractelement_P a -> Md.liftM A.C_extractelement (convert a) 
+    I.C_insertelement_I a -> Md.liftM A.C_insertelement (convert a)
+    I.C_insertelement_F a -> Md.liftM A.C_insertelement (convert a)
+    I.C_insertelement_P a -> Md.liftM A.C_insertelement (convert a)
+
+
+instance Conversion I.MdVar (Rm A.MdVar) where
+    convert (I.MdVar s) = return $ A.MdVar s
+
+instance Conversion I.MdNode (Rm A.MdNode) where
+    convert (I.MdNode s) = return $ A.MdNode s
+
+instance Conversion I.MetaConst (Rm A.MetaConst) where
+    convert (I.McStruct c) = mapM convert c >>= return . A.McStruct
+    convert (I.McString s) = return $ A.McString s
+    convert (I.McMn n) = convert n >>= return . A.McMn
+    convert (I.McMv n) = convert n >>= return . A.McMv
+    convert (I.McRef i) = return $ A.McRef i
+    convert (I.McSimple sc) = Md.liftM A.McSimple (convert sc)
+
+instance Conversion I.MetaKindedConst (Rm A.MetaKindedConst) where
+  convert x = case x of
+    (I.MetaKindedConst mk mc) -> Md.liftM (A.MetaKindedConst (tconvert () mk)) (convert mc)
+    I.UnmetaKindedNull -> return A.UnmetaKindedNull
+
+instance Conversion I.FunName (Rm A.FunName) where
+    convert (I.FunNameGlobal g) = return $ A.FunNameGlobal g
+    convert (I.FunNameString s) = return $ A.FunNameString s
+
+instance Conversion I.Value (Rm A.Value) where
+    convert (I.Val_ssa a) = return $ A.Val_local a
+    convert (I.Val_const a) = Md.liftM A.Val_const (convert a)
+
+instance Conversion I.CallSiteType (Rm A.Type) where
+  convert t = case t of
+    I.CallSiteRet x -> return $ tconvert () x
+    I.CallSiteFun ft as -> return $ tconvert () (I.Tpointer (I.ucast ft) as)
+    
+instance Conversion I.CallSite (Rm A.CallSite) where
+    convert  (I.CsFun cc pa t fn aps fa) = do { fna <- convert fn
+                                              ; apsa <- mapM convert aps
+                                              ; ta <- convert t
+                                              ; return $ A.CsFun cc pa ta fna apsa fa
+                                              }
+    convert (I.CsAsm t dia b1 b2 qs1 qs2 as fa) = do { asa <- mapM convert as
+                                                     ; ta <- convert t
+                                                     ; return $ A.CsAsm ta dia b1 b2 qs1 qs2 asa fa
+                                                     }
+    convert (I.CsConversion pa t cv as fa) = do { cva <- convert cv
+                                                ; asa <- mapM convert as
+                                                ; ta <- convert t
+                                                ; return $ A.CsConversion pa ta cva asa fa
+                                                }
+    convert (I.CsConversionV pa t cv as fa) = do { cva <- convert cv
+                                                 ; asa <- mapM convert as
+                                                 ; ta <- convert t
+                                                 ; return $ A.CsConversion pa ta cva asa fa
+                                                 }
+
+
+instance Conversion I.Clause (Rm A.Clause) where
+    convert (I.Catch tv) = convert tv >>= \tv' -> return $ A.Catch tv'
+    convert (I.Filter tc) = convert tc >>= \tc' -> return $ A.Filter tc'
+    convert (I.CcoS tc) = convert tc >>= return . A.Cco
+    convert (I.CcoV tc) = convert tc >>= return . A.Cco    
+
+instance Conversion I.GlobalOrLocalId (Rm A.GlobalOrLocalId) where
+    convert g = return g
+
+instance Conversion I.PersFn (Rm A.PersFn) where
+    convert (I.PersFnId s) = return $ A.PersFnId $ s
+    convert (I.PersFnCastS c) = convert c >>= return . A.PersFnCast
+    convert (I.PersFnCastV c) = convert c >>= return . A.PersFnCast    
+    convert (I.PersFnUndef) = return $ A.PersFnUndef
+    convert (I.PersFnNull) = return $ A.PersFnNull
+    convert (I.PersFnConst c) = Md.liftM A.PersFnConst (convert c)
+
+
+instance Conversion I.CInst (Rm A.ComputingInst) where
+  convert cinst = case cinst of 
+    I.I_alloca mar t mtv ma lhs -> do { mtva <- maybeM convert mtv 
+                                      ; return $ A.ComputingInst (Just lhs) $ A.RmO $ A.Alloca mar (tconvert () t) mtva ma
+                                      }
+    I.I_load atom tv aa nonterm invr nonull lhs -> do { tva <- convert tv 
+                                                      ; return $ A.ComputingInst (Just lhs) $ A.RmO $ A.Load atom (A.Pointer tva) aa nonterm invr nonull
+                                                      }
+    I.I_loadatomic atom v tv aa lhs -> do { tva <- convert tv 
+                                          ; return $ A.ComputingInst (Just lhs) $ A.RmO $ A.LoadAtomic atom v (A.Pointer tva) aa
+                                          }
+    I.I_store atom tv1 tv2 aa nonterm -> do { tv1a <- convert tv1
+                                            ; tv2a <- convert tv2
+                                            ; return $ A.ComputingInst Nothing (A.RmO $ A.Store atom tv1a (A.Pointer tv2a) aa nonterm)
+                                            }
+    I.I_storeatomic atom v tv1 tv2 aa -> do { tv1a <- convert tv1
+                                            ; tv2a <- convert tv2
+                                            ; return $ A.ComputingInst Nothing (A.RmO $ A.StoreAtomic atom v tv1a (A.Pointer tv2a) aa)
+                                            }
+    I.I_cmpxchg_I wk b1 tv1 tv2 tv3 b2 sord ford lhs-> do { tv1a <- convert tv1
+                                                           ; tv2a <- convert tv2
+                                                           ; tv3a <- convert tv3
+                                                           ; return $ A.ComputingInst (Just lhs) (A.RmO $ A.CmpXchg wk b1 (A.Pointer tv1a) tv2a tv3a b2 sord ford)
+                                                           }
+    I.I_cmpxchg_F wk b1 tv1 tv2 tv3 b2 sord ford lhs->
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; tv3a <- convert tv3
+         ; return $ A.ComputingInst (Just lhs) (A.RmO $ A.CmpXchg wk b1 (A.Pointer tv1a) tv2a tv3a b2 sord ford)
+         }    
+    I.I_cmpxchg_P wk b1 tv1 tv2 tv3 b2 sord ford lhs->
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; tv3a <- convert tv3
+         ; return $ A.ComputingInst (Just lhs) (A.RmO $ A.CmpXchg wk b1 (A.Pointer tv1a) tv2a tv3a b2 sord ford)
+         }    
+    I.I_atomicrmw b1 op tv1 tv2 b2 mf lhs-> 
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; return $ A.ComputingInst (Just lhs) (A.RmO $ A.AtomicRmw b1 op (A.Pointer tv1a) tv2a b2 mf)
+         }
+    I.I_fence b fo -> return $ A.ComputingInst Nothing $ A.RmO $ A.Fence b fo 
+    I.I_va_arg tv t lhs-> 
+      do { tv1 <- convert tv
+         ; return $ A.ComputingInst (Just lhs) $ A.RvA $ A.VaArg tv1 (tconvert () t)
+         }
+    I.I_va_start (I.T t v) -> 
+      do { let t1 = tconvert () t
+         ; va <- convert v
+         ; return $ A.ComputingInst Nothing $ A.Call A.TcNon $ A.CsFun Nothing [] A.Tvoid (A.FunNameGlobal $ A.GolG $ A.GlobalIdAlphaNum "llvm.va_start") 
+           [A.ActualParamData t1 [] Nothing va []] []
+         }      
+    I.I_va_end (I.T t v) -> 
+      do { let t1 = tconvert () t
+         ; va <- convert v 
+         ; return $ A.ComputingInst Nothing $ A.Call A.TcNon $ A.CsFun Nothing [] A.Tvoid (A.FunNameGlobal $ A.GolG $ A.GlobalIdAlphaNum "llvm.va_end") 
+           [A.ActualParamData t1 [] Nothing va []] []
+         }      
+    I.I_landingpad t1 t2 pf b cs lhs-> 
+      do { pfa <- convert pf
+         ; csa <- mapM convert cs
+         ; return $ A.ComputingInst (Just lhs) (A.RlP $ A.LandingPad (tconvert () t1) (tconvert () t2) pfa b csa)
+         }
+    I.I_extractelement_I tv1 tv2 lhs-> 
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; return $ A.ComputingInst (Just lhs) (A.ReE $ A.ExtractElement tv1a tv2a)
+         }
+    I.I_extractelement_F tv1 tv2 lhs-> 
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; return $ A.ComputingInst (Just lhs) (A.ReE $ A.ExtractElement tv1a tv2a)
+         }
+    I.I_extractelement_P tv1 tv2 lhs-> 
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; return $ A.ComputingInst (Just lhs) (A.ReE $ A.ExtractElement tv1a tv2a)
+         }    
+    I.I_extractvalue tv1 idx lhs-> 
+      do { tv1a <- convert tv1
+         ; return $ A.ComputingInst (Just lhs) (A.ReV $ A.ExtractValue tv1a idx)
+         }
+    I.I_getelementptr b ptr idx lhs-> 
+      do { ptra <- convert ptr
+         ; idxa <- mapM convert idx
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.EgEp $ A.GetElementPtr b (A.Pointer ptra) idxa) 
+         }
+    I.I_getelementptr_V b ptr idx lhs ->
+      do { ptra <- convert ptr
+         ; idxa <- mapM convert idx
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.EgEp $ A.GetElementPtr b (A.Pointer ptra) idxa) 
+         }    
+    I.I_icmp op t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.EiC $ A.Icmp op (tconvert () t) v1a v2a)
+         }
+    I.I_icmp_V op t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.EiC $ A.Icmp op (tconvert () t) v1a v2a)
+         }    
+    I.I_fcmp op t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.EfC $ A.Fcmp op (tconvert () t) v1a v2a)
+         }
+    I.I_fcmp_V op t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.EfC $ A.Fcmp op (tconvert () t) v1a v2a)
+         }
+    I.I_add n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Add (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_sub n t v1 v2 lhs -> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Sub (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_mul n t v1 v2 lhs -> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Mul (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_udiv n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Udiv (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_sdiv n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Sdiv (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_urem t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Urem [] (tconvert () t) v1a v2a)
+         }
+    I.I_srem t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Srem [] (tconvert () t) v1a v2a)
+         }
+    I.I_shl n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Shl (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_lshr n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Lshr (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_ashr n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Ashr (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_and t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2 
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.And [] (tconvert () t) v1a v2a)
+         }
+    I.I_or t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Or [] (tconvert () t) v1a v2a)
+         }
+    I.I_xor t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Xor [] (tconvert () t) v1a v2a)
+         }
+    I.I_add_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Add (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_sub_V n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Sub (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_mul_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Mul (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_udiv_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Udiv (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_sdiv_V n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Sdiv (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_urem_V t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Urem [] (tconvert () t) v1a v2a)
+         }
+    I.I_srem_V t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Srem [] (tconvert () t) v1a v2a)
+         }
+    I.I_shl_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Shl (cnowrap n) (tconvert () t) v1a v2a)
+         }
+    I.I_lshr_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Lshr (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_ashr_V n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Ashr (cexact n) (tconvert () t) v1a v2a)
+         }
+    I.I_and_V t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.And [] (tconvert () t) v1a v2a)
+         }
+    I.I_or_V t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Or [] (tconvert () t) v1a v2a)
+         }
+    I.I_xor_V t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Ie $ A.IbinExpr A.Xor [] (tconvert () t) v1a v2a)
+         }    
+    I.I_fadd n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_fsub n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_fmul n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_fdiv n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_frem n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_fadd_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_fsub_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_fmul_V n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_fdiv_V n t v1 v2 lhs-> 
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_frem_V n t v1 v2 lhs->
+      do { v1a <- convert v1
+         ; v2a <- convert v2
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Eb $ A.Fe $ A.FbinExpr A.Fadd n (tconvert () t) v1a v2a)
+         }
+    I.I_trunc tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Trunc tva (tconvert () dt)) 
+         }
+    I.I_zext tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Zext tva (tconvert () dt)) 
+         }    
+    I.I_sext tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Sext tva (tconvert () dt)) 
+         }    
+    I.I_fptrunc tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpTrunc tva (tconvert () dt)) 
+         }    
+    I.I_fpext tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpExt tva (tconvert () dt)) 
+         }    
+    I.I_fptoui tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpToUi tva (tconvert () dt)) 
+         }    
+    I.I_fptosi tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpToSi tva (tconvert () dt)) 
+         }    
+    I.I_uitofp tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.UiToFp tva (tconvert () dt)) 
+         }    
+    I.I_sitofp tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.SiToFp tva (tconvert () dt)) 
+         }    
+    I.I_ptrtoint tv dt lhs ->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.PtrToInt tva (tconvert () dt)) 
+         }    
+    I.I_inttoptr tv dt lhs -> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.IntToPtr tva (tconvert () dt)) 
+         }    
+    I.I_bitcast tv dt lhs -> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Bitcast tva (tconvert () dt)) 
+         }    
+    I.I_bitcast_D tv dt lhs -> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Bitcast tva (tconvert () dt)) 
+         }      
+    I.I_addrspacecast tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.AddrSpaceCast tva (tconvert () dt)) 
+         }    
+    I.I_trunc_V tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Trunc tva (tconvert () dt)) 
+         }
+    I.I_zext_V tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Zext tva (tconvert () dt)) 
+         }    
+    I.I_sext_V tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.Sext tva (tconvert () dt)) 
+         }    
+    I.I_fptrunc_V tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpTrunc tva (tconvert () dt)) 
+         }    
+    I.I_fpext_V tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpExt tva (tconvert () dt)) 
+         }    
+    I.I_fptoui_V tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpToUi tva (tconvert () dt)) 
+         }    
+    I.I_fptosi_V tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.FpToSi tva (tconvert () dt)) 
+         }    
+    I.I_uitofp_V tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.UiToFp tva (tconvert () dt)) 
+         }    
+    I.I_sitofp_V tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.SiToFp tva (tconvert () dt)) 
+         }    
+    I.I_ptrtoint_V tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.PtrToInt tva (tconvert () dt)) 
+         }    
+    I.I_inttoptr_V tv dt lhs->
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.IntToPtr tva (tconvert () dt)) 
+         }    
+    I.I_addrspacecast_V tv dt lhs-> 
+      do { tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Ec $ A.Conversion A.AddrSpaceCast tva (tconvert () dt)) 
+         }    
+    I.I_select_I cnd t f lhs->
+      do { cnda <- convert cnd
+         ; ta <- convert t
+         ; fa <- convert f
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Es $ A.Select cnda ta fa) 
+         }
+    I.I_select_F cnd t f lhs->
+      do { cnda <- convert cnd
+         ; ta <- convert t
+         ; fa <- convert f
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Es $ A.Select cnda ta fa) 
+         }
+    I.I_select_P cnd t f lhs->
+      do { cnda <- convert cnd
+         ; ta <- convert t
+         ; fa <- convert f
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Es $ A.Select cnda ta fa) 
+         }
+    I.I_select_First cnd t f lhs->
+      do { cnda <- convert cnd
+         ; ta <- convert t
+         ; fa <- convert f
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Es $ A.Select cnda ta fa) 
+         }
+    I.I_select_VI cnd t f lhs-> 
+      do { cnda <- convert cnd
+         ; ta <- convert t
+         ; fa <- convert f
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Es $ A.Select cnda ta fa) 
+         }
+    I.I_select_VF cnd t f lhs-> 
+      do { cnda <- convert cnd
+         ; ta <- convert t
+         ; fa <- convert f
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Es $ A.Select cnda ta fa) 
+         }
+    I.I_select_VP cnd t f lhs-> 
+      do { cnda <- convert cnd
+         ; ta <- convert t
+         ; fa <- convert f
+         ; return $ A.ComputingInst (Just lhs) (A.Re $ A.Es $ A.Select cnda ta fa) 
+         }
+    I.I_insertelement_I vtv tv idx lhs-> 
+      do { vtva <- convert vtv
+         ; tva <- convert tv
+         ; idxa <- convert idx
+         ; return $ A.ComputingInst (Just lhs) (A.RiE $ A.InsertElement vtva tva idxa) 
+         }
+    I.I_insertelement_F vtv tv idx lhs-> 
+      do { vtva <- convert vtv
+         ; tva <- convert tv
+         ; idxa <- convert idx
+         ; return $ A.ComputingInst (Just lhs) (A.RiE $ A.InsertElement vtva tva idxa) 
+         }
+    I.I_insertelement_P vtv tv idx lhs-> 
+      do { vtva <- convert vtv
+         ; tva <- convert tv
+         ; idxa <- convert idx
+         ; return $ A.ComputingInst (Just lhs) (A.RiE $ A.InsertElement vtva tva idxa) 
+         }
+    I.I_shufflevector_I tv1 tv2 tv3 lhs->
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; tv3a <- convert tv3
+         ; return $ A.ComputingInst (Just lhs) (A.RsV $ A.ShuffleVector tv1a tv2a tv3a) 
+         }
+    I.I_shufflevector_F tv1 tv2 tv3 lhs->
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; tv3a <- convert tv3
+         ; return $ A.ComputingInst (Just lhs) (A.RsV $ A.ShuffleVector tv1a tv2a tv3a) 
+         }
+    I.I_shufflevector_P tv1 tv2 tv3 lhs-> 
+      do { tv1a <- convert tv1
+         ; tv2a <- convert tv2
+         ; tv3a <- convert tv3
+         ; return $ A.ComputingInst (Just lhs) (A.RsV $ A.ShuffleVector tv1a tv2a tv3a) 
+         }
+    I.I_insertvalue vtv tv idx lhs-> 
+      do { vtva <- convert vtv
+         ; tva <- convert tv
+         ; return $ A.ComputingInst (Just lhs) $ A.RiV $ A.InsertValue vtva tva idx 
+         }
+    I.I_call_fun tc cc pa cstype fn ap fna lhs-> 
+      do { csa <- convert (I.CsFun cc pa cstype fn ap fna)
+         ; return $ A.ComputingInst lhs $ A.Call tc csa 
+         }
+    I.I_call_other tc cs lhs->
+      do { csa <- convert cs
+         ; return $ A.ComputingInst lhs $ A.Call tc csa 
+         }
+    I.I_llvm_dbg_declare ap ->
+      do { apa <- mapM convert ap
+         ; return $ A.ComputingInst Nothing $ A.Call A.TcNon $ A.CsFun Nothing [] A.Tvoid (A.FunNameGlobal $ A.GolG $ A.GlobalIdAlphaNum "llvm.dbg.declare")
+           apa []
+         }
+    I.I_llvm_dbg_value ap ->
+      do { apa <- mapM convert ap
+         ; return $ A.ComputingInst Nothing $ A.Call A.TcNon $ A.CsFun Nothing [] A.Tvoid (A.FunNameGlobal $ A.GolG $ A.GlobalIdAlphaNum "llvm.dbg.value")
+           apa []
+         }      
+    I.I_llvm_memcpy memLen tv1 tv2 tv3 tv4 tv5 -> 
+      do { (A.Typed t1 v1) <- convert tv1
+         ; (A.Typed t2 v2) <- convert tv2
+         ; (A.Typed t3 v3) <- convert tv3
+         ; (A.Typed t4 v4) <- convert tv4
+         ; (A.Typed t5 v5) <- convert tv5
+         ; let nm = case memLen of
+                 I.MemLenI32 -> "llvm.memcpy.p0i8.p0i8.i32"
+                 I.MemLenI64 -> "llvm.memcpy.p0i8.p0i8.i64"
+         ; return $ A.ComputingInst Nothing $ A.Call A.TcNon $ A.CsFun Nothing [] A.Tvoid (A.FunNameGlobal $ A.GolG $ A.GlobalIdAlphaNum nm) 
+           [A.ActualParamData t1 [] Nothing v1 []
+           ,A.ActualParamData t2 [] Nothing v2 []
+           ,A.ActualParamData t3 [] Nothing v3 []
+           ,A.ActualParamData t4 [] Nothing v4 []
+           ,A.ActualParamData t5 [] Nothing v5 []
+           ] []
+         }   
+                                      
+instance Conversion I.ActualParam (Rm A.ActualParam) where
+  convert x = case x of
+    (I.ActualParamData t pa1 ma v pa2) -> do { va <- convert v 
+                                             ; return $ A.ActualParamData (tconvert () t) pa1 ma va pa2
+                                             }
+    (I.ActualParamLabel t pa1 ma v pa2) -> do { va <- convert v 
+                                              ; return $ A.ActualParamData (tconvert () t) pa1 ma va pa2
+                                              }
+    (I.ActualParamMeta mc) -> Md.liftM (A.ActualParamMeta) (convert mc)
+
+instance Conversion I.Aliasee (Rm A.Aliasee) where
+  convert (I.AtV tv) = Md.liftM A.AtV (convert tv)
+  convert (I.Ac a) = Md.liftM A.Ac (convert a)
+  convert (I.AcV a) = Md.liftM A.Ac (convert a)  
+  convert (I.Agep a) = Md.liftM A.AgEp (convert a)
+  convert (I.AgepV a) = Md.liftM A.AgEp (convert a)  
+
+instance Conversion I.Prefix (Rm A.Prefix) where
+  convert (I.Prefix n) = Md.liftM A.Prefix (convert n)
+
+instance Conversion I.Prologue (Rm A.Prologue) where
+  convert (I.Prologue n) = Md.liftM A.Prologue (convert n)
+
+instance Conversion I.TypedConstOrNull (Rm A.TypedConstOrNull) where
+  convert x = case x of
+    I.TypedConst tv -> Md.liftM A.TypedConst (convert tv)
+    I.UntypedNull -> return A.UntypedNull
+
+instance Conversion I.FunctionPrototype (Rm A.FunctionPrototype) where
+    convert (I.FunctionPrototype f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f10a f11 f12 f13 f14) =
+      do { f13' <- convert f13
+         ; f14' <- convert f14
+         ; return $ A.FunctionPrototype f0 f1 f2 f3 f4 (tconvert () f5) 
+           f6 (tconvert () f7) f8 f9 f10 f10a f11 f12 f13' f14'
+         }
+
+
+instance Conversion I.PhiInst (Rm A.PhiInst) where
+  convert (I.PhiInst mg t branches) = 
+    Md.liftM (A.PhiInst (Just mg) (tconvert () t)) 
+    (mapM (pairM convert convert_to_PercentLabel) branches)
+
+
+instance Conversion I.TerminatorInst (Rm A.TerminatorInst) where
+  convert (I.RetVoid) = return A.RetVoid
+  convert (I.Return tvs) = Md.liftM A.Return (mapM convert tvs)
+  convert (I.Br t) = Md.liftM A.Br (convert_to_TargetLabel t)
+  convert (I.Cbr cnd t f) = Md.liftM3 A.Cbr (convert cnd) (convert_to_TargetLabel t) (convert_to_TargetLabel f)
+  convert (I.IndirectBr cnd bs) = Md.liftM2 A.IndirectBr (convert cnd) (mapM convert_to_TargetLabel bs)
+  convert (I.Switch cnd d cases) = Md.liftM3 A.Switch (convert cnd) (convert_to_TargetLabel d) 
+                                   (mapM (pairM convert convert_to_TargetLabel) cases)
+  convert (I.Invoke cs t f mg) = Md.liftM3 (A.Invoke mg) (convert cs) (convert_to_TargetLabel t) (convert_to_TargetLabel f)
+  convert (I.InvokeCmd cs t f) = Md.liftM3 (A.Invoke Nothing) (convert cs) (convert_to_TargetLabel t) (convert_to_TargetLabel f)
+  convert (I.Resume tv) = Md.liftM A.Resume (convert tv)
+  convert I.Unreachable = return A.Unreachable
+  convert I.Unwind = return A.Unwind
+
+instance Conversion I.Dbg (Rm A.Dbg) where
+    convert (I.Dbg mv mc) = Md.liftM2 A.Dbg (convert mv) (convert mc)
+
+instance Conversion I.PhiInstWithDbg (Rm A.PhiInstWithDbg) where
+  convert (I.PhiInstWithDbg ins dbgs) = Md.liftM2 A.PhiInstWithDbg (convert ins) (mapM convert dbgs)
+
+instance Conversion I.CInstWithDbg (Rm A.ComputingInstWithDbg) where
+    convert (I.CInstWithDbg ins dbgs) = Md.liftM2 A.ComputingInstWithDbg (convert ins) (mapM convert dbgs)
+
+instance Conversion I.TerminatorInstWithDbg (Rm A.TerminatorInstWithDbg) where
+    convert (I.TerminatorInstWithDbg term dbgs) = Md.liftM2 A.TerminatorInstWithDbg (convert term) (mapM convert dbgs)
+    
+    
+    
+instance Conversion I.TlTriple (Rm A.TlTriple) where
+  convert (I.TlTriple x) = return (A.TlTriple x)
+
+instance Conversion I.TlDataLayout (Rm A.TlDataLayout) where
+  convert (I.TlDataLayout x) = return (A.TlDataLayout x)
+
+instance Conversion I.TlAlias (Rm A.TlAlias) where  
+  convert (I.TlAlias  g v dll tlm na l a) = convert a >>= return . (A.TlAlias g v dll tlm na l)
+
+instance Conversion I.TlDbgInit (Rm A.TlDbgInit) where
+  convert (I.TlDbgInit s i) = return (A.TlDbgInit s i)
+  
+instance Conversion I.TlStandaloneMd (Rm A.TlStandaloneMd) where  
+  convert (I.TlStandaloneMd s tv) = convert tv >>= return . (A.TlStandaloneMd s)
+
+instance Conversion I.TlNamedMd (Rm A.TlNamedMd) where  
+  convert (I.TlNamedMd m ns) = do { m' <- convert m
+                                  ; ns' <- mapM convert ns
+                                  ; return $ A.TlNamedMd m' ns'
+                                  }
+                               
+instance Conversion I.TlDeclare (Rm A.TlDeclare) where                               
+  convert (I.TlDeclare f) = convert f >>= return . A.TlDeclare
+  
+instance Conversion (I.TlDefine a) (Rm A.TlDefine) where
+  convert (I.TlDefine f elbl g) = 
+    do { (bl, bm) <- graphToBlocks g
+       ; f' <- convert f
+       ; elbla <- convert elbl
+       ; let entryblk = case M.lookup elbla bm of
+               Just x -> x
+               Nothing -> error $ "irrefutable: entry block " ++ show elbl ++ " does not exist."
+       ; let bs'' = entryblk:(filter (\x -> x /= entryblk) bl) 
+       ; return $ A.TlDefine f' bs''
+       } -- TODO: this method will NOT emit the new nodes generated by hoopl passes, it should be fixed ASAP.
+
+                             
+instance Conversion I.TlGlobal (Rm A.TlGlobal) where
+  convert x = case x of
+    (I.TlGlobalDtype a1 a2 a3 a4 a5 a6 a7 a8 a8a a9 a10 a11 a12 a13) ->
+      do { a10a <- maybeM convert a10
+         ; return $ A.TlGlobal a1 a2 a3 a4 a5 a6 (fmap (tconvert ()) a7) 
+           a8 a8a (tconvert () a9) a10a a11 a12 a13
+         }
+    (I.TlGlobalOpaque a1 a2 a3 a4 a5 a6 a7 a8 a8a a9 a10 a11 a12 a13) ->
+      do { a10a <- maybeM convert a10
+         ; return $ A.TlGlobal a1 a2 a3 a4 a5 a6 (fmap (tconvert ()) a7) 
+           a8 a8a (tconvert () a9) a10a a11 a12 a13
+         }
+    
+instance Conversion I.TlTypeDef (Rm A.TlTypeDef) where    
+  convert x = case x of
+    (I.TlFunTypeDef lid t) -> return (A.TlTypeDef lid (tconvert () t))
+    (I.TlDatTypeDef lid t) -> return (A.TlTypeDef lid (tconvert () t))
+    (I.TlOpqTypeDef lid t) -> return (A.TlTypeDef lid (tconvert () t))
+
+instance Conversion I.TlDepLibs (Rm A.TlDepLibs) where  
+  convert (I.TlDepLibs s) = return (A.TlDepLibs s)
+  
+instance Conversion I.TlUnamedType (Rm A.TlUnamedType) where  
+  convert (I.TlUnamedType i t) = return (A.TlUnamedType i (tconvert () t))
+  
+instance Conversion I.TlModuleAsm (Rm A.TlModuleAsm) where  
+  convert (I.TlModuleAsm s) = return (A.TlModuleAsm s)
+
+instance Conversion I.TlAttribute (Rm A.TlAttribute) where
+  convert (I.TlAttribute n l) = return (A.TlAttribute n l)
+  
+instance Conversion I.TlComdat (Rm A.TlComdat) where  
+  convert (I.TlComdat l s) = return (A.TlComdat l s)
+
+    
+type Pblock = (A.BlockLabel, [A.PhiInstWithDbg], [A.ComputingInstWithDbg])
+
+getLabelId :: A.BlockLabel -> A.LabelId
+getLabelId (A.ImplicitBlockLabel _) = error "ImplicitBlockLabel should be normalized"
+getLabelId (A.ExplicitBlockLabel l) = l
+
+convertNode :: I.Node a e x -> Rm ([A.Block], M.Map A.LabelId A.Block, Maybe Pblock)
+               -> Rm ([A.Block], M.Map A.LabelId A.Block, Maybe Pblock)
+convertNode (I.Nlabel a) p = do { (bl, bs, Nothing) <- p
+                                ; a' <- convert_to_BlockLabel a
+                                ; return (bl, bs, Just (a', [], []))
+                                }
+convertNode (I.Pinst a) p = do { (bl, bs, Just (pb, phis, [])) <- p
+                               ; a' <- convert a
+                               ; return (bl, bs, Just (pb, a':phis, []))
+                               }
+convertNode (I.Cinst a) p = do { (bl, bs, Just (pb, phis, cs)) <- p
+                               ; a' <- convert a
+                               ; return (bl, bs, Just (pb, phis, a':cs))
+                               }
+convertNode (I.Comment a) p = do { (bl, bs, Just (pb, phis, cs)) <- p
+                                 ; return (bl, bs, Just (pb, phis, (A.ComputingInstWithComment a):cs))
+                                 }
+convertNode (I.Tinst a) p = do { (bl, bs, pb) <- p
+                               ; a' <- convert a
+                               ; case pb of
+                                 Nothing -> error "irrefutable"
+                                 Just (l, phis, cs) ->
+                                   let blk = A.Block l (reverse phis) (reverse cs) a'
+                                   in return (blk:bl, M.insert (getLabelId l) blk bs, Nothing)
+                               }
+convertNode (I.Additional _) _ = error "irrefutable:Additional node should be converted to LLVM node"                            
+  
+graphToBlocks :: H.Graph (I.Node a) H.C H.C -> Rm ([A.Block], M.Map A.LabelId A.Block)
+graphToBlocks g = do { (bl, bs, Nothing) <- H.foldGraphNodes convertNode g (return ([], M.empty, Nothing))
+                     ; return (reverse bl, bs)
+                     }
+
+toplevel2Ast :: I.Toplevel a -> Rm A.Toplevel
+toplevel2Ast (I.ToplevelTriple q) = Md.liftM A.ToplevelTriple (convert q)
+toplevel2Ast (I.ToplevelDataLayout q) = Md.liftM A.ToplevelDataLayout (convert q)
+toplevel2Ast (I.ToplevelAlias g) = Md.liftM A.ToplevelAlias (convert g)
+toplevel2Ast (I.ToplevelDbgInit s) = Md.liftM A.ToplevelDbgInit (convert s)
+toplevel2Ast (I.ToplevelStandaloneMd s) = Md.liftM (A.ToplevelStandaloneMd) (convert s)
+toplevel2Ast (I.ToplevelNamedMd m) = Md.liftM A.ToplevelNamedMd (convert m) 
+toplevel2Ast (I.ToplevelDeclare f) = Md.liftM A.ToplevelDeclare (convert f)
+toplevel2Ast (I.ToplevelDefine f) = Md.liftM A.ToplevelDefine (convert f)
+toplevel2Ast (I.ToplevelGlobal s) = Md.liftM A.ToplevelGlobal (convert s)
+toplevel2Ast (I.ToplevelTypeDef t) = Md.liftM A.ToplevelTypeDef (convert t)
+toplevel2Ast (I.ToplevelDepLibs qs) = Md.liftM A.ToplevelDepLibs (convert qs)
+toplevel2Ast (I.ToplevelUnamedType i) = Md.liftM A.ToplevelUnamedType (convert i)
+toplevel2Ast (I.ToplevelModuleAsm q) = Md.liftM A.ToplevelModuleAsm (convert q)
+toplevel2Ast (I.ToplevelComdat l) = Md.liftM A.ToplevelComdat (convert l)
+toplevel2Ast (I.ToplevelAttribute n) = Md.liftM A.ToplevelAttribute (convert n)
+
+irToAst ::  M.Map H.Label A.LabelId -> I.Module a -> A.Module
+irToAst iLm (I.Module ts) = runReader (Md.liftM A.Module (mapM toplevel2Ast ts)) iLm
diff --git a/src/Llvm/Data/Conversion/LabelMapM.hs b/src/Llvm/Data/Conversion/LabelMapM.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Conversion/LabelMapM.hs
@@ -0,0 +1,77 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+module Llvm.Data.Conversion.LabelMapM
+       (IdLabelMap,labelFor,LabelMapM(..),runLabelMapM,emptyIdLabelMap
+       ,typeDefs,a2h,invertMap)
+       where
+import qualified Compiler.Hoopl as H
+import qualified Data.Map as M
+import qualified Llvm.Data.Ast as A
+import Control.Applicative
+import Control.Monad (ap, liftM)
+#ifdef DEBUG
+import Debug.Trace
+import Llvm.Data.AsmPrint
+import Llvm.Data.AstWriter
+#endif
+
+#define FLC  (I.FileLoc $(I.srcLoc))
+
+{-
+-- LabelMapM monad is a CheckingFuelMonad with a data structure IdLabelMap to track
+-- the mapping between LLVM labels and Hoopl labels and the original order LLVM labels
+-- the mapping will be used to convert Hoopl labels back to LLVM labels to make 
+-- llvm-as happy
+-}
+
+data IdLabelMap =
+  IdLabelMap
+  { a2h :: M.Map A.LabelId H.Label
+    -- | readonly value, it should be converted to a reader monad later
+  , typedefs :: M.Map A.LocalId A.Type 
+  } deriving (Show)
+
+data LabelMapM m a = LabelMapM { unIlM :: IdLabelMap -> m (IdLabelMap, a) }
+
+instance Functor m => Functor (LabelMapM m) where 
+  fmap f mla = LabelMapM $ \iLm -> let ma = unIlM mla iLm 
+                                       fx = \(im, a) -> (im, f a) 
+                                   in fmap fx ma 
+  
+instance (Functor m, Applicative m, Monad m, H.UniqueMonad m) => Applicative (LabelMapM m) where  
+  pure = return
+  (<*>) = ap 
+  
+-- | we need to get a fresh Hoopl label for each LLVM label, so we use Hoopl Unique Monad
+instance (Applicative m, H.UniqueMonad m) => Monad (LabelMapM m) where
+  return x = LabelMapM $ \iLm -> return (iLm, x)
+  iLmM >>= k = LabelMapM $ \iLm -> unIlM iLmM iLm >>= \(iLm1, x) -> unIlM (k x) iLm1
+
+
+labelFor :: H.UniqueMonad m => A.LabelId -> LabelMapM m H.Label
+labelFor al = LabelMapM $ \iLm -> case M.lookup al (a2h iLm) of
+                                    Just hl -> return (iLm, hl)
+                                    Nothing -> do { hl <- H.freshLabel
+                                                  ; let a2h' = M.insert al hl (a2h iLm)
+                                                  ; return (iLm { a2h = a2h'}, hl)
+                                                  }
+
+typeDefs :: H.UniqueMonad m => LabelMapM m (M.Map A.LocalId A.Type)
+typeDefs = LabelMapM $ \iLm -> return (iLm, typedefs iLm)
+
+revertMap :: A.LabelId -> A.BlockLabel
+revertMap (A.LabelNumber _) = error "irrefutable"
+revertMap x = A.ExplicitBlockLabel x
+
+emptyIdLabelMap td = IdLabelMap { a2h = M.empty, typedefs = td}
+
+runLabelMapM :: H.UniqueMonad m => IdLabelMap -> LabelMapM m a -> m (IdLabelMap, a)
+runLabelMapM iLm (LabelMapM f) = f iLm
+
+invertMap :: (Ord k, Ord v) => M.Map k v -> M.Map v k
+invertMap m = foldl (\p (k,v) -> if M.member v p then
+                                   error $ "irrefutable error in invertMap, the values are not unique"
+                                 else 
+                                   M.insert v k p
+                    ) M.empty (M.toList m)
diff --git a/src/Llvm/Data/Conversion/TypeConversion.hs b/src/Llvm/Data/Conversion/TypeConversion.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Conversion/TypeConversion.hs
@@ -0,0 +1,350 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Llvm.Data.Conversion.TypeConversion where
+
+import qualified Llvm.Data.Type as A
+import qualified Llvm.Data.IrType as I
+import qualified Data.Map as M
+import Data.Either 
+
+#define FLC   (I.FileLoc $(I.srcLoc))
+
+type MP = M.Map A.LocalId A.Type
+
+class TypeConversion mp l1 l2 where
+  tconvert :: mp -> l1 -> l2
+  
+{-Ast Type to Ir type conversion -}
+
+instance TypeConversion () I.Dtype A.Type where
+  tconvert _ t = case t of
+    I.DtypeScalarI x -> tconvert () x
+    I.DtypeScalarF x -> tconvert () x
+    I.DtypeScalarP x -> tconvert () x
+    I.DtypeVectorI x -> tconvert () x
+    I.DtypeVectorF x -> tconvert () x
+    I.DtypeVectorP x -> tconvert () x
+    I.DtypeRecordD x -> tconvert () x
+    I.DtypeFirstClassD x -> tconvert () x
+
+instance TypeConversion () I.ScalarType A.Type where
+  tconvert _ t = case t of
+    I.ScalarTypeI x -> tconvert () x
+    I.ScalarTypeF x -> tconvert () x
+    I.ScalarTypeP x -> tconvert () x
+
+instance TypeConversion () (I.IntOrPtrType I.ScalarB) A.Type where
+  tconvert _ t = case t of
+    I.IntOrPtrTypeI x -> tconvert () x
+    I.IntOrPtrTypeP x -> tconvert () x
+
+instance TypeConversion () (I.IntOrPtrType I.VectorB) A.Type where
+  tconvert _ t = case t of
+    I.IntOrPtrTypeI x -> tconvert () x
+    I.IntOrPtrTypeP x -> tconvert () x
+
+instance TypeConversion () (Either I.Rtype (I.Type I.CodeFunB I.X)) A.Type where
+  tconvert _ (Left e) = tconvert () e
+  tconvert _ (Right e) = tconvert () (I.Tpointer (I.ucast e) 0)
+
+instance TypeConversion () I.FormalParam A.FormalParam where
+  tconvert _ (I.FormalParamData dt pa1 ma fp pa2) = A.FormalParamData (tconvert () dt) pa1 ma fp pa2
+  tconvert _ (I.FormalParamMeta mk fp) = A.FormalParamMeta (tconvert () mk) fp
+
+instance TypeConversion () I.FormalParamList A.FormalParamList where
+  tconvert _ (I.FormalParamList l ma fas) = A.FormalParamList (fmap (tconvert ()) l) ma fas
+
+instance TypeConversion MP A.FormalParam I.FormalParam where
+  tconvert mp (A.FormalParamData dt pa1 ma fp pa2) = 
+    I.FormalParamData (I.dcast FLC ((tconvert mp dt)::I.Utype)) pa1 ma fp pa2
+  tconvert mp (A.FormalParamMeta mk fp) = I.FormalParamMeta (tconvert mp mk) fp
+
+instance TypeConversion MP A.FormalParamList I.FormalParamList where
+  tconvert mp (A.FormalParamList l ma fas) = I.FormalParamList (fmap (tconvert mp) l) ma fas
+
+instance TypeConversion () I.Rtype A.Type where  
+  tconvert _ t = case t of
+    I.RtypeScalarI x -> tconvert () x
+    I.RtypeScalarF x -> tconvert () x    
+    I.RtypeScalarP x -> tconvert () x    
+    I.RtypeVectorI x -> tconvert () x
+    I.RtypeVectorF x -> tconvert () x
+    I.RtypeVectorP x -> tconvert () x
+    I.RtypeRecordD x -> tconvert () x
+    I.RtypeFirstClassD x -> tconvert () x    
+    I.RtypeVoidU _ -> A.Tvoid 
+    
+instance TypeConversion () I.Etype A.Type where
+  tconvert _ t = case t of
+    I.EtypeScalarI x -> tconvert () x 
+    I.EtypeScalarF x -> tconvert () x     
+    I.EtypeScalarP x -> tconvert () x     
+    I.EtypeVectorI x -> tconvert () x
+    I.EtypeVectorF x -> tconvert () x    
+    I.EtypeVectorP x -> tconvert () x    
+    I.EtypeRecordD x -> tconvert () x
+    I.EtypeOpaqueD x -> tconvert () x
+    I.EtypeFunX x -> tconvert () x
+    
+instance TypeConversion () I.Ftype A.Type where
+  tconvert _ t = case t of
+    I.FtypeScalarI x -> tconvert () x
+    I.FtypeScalarF x -> tconvert () x    
+    I.FtypeScalarP x -> tconvert () x    
+    I.FtypeVectorI x -> tconvert () x
+    I.FtypeVectorF x -> tconvert () x    
+    I.FtypeVectorP x -> tconvert () x    
+    I.FtypeFirstClassD x -> tconvert () x
+
+
+instance TypeConversion MP A.TypeParamList I.TypeParamList where
+  tconvert mp (A.TypeParamList l ma) = 
+    let (l1::[I.Utype]) = fmap (tconvert mp) l
+    in I.TypeParamList (fmap (I.dcast FLC) l1) ma
+
+instance TypeConversion () I.TypeParamList A.TypeParamList where
+  tconvert _ (I.TypeParamList l ma) = A.TypeParamList (fmap (tconvert ()) l) ma
+
+instance TypeConversion MP A.Type I.Utype where
+  tconvert _ (A.Tprimitive et) = case et of 
+    A.TpI n -> I.UtypeScalarI $ I.TpI n
+    A.TpF n -> I.UtypeScalarF $ I.TpF n
+    A.TpV n -> I.UtypeScalarI $ I.TpV n
+    A.TpHalf -> I.UtypeScalarF $ I.TpHalf 
+    A.TpFloat -> I.UtypeScalarF $ I.TpFloat
+    A.TpDouble -> I.UtypeScalarF $ I.TpDouble
+    A.TpFp128 -> I.UtypeScalarF $ I.TpFp128 
+    A.TpX86Fp80 -> I.UtypeScalarF $ I.TpX86Fp80
+    A.TpPpcFp128 -> I.UtypeScalarF $ I.TpPpcFp128
+    A.TpX86Mmx -> I.UtypeScalarI $ I.TpX86Mmx
+    A.TpLabel -> I.UtypeLabelX $ I.TpLabel
+  tconvert _ A.Tvoid = I.ucast I.Tvoid
+  tconvert mp (A.Tarray n et) = 
+    let (eta::I.Utype) = tconvert mp et
+    in case eta of
+      I.UtypeOpaqueD _ -> I.UtypeOpaqueD $ I.Topaque_array n (I.dcast FLC eta)
+      _ -> I.UtypeRecordD $ I.Tarray n (I.dcast FLC eta)
+  tconvert mp (A.Tvector n et) = case matchType mp et of
+    Tk_ScalarI -> let et1 = I.dcast FLC $ ((tconvert mp et)::I.Utype)
+                  in I.UtypeVectorI $ I.TvectorI n et1
+    Tk_ScalarF -> let et1 = I.dcast FLC $ ((tconvert mp et)::I.Utype)
+                  in I.UtypeVectorF $ I.TvectorF n et1
+    Tk_ScalarP -> let et1 = I.dcast FLC $ ((tconvert mp et)::I.Utype)
+                  in I.UtypeVectorP $ I.TvectorP n et1
+    _ -> I.errorLoc FLC "$$$$$$$$$"
+  tconvert mp (A.Tstruct pk dts) = 
+    let (dts0::[I.Utype]) = fmap (tconvert mp) dts
+        dts1 = fmap (\e -> case e of
+                        I.UtypeOpaqueD ea -> Right ea
+                        _ -> Left ((I.dcast FLC e)::I.Dtype)
+                    ) dts0
+    in if any isRight dts1 then I.UtypeOpaqueD (I.Topaque_struct pk dts1)
+       else I.UtypeRecordD (I.Tstruct pk $ lefts dts1)
+  tconvert mp (A.Tpointer et as) = let n1 = case as of
+                                         A.AddrSpace n -> n
+                                         A.AddrSpaceUnspecified -> 0 
+                                       et1 = I.dcast FLC ((tconvert mp et)::I.Utype)  
+                                   in I.UtypeScalarP $ I.Tpointer et1 n1
+  tconvert mp A.Topaque = I.ucast $ I.Topaque
+  tconvert mp tn@(A.Tname s) = case getTk mp (castTnameToLocalId tn) of 
+    Tk_ScalarI -> I.ucast $ I.TnameScalarI s
+    Tk_ScalarF -> I.ucast $ I.TnameScalarF s
+    Tk_ScalarP -> I.ucast $ I.TnameScalarP s    
+    Tk_VectorI -> I.ucast $ I.TnameVectorI s
+    Tk_VectorF -> I.ucast $ I.TnameVectorF s
+    Tk_VectorP -> I.ucast $ I.TnameVectorP s
+    Tk_RecordD -> I.ucast $ I.TnameRecordD s
+    Tk_CodeFunX -> I.ucast $ I.TnameCodeFunX s
+    Tk_Opaque -> I.ucast $ I.TnameOpaqueD s
+  tconvert mp tn@(A.TquoteName s) = case getTk mp (castTnameToLocalId tn) of 
+    Tk_ScalarI -> I.ucast $ I.TquoteNameScalarI s
+    Tk_ScalarF -> I.ucast $ I.TquoteNameScalarF s    
+    Tk_ScalarP -> I.ucast $ I.TquoteNameScalarP s    
+    Tk_VectorI -> I.ucast $ I.TquoteNameVectorI s
+    Tk_VectorF -> I.ucast $ I.TquoteNameVectorF s    
+    Tk_VectorP -> I.ucast $ I.TquoteNameVectorP s    
+    Tk_RecordD -> I.ucast $ I.TquoteNameRecordD s
+    Tk_CodeFunX -> I.ucast $ I.TquoteNameCodeFunX s
+    Tk_Opaque -> I.ucast $ I.TquoteNameOpaqueD s    
+  tconvert mp tn@(A.Tno s) = case getTk mp (castTnameToLocalId tn) of 
+    Tk_ScalarI -> I.ucast $ I.TnoScalarI s
+    Tk_ScalarF -> I.ucast $ I.TnoScalarF s    
+    Tk_ScalarP -> I.ucast $ I.TnoScalarP s    
+    Tk_VectorI -> I.ucast $ I.TnoVectorI s
+    Tk_VectorF -> I.ucast $ I.TnoVectorF s
+    Tk_VectorP -> I.ucast $ I.TnoVectorP s
+    Tk_RecordD -> I.ucast $ I.TnoRecordD s
+    Tk_CodeFunX -> I.ucast $ I.TnoCodeFunX s
+    Tk_Opaque -> I.ucast $ I.TnoOpaqueD s
+  tconvert mp (A.Tfunction rt tp fa) = 
+    let rt1 = I.dcast FLC ((tconvert mp rt)::I.Utype)
+    in I.UtypeFunX (I.Tfunction rt1 (tconvert mp tp) fa)
+                                    
+                                    
+instance TypeConversion MP A.AddrSpace I.AddrSpace where                                    
+  tconvert _ (A.AddrSpace n) = n
+  tconvert _ (A.AddrSpaceUnspecified) = 0
+
+instance TypeConversion () I.AddrSpace A.AddrSpace where                                    
+  tconvert _ 0 = A.AddrSpaceUnspecified
+  tconvert _ n = A.AddrSpace n
+  
+instance TypeConversion MP A.MetaKind I.MetaKind where
+  tconvert mp x = case x of
+    A.Mtype e -> I.Mtype (tconvert mp e)
+    A.Mmetadata -> I.Mmetadata
+
+  
+instance TypeConversion () I.MetaKind A.MetaKind where
+  tconvert _ x = case x of
+    I.Mtype e -> A.Mtype (tconvert () e)
+    I.Mmetadata -> A.Mmetadata
+
+
+instance TypeConversion () (I.Type s r) A.Type where -- Primitive where
+  tconvert _ t = case t of
+    I.TpI n -> A.Tprimitive $ A.TpI n
+    I.TpF n -> A.Tprimitive $ A.TpF n
+    I.TpV n -> A.Tprimitive $ A.TpV n
+    I.TpHalf -> A.Tprimitive $ A.TpHalf 
+    I.TpFloat -> A.Tprimitive $ A.TpFloat
+    I.TpDouble -> A.Tprimitive $ A.TpDouble
+    I.TpFp128 -> A.Tprimitive $ A.TpFp128 
+    I.TpX86Fp80 -> A.Tprimitive $ A.TpX86Fp80
+    I.TpPpcFp128 -> A.Tprimitive $ A.TpPpcFp128
+    I.TpX86Mmx -> A.Tprimitive $ A.TpX86Mmx
+    I.Tpointer el 0 -> A.Tpointer (tconvert () el) A.AddrSpaceUnspecified
+    I.Tpointer el as -> A.Tpointer (tconvert () el) (A.AddrSpace as)
+    
+    I.Tarray n dt -> A.Tarray n (tconvert () dt)
+    I.Tstruct p dts -> A.Tstruct p (fmap (tconvert ()) dts)
+    
+    I.Tfirst_class_array n dt -> A.Tarray n (tconvert () dt)
+    I.Tfirst_class_struct p dts -> A.Tstruct p (fmap (tconvert ()) dts)
+    
+    I.Tfirst_class_no n -> A.Tno n
+    I.Tfirst_class_name s -> A.Tname s
+    I.Tfirst_class_quoteName s -> A.TquoteName s
+
+    I.Topaque_struct p dts -> A.Tstruct p (fmap (either (tconvert()) (tconvert ())) dts)
+    I.Topaque_array n dt -> A.Tarray n (tconvert () dt)
+    
+    I.TvectorI n dt -> A.Tvector n (tconvert () dt)
+    I.TvectorF n dt -> A.Tvector n (tconvert () dt)    
+    I.TvectorP n dt -> A.Tvector n (tconvert () dt)    
+    I.Tvoid -> A.Tvoid
+    
+    I.TnoScalarI n -> A.Tno n
+    I.TnameScalarI s -> A.Tname s
+    I.TquoteNameScalarI s -> A.TquoteName s
+    
+    I.TnoScalarF n -> A.Tno n
+    I.TnameScalarF s -> A.Tname s
+    I.TquoteNameScalarF s -> A.TquoteName s
+
+    I.TnoScalarP n -> A.Tno n
+    I.TnameScalarP s -> A.Tname s
+    I.TquoteNameScalarP s -> A.TquoteName s
+
+    I.TnoVectorI n -> A.Tno n
+    I.TnameVectorI s -> A.Tname s
+    I.TquoteNameVectorI s -> A.TquoteName s
+    
+    I.TnoVectorF n -> A.Tno n
+    I.TnameVectorF s -> A.Tname s
+    I.TquoteNameVectorF s -> A.TquoteName s
+
+    I.TnoVectorP n -> A.Tno n
+    I.TnameVectorP s -> A.Tname s
+    I.TquoteNameVectorP s -> A.TquoteName s
+
+    I.TnoRecordD n -> A.Tno n
+    I.TnameRecordD s -> A.Tname s
+    I.TquoteNameRecordD s -> A.TquoteName s
+    
+    I.TnoCodeFunX n -> A.Tno n
+    I.TnameCodeFunX s -> A.Tname s
+    I.TquoteNameCodeFunX s -> A.TquoteName s
+
+    I.TnoOpaqueD n -> A.Tno n
+    I.TnameOpaqueD s -> A.Tname s
+    I.TquoteNameOpaqueD s -> A.TquoteName s
+
+    I.Tfunction rt tp fa -> A.Tfunction (tconvert () rt) (tconvert () tp) fa
+    I.TpNull -> A.Tprimitive A.TpNull
+    I.TpLabel -> A.Tprimitive A.TpLabel
+    I.Topaque -> A.Topaque
+
+instance TypeConversion () I.Utype A.Type where
+  tconvert _ t = case t of
+    I.UtypeScalarI x -> tconvert () x
+    I.UtypeScalarF x -> tconvert () x
+    I.UtypeScalarP x -> tconvert () x
+    I.UtypeVectorI x -> tconvert () x
+    I.UtypeVectorF x -> tconvert () x
+    I.UtypeVectorP x -> tconvert () x
+    I.UtypeRecordD x -> tconvert () x
+    I.UtypeFunX x -> tconvert () x
+    I.UtypeLabelX x -> tconvert () x
+    I.UtypeOpaqueD x -> tconvert () x
+    I.UtypeVoidU x -> tconvert () x
+
+data Tk = Tk_ScalarI
+        | Tk_ScalarP
+        | Tk_ScalarF
+        | Tk_VectorI
+        | Tk_VectorF          
+        | Tk_VectorP          
+        | Tk_RecordD
+        | Tk_CodeFunX
+        | Tk_CodeLabelX
+        | Tk_Opaque
+             
+             
+getTk :: MP -> A.LocalId -> Tk
+getTk mp lid = case M.lookup lid mp of 
+  Nothing -> error $ "undefined " ++ show lid
+  Just e -> matchType mp e
+
+matchType :: MP -> A.Type -> Tk
+matchType mp t = case t of
+  A.Tprimitive e -> case e of
+    A.TpI _ -> Tk_ScalarI
+    A.TpF _ -> Tk_ScalarF
+    A.TpV _ -> Tk_ScalarI
+    A.TpHalf -> Tk_ScalarF
+    A.TpFloat -> Tk_ScalarF
+    A.TpDouble -> Tk_ScalarF
+    A.TpFp128 -> Tk_ScalarF
+    A.TpX86Fp80 -> Tk_ScalarF
+    A.TpPpcFp128 -> Tk_ScalarF
+    A.TpX86Mmx -> Tk_ScalarI
+    A.TpLabel -> Tk_CodeLabelX
+    A.TpNull ->  I.errorLoc FLC "TpNull"
+  A.Tarray _ _ -> Tk_RecordD
+  A.Tstruct _ _ -> Tk_RecordD
+  A.Tpointer _ _ -> Tk_ScalarP
+  A.Tfunction _ _ _ -> Tk_CodeFunX
+  A.Tvector _ e -> let ek = matchType mp e
+                   in case ek of
+                     Tk_ScalarI -> Tk_VectorI
+                     Tk_ScalarF -> Tk_VectorF
+                     Tk_ScalarP -> Tk_VectorP
+                     _ -> error $ "RRRRRRR"
+  A.Tname _ -> getTk mp (castTnameToLocalId t)
+  A.TquoteName _ -> getTk mp (castTnameToLocalId t)
+  A.Tno _ -> getTk mp (castTnameToLocalId t)
+  A.Topaque -> Tk_Opaque
+  _ -> I.errorLoc FLC (show t)
+
+
+castTnameToLocalId :: A.Type -> A.LocalId    
+castTnameToLocalId x = case x of
+  A.Tname s -> A.LocalIdAlphaNum s
+  A.TquoteName s -> A.LocalIdDqString s
+  A.Tno s -> A.LocalIdNum s  
diff --git a/src/Llvm/Data/CoreIr.hs b/src/Llvm/Data/CoreIr.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/CoreIr.hs
@@ -0,0 +1,782 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Llvm.Data.CoreIr
+       ( module Llvm.Data.CoreIr
+       , module Llvm.Data.Shared
+       , module Llvm.Data.IrType
+       , module Data.Word
+       , Label
+       ) where
+import Llvm.Data.Shared
+import Llvm.Data.IrType
+import Compiler.Hoopl (Label)
+import Data.Int
+import Data.Word (Word8, Word16, Word32, Word64)
+import Data.DoubleWord
+
+data NoWrap =
+  -- | No Signed Wrap
+  Nsw
+  -- | No Unsigned Wrap
+  | Nuw
+  -- | No Signed and Unsigned Wrap
+  | Nsuw deriving (Eq,Ord,Show)
+
+data Exact = Exact deriving (Eq,Ord,Show)
+
+data Conversion s v where {
+  Trunc :: T (Type s I) v -> Type s I -> Conversion s v;
+  Zext :: T (Type s I) v -> Type s I -> Conversion s v;
+  Sext :: T (Type s I) v -> Type s I -> Conversion s v;
+  FpTrunc ::  T (Type s F) v -> Type s F -> Conversion s v;
+  FpExt :: T (Type s F) v -> Type s F -> Conversion s v;
+  FpToUi :: T (Type s F) v -> Type s I -> Conversion s v;
+  FpToSi :: T (Type s F) v -> Type s I -> Conversion s v;
+  UiToFp :: T (Type s I) v -> Type s F -> Conversion s v;
+  SiToFp :: T (Type s I) v -> Type s F -> Conversion s v;
+  PtrToInt :: T (Type s P) v -> Type s I -> Conversion s v;
+  IntToPtr :: T (Type s I) v -> Type s P -> Conversion s v;
+  Bitcast :: T Dtype v -> Dtype -> Conversion s v;
+  AddrSpaceCast :: T (Type s P) v -> Type s P -> Conversion s v;
+  } deriving (Eq, Ord, Show)
+
+data GetElementPtr s v = GetElementPtr (IsOrIsNot InBounds) (T (Type s P) v) [T (Type s I) v]
+                       deriving (Eq,Ord,Show)
+
+data Select s r v = Select (Either (T (Type ScalarB I) v) (T (Type s I) v)) (T (Type s r) v) (T (Type s r) v)
+                  deriving (Eq,Ord,Show)
+
+data Icmp s v = Icmp IcmpOp (IntOrPtrType s) v v deriving (Eq,Ord,Show)
+
+data Fcmp s v = Fcmp FcmpOp (Type s F) v v deriving (Eq,Ord,Show)
+
+{- vector operations -}
+data ShuffleVector r v = ShuffleVector (T (Type VectorB r) v) (T (Type VectorB r) v) (T (Type VectorB I) v)
+                       deriving (Eq,Ord,Show)
+
+data ExtractElement r v = ExtractElement (T (Type VectorB r) v) (T (Type ScalarB I) v)
+                        deriving (Eq,Ord,Show)
+
+data InsertElement r v = InsertElement (T (Type VectorB r) v) (T (Type ScalarB r) v) (T (Type ScalarB I) v)
+                       deriving (Eq,Ord,Show)
+
+{- aggregate operations -}
+data ExtractValue v = ExtractValue (T (Type RecordB D) v) [Word32] deriving (Eq,Ord,Show)
+
+data InsertValue v = InsertValue (T (Type RecordB D) v) (T Dtype v) [Word32] deriving (Eq,Ord,Show)
+
+data Const where {
+  C_u8 :: Word8 -> Const;
+  C_u16 :: Word16 -> Const;
+  C_u32 :: Word32 -> Const;
+  C_u64 :: Word64 -> Const;
+  C_u96 :: Word96 -> Const;
+  C_u128 :: Word128 -> Const;
+  C_s8 :: Int8 -> Const;
+  C_s16 :: Int16 -> Const;
+  C_s32 :: Int32 -> Const;
+  C_s64 :: Int64 -> Const;
+  C_s96 :: Int96 -> Const;
+  C_s128 :: Int128 -> Const;
+  C_int :: String -> Const;
+  C_uhex_int :: String -> Const;
+  C_shex_int :: String -> Const;
+  C_float :: String -> Const;
+  C_null :: Const;
+  C_undef :: Const;
+  C_true :: Const;
+  C_false :: Const;
+  C_zeroinitializer :: Const;
+  C_globalAddr :: GlobalId -> Const;
+  C_str :: String -> Const;
+  C_struct :: Packing -> [TypedConstOrNull] -> Const;
+  C_vector :: [TypedConstOrNull] -> Const;
+  C_vectorN :: Word32 -> TypedConstOrNull -> Const;
+  C_array :: [TypedConstOrNull] -> Const;
+  C_arrayN :: Word32 -> TypedConstOrNull -> Const;
+  C_localId :: LocalId -> Const;
+  C_labelId :: Label -> Const;
+  C_block :: GlobalId -> Label -> Const;
+
+  C_add :: Maybe NoWrap -> Type ScalarB I -> Const -> Const -> Const;
+  C_sub :: Maybe NoWrap -> Type ScalarB I -> Const -> Const -> Const;
+  C_mul :: Maybe NoWrap -> Type ScalarB I -> Const -> Const -> Const;
+  C_udiv :: Maybe Exact -> Type ScalarB I -> Const -> Const -> Const;
+  C_sdiv :: Maybe Exact -> Type ScalarB I -> Const -> Const -> Const;
+  C_urem :: Type ScalarB I -> Const -> Const -> Const;
+  C_srem :: Type ScalarB I -> Const -> Const -> Const;
+  C_shl :: Maybe NoWrap -> Type ScalarB I -> Const -> Const -> Const;
+  C_lshr :: Maybe Exact -> Type ScalarB I -> Const -> Const -> Const;
+  C_ashr :: Maybe Exact -> Type ScalarB I -> Const -> Const -> Const;
+  C_and :: Type ScalarB I -> Const -> Const -> Const;
+  C_or :: Type ScalarB I -> Const -> Const -> Const;
+  C_xor :: Type ScalarB I -> Const -> Const -> Const;
+
+  C_add_V :: Maybe NoWrap -> Type VectorB I -> Const -> Const -> Const;
+  C_sub_V :: Maybe NoWrap -> Type VectorB I -> Const -> Const -> Const;
+  C_mul_V :: Maybe NoWrap -> Type VectorB I -> Const -> Const -> Const;
+  C_udiv_V :: Maybe Exact -> Type VectorB I -> Const -> Const -> Const;
+  C_sdiv_V :: Maybe Exact -> Type VectorB I -> Const -> Const -> Const;
+  C_urem_V :: Type VectorB I -> Const -> Const -> Const;
+  C_srem_V :: Type VectorB I -> Const -> Const -> Const;
+  C_shl_V :: Maybe NoWrap -> Type VectorB I -> Const -> Const -> Const;
+  C_lshr_V :: Maybe Exact -> Type VectorB I -> Const -> Const -> Const;
+  C_ashr_V :: Maybe Exact -> Type VectorB I -> Const -> Const -> Const;
+  C_and_V :: Type VectorB I -> Const -> Const -> Const;
+  C_or_V :: Type VectorB I -> Const -> Const -> Const;
+  C_xor_V :: Type VectorB I -> Const -> Const -> Const;
+
+  C_fadd :: FastMathFlags -> Type ScalarB F -> Const -> Const -> Const;
+  C_fsub :: FastMathFlags -> Type ScalarB F -> Const -> Const -> Const;
+  C_fmul :: FastMathFlags -> Type ScalarB F -> Const -> Const -> Const;
+  C_fdiv :: FastMathFlags -> Type ScalarB F -> Const -> Const -> Const;
+  C_frem :: FastMathFlags -> Type ScalarB F -> Const -> Const -> Const;
+
+  C_fadd_V :: FastMathFlags -> Type VectorB F -> Const -> Const -> Const;
+  C_fsub_V :: FastMathFlags -> Type VectorB F -> Const -> Const -> Const;
+  C_fmul_V :: FastMathFlags -> Type VectorB F -> Const -> Const -> Const;
+  C_fdiv_V :: FastMathFlags -> Type VectorB F -> Const -> Const -> Const;
+  C_frem_V :: FastMathFlags -> Type VectorB F -> Const -> Const -> Const;
+
+  C_trunc :: T (Type ScalarB I) Const -> Type ScalarB I -> Const;
+  C_zext :: T (Type ScalarB I) Const -> Type ScalarB I -> Const;
+  C_sext :: T (Type ScalarB I) Const -> Type ScalarB I -> Const;
+  C_fptrunc ::  T (Type ScalarB F) Const -> Type ScalarB F -> Const;
+  C_fpext :: T (Type ScalarB F) Const -> Type ScalarB F -> Const;
+  C_fptoui :: T (Type ScalarB F) Const -> Type ScalarB I -> Const;
+  C_fptosi :: T (Type ScalarB F) Const -> Type ScalarB I -> Const;
+  C_uitofp :: T (Type ScalarB I) Const -> Type ScalarB F -> Const;
+  C_sitofp :: T (Type ScalarB I) Const -> Type ScalarB F -> Const;
+  C_ptrtoint :: T (Type ScalarB P) Const -> Type ScalarB I -> Const;
+  C_inttoptr :: T (Type ScalarB I) Const -> Type ScalarB P -> Const;
+  C_bitcast :: T Dtype Const -> Dtype -> Const;
+  C_addrspacecast :: T (Type ScalarB P) Const -> Type ScalarB P -> Const;
+
+  C_trunc_V :: T (Type VectorB I) Const -> Type VectorB I -> Const;
+  C_zext_V :: T (Type VectorB I) Const -> Type VectorB I -> Const;
+  C_sext_V :: T (Type VectorB I) Const -> Type VectorB I -> Const;
+  C_fptrunc_V ::  T (Type VectorB F) Const -> Type VectorB F -> Const;
+  C_fpext_V :: T (Type VectorB F) Const -> Type VectorB F -> Const;
+  C_fptoui_V :: T (Type VectorB F) Const -> Type VectorB I -> Const;
+  C_fptosi_V :: T (Type VectorB F) Const -> Type VectorB I -> Const;
+  C_uitofp_V :: T (Type VectorB I) Const -> Type VectorB F -> Const;
+  C_sitofp_V :: T (Type VectorB I) Const -> Type VectorB F -> Const;
+  C_ptrtoint_V :: T (Type VectorB P) Const -> Type VectorB I -> Const;
+  C_inttoptr_V :: T (Type VectorB I) Const -> Type VectorB P -> Const;
+  C_addrspacecast_V :: T (Type VectorB P) Const -> Type VectorB P -> Const;
+
+  C_getelementptr :: IsOrIsNot InBounds -> T (Type ScalarB P) Const -> [T (Type ScalarB I) Const] -> Const;
+  C_getelementptr_V :: IsOrIsNot InBounds -> T (Type VectorB P) Const -> [T (Type VectorB I) Const] -> Const;
+
+  C_select_I :: Select ScalarB I Const -> Const;
+  C_select_F :: Select ScalarB F Const -> Const;
+  C_select_P :: Select ScalarB P Const -> Const;
+
+  C_select_First :: T (Type ScalarB I) Const -> T (Type FirstClassB D) Const -> T (Type FirstClassB D) Const -> Const;
+
+  C_select_VI :: Select VectorB I Const -> Const;
+  C_select_VF :: Select VectorB F Const -> Const;
+  C_select_VP :: Select VectorB P Const -> Const;
+
+  C_icmp :: Icmp ScalarB Const -> Const;
+  C_icmp_V :: Icmp VectorB Const -> Const;
+
+  C_fcmp :: Fcmp ScalarB Const -> Const;
+  C_fcmp_V :: Fcmp VectorB Const -> Const;
+
+  C_shufflevector_I :: ShuffleVector I Const -> Const;
+  C_shufflevector_F :: ShuffleVector F Const -> Const;
+  C_shufflevector_P :: ShuffleVector P Const -> Const;
+
+  C_extractelement_I :: ExtractElement I Const -> Const;
+  C_extractelement_F :: ExtractElement F Const -> Const;
+  C_extractelement_P :: ExtractElement P Const -> Const;
+
+  C_insertelement_I :: InsertElement I Const -> Const;
+  C_insertelement_F :: InsertElement F Const -> Const;
+  C_insertelement_P :: InsertElement P Const -> Const;
+
+  C_extractvalue :: ExtractValue Const -> Const;
+  C_insertvalue :: InsertValue Const -> Const;
+  } deriving (Eq, Ord, Show)
+
+data MdVar = MdVar String deriving (Eq,Ord,Show)
+data MdNode = MdNode String deriving (Eq,Ord,Show)
+data MetaConst = McStruct [MetaKindedConst]
+               | McString DqString
+               | McMn MdNode
+               | McMv MdVar
+               | McRef LocalId
+               | McSimple Const
+               deriving (Eq,Ord,Show)
+
+data MetaKindedConst = MetaKindedConst MetaKind MetaConst
+                     | UnmetaKindedNull
+                     deriving (Eq, Ord, Show)
+
+data FunName = FunNameGlobal GlobalOrLocalId
+             | FunNameString String
+             deriving (Eq,Ord,Show)
+
+data CallSiteType = CallSiteRet Rtype
+                  | CallSiteFun (Type CodeFunB X) AddrSpace
+                  deriving (Eq, Ord, Show)
+
+data CallSite = CsFun (Maybe CallConv) [ParamAttr] CallSiteType FunName [ActualParam] [FunAttr]
+              | CsAsm CallSiteType (Maybe SideEffect) (Maybe AlignStack) AsmDialect DqString DqString [ActualParam] [FunAttr]
+              | CsConversion [ParamAttr] CallSiteType (Conversion ScalarB Const) [ActualParam] [FunAttr]
+              | CsConversionV [ParamAttr] CallSiteType (Conversion VectorB Const) [ActualParam] [FunAttr]
+              deriving (Eq,Ord,Show)
+
+data Clause = Catch (T Dtype Value)
+            | Filter TypedConstOrNull
+            | CcoS (Conversion ScalarB Value)
+            | CcoV (Conversion VectorB Value)
+            deriving (Eq,Ord,Show)
+
+data PersFn = PersFnId GlobalOrLocalId
+            | PersFnCastS (Conversion ScalarB GlobalOrLocalId)
+            | PersFnCastV (Conversion VectorB GlobalOrLocalId)
+            | PersFnUndef
+            | PersFnNull
+            | PersFnConst Const
+            deriving (Eq, Ord, Show)
+
+data Dbg = Dbg MdVar MetaConst deriving (Eq, Ord, Show)
+
+data PhiInst = PhiInst LocalId Ftype [(Value, Label)] deriving (Eq, Ord, Show)
+
+data PhiInstWithDbg = PhiInstWithDbg PhiInst [Dbg] deriving (Eq, Ord, Show)
+
+i_alloca :: FileLoc -> CInst
+i_alloca loc = I_alloca { result = errorLoc loc "please assign a new variable name"
+                        , inAllocaAttr = IsNot InAllocaAttr
+                        , dtype = errorLoc loc "please specify the allocated date type"
+                        , size = Nothing
+                        , alignment = Nothing
+                        }
+
+i_getelementptr :: FileLoc -> CInst
+i_getelementptr loc = I_getelementptr { result = errorLoc loc "please assign a new variable name"
+                                      , inBounds = IsNot InBounds
+                                      , pointer = errorLoc loc "please assign a pointer"
+                                      , indices = []
+                                      }
+
+
+i_store :: FileLoc -> CInst
+i_store loc = I_store { volatile = IsNot Volatile
+                      , storedvalue = errorLoc loc "please specified the stored value"
+                      , pointer = errorLoc loc " please assign a pointer"
+                      , alignment = Nothing
+                      , nontemporal = Nothing
+                      }
+
+data CInst where {
+  I_alloca :: { inAllocaAttr :: IsOrIsNot InAllocaAttr
+              , dtype :: Dtype
+              , size :: Maybe (T (Type ScalarB I) Value)
+              , alignment :: Maybe Alignment
+              , result :: LocalId
+              } -> CInst;
+
+  I_load :: { volatile :: IsOrIsNot Volatile
+            , pointer :: T (Type ScalarB P) Value
+            , alignment :: Maybe Alignment
+            , temporal :: Maybe Nontemporal
+            , invariantLoad :: Maybe InvariantLoad
+            , nonull :: Maybe Nonnull
+            , result :: LocalId
+            } -> CInst;
+
+  I_loadatomic :: { atomicity :: Atomicity
+                  , volatile :: IsOrIsNot Volatile
+                  , pointer :: T (Type ScalarB P) Value
+                  , alignment :: Maybe Alignment
+                  , result :: LocalId
+                  } -> CInst;
+
+  I_store :: { volatile :: IsOrIsNot Volatile
+             , storedvalue :: T Dtype Value
+             , pointer :: T (Type ScalarB P) Value
+             , alignment :: Maybe Alignment
+             , nontemporal :: Maybe Nontemporal 
+             } -> CInst;
+
+  I_storeatomic :: { atomicity :: Atomicity
+                   , volatile :: IsOrIsNot Volatile
+                   , storedvalue :: T Dtype Value
+                   , pointer :: T (Type ScalarB P) Value
+                   , alignment :: Maybe Alignment 
+                   } -> CInst;
+
+  I_fence :: { singleThread :: IsOrIsNot SingleThread
+             , ordering :: AtomicMemoryOrdering } -> CInst;
+
+  I_cmpxchg_I :: { weak :: IsOrIsNot Weak
+                 , volatile :: IsOrIsNot Volatile
+                 , pointer ::  T (Type ScalarB P) Value
+                 , cmpi :: T (Type ScalarB I) Value
+                 , newi :: T (Type ScalarB I) Value
+                 , singlethread :: IsOrIsNot SingleThread
+                 , success_ordering :: AtomicMemoryOrdering
+                 , failure_ordering :: AtomicMemoryOrdering
+                 , result :: LocalId } -> CInst;
+
+  I_cmpxchg_F :: { weak :: IsOrIsNot Weak
+                 , volatile :: IsOrIsNot Volatile
+                 , pointer :: T (Type ScalarB P) Value
+                 , cmpf :: T (Type ScalarB F) Value
+                 , newf :: T (Type ScalarB F) Value
+                 , singlethread :: IsOrIsNot SingleThread
+                 , success_ordering :: AtomicMemoryOrdering
+                 , failure_ordering :: AtomicMemoryOrdering
+                 , result :: LocalId } -> CInst;
+
+  I_cmpxchg_P :: { weak :: IsOrIsNot Weak
+                 , volatile :: IsOrIsNot Volatile
+                 , pointer :: T (Type ScalarB P) Value
+                 , cmpp :: T (Type ScalarB P) Value
+                 , newp :: T (Type ScalarB P) Value
+                 , singlethread :: IsOrIsNot SingleThread
+                 , success_ordering :: AtomicMemoryOrdering
+                 , failure_ordering :: AtomicMemoryOrdering
+                 , result :: LocalId } -> CInst;
+
+  I_atomicrmw :: { volatile :: IsOrIsNot Volatile
+                 , atomicOp :: AtomicOp
+                 , pointer :: T (Type ScalarB P) Value
+                 , val :: T (Type ScalarB I) Value
+                 , singlethread :: IsOrIsNot SingleThread
+                 , ordering :: AtomicMemoryOrdering
+                 , result :: LocalId } -> CInst;
+
+  I_call_fun :: { tailCall :: TailCall
+                , callConv :: Maybe CallConv
+                , paramAttrs :: [ParamAttr]
+                , callSiteType :: CallSiteType
+                , calleeName :: FunName
+                , actualParams :: [ActualParam]
+                , funAttrs :: [FunAttr]
+                , callReturn :: Maybe LocalId } -> CInst;
+
+  I_call_other :: { tailCall :: TailCall
+                  , callSite :: CallSite
+                  , callReturn :: Maybe LocalId } -> CInst;
+
+  I_extractelement_I :: { vectorI :: T (Type VectorB I) Value
+                        , index :: T (Type ScalarB I) Value
+                        , result :: LocalId } -> CInst;
+
+  I_extractelement_F :: { vectorF :: T (Type VectorB F) Value
+                        , index :: T (Type ScalarB I) Value
+                        , result :: LocalId } -> CInst;
+
+  I_extractelement_P :: { vectorP :: T (Type VectorB P) Value
+                        , index :: T (Type ScalarB I) Value
+                        , result :: LocalId } -> CInst;
+
+  I_insertelement_I :: { vectorI :: T (Type VectorB I) Value
+                       , elementI :: T (Type ScalarB I) Value
+                       , index :: T (Type ScalarB I) Value
+                       , result :: LocalId } -> CInst;
+
+  I_insertelement_F :: { vectorF :: T (Type VectorB F) Value
+                       , elementF :: T (Type ScalarB F) Value
+                       , index :: T (Type ScalarB I) Value
+                       , result :: LocalId
+                       } -> CInst;
+
+  I_insertelement_P :: { vectorP :: T (Type VectorB P) Value
+                       , elementP :: T (Type ScalarB P) Value
+                       , index :: T (Type ScalarB I) Value
+                       , result :: LocalId
+                       } -> CInst;
+
+  I_shufflevector_I :: { vector1I :: T (Type VectorB I) Value
+                       , vector2I :: T (Type VectorB I) Value
+                       , vectorIdx :: T (Type VectorB I) Value
+                       , result :: LocalId
+                       } -> CInst;
+
+  I_shufflevector_F :: { vector1F :: T (Type VectorB F) Value
+                       , vector2F :: T (Type VectorB F) Value
+                       , vectorIdx :: T (Type VectorB I) Value
+                       , result :: LocalId
+                       } -> CInst;
+
+  I_shufflevector_P :: { vector1P :: T (Type VectorB P) Value
+                       , vector2P :: T (Type VectorB P) Value
+                       , vectorIdx :: T (Type VectorB I) Value
+                       , result :: LocalId
+                       } -> CInst;
+
+  I_extractvalue :: T (Type RecordB D) Value -> [Word32] -> LocalId ->  CInst;
+  I_insertvalue :: T (Type RecordB D) Value -> T Dtype Value -> [Word32] -> LocalId ->  CInst;
+
+  I_va_arg :: { dv :: T Dtype Value 
+              , typeD :: Dtype 
+              , result :: LocalId 
+              } -> CInst;
+  
+  I_va_start :: { pointer :: T (Type ScalarB P) Value } -> CInst;
+  I_va_end :: { pointer :: T (Type ScalarB P) Value } -> CInst;
+
+  I_landingpad :: Dtype -> Dtype -> PersFn -> Maybe Cleanup -> [Clause] -> LocalId -> CInst;
+
+  I_getelementptr :: { inBounds :: IsOrIsNot InBounds
+                     , pointer :: T (Type ScalarB P) Value
+                     , indices :: [T (Type ScalarB I) Value]
+                     , result :: LocalId 
+                     } -> CInst;
+
+  I_getelementptr_V :: { inBounds :: IsOrIsNot InBounds
+                       , vpointer :: T (Type VectorB P) Value
+                       , vindices :: [T (Type VectorB I) Value]
+                       , result :: LocalId 
+                       } -> CInst;
+
+  {- Scalar Integer cmp -}
+  I_icmp :: { icmpOp :: IcmpOp
+            , icmpType :: IntOrPtrType ScalarB
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId
+            } -> CInst;
+
+  {- Vector Integer cmp -}
+  I_icmp_V :: { icmpOp :: IcmpOp
+              , icmpTypeV :: IntOrPtrType VectorB
+              , operand1 :: Value
+              , operand2 :: Value
+              , result :: LocalId
+              } -> CInst;
+
+  {- Scalar Float cmp -}
+  I_fcmp :: { fcmpOp :: FcmpOp
+            , fcmpTypeF :: Type ScalarB F
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId
+            } -> CInst;
+
+  I_fcmp_V :: { fcmpOp :: FcmpOp 
+              , fcmpTypeVF :: Type VectorB F 
+              , operand1 :: Value 
+              , operand2 :: Value 
+              , result :: LocalId 
+              } -> CInst;
+
+  {-- int bin exp --}
+  I_add :: { flagI :: Maybe NoWrap
+           , typeI :: Type ScalarB I
+           , operand1 :: Value
+           , operand2 :: Value
+           , result :: LocalId 
+           } -> CInst;
+
+  I_sub :: { flagI :: Maybe NoWrap
+           , typeI :: Type ScalarB I
+           , operand1 :: Value
+           , operand2 :: Value
+           , result :: LocalId
+           } -> CInst;
+
+  I_mul :: { flagI :: Maybe NoWrap
+           , typeI :: Type ScalarB I
+           , operand1 :: Value
+           , operand2 :: Value
+           , result :: LocalId 
+           } -> CInst;
+
+  I_udiv :: { flagE :: Maybe Exact
+            , typeI :: Type ScalarB I
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId 
+            } -> CInst;
+
+  I_sdiv :: { flagE :: Maybe Exact
+            , typeI :: Type ScalarB I
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId 
+            } -> CInst;
+
+  I_urem :: { typeI :: Type ScalarB I
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId 
+            } -> CInst;
+
+  I_srem :: { typeI :: Type ScalarB I
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId 
+            } -> CInst;
+
+  I_shl :: { flagW :: Maybe NoWrap
+           , typeI :: Type ScalarB I
+           , operand1 :: Value
+           , operand2 :: Value
+           , result :: LocalId 
+           } -> CInst;
+
+  I_lshr :: { flagE :: Maybe Exact
+            , typeI :: Type ScalarB I
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId 
+            } -> CInst;
+
+  I_ashr :: { flagE :: Maybe Exact
+            , typeI :: Type ScalarB I
+            , operand1 :: Value
+            , operand2 :: Value
+            , result :: LocalId 
+            } -> CInst;
+
+  I_and :: { typeI :: Type ScalarB I
+           , operand1 :: Value
+           , operand2 :: Value
+           , result :: LocalId 
+           } -> CInst;
+
+  I_or :: { typeI :: Type ScalarB I
+          , operand1 :: Value
+          , operand2 :: Value
+          , result :: LocalId 
+          } -> CInst;
+
+  I_xor :: { typeI :: Type ScalarB I
+           , operand1 :: Value
+           , operand2 :: Value
+           , result :: LocalId 
+           } -> CInst;
+
+  {-- int bin vector exp --}
+  I_add_V :: (Maybe NoWrap) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_sub_V :: (Maybe NoWrap) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_mul_V :: (Maybe NoWrap) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_udiv_V :: (Maybe Exact) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_sdiv_V :: (Maybe Exact) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_urem_V :: Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_srem_V :: Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_shl_V :: (Maybe NoWrap) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_lshr_V :: (Maybe Exact) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_ashr_V :: (Maybe Exact) -> Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_and_V :: Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_or_V :: Type VectorB I -> Value -> Value -> LocalId -> CInst;
+  I_xor_V :: Type VectorB I -> Value -> Value -> LocalId -> CInst;
+
+  {- float bin exp -}
+  I_fadd :: FastMathFlags -> Type ScalarB F -> Value -> Value -> LocalId -> CInst;
+  I_fsub :: FastMathFlags -> Type ScalarB F -> Value -> Value -> LocalId -> CInst;
+  I_fmul :: FastMathFlags -> Type ScalarB F -> Value -> Value -> LocalId -> CInst;
+  I_fdiv :: FastMathFlags -> Type ScalarB F -> Value -> Value -> LocalId -> CInst;
+  I_frem :: FastMathFlags -> Type ScalarB F -> Value -> Value -> LocalId -> CInst;
+
+  {- float bin exp -}
+  I_fadd_V :: FastMathFlags -> Type VectorB F -> Value -> Value -> LocalId -> CInst;
+  I_fsub_V :: FastMathFlags -> Type VectorB F -> Value -> Value -> LocalId -> CInst;
+  I_fmul_V :: FastMathFlags -> Type VectorB F -> Value -> Value -> LocalId -> CInst;
+  I_fdiv_V :: FastMathFlags -> Type VectorB F -> Value -> Value -> LocalId -> CInst;
+  I_frem_V :: FastMathFlags -> Type VectorB F -> Value -> Value -> LocalId -> CInst;
+
+  {-- Scalar conversion --}
+  I_trunc :: { srcI :: T (Type ScalarB I) Value
+             , toI :: Type ScalarB I
+             , result :: LocalId } -> CInst;
+
+  I_zext :: { srcI :: T (Type ScalarB I) Value
+            , toI :: Type ScalarB I
+            , result :: LocalId } -> CInst;
+
+  I_sext :: { srcI :: T (Type ScalarB I) Value
+            , toI :: Type ScalarB I
+            , result :: LocalId } -> CInst;
+
+  I_fptrunc ::  { srcF :: T (Type ScalarB F) Value
+                , toF :: Type ScalarB F
+                , result :: LocalId } -> CInst;
+
+  I_fpext ::  { srcF :: T (Type ScalarB F) Value
+              , toF :: Type ScalarB F
+              , result :: LocalId } -> CInst;
+
+  I_fptoui :: { srcF :: T (Type ScalarB F) Value
+              , toI :: Type ScalarB I
+              , result :: LocalId } -> CInst;
+
+  I_fptosi :: { srcF ::T (Type ScalarB F) Value
+              , toI :: Type ScalarB I
+              , result :: LocalId } -> CInst;
+
+  I_uitofp :: { srcI :: T (Type ScalarB I) Value
+              , toF :: Type ScalarB F
+              , result :: LocalId } -> CInst;
+
+  I_sitofp :: { srcI :: T (Type ScalarB I) Value
+              , toF :: Type ScalarB F
+              , result :: LocalId } -> CInst;
+
+  I_ptrtoint :: { srcP :: T (Type ScalarB P) Value
+                , toI :: Type ScalarB I
+                , result :: LocalId } -> CInst;
+
+  I_inttoptr :: { srcI :: T (Type ScalarB I) Value
+                , toP :: Type ScalarB P
+                , result :: LocalId } -> CInst;
+
+  I_addrspacecast :: T (Type ScalarB P) Value -> Type ScalarB P -> LocalId -> CInst;
+
+
+  I_bitcast :: { srcP :: T (Type ScalarB P) Value
+               , toP :: Type ScalarB P
+               , result :: LocalId } -> CInst;
+
+  I_bitcast_D :: { srcD :: T Dtype Value
+                 , toD :: Dtype
+                 , result :: LocalId } -> CInst;
+
+  {-- Vector conversion --}
+  I_trunc_V :: T (Type VectorB I) Value -> Type VectorB I -> LocalId -> CInst;
+  I_zext_V :: T (Type VectorB I) Value -> Type VectorB I -> LocalId -> CInst;
+  I_sext_V :: T (Type VectorB I) Value -> Type VectorB I -> LocalId -> CInst;
+  I_fptrunc_V :: T (Type VectorB F) Value -> Type VectorB F -> LocalId -> CInst;
+  I_fpext_V :: T (Type VectorB F) Value -> Type VectorB F -> LocalId -> CInst;
+  I_fptoui_V :: T (Type VectorB F) Value -> Type VectorB I -> LocalId -> CInst;
+  I_fptosi_V :: T (Type VectorB F) Value -> Type VectorB I -> LocalId -> CInst;
+  I_uitofp_V :: T (Type VectorB I) Value -> Type VectorB F -> LocalId -> CInst;
+  I_sitofp_V :: T (Type VectorB I) Value -> Type VectorB F -> LocalId -> CInst;
+
+  I_ptrtoint_V :: { srcVP :: T (Type VectorB P) Value
+                  , toVI :: Type VectorB I
+                  , result :: LocalId } -> CInst;
+
+  I_inttoptr_V :: { srcVI :: T (Type VectorB I) Value
+                  , toVP :: Type VectorB P
+                  , result :: LocalId } -> CInst;
+
+  I_addrspacecast_V :: { srcVP :: T (Type VectorB P) Value
+                       , toVP :: Type VectorB P
+                       , result :: LocalId } -> CInst;
+
+  I_select_I :: T (Type ScalarB I) Value -> T (Type ScalarB I) Value -> T (Type ScalarB I) Value -> LocalId -> CInst;
+  I_select_F :: T (Type ScalarB I) Value -> T (Type ScalarB F) Value -> T (Type ScalarB F) Value -> LocalId -> CInst;
+  I_select_P :: T (Type ScalarB I) Value -> T (Type ScalarB P) Value -> T (Type ScalarB P) Value -> LocalId -> CInst;
+
+  I_select_VI :: Either (T (Type ScalarB I) Value) (T (Type VectorB I) Value)
+                 -> T (Type VectorB I) Value -> T (Type VectorB I) Value -> LocalId -> CInst;
+  I_select_VF :: Either (T (Type ScalarB I) Value) (T (Type VectorB I) Value)
+                 -> T (Type VectorB F) Value -> T (Type VectorB F) Value -> LocalId -> CInst;
+
+  I_select_VP :: { condV :: Either (T (Type ScalarB I) Value) (T (Type VectorB I) Value)
+                 , trueVP :: T (Type VectorB P) Value
+                 , falseVP :: T (Type VectorB P) Value
+                 , result :: LocalId } -> CInst;
+
+  I_select_First :: { cond :: T (Type ScalarB I) Value
+                    , trueFirst :: T (Type FirstClassB D) Value
+                    , falseFirst :: T (Type FirstClassB D) Value
+                    , result :: LocalId } -> CInst;
+
+  {-- llvm intrinsic function calls --}
+  I_llvm_memcpy:: { memlen :: MemLen
+                  , dest :: T (Type ScalarB P) Value
+                  , src :: T (Type ScalarB P) Value
+                  , len :: T (Type ScalarB I) Value
+                  , align :: T (Type ScalarB I) Value
+                  , isvolatile :: T (Type ScalarB I) Value
+                  } -> CInst;
+  
+  I_llvm_dbg_declare :: [ActualParam] -> CInst;
+  I_llvm_dbg_value :: [ActualParam] -> CInst;
+  } deriving (Eq, Ord, Show)
+
+data MemLen = MemLenI32
+            | MemLenI64 deriving (Eq, Ord, Show)
+
+{- -}
+data CInstWithDbg = CInstWithDbg CInst [Dbg] deriving (Eq, Ord, Show)
+
+data TerminatorInst = Unreachable
+                    | RetVoid
+                    | Return [T Dtype Value]
+                    | Br Label
+                    | Cbr Value Label Label
+                    | IndirectBr (T (Type ScalarB P) Value) [Label]
+                    | Switch (T (Type ScalarB I) Value) Label [((T (Type ScalarB I) Value), Label)]
+                    | Invoke CallSite Label Label (Maybe LocalId)
+                    | InvokeCmd CallSite Label Label
+                    | Resume (T Dtype Value)
+                    | Unwind
+                    deriving (Eq, Ord, Show)
+
+data TerminatorInstWithDbg = TerminatorInstWithDbg TerminatorInst [Dbg] deriving (Eq, Ord, Show)
+
+data ActualParam = ActualParamData Dtype [ParamAttr] (Maybe Alignment) Value [ParamAttr]
+                 | ActualParamLabel (Type CodeLabelB X) [ParamAttr] (Maybe Alignment) Value [ParamAttr]
+                 | ActualParamMeta MetaKindedConst
+                 deriving (Eq,Ord,Show)
+
+data Value = Val_ssa LocalId
+           | Val_const Const
+           deriving (Eq,Ord,Show)
+
+data T t v = T t v deriving (Eq, Ord, Show)
+
+data Aliasee = AtV (T Dtype Value)
+             | Ac (Conversion ScalarB Const)
+             | AcV (Conversion VectorB Const)
+             | Agep (GetElementPtr ScalarB Const)
+             | AgepV (GetElementPtr VectorB Const)
+             deriving (Eq, Ord, Show)
+
+data FunctionPrototype = FunctionPrototype { fp_linkage :: Maybe Linkage
+                                           , fp_visibility :: Maybe Visibility
+                                           , fp_dllstorage :: Maybe DllStorageClass
+                                           , fp_call_conv :: Maybe CallConv
+                                           , fp_param_attrs :: [ParamAttr]
+                                           , fp_ret_type :: Rtype
+                                           , fp_fun_name :: GlobalId
+                                           , fp_param_list :: FormalParamList
+                                           , fp_addr_naming :: Maybe AddrNaming
+                                           , fp_fun_attrs :: [FunAttr]
+                                           , fp_section :: Maybe Section
+                                           , fp_comdat :: Maybe Comdat
+                                           , fp_alignment :: Maybe Alignment
+                                           , fp_gc :: Maybe Gc
+                                           , fp_prefix :: Maybe Prefix
+                                           , fp_prologue :: Maybe Prologue
+                                           } deriving (Eq,Ord,Show)
+
+data Prefix = Prefix TypedConstOrNull deriving (Eq, Ord, Show)
+data Prologue = Prologue TypedConstOrNull deriving (Eq, Ord, Show)
+
+data TypedConstOrNull = TypedConst (T Dtype Const)
+                      | UntypedNull deriving (Eq, Ord, Show)
+
+
+instance Ucast Const Const where
+  ucast = id
+
+instance Ucast Const Value where
+  ucast = Val_const
+
+instance Ucast Value Value where
+  ucast = id
+
+instance Dcast Value Value where
+  dcast _ = id
+
+instance Dcast Value Const where
+  dcast lc x = case x of
+    Val_const v -> v
+    _ -> dcastError lc "Const" x
+
+instance (Ucast t s, Ucast u v) => Ucast (T t u) (T s v) where
+  ucast (T t u) = T (ucast t) (ucast u)
+
+instance (Dcast s t, Dcast v u) => Dcast (T s v) (T t u) where
+  dcast lc (T s v) = T (dcast lc s) (dcast lc v)
diff --git a/src/Llvm/Data/Ir.hs b/src/Llvm/Data/Ir.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Ir.hs
@@ -0,0 +1,162 @@
+{-# LANGUAGE GADTs #-}
+module Llvm.Data.Ir
+    (module Llvm.Data.Ir
+    , module Llvm.Data.CoreIr
+    , module Data.Word
+    )
+    where
+import Llvm.Data.CoreIr
+import qualified Llvm.Data.CoreIr as Ci
+import qualified Compiler.Hoopl as H
+import qualified Data.Set as S
+import Data.Word (Word32)
+
+{- An intermediate representation that is suitable for Hoopl -}
+
+data Toplevel a = ToplevelTriple TlTriple
+                | ToplevelDataLayout TlDataLayout
+                | ToplevelAlias TlAlias
+                | ToplevelDbgInit TlDbgInit
+                | ToplevelStandaloneMd TlStandaloneMd
+                | ToplevelNamedMd TlNamedMd
+                | ToplevelDeclare TlDeclare
+                | ToplevelDefine (TlDefine a)
+                | ToplevelGlobal TlGlobal
+                | ToplevelTypeDef TlTypeDef
+                | ToplevelDepLibs TlDepLibs
+                | ToplevelUnamedType TlUnamedType
+                | ToplevelModuleAsm TlModuleAsm
+                | ToplevelAttribute TlAttribute
+                | ToplevelComdat TlComdat
+
+data TlTriple = TlTriple Ci.TargetTriple deriving (Eq)
+
+data TlDataLayout = TlDataLayout Ci.DataLayout deriving (Eq)
+
+data TlAlias = TlAlias { tla_lhs :: Ci.GlobalId
+                       , tla_visibility :: Maybe Ci.Visibility
+                       , tla_dllstorage :: Maybe Ci.DllStorageClass
+                       , tla_tls :: Maybe Ci.ThreadLocalStorage
+                       , tla_addrnaming :: AddrNaming
+                       , tla_linkage :: Maybe Ci.Linkage
+                       , tla_aliasee :: Ci.Aliasee
+                       } deriving (Eq, Ord, Show)
+
+data TlDbgInit = TlDbgInit String Word32 deriving (Eq, Ord, Show)
+
+data TlStandaloneMd = TlStandaloneMd String MetaKindedConst deriving (Eq, Ord, Show)
+
+data TlNamedMd = TlNamedMd Ci.MdVar [Ci.MdNode] deriving (Eq, Ord, Show)
+
+data TlDeclare = TlDeclare Ci.FunctionPrototype deriving (Eq)
+
+type NOOP = ()
+
+data TlDefine a = TlDefine Ci.FunctionPrototype H.Label (H.Graph (Node a) H.C H.C) 
+
+data TlGlobal = TlGlobalDtype { tlg_lhs :: (Maybe Ci.GlobalId)
+                              , tlg_linkage :: (Maybe Ci.Linkage)
+                              , tlg_visibility :: (Maybe Ci.Visibility)
+                              , tlg_dllstorage :: (Maybe Ci.DllStorageClass)
+                              , tlg_tls :: (Maybe Ci.ThreadLocalStorage)
+                              , tlg_addrnaming :: AddrNaming
+                              , tlg_addrspace :: (Maybe Ci.AddrSpace)
+                              , tlg_externallyInitialized :: (IsOrIsNot Ci.ExternallyInitialized)
+                              , tlg_globalType :: Ci.GlobalType
+                              , tlg_dtype :: Ci.Dtype
+                              , tlg_const :: (Maybe Ci.Const)
+                              , tlg_section :: (Maybe Ci.Section)
+                              , tlg_comdat :: (Maybe Ci.Comdat)
+                              , tlg_alignment :: (Maybe Ci.Alignment)
+                              }
+              | TlGlobalOpaque { tlg_lhs :: (Maybe Ci.GlobalId)
+                               , tlg_linkage :: (Maybe Ci.Linkage)
+                               , tlg_visiblity :: (Maybe Ci.Visibility)
+                               , tlg_dllstorage :: (Maybe Ci.DllStorageClass)
+                               , tlg_tls :: (Maybe Ci.ThreadLocalStorage)
+                               , tlg_addrnaming :: AddrNaming
+                               , tlg_addrspace :: (Maybe Ci.AddrSpace)
+                               , tlg_externallyInitialized :: (IsOrIsNot Ci.ExternallyInitialized)
+                               , tlg_globalType :: Ci.GlobalType
+                               , tlg_otype :: (Ci.Type Ci.OpaqueB D)
+                               , tlg_const :: (Maybe Ci.Const)
+                               , tlg_section :: (Maybe Ci.Section)
+                               , tlg_comdat :: (Maybe Ci.Comdat)
+                               , tlg_alignment :: (Maybe Ci.Alignment)
+                               } deriving (Eq, Ord, Show)
+
+data TlTypeDef = TlDatTypeDef Ci.LocalId Ci.Dtype
+               | TlOpqTypeDef Ci.LocalId (Ci.Type OpaqueB D)
+               | TlFunTypeDef Ci.LocalId (Ci.Type CodeFunB X) deriving (Eq, Ord, Show)
+
+data TlDepLibs = TlDepLibs [Ci.DqString] deriving (Eq, Ord, Show)
+
+data TlUnamedType = TlUnamedType Word32 Ci.Dtype deriving (Eq, Ord, Show)
+
+data TlModuleAsm = TlModuleAsm Ci.DqString deriving (Eq, Ord, Show)
+
+data TlAttribute = TlAttribute Word32 [FunAttr] deriving (Eq, Ord, Show)
+
+data TlComdat = TlComdat Ci.DollarId Ci.SelectionKind deriving (Eq, Ord, Show)
+
+data Module a = Module [Toplevel a] 
+
+-- each instruction represents a node
+data Node a e x where
+  Nlabel :: H.Label -> Node a H.C H.O
+  Pinst  :: Ci.PhiInstWithDbg -> Node a H.O H.O
+  Cinst  :: Ci.CInstWithDbg -> Node a H.O H.O
+  Comment :: String -> Node a H.O H.O
+  Tinst  :: Ci.TerminatorInstWithDbg -> Node a H.O H.C
+  Additional :: a -> Node a H.O H.O
+
+instance Show a => Show (Node a e x) where
+  show x = case x of
+    Nlabel v -> "Nlabel: Node C O:" ++ show v
+    Pinst v -> "Pinst : Node O O:" ++ show v
+    Cinst v -> "Cinst : Node O O:" ++ show v
+    Tinst v -> "Tinst : Node O C:" ++ show v
+    Comment s -> "Comment : Node O O:" ++ s
+    Additional a -> "Additional : Node O O:" ++ show a
+
+instance Eq a => Eq (Node a e x) where
+  (==) x1 x2 = case (x1, x2) of
+    (Nlabel l1, Nlabel l2) -> l1 == l2
+    (Pinst v1, Pinst v2) -> v1 == v2
+    (Cinst v1, Cinst v2) -> v1 == v2
+    (Tinst v1, Tinst v2) -> v1 == v2
+    (Comment v1, Comment v2) -> v1 == v2
+    (Additional a1, Additional a2) -> a1 == a2
+    (_, _) -> False
+
+instance (Show a, Ord a) => Ord (Node a e x) where
+  compare x1 x2 = case (x1, x2) of
+    (Nlabel l1, Nlabel l2) -> compare l1 l2
+    (Pinst v1, Pinst v2) -> compare v1 v2
+    (Cinst v1, Cinst v2) -> compare v1 v2
+    (Tinst v1, Tinst v2) -> compare v1 v2
+    (Comment v1, Comment v2) -> compare v1 v2
+    (Additional v1, Additional v2) -> compare v1 v2
+    (_, _) -> compare (show x1) (show x2)
+
+instance H.NonLocal (Node a) where
+  entryLabel (Nlabel l) = l
+  successors (Tinst (Ci.TerminatorInstWithDbg inst _)) = suc inst
+    where
+      suc (Ci.Unreachable) = []
+      suc (Ci.Return _) = []
+      suc (Ci.RetVoid) = []
+      suc (Ci.Br l) = [l]
+      suc (Ci.Cbr _ l1 l2) = [l1, l2]
+      suc (Ci.IndirectBr _ ls) = ls
+      suc (Ci.Switch _ d ls) = (d):(map snd ls)
+      suc (Ci.Invoke  _ l1 l2 _) = [l1, l2]
+      suc (Ci.InvokeCmd _ l1 l2) = [l1, l2]
+      suc (Ci.Resume _) = error "what is resume"
+      suc (Ci.Unwind) = error "what is unwind"
+
+globalIdOfModule :: (Module a) -> S.Set (Ci.Dtype, Ci.GlobalId) -- this should be a map, globalid might have an opaque type
+globalIdOfModule (Module tl) = foldl (\a b -> S.union a (globalIdOf b)) S.empty tl
+                               where globalIdOf (ToplevelGlobal (TlGlobalDtype lhs _ _ _ _ _ _ _ _ t _ _ _ _)) =
+                                       maybe S.empty (\x -> S.singleton (t, x)) lhs
+                                     globalIdOf _ = S.empty
diff --git a/src/Llvm/Data/IrType.hs b/src/Llvm/Data/IrType.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/IrType.hs
@@ -0,0 +1,1069 @@
+{-# OPTIONS_GHC -cpp -fwarn-incomplete-patterns #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell #-}
+module Llvm.Data.IrType
+       (module Llvm.Data.Shared.AtomicEntity
+       ,module Llvm.Data.IrType
+       ,module Llvm.Data.Shared.Util
+       ,module Data.Word
+       )
+       where
+
+import Llvm.Data.Shared.AtomicEntity
+import Llvm.Data.Shared.Util
+import Data.Word (Word32)
+
+#define FLC   (FileLoc $(srcLoc))
+
+data ScalarB -- Scalar Storage Block
+data VectorB -- Vector Storage Block
+data FirstClassB  -- First Class Storage Block
+data RecordB -- Record (struct and array) Storage Block
+data CodeFunB -- Code Fun Storage Block
+data CodeLabelB -- Code Label Storage Block
+data OpaqueB -- Opaque Storage Block
+data NoB -- No Storage Block
+
+data I -- Integer representation
+data F -- Float representation
+data P -- Pointer representation
+data D -- Data (I,F,P) representation
+data U -- Unknown representation
+data X -- Executable representation
+
+data Type sto rep where {
+  TpI :: Word32 -> Type ScalarB I;
+  TpF :: Word32 -> Type ScalarB F;
+  TpV :: Word32 -> Type ScalarB I;
+  TpHalf :: Type ScalarB F;
+  TpFloat :: Type ScalarB F;
+  TpDouble :: Type ScalarB F;
+  TpFp128 :: Type ScalarB F;
+  TpX86Fp80 :: Type ScalarB F;
+  TpPpcFp128 :: Type ScalarB F;
+  TpX86Mmx :: Type ScalarB I;
+  TvectorI :: Word32 -> Type ScalarB I -> Type VectorB I;
+  TvectorF :: Word32 -> Type ScalarB F -> Type VectorB F;
+  TvectorP :: Word32 -> Type ScalarB P -> Type VectorB P;
+  TpNull :: Type ScalarB I;
+  TpLabel :: Type CodeLabelB X;
+  Tvoid :: Type NoB U;
+  Topaque :: Type OpaqueB D;
+  
+  {- first class aggregate types -}
+  Tfirst_class_array :: Word32 -> ScalarType -> Type FirstClassB D;
+  Tfirst_class_struct :: Packing -> [ScalarType] -> Type FirstClassB D;
+  Tfirst_class_name :: String -> Type FirstClassB D;
+  Tfirst_class_quoteName :: String -> Type FirstClassB D;
+  Tfirst_class_no :: Word32 -> Type FirstClassB D;
+  
+  Tarray :: Word32 -> Dtype -> Type RecordB D;
+  Tstruct :: Packing -> [Dtype] -> Type RecordB D;
+  
+  Topaque_struct :: Packing -> [Either Dtype (Type OpaqueB D)] -> Type OpaqueB D;
+  Topaque_array :: Word32 -> Type OpaqueB D -> Type OpaqueB D;
+  
+  Tpointer :: Etype -> AddrSpace -> Type ScalarB P;
+  Tfunction :: Rtype -> TypeParamList -> [FunAttr] -> Type CodeFunB X;
+  {- reference types -}
+
+  {- referee is Scalar -}
+  TnameScalarI :: String -> Type ScalarB I;
+  TquoteNameScalarI :: String -> Type ScalarB I;
+  TnoScalarI :: Word32 -> Type ScalarB I;
+
+  TnameScalarF :: String -> Type ScalarB F;
+  TquoteNameScalarF :: String -> Type ScalarB F;
+  TnoScalarF :: Word32 -> Type ScalarB F;
+
+  TnameScalarP :: String -> Type ScalarB P;
+  TquoteNameScalarP :: String -> Type ScalarB P;
+  TnoScalarP :: Word32 -> Type ScalarB P;
+
+  {- referee is Vector -}
+  TnameVectorI :: String -> Type VectorB I;
+  TquoteNameVectorI :: String -> Type VectorB I;
+  TnoVectorI :: Word32 -> Type VectorB I;
+
+  TnameVectorF :: String -> Type VectorB F;
+  TquoteNameVectorF :: String -> Type VectorB F;
+  TnoVectorF :: Word32 -> Type VectorB F;
+
+  TnameVectorP :: String -> Type VectorB P;
+  TquoteNameVectorP :: String -> Type VectorB P;
+  TnoVectorP :: Word32 -> Type VectorB P;
+
+  {- referee is Large Block -}
+  TnameRecordD :: String -> Type RecordB D;
+  TquoteNameRecordD :: String -> Type RecordB D;
+  TnoRecordD :: Word32 -> Type RecordB D;
+
+  {- referee is Code Fun Block -}
+  TnameCodeFunX :: String -> Type CodeFunB X;
+  TquoteNameCodeFunX :: String -> Type CodeFunB X;
+  TnoCodeFunX :: Word32 -> Type CodeFunB X;
+  
+  {- referee is Opaque -}
+  TnameOpaqueD :: String -> Type OpaqueB D;
+  TquoteNameOpaqueD :: String -> Type OpaqueB D;
+  TnoOpaqueD :: Word32 -> Type OpaqueB D;
+  }
+
+
+instance Show (Type s r) where
+  show x = case x of
+    TpI n -> "TpI " ++ show n
+    TpF n -> "TpF " ++ show n
+    TpV n -> "TpV " ++ show n
+    Tvoid -> "Tvoid"
+    TpHalf -> "TpHalf"
+    TpFloat -> "TpFloat"
+    TpDouble -> "TpDouble"
+    TpFp128 -> "TpFp128"
+    TpX86Fp80 -> "TpX86Fp80"
+    TpPpcFp128 -> "TpPpcFp128"
+    TpX86Mmx -> "TpX86Mmx"
+    TpNull -> "TpNull"
+    TpLabel -> "TpLabel"
+    Topaque -> "Topaque"
+    Tarray n d -> "Tarray " ++ show n ++ " " ++ show d
+
+    TvectorI n d -> "TvectorI " ++ show n ++ " " ++ show d
+    TvectorF n d -> "TvectorF " ++ show n ++ " " ++ show d
+    TvectorP n d -> "TvectorP " ++ show n ++ " " ++ show d
+
+    Tstruct p ds -> "Tstruct " ++ show p ++ " " ++ show ds
+    Tpointer e as -> "Tpointer " ++ show e ++ " " ++ show as
+    Tfunction rt tp fa -> "Tfunction " ++ show rt ++ " " ++ show tp ++ " " ++ show fa
+    {- Scalar -}
+    TnameScalarI s -> "TnameScalarI " ++ show s
+    TquoteNameScalarI s -> "TquoteNameScalarI " ++ show s
+    TnoScalarI n -> "TnoScalarI " ++ show n
+
+    TnameScalarF s -> "TnameScalarF " ++ show s
+    TquoteNameScalarF s -> "TquoteNameScalarF " ++ show s
+    TnoScalarF n -> "TnoScalarF " ++ show n
+
+    TnameScalarP s -> "TnameScalarP " ++ show s
+    TquoteNameScalarP s -> "TquoteNameScalarP " ++ show s
+    TnoScalarP n -> "TnoScalarP " ++ show n
+
+    {- Vector -}
+    TnameVectorI s -> "TnameVectorI " ++ show s
+    TquoteNameVectorI s -> "TquoteNameVectorI " ++ show s
+    TnoVectorI n -> "TnoVectorI " ++ show n
+
+    TnameVectorF s -> "TnameVectorF " ++ show s
+    TquoteNameVectorF s -> "TquoteNameVectorF " ++ show s
+    TnoVectorF n -> "TnoVectorF " ++ show n
+
+    TnameVectorP s -> "TnameVectorP " ++ show s
+    TquoteNameVectorP s -> "TquoteNameVectorP " ++ show s
+    TnoVectorP n -> "TnoVectorP " ++ show n
+
+    {- Large -}
+    TnameRecordD s -> "TnameRecordD " ++ show s
+    TquoteNameRecordD s -> "TquoteNameRecordD " ++ show s
+    TnoRecordD n -> "TnoRecordD " ++ show n
+
+    {- Code -}
+    TnameCodeFunX s -> "TnameCodeFunX " ++ show s
+    TquoteNameCodeFunX s -> "TquoteNameCodeFunX " ++ show s
+    TnoCodeFunX n -> "TnoCodeFunX " ++ show n
+
+    {- Opaque -}
+    TnameOpaqueD s -> "TnameOpaqueD " ++ show s
+    TquoteNameOpaqueD s -> "TquoteNameOpaqueD " ++ show s
+    TnoOpaqueD n -> "TnoOpaqueD " ++ show n
+    
+    Topaque_struct pk l -> "Topaque_struct " ++ show pk ++ " " ++ show l
+    Topaque_array n e -> "Topaque_array " ++ show n ++ " " ++ show e 
+    
+    Tfirst_class_array n e -> "Tfirst_class_array " ++ show n ++ " " ++ show e
+    Tfirst_class_struct pk l -> "Tfirst_class_struct " ++ show pk ++ " " ++ show l
+    Tfirst_class_name s -> "Tfirst_class_name " ++ show s
+    Tfirst_class_quoteName s -> "Tfirst_class_quoteName " ++ show s
+    Tfirst_class_no s -> "Tfirst_class_no " ++ show s
+
+instance Mingle (Type s r) where
+  mingle x = case x of
+    TpI n -> "i" ++ show n
+    TpF n -> "f" ++ show n
+    TpV n -> "vi" ++ show n
+    Tvoid -> "void"
+    TpHalf -> "half"
+    TpFloat -> "float"
+    TpDouble -> "double"
+    TpFp128 -> "fp128"
+    TpX86Fp80 -> "x86fp80"
+    TpPpcFp128 -> "ppcfp128"
+    TpX86Mmx -> "x86mmx"
+    TpNull -> "null"
+    TpLabel -> "label"
+    Topaque -> "opaque"
+    Tarray n d -> "a_" ++ show n ++ "_" ++ mingle d
+
+    TvectorI n d -> "vi_" ++ show n ++ "_" ++ mingle d
+    TvectorF n d -> "vf_" ++ show n ++ "_" ++ mingle d
+    TvectorP n d -> "vp_" ++ show n ++ "_" ++ mingle d
+
+    Tstruct p ds -> "s_" ++ show p ++ "_" ++ mingle ds
+    Tpointer e as -> "ptr_" ++ mingle e ++ "_" ++ show as
+    Tfunction rt tp fa -> "fun_" ++ mingle rt ++ " " ++ mingle tp ++ " " ++ show fa
+    {- Scalar -}
+    TnameScalarI s -> show s
+    TquoteNameScalarI s -> show s
+    TnoScalarI n -> show n
+
+    TnameScalarF s -> show s
+    TquoteNameScalarF s -> show s
+    TnoScalarF n -> show n
+
+    TnameScalarP s -> show s
+    TquoteNameScalarP s -> show s
+    TnoScalarP n -> show n
+
+    {- Vector -}
+    TnameVectorI s -> show s
+    TquoteNameVectorI s -> show s
+    TnoVectorI n -> show n
+
+    TnameVectorF s -> show s
+    TquoteNameVectorF s -> show s
+    TnoVectorF n -> show n
+
+    TnameVectorP s -> show s
+    TquoteNameVectorP s -> show s
+    TnoVectorP n -> show n
+
+    {- Large -}
+    TnameRecordD s -> show s
+    TquoteNameRecordD s -> show s
+    TnoRecordD n -> show n
+
+    {- Code -}
+    TnameCodeFunX s -> show s
+    TquoteNameCodeFunX s -> show s
+    TnoCodeFunX n -> show n
+
+    {- Opaque -}
+    TnameOpaqueD s -> show s
+    TquoteNameOpaqueD s -> show s
+    TnoOpaqueD n -> show n
+    
+    Topaque_struct pk l -> "os_" ++ show pk ++ "_" ++ show l
+    Topaque_array n e -> "oa_" ++ show n ++ "_" ++ show e 
+    
+    Tfirst_class_array n e -> "1ca_" ++ show n ++ " " ++ show e
+    Tfirst_class_struct pk l -> "1cs_" ++ show pk ++ " " ++ show l
+    Tfirst_class_name s -> show s
+    Tfirst_class_quoteName s -> show s
+    Tfirst_class_no s -> show s
+
+instance Eq (Type s r) where
+  (==) x1 x2 = case (x1, x2) of
+    (TpI n, TpI n1) -> n == n1
+    (TpF n, TpF n1) -> n == n1
+    (TpV n, TpV n1) -> n == n1
+    (Tvoid, Tvoid) -> True
+    (TpHalf, TpHalf) -> True
+    (TpFloat, TpFloat) -> True
+    (TpDouble, TpDouble) -> True
+    (TpFp128, TpFp128) -> True
+    (TpX86Fp80, TpX86Fp80) -> True
+    (TpPpcFp128, TpPpcFp128) -> True
+    (TpX86Mmx, TpX86Mmx) -> True
+    (TpNull, TpNull) -> error "Eq: comparing TpNull"
+    (TpLabel, TpLabel) -> error "Eq: comparing TpLabel"
+    (Topaque, Topaque) -> error "Eq: comparing Topaque"
+
+
+    (TvectorI n d, TvectorI n1 d1) -> eq2 (n,n1) (d,d1)
+    (TvectorF n d, TvectorF n1 d1) -> eq2 (n,n1) (d,d1)
+    (TvectorP n d, TvectorP n1 d1) -> eq2 (n,n1) (d,d1)
+
+    (Tarray n d, Tarray n1 d1) -> eq2 (n,n1) (d,d1)
+    (Tstruct p ds, Tstruct p1 ds1) -> eq2 (p,p1) (ds,ds1)
+    
+    (Tfirst_class_array n d, Tfirst_class_array n1 d1) -> eq2 (n,n1) (d,d1)
+    (Tfirst_class_struct p ds, Tfirst_class_struct p1 ds1) -> eq2 (p,p1) (ds,ds1)
+    (Tfirst_class_name s, Tfirst_class_name s1) -> s == s1
+    (Tfirst_class_quoteName s, Tfirst_class_quoteName s1) -> s == s1    
+    (Tfirst_class_no s, Tfirst_class_no s1) -> s == s1    
+    
+    
+    (Tpointer e as, Tpointer e1 as1) -> eq2 (e,e1) (as,as1)
+    (Tfunction rt tp fa, Tfunction rt1 tp1 fa1) -> eq3 (rt,rt1) (tp,tp1) (fa,fa1)
+
+    {- Scalar -}
+    (TnameScalarI s, TnameScalarI s1) -> s == s1
+    (TquoteNameScalarI s, TquoteNameScalarI s1) -> s == s1
+    (TnoScalarI n, TnoScalarI n1) -> n == n1
+
+    (TnameScalarF s, TnameScalarF s1) -> s == s1
+    (TquoteNameScalarF s, TquoteNameScalarF s1) -> s == s1
+    (TnoScalarF n, TnoScalarF n1) -> n == n1
+
+    (TnameScalarP s, TnameScalarP s1) -> s == s1
+    (TquoteNameScalarP s, TquoteNameScalarP s1) -> s == s1
+    (TnoScalarP n, TnoScalarP n1) -> n == n1
+
+    {- Vector -}
+    (TnameVectorI s, TnameVectorI s1) -> s == s1
+    (TquoteNameVectorI s, TquoteNameVectorI s1) -> s == s1
+    (TnoVectorI n, TnoVectorI n1) -> n == n1
+
+    (TnameVectorF s, TnameVectorF s1) -> s == s1
+    (TquoteNameVectorF s, TquoteNameVectorF s1) -> s == s1
+    (TnoVectorF n, TnoVectorF n1) -> n == n1
+
+    (TnameVectorP s, TnameVectorP s1) -> s == s1
+    (TquoteNameVectorP s, TquoteNameVectorP s1) -> s == s1
+    (TnoVectorP n, TnoVectorP n1) -> n == n1
+
+    {- Record -}
+    (TnameRecordD s, TnameRecordD s1) -> s == s1
+    (TquoteNameRecordD s, TquoteNameRecordD s1) -> s == s1
+    (TnoRecordD n, TnoRecordD n1) -> n == n1
+
+    {- Fun Code -}
+    (TnameCodeFunX s, TnameCodeFunX s1) -> s == s1
+    (TquoteNameCodeFunX s, TquoteNameCodeFunX s1) -> s == s1
+    (TnoCodeFunX n, TnoCodeFunX n1) -> n == n1
+
+    {- Opaque -}
+    (TnameOpaqueD _, TnameOpaqueD _) -> errorLoc FLC "comparing opaque types"
+    (TquoteNameOpaqueD _, TquoteNameOpaqueD _) -> errorLoc FLC "comparing opaque types"
+    (TnoOpaqueD _, TnoOpaqueD _) -> errorLoc FLC "comparing opaque types"
+    (Topaque_struct _ _, Topaque_struct _ _) -> errorLoc FLC "comparing opaque types"
+    (Topaque_array _ _, Topaque_array _ _) -> errorLoc FLC "comparing opaque types"
+
+    (_,_) -> False
+
+
+
+instance Ord (Type s r) where
+  compare x1 x2 = case (x1, x2) of
+    (TpI n, TpI n1) -> compare n n1
+    (TpF n, TpF n1) -> compare n n1
+    (TpV n, TpV n1) -> compare n n1
+    (Tvoid, Tvoid) -> EQ
+    (TpHalf, TpHalf) -> EQ
+    (TpFloat, TpFloat) -> EQ
+    (TpDouble, TpDouble) -> EQ
+    (TpFp128, TpFp128) -> EQ
+    (TpX86Fp80, TpX86Fp80) -> EQ
+    (TpPpcFp128, TpPpcFp128) -> EQ
+    (TpX86Mmx, TpX86Mmx) -> EQ
+    (TpNull, TpNull) -> error "Ord: comparing TpNull"
+    (TpLabel, TpLabel) -> error "Ord: comparing TpLabel"
+    (Topaque, Topaque) -> error "Ord: comparing Topaque"
+
+
+    (TvectorI n d, TvectorI n1 d1) -> compare2 (n,n1) (d,d1)
+    (TvectorF n d, TvectorF n1 d1) -> compare2 (n,n1) (d,d1)
+    (TvectorP n d, TvectorP n1 d1) -> compare2 (n,n1) (d,d1)
+
+    (Tarray n d, Tarray n1 d1) -> compare2 (n,n1) (d,d1)
+    (Tstruct p ds, Tstruct p1 ds1) -> compare2 (p,p1) (ds,ds1)
+    
+    (Tfirst_class_array n d, Tfirst_class_array n1 d1) -> compare2 (n,n1) (d,d1)
+    (Tfirst_class_struct p ds, Tfirst_class_struct p1 ds1) -> compare2 (p,p1) (ds,ds1)
+    (Tfirst_class_name s, Tfirst_class_name s1) -> compare s s1
+    (Tfirst_class_quoteName s, Tfirst_class_quoteName s1) -> compare s s1    
+    (Tfirst_class_no s, Tfirst_class_no s1) -> compare s s1
+
+
+    (Tpointer e as, Tpointer e1 as1) -> compare2 (e,e1) (as,as1)
+    (Tfunction rt tp fa, Tfunction rt1 tp1 fa1) -> compare3 (rt,rt1) (tp,tp1) (fa,fa1)
+
+    {- Scalar -}
+    (TnameScalarI s, TnameScalarI s1) -> compare s s1
+    (TquoteNameScalarI s, TquoteNameScalarI s1) -> compare s s1
+    (TnoScalarI n, TnoScalarI n1) -> compare n n1
+
+    (TnameScalarF s, TnameScalarF s1) -> compare s s1
+    (TquoteNameScalarF s, TquoteNameScalarF s1) -> compare s s1
+    (TnoScalarF n, TnoScalarF n1) -> compare n n1
+
+    (TnameScalarP s, TnameScalarP s1) -> compare s s1
+    (TquoteNameScalarP s, TquoteNameScalarP s1) -> compare s s1
+    (TnoScalarP n, TnoScalarP n1) -> compare n n1
+
+    {- Vector -}
+    (TnameVectorI s, TnameVectorI s1) -> compare s s1
+    (TquoteNameVectorI s, TquoteNameVectorI s1) -> compare s s1
+    (TnoVectorI n, TnoVectorI n1) -> compare n n1
+
+    (TnameVectorF s, TnameVectorF s1) -> compare s s1
+    (TquoteNameVectorF s, TquoteNameVectorF s1) -> compare s s1
+    (TnoVectorF n, TnoVectorF n1) -> compare n n1
+
+    (TnameVectorP s, TnameVectorP s1) -> compare s s1
+    (TquoteNameVectorP s, TquoteNameVectorP s1) -> compare s s1
+    (TnoVectorP n, TnoVectorP n1) -> compare n n1
+
+    {- Large -}
+    (TnameRecordD s, TnameRecordD s1) -> compare s s1
+    (TquoteNameRecordD s, TquoteNameRecordD s1) -> compare s s1
+    (TnoRecordD n, TnoRecordD n1) -> compare n n1
+
+    {- Code -}
+    (TnameCodeFunX s, TnameCodeFunX s1) -> compare s s1
+    (TquoteNameCodeFunX s, TquoteNameCodeFunX s1) -> compare s s1
+    (TnoCodeFunX n, TnoCodeFunX n1) -> compare n n1
+
+    {- Opaque -}
+    (TnameOpaqueD _, TnameOpaqueD _) -> errorLoc FLC "comparing opaque types"
+    (TquoteNameOpaqueD _, TquoteNameOpaqueD _) -> errorLoc FLC "comparing opaque types"
+    (TnoOpaqueD _, TnoOpaqueD _) -> errorLoc FLC "comparing opaque types"
+    (Topaque_struct _ _, Topaque_struct _ _) -> errorLoc FLC "comparing opaque types"
+    (Topaque_array _ _, Topaque_array _ _) -> errorLoc FLC "comparing opaque types"    
+
+    (_,_) -> compare (show x1) (show x2)
+
+data FormalParam = FormalParamData Dtype [ParamAttr] (Maybe Alignment) Fparam [ParamAttr]
+                 | FormalParamMeta MetaKind Fparam
+                 deriving (Eq,Ord,Show)
+
+data FormalParamList = FormalParamList [FormalParam] (Maybe VarArgParam) [FunAttr]
+                     deriving (Eq,Ord,Show)
+
+data TypeParamList = TypeParamList [Dtype] (Maybe VarArgParam) deriving (Eq,Ord,Show)
+
+instance Mingle TypeParamList where
+  mingle (TypeParamList l va) = "(" ++ mingle l ++ show va ++ ")"
+
+type AddrSpace = Word32
+
+data MetaKind = Mtype Utype
+              | Mmetadata
+              deriving (Eq, Ord,Show)
+
+
+{- short hand notations -}
+uc :: Ucast a b => a -> b
+uc x = ucast x
+
+dc :: Dcast a b => FileLoc -> String -> a -> b
+dc lc s x = dcast lc x
+
+data Utype = UtypeScalarI (Type ScalarB I)
+           | UtypeScalarF (Type ScalarB F)
+           | UtypeScalarP (Type ScalarB P)
+           | UtypeVectorI (Type VectorB I)
+           | UtypeVectorF (Type VectorB F)
+           | UtypeVectorP (Type VectorB P)
+           | UtypeFirstClassD (Type FirstClassB D)
+           | UtypeRecordD (Type RecordB D)
+           | UtypeOpaqueD (Type OpaqueB D)
+           | UtypeVoidU (Type NoB U)
+           | UtypeFunX (Type CodeFunB X)
+           | UtypeLabelX (Type CodeLabelB X)
+           deriving (Eq,Ord,Show)
+
+data Etype = EtypeScalarI (Type ScalarB I)
+            | EtypeScalarF (Type ScalarB F)
+            | EtypeScalarP (Type ScalarB P)
+            | EtypeVectorI (Type VectorB I)
+            | EtypeVectorF (Type VectorB F)
+            | EtypeVectorP (Type VectorB P)
+            | EtypeFirstClassD (Type FirstClassB D)              
+            | EtypeRecordD (Type RecordB D)
+            | EtypeOpaqueD (Type OpaqueB D)
+            | EtypeFunX (Type CodeFunB X)
+            deriving (Eq, Ord, Show)
+
+{- this will be replicated in multiple nodes to reduce the depth of AST, a lower depth AST is
+   more friendly for manual AST construction
+-}
+data Rtype = RtypeScalarI (Type ScalarB I)
+           | RtypeScalarF (Type ScalarB F)
+           | RtypeScalarP (Type ScalarB P)
+           | RtypeVectorI (Type VectorB I)
+           | RtypeVectorF (Type VectorB F)
+           | RtypeVectorP (Type VectorB P)
+           | RtypeFirstClassD (Type FirstClassB D)
+           | RtypeRecordD (Type RecordB D)
+           | RtypeVoidU (Type NoB U)
+           deriving (Eq, Ord, Show)
+
+data Dtype = DtypeScalarI (Type ScalarB I)
+           | DtypeScalarF (Type ScalarB F)
+           | DtypeScalarP (Type ScalarB P)
+           | DtypeVectorI (Type VectorB I)
+           | DtypeVectorF (Type VectorB F)
+           | DtypeVectorP (Type VectorB P)
+           | DtypeFirstClassD (Type FirstClassB D)
+           | DtypeRecordD (Type RecordB D)
+           deriving (Eq, Ord, Show)
+
+{- First class type -}
+data Ftype = FtypeScalarI (Type ScalarB I)
+           | FtypeScalarF (Type ScalarB F)
+           | FtypeScalarP (Type ScalarB P)
+           | FtypeVectorI (Type VectorB I)
+           | FtypeVectorF (Type VectorB F)
+           | FtypeVectorP (Type VectorB P)
+           | FtypeFirstClassD (Type FirstClassB D)
+           deriving (Eq, Ord, Show)
+
+
+data ScalarType = ScalarTypeI (Type ScalarB I)
+                | ScalarTypeF (Type ScalarB F)
+                | ScalarTypeP (Type ScalarB P)
+                deriving (Eq, Ord, Show)
+                         
+data IntOrPtrType s = IntOrPtrTypeI (Type s I)                         
+                    | IntOrPtrTypeP (Type s P)
+                    deriving (Eq, Ord, Show)
+
+{- Type s r, which represents all types,  ucast to Utype -}
+instance Ucast (Type s r) (Type s r) where
+  ucast = id
+  
+instance Ucast (Type s r) Utype where
+  ucast x = case x of
+    TpI _ -> UtypeScalarI x
+    TpF _ -> UtypeScalarF x
+    TpV _ -> UtypeScalarI x
+    Tvoid -> UtypeVoidU x
+    TpHalf -> UtypeScalarF x
+    TpFloat -> UtypeScalarF x
+    TpDouble -> UtypeScalarF x
+    TpFp128 -> UtypeScalarF x
+    TpX86Fp80 -> UtypeScalarF x
+    TpPpcFp128 -> UtypeScalarF x
+    TpX86Mmx -> UtypeScalarI x
+    TpNull -> UtypeScalarI x
+    TpLabel -> UtypeLabelX x
+    Topaque -> UtypeOpaqueD x
+
+    TvectorI _ _ -> UtypeVectorI x
+    TvectorF _ _ -> UtypeVectorF x
+    TvectorP _ _ -> UtypeVectorP x
+  
+    Tfirst_class_array _ _ -> UtypeFirstClassD x
+    Tfirst_class_struct _ _ -> UtypeFirstClassD x
+    Tfirst_class_name _ -> UtypeFirstClassD x
+    Tfirst_class_quoteName _ -> UtypeFirstClassD x    
+    Tfirst_class_no _ -> UtypeFirstClassD x    
+    
+    Tarray _ _ -> UtypeRecordD x
+    Tstruct _ _ -> UtypeRecordD x
+    
+    Topaque_struct _ _ -> UtypeOpaqueD x
+    Topaque_array _ _ -> UtypeOpaqueD x    
+    
+    Tpointer _ _ -> UtypeScalarP x
+    Tfunction _ _ _ -> UtypeFunX x
+
+    {- Scalar -}
+    TnameScalarI _ -> UtypeScalarI x
+    TquoteNameScalarI _ -> UtypeScalarI x
+    TnoScalarI _ -> UtypeScalarI x
+
+    TnameScalarF _ -> UtypeScalarF x
+    TquoteNameScalarF _ -> UtypeScalarF x
+    TnoScalarF _ -> UtypeScalarF x
+
+    TnameScalarP _ -> UtypeScalarP x
+    TquoteNameScalarP _ -> UtypeScalarP x
+    TnoScalarP _ -> UtypeScalarP x
+
+    {- Vector -}
+    TnameVectorI _ -> UtypeVectorI x
+    TquoteNameVectorI _ -> UtypeVectorI x
+    TnoVectorI _ -> UtypeVectorI x
+
+    TnameVectorF _ -> UtypeVectorF x
+    TquoteNameVectorF _ -> UtypeVectorF x
+    TnoVectorF _ -> UtypeVectorF x
+
+    TnameVectorP _ -> UtypeVectorP x
+    TquoteNameVectorP _ -> UtypeVectorP x
+    TnoVectorP _ -> UtypeVectorP x
+
+    {- Large -}
+    TnameRecordD _ -> UtypeRecordD x
+    TquoteNameRecordD _ -> UtypeRecordD x
+    TnoRecordD _ -> UtypeRecordD x
+
+    {- Code -}
+    TnameCodeFunX _ -> UtypeFunX x
+    TquoteNameCodeFunX _ -> UtypeFunX x
+    TnoCodeFunX _ -> UtypeFunX x
+
+    {- Opaque -}
+    TnameOpaqueD _ -> UtypeOpaqueD x
+    TquoteNameOpaqueD _ -> UtypeOpaqueD x
+    TnoOpaqueD _ -> UtypeOpaqueD x
+
+instance Dcast Utype (Type ScalarB I) where
+  dcast lc e = case e of
+    UtypeScalarI x -> x
+    _ -> dcastError lc "Type ScalarB I" e
+
+instance Dcast Utype (Type ScalarB F) where
+  dcast lc e = case e of
+    UtypeScalarF x -> x
+    _ -> dcastError lc "Type ScalarB F" e
+
+instance Dcast Utype (Type ScalarB P) where
+  dcast lc e = case e of
+    UtypeScalarP x -> x
+    _ -> dcastError lc "Type ScalarB P" e
+
+instance Dcast Utype (Type VectorB I) where
+  dcast lc e = case e of
+    UtypeVectorI x -> x
+    _ -> dcastError lc "Type VectorB I" e
+
+instance Dcast Utype (Type VectorB F) where
+  dcast lc e = case e of
+    UtypeVectorF x -> x
+    _ -> dcastError lc "Type VectorB F" e
+
+instance Dcast Utype (Type VectorB P) where
+  dcast lc e = case e of
+    UtypeVectorP x -> x
+    _ -> dcastError lc "Type VectorB P" e
+
+instance Dcast Utype (Type FirstClassB D) where
+  dcast lc e = case e of
+    UtypeFirstClassD x -> x
+    _ -> dcastError lc "Type FirstClassB D" e
+
+instance Dcast Utype (Type RecordB D) where
+  dcast lc e = case e of
+    UtypeRecordD x -> x
+    _ -> dcastError lc "Type RecordB D" e
+
+
+instance Dcast Utype (Type CodeFunB X) where
+  dcast lc e = case e of
+    UtypeFunX x -> x
+    _ -> dcastError lc "Type CodeFunB X" e
+
+instance Dcast Utype (Type CodeLabelB X) where
+  dcast lc e = case e of
+    UtypeLabelX x -> x
+    _ -> dcastError lc "Type CodeLabelB X" e
+
+
+instance Dcast Utype (Type OpaqueB D) where
+  dcast lc e = case e of
+    UtypeOpaqueD x -> x
+    _ -> dcastError lc "Type OpaqueB D" e
+
+
+{- Etype's dcast, ucast, dcast -}
+instance Dcast Utype Etype where
+  dcast lc x = case x of
+    UtypeScalarI e -> EtypeScalarI e
+    UtypeScalarF e -> EtypeScalarF e
+    UtypeScalarP e -> EtypeScalarP e
+    UtypeVectorI e -> EtypeVectorI e
+    UtypeVectorF e -> EtypeVectorF e
+    UtypeVectorP e -> EtypeVectorP e
+    UtypeFirstClassD e -> EtypeFirstClassD e    
+    UtypeRecordD e -> EtypeRecordD e
+    UtypeOpaqueD e -> EtypeOpaqueD e
+    UtypeFunX e -> EtypeFunX e
+    _ -> dcastError lc "Etype" x
+
+instance Ucast Etype Utype where
+  ucast x = case x of
+    EtypeScalarI e -> UtypeScalarI e
+    EtypeScalarF e -> UtypeScalarF e
+    EtypeScalarP e -> UtypeScalarP e
+    EtypeVectorI e -> UtypeVectorI e
+    EtypeVectorF e -> UtypeVectorF e
+    EtypeVectorP e -> UtypeVectorP e
+    EtypeFirstClassD e -> UtypeFirstClassD e
+    EtypeRecordD e -> UtypeRecordD e
+    EtypeOpaqueD e -> UtypeOpaqueD e
+    EtypeFunX e -> UtypeFunX e
+
+instance Dcast Etype Dtype where
+  dcast lc x = case x of
+    EtypeScalarI e -> DtypeScalarI e
+    EtypeScalarF e -> DtypeScalarF e
+    EtypeScalarP e -> DtypeScalarP e
+    EtypeVectorI e -> DtypeVectorI e
+    EtypeVectorF e -> DtypeVectorF e
+    EtypeVectorP e -> DtypeVectorP e
+    EtypeFirstClassD e -> DtypeFirstClassD e
+    EtypeRecordD e -> DtypeRecordD e
+    _ -> dcastError lc "Dtype" x
+
+instance Dcast (Type s r) Etype where
+  dcast lc x = let (x1::Utype) = ucast x
+               in dcast lc x1
+
+instance Ucast (Type x I) Etype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x F) Etype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x P) Etype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type FirstClassB x) Etype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type RecordB D) Etype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type CodeFunB X) Etype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+
+{- Rtype's dcast, ucast, dcast -}
+instance Dcast Utype Rtype where
+  dcast lc x = case x of
+    UtypeScalarI e -> RtypeScalarI e
+    UtypeScalarF e -> RtypeScalarF e
+    UtypeScalarP e -> RtypeScalarP e
+    UtypeVectorI e -> RtypeVectorI e
+    UtypeVectorF e -> RtypeVectorF e
+    UtypeVectorP e -> RtypeVectorP e
+    UtypeRecordD e -> RtypeRecordD e
+    UtypeVoidU e -> RtypeVoidU e
+    _ -> dcastError lc "Rtype" x
+
+instance Ucast Rtype Utype where
+  ucast x = case x of
+    RtypeScalarI e -> UtypeScalarI e
+    RtypeScalarF e -> UtypeScalarF e
+    RtypeScalarP e -> UtypeScalarP e
+    RtypeVectorI e -> UtypeVectorI e
+    RtypeVectorF e -> UtypeVectorF e
+    RtypeVectorP e -> UtypeVectorP e
+    RtypeRecordD e -> UtypeRecordD e
+    RtypeFirstClassD e -> UtypeFirstClassD e
+    RtypeVoidU e -> UtypeVoidU e
+
+instance Dcast Rtype Dtype where
+  dcast lc x = case x of
+    RtypeScalarI e -> DtypeScalarI e
+    RtypeScalarF e -> DtypeScalarF e
+    RtypeScalarP e -> DtypeScalarP e
+    RtypeVectorI e -> DtypeVectorI e
+    RtypeVectorF e -> DtypeVectorF e
+    RtypeVectorP e -> DtypeVectorP e
+    RtypeRecordD e -> DtypeRecordD e
+    _ -> dcastError lc "Rtype" x
+
+instance Dcast (Type s r) Rtype where
+  dcast lc x = let (x1::Utype) = ucast x
+               in dcast lc x1
+
+instance Ucast (Type x I) Rtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x F) Rtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x P) Rtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type FirstClassB D) Rtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type RecordB D) Rtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type NoB U) Rtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+{- Dtype's dcast, ucast, dcast -}
+instance Dcast Utype Dtype where
+  dcast lc x = case x of
+    UtypeScalarI e -> DtypeScalarI e
+    UtypeScalarF e -> DtypeScalarF e
+    UtypeScalarP e -> DtypeScalarP e
+    UtypeVectorI e -> DtypeVectorI e
+    UtypeVectorF e -> DtypeVectorF e
+    UtypeVectorP e -> DtypeVectorP e
+    UtypeFirstClassD e -> DtypeFirstClassD e    
+    UtypeRecordD e -> DtypeRecordD e
+    _ -> dcastError lc "Dtype" x
+
+instance Ucast Dtype Utype where
+  ucast x = case x of
+    DtypeScalarI e -> UtypeScalarI e
+    DtypeScalarF e -> UtypeScalarF e
+    DtypeScalarP e -> UtypeScalarP e
+    DtypeVectorI e -> UtypeVectorI e
+    DtypeVectorF e -> UtypeVectorF e
+    DtypeVectorP e -> UtypeVectorP e
+    DtypeFirstClassD e -> UtypeFirstClassD e    
+    DtypeRecordD e -> UtypeRecordD e
+
+instance Ucast Dtype Etype where
+  ucast x = case x of
+    DtypeScalarI e -> EtypeScalarI e
+    DtypeScalarF e -> EtypeScalarF e
+    DtypeScalarP e -> EtypeScalarP e
+    DtypeVectorI e -> EtypeVectorI e
+    DtypeVectorF e -> EtypeVectorF e
+    DtypeVectorP e -> EtypeVectorP e
+    DtypeFirstClassD e -> EtypeFirstClassD e    
+    DtypeRecordD e -> EtypeRecordD e
+
+instance Dcast (Type s r) Dtype where
+  dcast lc x = let (x1::Utype) = ucast x
+               in dcast lc x1
+
+instance Ucast (Type x I) Dtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x F) Dtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x P) Dtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type RecordB D) Dtype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Dcast Dtype (Type ScalarB P) where
+  dcast lc x = case x of
+    DtypeScalarP e -> e
+    _ -> dcastError lc "Type ScalarB P" x
+
+instance Dcast Dtype (Type ScalarB I) where
+  dcast lc x = case x of
+    DtypeScalarI e -> e
+    _ -> dcastError lc "Type ScalarB I" x
+
+{- Ftype's dcast, ucast, dcast -}
+instance Dcast Utype Ftype where
+  dcast lc x = case x of
+    UtypeScalarI e -> FtypeScalarI e
+    UtypeScalarF e -> FtypeScalarF e
+    UtypeScalarP e -> FtypeScalarP e
+    UtypeVectorI e -> FtypeVectorI e
+    UtypeVectorF e -> FtypeVectorF e
+    UtypeVectorP e -> FtypeVectorP e
+    UtypeFirstClassD e -> FtypeFirstClassD e
+    _ -> dcastError lc "Ftype" x
+
+instance Ucast Ftype Utype where
+  ucast x = case x of
+    FtypeScalarI e -> UtypeScalarI e
+    FtypeScalarF e -> UtypeScalarF e
+    FtypeScalarP e -> UtypeScalarP e
+    FtypeVectorI e -> UtypeVectorI e
+    FtypeVectorF e -> UtypeVectorF e
+    FtypeVectorP e -> UtypeVectorP e
+    FtypeFirstClassD e -> UtypeFirstClassD e    
+
+instance Dcast (Type s r) Ftype where
+  dcast lc x = let (x1::Utype) = ucast x
+               in dcast lc x1
+
+instance Ucast (Type x I) Ftype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x F) Ftype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x P) Ftype where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+
+{- ScalarType's dcast, ucast, dcast -}
+instance Dcast Utype ScalarType where
+  dcast lc x = case x of
+    UtypeScalarI e -> ScalarTypeI e
+    UtypeScalarF e -> ScalarTypeF e
+    UtypeScalarP e -> ScalarTypeP e
+    _ -> dcastError lc "ScalarType" x
+
+instance Ucast ScalarType Utype where
+  ucast x = case x of
+    ScalarTypeI e -> UtypeScalarI e
+    ScalarTypeF e -> UtypeScalarF e
+    ScalarTypeP e -> UtypeScalarP e
+
+instance Dcast Dtype ScalarType where
+  dcast lc x = case x of
+    DtypeScalarI e -> ScalarTypeI e
+    DtypeScalarF e -> ScalarTypeF e
+    DtypeScalarP e -> ScalarTypeP e
+    _ -> dcastError lc "ScalarType" x
+
+instance Ucast ScalarType Dtype where
+  ucast x = case x of
+    ScalarTypeI e -> DtypeScalarI e
+    ScalarTypeF e -> DtypeScalarF e
+    ScalarTypeP e -> DtypeScalarP e
+
+instance Dcast (Type s r) ScalarType where
+  dcast lc x = let (x1::Utype) = ucast x
+               in dcast lc x1
+
+instance Ucast (Type x I) ScalarType where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x F) ScalarType where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type x P) ScalarType where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+
+{- IntOrPtrType's dcast, ucast, dcast -}
+instance Dcast Utype (IntOrPtrType ScalarB)  where
+  dcast lc x = case x of
+    UtypeScalarI e -> IntOrPtrTypeI e
+    UtypeScalarP e -> IntOrPtrTypeP e
+    _ -> dcastError lc "IntOrPtrType ScalarB" x
+
+instance Dcast Utype (IntOrPtrType VectorB)  where
+  dcast lc x = case x of
+    UtypeVectorI e -> IntOrPtrTypeI e
+    UtypeVectorP e -> IntOrPtrTypeP e
+    _ -> dcastError lc "IntOrPtrType VectorB" x
+
+instance Ucast (IntOrPtrType ScalarB) Utype where
+  ucast x = case x of
+    IntOrPtrTypeI e -> UtypeScalarI e
+    IntOrPtrTypeP e -> UtypeScalarP e
+
+instance Ucast (IntOrPtrType VectorB) Utype where
+  ucast x = case x of
+    IntOrPtrTypeI e -> UtypeVectorI e
+    IntOrPtrTypeP e -> UtypeVectorP e
+
+
+instance Dcast (Type s r) (IntOrPtrType ScalarB) where
+  dcast lc x = let (x1::Utype) = ucast x
+               in dcast lc x1
+
+instance Dcast (Type s r) (IntOrPtrType VectorB) where
+  dcast lc x = let (x1::Utype) = ucast x
+               in dcast lc x1
+
+instance Ucast (Type ScalarB I) (IntOrPtrType ScalarB) where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type ScalarB P) (IntOrPtrType ScalarB) where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type VectorB I) (IntOrPtrType VectorB) where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+instance Ucast (Type VectorB P) (IntOrPtrType VectorB) where
+  ucast x = let (x1::Utype) = ucast x
+            in dcast (FileLoc "irrefutable") x1
+
+
+squeeze :: FileLoc -> Type RecordB D -> Type FirstClassB D
+squeeze loc x = case x of
+  Tstruct pk dl -> Tfirst_class_struct pk (fmap (dcast loc) dl)
+  Tarray n el -> Tfirst_class_array n (dcast loc el)
+  TnameRecordD e -> Tfirst_class_name e
+  TquoteNameRecordD e -> Tfirst_class_quoteName e
+  TnoRecordD e -> Tfirst_class_no e
+  
+  
+void :: Type NoB U
+void = Tvoid
+
+i1 :: Type ScalarB I
+i1 = TpI 1
+
+i8 :: Type ScalarB I
+i8 = TpI 8
+
+i16 :: Type ScalarB I
+i16 = TpI 16
+
+i32 :: Type ScalarB I
+i32 = TpI 32
+
+i64 :: Type ScalarB I
+i64 = TpI 64
+
+i128 :: Type ScalarB I
+i128 = TpI 128
+
+ptr0 :: Type s r -> Type ScalarB P
+ptr0 t = Tpointer (dcast FLC t) 0
+
+half :: Type ScalarB F
+half = TpHalf
+
+float :: Type ScalarB F
+float = TpFloat
+
+double :: Type ScalarB F
+double = TpDouble
+
+fp128 :: Type ScalarB F
+fp128 = TpFp128
+
+x86_fp80 :: Type ScalarB F
+x86_fp80 = TpX86Fp80
+
+
+instance Mingle Dtype where
+  mingle t = let (t0::Utype) = ucast t 
+             in mingle t0
+    
+instance Mingle Rtype where
+  mingle t = let (t0::Utype) = ucast t 
+             in mingle t0
+    
+instance Mingle Etype where
+  mingle t = let (t0::Utype) = ucast t 
+             in mingle t0
+
+instance Mingle Utype where    
+  mingle t = case t of
+    UtypeScalarI e -> mingle e
+    UtypeScalarF e -> mingle e
+    UtypeScalarP e -> mingle e
+    UtypeVectorI e -> mingle e
+    UtypeVectorF e -> mingle e
+    UtypeVectorP e -> mingle e
+    UtypeFirstClassD e -> mingle e
+    UtypeRecordD e -> mingle e
+    UtypeOpaqueD e -> mingle e
+    UtypeVoidU e -> mingle e
+    UtypeFunX e -> mingle e
+    UtypeLabelX e -> mingle e
diff --git a/src/Llvm/Data/Shared.hs b/src/Llvm/Data/Shared.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Shared.hs
@@ -0,0 +1,21 @@
+module Llvm.Data.Shared 
+       (module Llvm.Data.Shared.AtomicEntity
+       ,module Llvm.Data.Shared.SimpleConst
+       ,module Llvm.Data.Shared.DataLayout
+       ,module Llvm.Data.Shared.Util
+       )
+       where
+
+import Llvm.Data.Shared.AtomicEntity
+import Llvm.Data.Shared.SimpleConst
+-- import Llvm.Data.Shared.Type
+import Llvm.Data.Shared.DataLayout
+import Llvm.Data.Shared.Util
+
+
+
+{-
+data Typed v where
+  TypedData :: Type -> v -> Typed v 
+  UntypedNull :: Typed v -- Const
+-}
diff --git a/src/Llvm/Data/Shared/AtomicEntity.hs b/src/Llvm/Data/Shared/AtomicEntity.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Shared/AtomicEntity.hs
@@ -0,0 +1,324 @@
+module Llvm.Data.Shared.AtomicEntity where
+import qualified Data.Map as M
+import Data.Word(Word32)
+
+-- | Double Quoted String
+data DqString = DqString String deriving (Eq, Ord, Show)
+
+data IcmpOp = IcmpEq | IcmpNe | IcmpUgt | IcmpUge | IcmpUlt 
+            | IcmpUle | IcmpSgt | IcmpSge | IcmpSlt | IcmpSle
+            deriving (Eq,Ord,Show)
+
+icmpOpMap :: M.Map IcmpOp String
+icmpOpMap = M.fromList [(IcmpEq, "eq"), (IcmpNe, "ne")
+                       ,(IcmpUgt, "ugt"),(IcmpUge, "uge")
+                       ,(IcmpUlt, "ult"),(IcmpUle, "ule")
+                       ,(IcmpSgt, "sgt"), (IcmpSge, "sge")
+                       ,(IcmpSlt, "slt"),(IcmpSle, "sle")
+                       ]
+
+data FcmpOp = FcmpTrue | FcmpFalse
+            | FcmpOeq | FcmpOgt | FcmpOge
+            | FcmpOlt | FcmpOle | FcmpOne | FcmpOrd
+            | FcmpUeq | FcmpUgt | FcmpUge | FcmpUlt
+            | FcmpUle | FcmpUne | FcmpUno
+            deriving (Eq,Ord,Show)
+
+fcmpOpMap :: M.Map FcmpOp String
+fcmpOpMap = M.fromList [(FcmpTrue, "true"), (FcmpFalse, "false")
+                       ,(FcmpOeq, "oeq"), (FcmpOgt, "ogt"), (FcmpOge, "oge")
+                       ,(FcmpOlt, "olt"), (FcmpOle, "ole"), (FcmpOne, "one"), (FcmpOrd, "ord")
+                       ,(FcmpUeq, "ueq"), (FcmpUgt, "ugt"), (FcmpUge, "uge")
+                       ,(FcmpUlt, "ult"), (FcmpUle, "ule"), (FcmpUne, "une"), (FcmpUno, "uno") 
+                       ]
+
+-- | Linkage Types <http://llvm.org/releases/3.5.0/docs/LangRef.html#linkage-types>
+data Linkage = LinkagePrivate
+             | LinkageInternal    
+             | LinkageAvailableExternally
+             | LinkageLinkonce
+             | LinkageCommon
+             | LinkageWeak
+             | LinkageAppending
+             | LinkageExternWeak
+             | LinkageLinkonceOdr
+             | LinkageWeakOdr
+             | LinkageExternal
+             deriving (Eq,Ord,Show)
+
+-- | Calling Conventions <http://llvm.org/releases/3.5.0/docs/LangRef.html#calling-conventions>
+data CallConv = Ccc 
+              | CcFast 
+              | CcCold 
+              | CcGhc
+              | CcHiPe
+              | Cc String
+              | CcWebkit_Js
+              | CcAnyReg
+              | CcPreserveMost
+              | CcPreserveAll
+              | CcFirstTarget
+              | CcX86_StdCall
+              | CcX86_FastCall
+              | CcArm_Apcs
+              | CcArm_Aapcs
+              | CcArm_Aapcs_Vfp
+              | CcMsp430_Intr
+              | CcX86_ThisCall
+              | CcPtx_Kernel
+              | CcPtx_Device
+              | CcSpir_Func
+              | CcSpir_Kernel
+              | CcIntel_Ocl_Bi
+              | CcX86_64_SysV
+              | CcX86_64_Win64
+              | CcX86_VectorCall
+              deriving (Eq,Ord,Show)
+
+-- | Visibility Styles <http://llvm.org/releases/3.5.0/docs/LangRef.html#visibility-styles>
+data Visibility = VisDefault | VisHidden | VisProtected
+                  deriving (Eq,Ord,Show)
+
+-- | DLL Storage Classes <http://llvm.org/releases/3.5.0/docs/LangRef.html#dll-storage-classes>              
+data DllStorageClass = DscImport
+                     | DscExport deriving (Eq, Ord, Show)
+                                     
+-- | Thread Local Storage Models <http://llvm.org/releases/3.5.0/docs/LangRef.html#thread-local-storage-models>
+data ThreadLocalStorage = TlsLocalDynamic
+                        | TlsInitialExec
+                        | TlsLocalExec
+                        | TlsNone
+                        deriving (Eq, Ord, Show)
+
+-- | Parameter Attributes <http://llvm.org/releases/3.5.0/docs/LangRef.html#parameter-attributes>
+data ParamAttr = PaZeroExt 
+               | PaSignExt
+               | PaInReg 
+               | PaByVal 
+               | PaInAlloca
+               | PaSRet
+               | PaNoAlias 
+               | PaNoCapture
+               | PaNest 
+               | PaReturned
+               | PaNonNull
+               | PaDereferenceable Word32 -- Integer
+               | PaReadOnly
+               | PaReadNone
+               | PaAlign Word32 -- Integer
+                 deriving (Eq,Ord,Show)
+
+-- | Function Attributes <http://llvm.org/releases/3.5.0/docs/LangRef.html#function-attributes>
+data FunAttr = FaAlignStack Word32 -- Integer
+             | FaAlwaysInline
+             | FaBuiltin
+             | FaCold
+             | FaInlineHint
+             | FaJumpTable
+             | FaMinSize
+             | FaNaked
+             | FaNoBuiltin
+             | FaNoDuplicate
+             | FaNoImplicitFloat
+             | FaNoInline
+             | FaNonLazyBind
+             | FaNoRedZone
+             | FaNoReturn
+             | FaNoUnwind
+             | FaOptNone
+             | FaOptSize
+             | FaReadNone
+             | FaReadOnly
+             | FaReturnsTwice
+             | FaSanitizeAddress
+             | FaSanitizeMemory
+             | FaSanitizeThread
+             | FaSsp
+             | FaSspReq
+             | FaSspStrong
+             | FaUwTable
+             | FaPair DqString (Maybe DqString)
+             | FaAlign Word32 -- Integer
+             | FaGroup Word32 -- Integer
+             deriving (Eq,Ord,Show)
+
+
+data SelectionKind = Any
+                   | ExactMatch
+                   | Largest
+                   | NoDuplicates
+                   | SameSize
+                   deriving (Eq, Ord, Show)
+
+selectionKindMap :: M.Map  SelectionKind String
+selectionKindMap = M.fromList [(Any, "any"), (ExactMatch, "exactmatch"), (Largest, "largest"), (NoDuplicates, "noduplicates"), (SameSize, "samesize")]
+
+data Section = Section DqString deriving (Eq,Ord,Show)
+
+data Alignment = Alignment Word32 deriving (Eq,Ord,Show)
+type MaybeAlignment = Maybe Alignment
+
+data Gc = Gc DqString deriving (Eq,Ord,Show)
+data GlobalType = GlobalType String deriving (Eq,Ord,Show)
+
+data AddrNaming = UnnamedAddr
+                | NamedAddr deriving (Eq, Ord, Show)
+
+
+data GlobalOrLocalId = GolG GlobalId
+                     | GolL LocalId
+                       deriving (Eq,Ord,Show)
+
+data LocalId = LocalIdNum Word32 -- Integer
+             | LocalIdAlphaNum String
+             | LocalIdDqString String
+             deriving (Eq,Ord,Show)
+
+
+data DollarId = DollarIdNum Word32 
+              | DollarIdAlphaNum String
+              | DollarIdDqString String
+              deriving (Eq, Ord, Show)                      
+
+data Comdat = Comdat (Maybe DollarId) deriving (Eq, Ord, Show)
+
+data GlobalId = GlobalIdNum Word32
+              | GlobalIdAlphaNum String
+              | GlobalIdDqString String
+              deriving (Eq,Ord,Show)
+                       
+-- | Atomic Memory Ordering Constraints <http://llvm.org/releases/3.5.0/docs/LangRef.html#atomic-memory-ordering-constraints>
+data AtomicMemoryOrdering = AmoAcquire | AmoRelease | AmoAcqRel 
+                          | AmoSeqCst | AmoUnordered | AmoMonotonic
+                          deriving (Eq,Ord,Show)
+
+atomicMemoryOrderingMap :: M.Map AtomicMemoryOrdering String                                   
+atomicMemoryOrderingMap = M.fromList [(AmoAcquire, "acquire"), (AmoRelease, "release")
+                                     ,(AmoAcqRel, "acq_rel"), (AmoSeqCst, "seq_cst")
+                                     ,(AmoUnordered, "unordered"), (AmoMonotonic, "monotonic")
+                                     ] 
+
+-- | atomicrmw operation <http://llvm.org/releases/3.5.0/docs/LangRef.html#id175>
+data AtomicOp = AoXchg | AoAdd | AoSub | AoAnd | AoNand 
+              | AoOr | AoXor 
+              | AoMax | AoMin | AoUmax | AoUmin
+              deriving (Eq,Ord,Show)
+                       
+atomicOpMap :: M.Map AtomicOp String                       
+atomicOpMap = M.fromList [(AoXchg, "xchg"), (AoAdd, "add"), (AoSub, "sub")
+                         ,(AoAnd, "and"), (AoNand, "nand")
+                         ,(AoOr, "or"), (AoXor, "xor")
+                         ,(AoMax, "max"), (AoMin, "min"), (AoUmax, "umax"), (AoUmin, "umin")]
+                                                                                                                            
+                         
+{- syntatical representation: c"...." -}                         
+{-- data Cstring = Cstring String deriving (Eq,Ord,Show) -}
+
+                    
+data Atomicity = Atomicity (IsOrIsNot SingleThread) AtomicMemoryOrdering
+               deriving (Eq, Ord, Show)
+                        
+data Nontemporal = Nontemporal Word32 deriving (Eq, Ord, Show)
+type MaybeNontemporal = Maybe Nontemporal
+                          
+data InvariantLoad = InvariantLoad Word32 deriving (Eq, Ord, Show)
+                            
+data Nonnull = Nonnull Word32 deriving (Eq, Ord, Show)
+                             
+data Volatile = Volatile deriving (Eq, Ord, Show)
+
+data SingleThread = SingleThread deriving (Eq, Ord, Show)
+
+data InAllocaAttr = InAllocaAttr deriving (Eq, Ord, Show)
+  
+data TailCall = TcNon
+              | TcTailCall
+              | TcMustTailCall deriving (Eq, Ord, Show)
+
+data Weak = Weak deriving (Eq, Ord, Show)
+
+
+data IsOrIsNot a = Is a
+                 | IsNot a
+                 deriving (Eq, Ord, Show)
+                          
+data InBounds = InBounds deriving (Eq, Ord, Show)
+
+{- short hand notations -}
+isInBounds :: IsOrIsNot InBounds
+isInBounds = Is InBounds
+
+isNotInBounds :: IsOrIsNot InBounds
+isNotInBounds = IsNot InBounds
+
+data FastMathFlag = Fmfnnan
+                  | Fmfninf
+                  | Fmfnsz
+                  | Fmfarcp
+                  | Fmffast
+                  deriving (Eq, Ord, Show)
+                           
+fastMathFlagMap :: M.Map FastMathFlag String
+fastMathFlagMap = M.fromList [(Fmfnnan, "nnan"), (Fmfninf, "ninf"), (Fmfnsz, "nsz"), (Fmfarcp, "arcp"), (Fmffast, "fast")]
+
+data FastMathFlags = FastMathFlags [FastMathFlag] deriving (Eq, Ord, Show)
+
+data ExternallyInitialized = ExternallyInitialized deriving (Eq, Ord, Show)
+
+data AsmDialect = AsmDialectAtt
+                | AsmDialectIntel
+                deriving (Eq, Ord, Show)
+
+data SideEffect = SideEffect deriving (Eq, Ord, Show)
+data AlignStack = AlignStack deriving (Eq, Ord, Show)
+
+data Cleanup = Cleanup deriving (Eq, Ord, Show)
+
+
+data Arch = Arch_i386
+          | Arch_i686
+          | Arch_x86
+          | Arch_x86_64
+          | Arch_PowerPc
+          | Arch_PowerPc64
+          | Arch_Arm String
+          | Arch_ThumbV7
+          | Arch_Itanium
+          | Arch_Mips String
+          | Arch_String String
+          deriving (Eq, Ord, Show)
+                           
+data Vendor = Vendor_Pc          
+            | Vendor_Apple
+            | Vendor_Unknown
+            | Vendor_String String
+            deriving (Eq, Ord, Show)
+                     
+data Os = Os_Linux                     
+        | Os_Windows
+        | Os_Win32
+        | Os_FreeBsd String
+        | Os_Darwin String
+        | Os_Macosx String
+        | Os_Ios String
+        | Os_Mingw32
+        | Os_Unknown
+        | Os_String String
+        deriving (Eq, Ord, Show)
+                 
+data OsEnv = OsEnv_Gnu                 
+           | OsEnv_String String
+           deriving (Eq, Ord, Show)
+
+data TargetTriple = TargetTriple Arch (Maybe Vendor) (Maybe Os) (Maybe OsEnv) deriving (Eq, Ord, Show)
+
+
+data Fparam = FimplicitParam
+            | FexplicitParam LocalId
+            deriving (Eq,Ord,Show)
+
+data Packing = Packed                
+             | Unpacked
+             deriving (Eq, Ord, Show)
+
+data VarArgParam = VarArgParam deriving (Eq, Ord, Show)
diff --git a/src/Llvm/Data/Shared/DataLayout.hs b/src/Llvm/Data/Shared/DataLayout.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Shared/DataLayout.hs
@@ -0,0 +1,86 @@
+module Llvm.Data.Shared.DataLayout where
+
+import qualified Data.Map as M
+import Data.Word
+
+data Endianness = LittleEndian
+                | BigEndian deriving (Eq, Ord, Show)
+
+data LayoutAddrSpace = LayoutAddrSpace Word32
+                     | LayoutAddrSpaceUnspecified deriving (Eq, Ord, Show)
+                                                           
+data StackAlign = StackAlign AlignInBit
+                | StackAlignUnspecified deriving (Eq, Ord, Show)
+
+data SizeInBit = SizeInBit Word32 deriving (Eq, Ord, Show)
+data AlignInBit = AlignInBit Word32 deriving (Eq, Ord, Show)
+
+data AbiAlign = AbiAlign AlignInBit deriving (Eq, Ord, Show)
+
+data PrefAlign = PrefAlign AlignInBit deriving (Eq, Ord, Show)
+
+data Mangling = ManglingE
+              | ManglingM
+              | ManglingO
+              | ManglingW deriving (Eq, Ord, Show)
+                
+data LayoutSpec = DlE Endianness
+                | DlS StackAlign
+                | DlLittleS (Maybe Word32) (Maybe Word32) (Maybe Word32)
+                | DlP LayoutAddrSpace SizeInBit AbiAlign (Maybe PrefAlign)
+                | DlI SizeInBit AbiAlign (Maybe PrefAlign)
+                | DlF SizeInBit AbiAlign (Maybe PrefAlign)
+                | DlV SizeInBit AbiAlign (Maybe PrefAlign) 
+                | DlA (Maybe SizeInBit) AbiAlign (Maybe PrefAlign)
+                | DlM Mangling
+                | DlN [SizeInBit] deriving (Eq, Ord, Show)
+                
+data DataLayout = DataLayout [LayoutSpec] deriving (Eq, Ord, Show)
+
+
+data DataLayoutInfo = DataLayoutInfo 
+                      { endianess :: Endianness
+                      , stackAlign :: StackAlign
+                      , pointers :: M.Map LayoutAddrSpace (SizeInBit, AbiAlign, Maybe PrefAlign)
+                      , ints :: M.Map SizeInBit (AbiAlign, Maybe PrefAlign) 
+                      , floats :: M.Map SizeInBit (AbiAlign, Maybe PrefAlign) 
+                      , vectors :: M.Map SizeInBit (AbiAlign, Maybe PrefAlign)
+                      , aggregates :: M.Map (Maybe SizeInBit) (AbiAlign, Maybe PrefAlign)
+                      , nativeInt :: [SizeInBit]
+                      , mangling :: Maybe Mangling
+                      } deriving (Eq, Ord, Show)
+                                 
+                                 
+data AlignType = AlignAbi | AlignPref deriving (Eq, Ord, Show)
+
+selectAlignment :: AlignType -> AbiAlign -> Maybe PrefAlign -> AlignInBit
+selectAlignment at (AbiAlign aba) pa = case at of
+  AlignAbi -> aba
+  AlignPref -> maybe aba (\(PrefAlign n) -> n) pa
+                                 
+
+emptyDataLayoutInfo :: DataLayoutInfo
+emptyDataLayoutInfo = DataLayoutInfo { endianess = LittleEndian
+                                     , stackAlign = StackAlignUnspecified
+                                     , pointers = M.empty -- (LayoutAddrSpaceUnspecified, SizeInBit 0, AbiAlign 0, Nothing)
+                                     , ints = M.empty
+                                     , floats = M.empty
+                                     , vectors = M.empty
+                                     , aggregates = M.empty
+                                     , nativeInt = []
+                                     , mangling = Nothing
+                                     }
+  
+getDataLayoutInfo :: DataLayout -> DataLayoutInfo                                 
+getDataLayoutInfo (DataLayout ls) = foldl (\p v -> case v of
+                                                 DlE x -> p { endianess = x}
+                                                 DlS x -> p { stackAlign = x}
+                                                 DlP la s aa pa -> p { pointers = M.insert la (s, aa, pa) (pointers p) }
+                                                 DlI s aa pa -> p { ints = M.insert s (aa, pa) (ints p) }
+                                                 DlF s aa pa -> p { floats = M.insert s (aa, pa) (floats p) }
+                                                 DlV s aa pa -> p { vectors = M.insert s (aa, pa) (vectors p) }
+                                                 DlA s aa pa -> p { aggregates = M.insert s (aa, pa) (aggregates p) }
+                                                 DlN l -> p { nativeInt = l }
+                                                 DlM m -> p { mangling = Just m }
+                                                 _ -> error $ "unexpected case " ++ show v
+                                          ) emptyDataLayoutInfo ls
diff --git a/src/Llvm/Data/Shared/SimpleConst.hs b/src/Llvm/Data/Shared/SimpleConst.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Shared/SimpleConst.hs
@@ -0,0 +1,42 @@
+module Llvm.Data.Shared.SimpleConst 
+       (module Llvm.Data.Shared.SimpleConst
+       ,module Llvm.Data.Shared.AtomicEntity
+       )
+       where
+
+import Llvm.Data.Shared.AtomicEntity (GlobalId)
+import Data.Int
+import Data.Word
+import Data.DoubleWord
+
+-- | Simple Constants <http://llvm.org/releases/3.0/docs/LangRef.html#simpleconstants>  
+data SimpleConstant = CpInt String
+                    | CpUhexInt String
+                    | CpShexInt String
+                    | CpFloat String
+                    -- | null pointer constant
+                    | CpNull
+                    | CpUndef
+                    -- | true::i1 
+                    | CpTrue
+                    -- | false::i1
+                    | CpFalse
+                    | CpZeroInitializer
+                    | CpGlobalAddr GlobalId
+                    | CpStr String
+                    | CpBconst BinaryConstant
+                    deriving (Eq, Ord, Show)
+
+data BinaryConstant = BconstUint8 Word8
+                    | BconstUint16 Word16
+                    | BconstUint32 Word32
+                    | BconstUint64 Word64
+                    | BconstUint96 Word96
+                    | BconstUint128 Word128
+                    | BconstInt8 Int8
+                    | BconstInt16 Int16
+                    | BconstInt32 Int32
+                    | BconstInt64 Int64
+                    | BconstInt96 Int96
+                    | BconstInt128 Int128
+                    deriving (Eq, Ord, Show)
diff --git a/src/Llvm/Data/Shared/Util.hs b/src/Llvm/Data/Shared/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Shared/Util.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell #-}
+module Llvm.Data.Shared.Util where
+
+import Language.Haskell.TH
+
+eq2 :: (Eq a, Eq b) => (a,a) -> (b,b) -> Bool
+eq2 (a1,a2) (b1,b2) = a1==a2 && b1==b2
+
+eq3 :: (Eq a, Eq b, Eq c) => (a,a) -> (b,b) -> (c,c) -> Bool
+eq3 (a1,a2) (b1,b2) (c1,c2) = eq2 (a1,a2) (b1,b2) && c1 == c2
+
+eq4 :: (Eq a, Eq b, Eq c, Eq d) => (a,a) -> (b,b) -> (c,c) -> (d,d) -> Bool
+eq4 (a1,a2) (b1,b2) (c1,c2) (d1, d2) = eq3 (a1,a2) (b1,b2) (c1, c2) && d1 == d2
+
+eq5 :: (Eq a, Eq b, Eq c, Eq d, Eq e) => (a,a) -> (b,b) -> (c,c) -> (d,d) -> (e,e) -> Bool
+eq5 (a1,a2) (b1,b2) (c1,c2) (d1, d2) (e1, e2) = eq4 (a1,a2) (b1,b2) (c1,c2) (d1,d2) && e1 == e2
+
+
+compare2 :: (Ord a, Ord b) => (a,a) -> (b, b) -> Ordering    
+compare2 (a1,a2) (b1, b2) = let v = compare a1 a2
+                            in if v == EQ then compare b1 b2
+                               else v
+
+compare3 :: (Ord a, Ord b, Ord c) => (a,a) -> (b,b) -> (c,c) -> Ordering
+compare3 (a1,a2) (b1,b2) (c1,c2) = let v = compare2 (a1,a2) (b1,b2)
+                                   in if v == EQ then compare c1 c2
+                                      else v
+
+compare4 :: (Ord a, Ord b, Ord c, Ord d) => (a,a) -> (b,b) -> (c,c) -> (d,d) -> Ordering
+compare4 (a1,a2) (b1,b2) (c1,c2) (d1,d2) = let v = compare3 (a1,a2) (b1,b2) (c1,c2)
+                                           in if v == EQ then compare d1 d2
+                                              else v
+
+compare5 :: (Ord a, Ord b, Ord c, Ord d, Ord e) => (a,a) -> (b,b) -> (c,c) -> (d,d) -> (e,e) -> Ordering
+compare5 (a1,a2) (b1,b2) (c1,c2) (d1, d2) (e1, e2) = let v = compare4 (a1,a2) (b1,b2) (c1,c2) (d1,d2)
+                                                     in if v == EQ then compare e1 e2
+                                                        else v
+
+newtype FileLoc = FileLoc String deriving (Eq, Ord, Show)
+
+castError :: Show a => FileLoc -> String -> a -> b
+castError (FileLoc loc) s x = error $ (loc ++ "irrefutable error, casting " ++ show x ++ " to " ++ s)
+
+dcastError :: Show a => FileLoc -> String -> a -> b
+dcastError = castError
+
+
+srcLoc :: ExpQ
+srcLoc = do { (Loc f p m s e) <- location
+            ; stringE (p ++ ":" ++ m ++ "@" ++ show s)
+            }            
+                       
+errorLoc :: FileLoc -> String -> a
+errorLoc (FileLoc lc) s = error (lc ++ ":" ++ s)
+
+{- up casting -}
+class Ucast l1 l2 where
+  ucast :: l1 -> l2
+
+{- down casting -}
+class Dcast l1 l2 where
+  dcast :: FileLoc -> l1 -> l2
+  
+{- horizontal casting -}
+class Hcast l1 l2 where 
+  hcast :: FileLoc -> l1 -> l2
+  
+  
+class Mingle a where  
+  mingle :: a -> String
+  
+instance Mingle a => Mingle ([a]) where  
+  mingle l = foldl (\p e -> p ++ (mingle e)) "" l
diff --git a/src/Llvm/Data/Type.hs b/src/Llvm/Data/Type.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Data/Type.hs
@@ -0,0 +1,54 @@
+module Llvm.Data.Type  
+       (module Llvm.Data.Type
+       ,module Llvm.Data.Shared.AtomicEntity 
+       )
+       where
+
+import Llvm.Data.Shared.AtomicEntity hiding (AddrSpace(..))
+import Data.Word (Word32)
+
+data TypePrimitive = TpI Word32
+                   | TpF Word32 
+                   | TpV Word32 
+                   | TpHalf | TpFloat | TpDouble | TpFp128 | TpX86Fp80 | TpPpcFp128 
+                   | TpX86Mmx 
+                   | TpNull
+                   | TpLabel
+                   deriving (Eq,Ord,Show)
+
+
+splitCallReturnType :: Type -> (Type, Maybe (Type, AddrSpace))
+splitCallReturnType (Tpointer f@(Tfunction rt _ _) as) = (rt, Just (f, as))
+splitCallReturnType x = (x, Nothing)
+
+data Type = Tprimitive TypePrimitive
+          | Topaque 
+          | Tname String
+          | TquoteName String
+          | Tno Word32
+          | Tarray Word32 Type
+          | Tvector Word32 Type
+          | Tstruct Packing [Type]
+          | Tpointer Type AddrSpace
+          | Tfunction Type TypeParamList [FunAttr]
+          | Tvoid
+          -- | deref a type will strip off Tpointer, this is a syntatical
+          -- | representation that should be evaluated later.
+          -- | Tderef Type 
+          deriving (Eq,Ord,Show)
+
+
+data MetaKind = Mtype Type
+              | Mmetadata
+              deriving (Eq, Ord, Show)
+                   
+data FormalParam = FormalParamData Type [ParamAttr] (Maybe Alignment) Fparam [ParamAttr]
+                 | FormalParamMeta MetaKind Fparam
+                 deriving (Eq,Ord,Show)
+
+data FormalParamList = FormalParamList [FormalParam] (Maybe VarArgParam) [FunAttr] deriving (Eq,Ord,Show)
+
+data TypeParamList = TypeParamList [Type] (Maybe VarArgParam) deriving (Eq,Ord,Show)
+
+data AddrSpace = AddrSpace Word32 
+               | AddrSpaceUnspecified deriving (Eq,Ord,Show)
diff --git a/src/Llvm/Pass/Dominator.hs b/src/Llvm/Pass/Dominator.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/Dominator.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE Safe #-}
+
+module Llvm.Pass.Dominator
+    ( Doms, DPath(..), domPath, domEntry, domLattice, extendDom
+    , DominatorNode(..), DominatorTree(..), tree
+    , immediateDominators
+    , domPass
+    )
+    where
+
+import Data.Maybe
+
+import Compiler.Hoopl
+
+
+type Doms = WithBot DPath
+-- ^ List of labels, extended with a standard bottom element
+
+-- | The fact that goes into the entry of a dominator analysis: the first node
+-- is dominated only by the entry point, which is represented by the empty list
+-- of labels.
+domEntry :: Doms
+domEntry = PElem (DPath [])
+
+newtype DPath = DPath [Label]
+  -- ^ represents part of the domination relation: each label
+  -- in a list is dominated by all its successors.  This is a newtype only so
+  -- we can give it a fancy Show instance.
+
+instance Show DPath where
+  show (DPath ls) = concat (foldr (\l path -> show l : " -> " : path) ["entry"] ls)
+
+domPath :: Doms -> [Label]
+domPath Bot = [] -- lies: an unreachable node appears to be dominated by the entry
+domPath (PElem (DPath ls)) = ls
+
+extendDom :: Label -> DPath -> DPath
+extendDom l (DPath ls) = DPath (l:ls)
+
+domLattice :: DataflowLattice Doms
+domLattice = addPoints "dominators" extend
+
+extend :: JoinFun DPath
+extend _ (OldFact (DPath l)) (NewFact (DPath l')) =
+                                (changeIf (l `lengthDiffers` j), DPath j)
+    where j = lcs l l'
+          lcs :: [Label] -> [Label] -> [Label] -- longest common suffix
+          lcs l l' | length l > length l' = lcs (drop (length l - length l') l) l'
+                   | length l < length l' = lcs l' l
+                   | otherwise = dropUnlike l l' l
+          dropUnlike [] [] maybe_like = maybe_like
+          dropUnlike (x:xs) (y:ys) maybe_like =
+              dropUnlike xs ys (if x == y then maybe_like else xs)
+          dropUnlike _ _ _ = error "this can't happen"
+
+          lengthDiffers [] [] = False
+          lengthDiffers (_:xs) (_:ys) = lengthDiffers xs ys
+          lengthDiffers [] (_:_) = True
+          lengthDiffers (_:_) [] = True
+
+
+
+-- | Dominator pass
+domPass :: (NonLocal n, Monad m) => FwdPass m n Doms
+domPass = FwdPass domLattice (mkFTransfer3 first (const id) distributeFact) noFwdRewrite
+  where first n = fmap (extendDom $ entryLabel n)
+
+----------------------------------------------------------------
+
+data DominatorNode = Entry | Labelled Label
+data DominatorTree = Dominates DominatorNode [DominatorTree]
+-- ^ This data structure is a *rose tree* in which each node may have
+--  arbitrarily many children.  Each node dominates all its descendants.
+
+-- | Map from a FactBase for dominator lists into a
+-- dominator tree.  
+tree :: [(Label, Doms)] -> DominatorTree
+tree facts = Dominates Entry $ merge $ map reverse $ map mkList facts
+   -- This code has been lightly tested.  The key insight is this: to
+   -- find lists that all have the same head, convert from a list of
+   -- lists to a finite map, in 'children'.  Then, to convert from the
+   -- finite map to list of dominator trees, use the invariant that
+   -- each key dominates all the lists of values.
+  where merge lists = mapTree $ children $ filter (not . null) lists
+        children = foldl addList noFacts
+        addList :: FactBase [[Label]] -> [Label] -> FactBase [[Label]]
+        addList map (x:xs) = mapInsert x (xs:existing) map
+            where existing = fromMaybe [] $ lookupFact x map
+        addList _ [] = error "this can't happen"
+        mapTree :: FactBase [[Label]] -> [DominatorTree]
+        mapTree map = [Dominates (Labelled x) (merge lists) |
+                                                    (x, lists) <- mapToList map]
+        mkList (l, doms) = l : domPath doms
+
+
+instance Show DominatorTree where
+  show = tree2dot
+
+-- | Given a dominator tree, produce a string representation, in the
+-- input language of dot, that will enable dot to produce a
+-- visualization of the tree.  For more info about dot see
+-- http://www.graphviz.org.
+
+tree2dot :: DominatorTree -> String
+tree2dot t = concat $ "digraph {\n" : dot t ["}\n"]
+  where
+    dot :: DominatorTree -> [String] -> [String]
+    dot (Dominates root trees) = 
+                   (dotnode root :) . outedges trees . flip (foldl subtree) trees
+      where outedges [] = id
+            outedges (Dominates n _ : ts) =
+                \s -> "  " : show root : " -> " : show n : "\n" : outedges ts s
+            dotnode Entry = "  entryNode [shape=plaintext, label=\"entry\"]\n"
+            dotnode (Labelled l) = "  " ++ show l ++ "\n"
+            subtree = flip dot
+
+instance Show DominatorNode where
+  show Entry = "entryNode"
+  show (Labelled l) = show l
+
+----------------------------------------------------------------
+
+-- | Takes FactBase from dominator analysis and returns a map from each 
+-- label to its immediate dominator, if any
+immediateDominators :: FactBase Doms -> LabelMap Label
+immediateDominators = mapFoldWithKey add mapEmpty
+    where add l (PElem (DPath (idom:_))) = mapInsert l idom 
+          add _ _ = id
+
diff --git a/src/Llvm/Pass/Liveness.hs b/src/Llvm/Pass/Liveness.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/Liveness.hs
@@ -0,0 +1,122 @@
+{-# LANGUAGE ScopedTypeVariables, GADTs #-}
+
+module Llvm.Pass.Liveness (dce) where
+import Data.Maybe
+import qualified Data.Set as Ds
+import qualified Data.List as L
+
+import qualified Compiler.Hoopl as H
+import Llvm.Data.Ir
+import Llvm.Pass.Uda
+import Llvm.Syntax.Printer.IrPrint
+
+type Live = Ds.Set LocalId
+liveLattice :: H.DataflowLattice Live
+liveLattice = H.DataflowLattice
+              { H.fact_name = "Live variables"
+              , H.fact_bot = Ds.empty
+              , H.fact_join = add
+              }
+    where add _ (H.OldFact old) (H.NewFact new) = (ch, j)
+              where
+                j = new `Ds.union` old
+                ch= H.changeIf (Ds.size j > Ds.size old)
+
+liveness :: H.BwdTransfer (Node a) Live
+liveness = H.mkBTransfer live
+  where
+    live = undefined
+    {-
+    live :: Node e x -> H.Fact x Live -> Live
+    live (Nlabel _) f = f
+    live (Pinst n) f = f `Ds.union` (filterOutGlobalId $ u1ofPinstWithDbg n) `Ds.difference` (filterOutGlobalId $ d1ofPinstWithDbg n)
+    -- | FIXME
+    -- | this is a very simplistic implementation and it does not consider function calls might have side effects.
+    -- | we need to distinguish the uses of a possible side effect computation from the uses of a pure computation.
+    live (Cinst n) f = f `Ds.union` (filterOutGlobalId $ u1ofComputingInstWithDbg n) `Ds.difference` (filterOutGlobalId $ d1ofComputingInstWithDbg n)
+    live x@(Tinst n) f = let bs = H.successors x
+                             f' = foldl (\p -> \l -> p `Ds.union` (fact f l)) Ds.empty bs
+                         in f' `Ds.union` (filterOutGlobalId $ u1ofTerminatorInstWithDbg n) `Ds.difference` (filterOutGlobalId $ d1ofTerminatorInstWithDbg n)
+--    fact :: FactBase (Ds.Set LocalId) -> Label -> Live
+    fact f l = fromMaybe Ds.empty $ H.lookupFact l f
+-}
+
+deadAsstElim :: forall a. forall m. H.FuelMonad m => H.BwdRewrite m (Node a) Live
+deadAsstElim = H.mkBRewrite d
+   where
+     d :: Node a e x -> H.Fact x Live -> m (Maybe (H.Graph (Node a) e x))
+     d (Cinst n) live = dead n live
+     d _ _ = return Nothing
+
+
+dead :: forall a.forall m. H.FuelMonad m => CInstWithDbg -> H.Fact H.O Live -> m (Maybe (H.Graph (Node a) H.O H.O))
+dead (CInstWithDbg ci _) live = deadCi ci live
+
+
+deadCi :: forall a.forall m. H.FuelMonad m => CInst -> H.Fact H.O Live -> m (Maybe (H.Graph (Node a) H.O H.O))
+deadCi = undefined
+{-
+deadCi (ComputingInst Nothing (RmO m)) live = deadRmo m live
+deadCi (ComputingInst Nothing (Call _ cs)) live = deadCallSite cs live
+deadCi (ComputingInst _ (LandingPad _ _ _ _ _)) _ = return Nothing
+deadCi (ComputingInst lhsOpt _) live = case lhsOpt of
+                                         Just (GolL x) | not (x `Ds.member` live) -> return $ Just H.emptyGraph
+                                         _  -> return Nothing
+
+
+deadRmo :: forall m. H.FuelMonad m => MemOp -> H.Fact H.O Live -> m (Maybe (H.Graph Node H.O H.O))
+deadRmo inst live = case inst of
+  (Store _ _ (TypedData _ (Pointer v)) _ _) -> case localIdOfValue v of
+    Just x | not (x `Ds.member` live) -> return $ Just H.emptyGraph
+    _ -> return Nothing
+  (StoreAtomic _ _ _ (TypedData _ (Pointer v)) _) -> case localIdOfValue v of
+    Just x | not (x `Ds.member` live) -> return $ Just H.emptyGraph
+    _ -> return Nothing
+  _ -> return Nothing
+  where localIdOfValue (VgOl (GolL x)) = Just x
+        localIdOfValue _ = Nothing
+-}
+
+isDeclare :: FunName -> Bool
+isDeclare (FunNameGlobal (GolG gl)) | (render $ printIr gl) == "@llvm.dbg.declare" = True
+isDeclare _ = False
+
+
+isDeadAP :: H.Fact H.O Live -> ActualParam -> Bool
+isDeadAP = undefined
+{-
+isDeadAP live ap  = let u = filterOutGlobalId $ u1 $ uDofActualParam ap
+                        dif = u `Ds.intersection` live
+                    in dif == Ds.empty
+-}
+
+deadCallSite :: forall a.forall m. H.FuelMonad m => CallSite -> H.Fact H.O Live -> m (Maybe (H.Graph (Node a) H.O H.O))
+deadCallSite (CsFun _ _ _ fn ap _) live | isDeclare fn =
+  if L.all (isDeadAP live) ap then return $ Just H.emptyGraph
+  else return Nothing
+deadCallSite _ _ = return Nothing
+
+
+
+filterOutGlobalId :: Ds.Set GlobalOrLocalId -> Ds.Set LocalId
+filterOutGlobalId s = Ds.foldl (\a b -> case b of
+                                         GolL l -> Ds.insert l a
+                                         _ -> a) Ds.empty s
+
+
+
+
+
+dcePass :: forall a. forall m. H.FuelMonad m => H.BwdPass m (Node a) Live
+dcePass = H.BwdPass { H.bp_lattice = liveLattice
+                    , H.bp_transfer = liveness
+                    , H.bp_rewrite = deadAsstElim
+                    }
+
+dce :: (H.CheckpointMonad m, H.FuelMonad m) => Ds.Set (Dtype, GlobalId) -> Label -> H.Graph (Node a) H.C H.C -> m (H.Graph (Node a) H.C H.C)
+dce _ entry graph =
+  do { (graph', _, _) <- H.analyzeAndRewriteBwd bwd (H.JustC [entry]) graph
+                         H.mapEmpty
+     ; return graph'
+     }
+  where bwd = dcePass
diff --git a/src/Llvm/Pass/Mem2Reg.hs b/src/Llvm/Pass/Mem2Reg.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/Mem2Reg.hs
@@ -0,0 +1,129 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE GADTs #-}
+module Llvm.Pass.Mem2Reg (mem2reg) where
+
+import Compiler.Hoopl
+import Llvm.Data.Ir
+import qualified Data.Map as Dm
+import qualified Data.Set as Ds
+import Control.Monad
+import Llvm.Pass.Rewriter (rwNode,nodeToGraph)
+import Prelude hiding(lookup)
+#ifdef DEBUG
+import Debug.Trace
+#endif
+
+
+-- | TODO: describe in details what this pass is doing
+type Mem2RegFact = Dm.Map LValue (WithTop Value)
+
+data LValue = Mem LocalId
+            | Ref LocalId
+            deriving (Eq, Show, Ord)
+
+mem2RegLattice :: DataflowLattice Mem2RegFact
+mem2RegLattice = DataflowLattice { fact_name = "Mem 2 Reg"
+                                 , fact_bot = Dm.empty
+                                 , fact_join = joinMaps (extendJoinDomain factAdd)
+                                 }
+  where
+    factAdd _ (OldFact old) (NewFact new)
+      = if new == old then (NoChange, PElem new)
+        else (SomeChange, Top)
+
+isReg :: FwdTransfer (Node a) Mem2RegFact
+isReg = mkFTransfer ft
+
+ft :: (Node a) e x -> Mem2RegFact -> Fact x Mem2RegFact
+ft (Nlabel _) f = f
+ft (Pinst _) f = f
+ft (Cinst cinst) f = cinstft cinst f
+ft n@(Tinst tinst) f = tinstft n tinst f
+ 
+
+tinstft :: (Node a) O C -> TerminatorInstWithDbg -> Mem2RegFact -> Fact C Mem2RegFact
+tinstft n t@(TerminatorInstWithDbg term _) f =  
+  let targets = successors n -- targetOf term
+  in case targets of
+    [] -> mapEmpty
+    l -> mkFactBase mem2RegLattice
+         (map (\x -> (x, f)) l)
+
+cinstft :: CInstWithDbg -> Mem2RegFact -> Fact O Mem2RegFact
+cinstft = undefined
+
+{-
+cinstft (ComputingInstWithDbg (ComputingInst lhs rhs) _) f = cinstft' lhs rhs f
+
+
+cinstft' :: Maybe GlobalOrLocalId -> Rhs -> Mem2RegFact -> Fact O Mem2RegFact
+cinstft' lhs (RmO m) f = memOp lhs m f
+cinstft' lhs (Re (Ev tv)) f = maybe f (\a -> let TypedData _ v = tv in
+                                        case a of
+                                          GolG _ -> f
+                                          GolL s -> Dm.insert (Ref $ localIdToLstring s) (PElem v) f) lhs
+cinstft' _ (Re _) f = f
+cinstft' _ _ f = f
+
+
+memOp :: Maybe GlobalOrLocalId -> MemOp -> Mem2RegFact -> Fact O Mem2RegFact
+memOp (Just (GolL lhs)) (Allocate _ _ Nothing _) f = insert (Mem $ localIdToLstring lhs) Top f
+memOp _ (Store _ (TypedData _ v1) (TypedData _ (Pointer (VgOl (GolL ptr)))) _ _) f =
+    let x = Mem $ localIdToLstring ptr
+    in if (x `Dm.member` f) then insert x (PElem v1) f
+       else f
+memOp _ (StoreAtomic _ _ (TypedData _ v1) (TypedData _ (Pointer (VgOl (GolL ptr)))) _) f =
+    let x = Mem $ localIdToLstring ptr
+    in if (x `Dm.member` f) then insert x (PElem v1) f
+       else f
+memOp _ _ f = f
+-}
+
+insert :: Ord k => k -> v -> Dm.Map k v -> Dm.Map k v
+#ifdef DEBUG
+insert x v1 f | trace ("insert " ++ (show x) ++ "->" ++ (show v1)) False = undefined
+#endif
+insert x v1 f = Dm.insert x v1 f
+
+badAss :: Monad m => (Value -> Maybe Value) -> Node a e x -> m (Maybe (Node a e x))
+badAss f node = return (rwNode f node)
+
+
+mem2Reg :: forall a.forall m . FuelMonad m => FwdRewrite m (Node a) Mem2RegFact
+mem2Reg = mkFRewrite cp
+    where
+      -- each node is rewritten to a one node graph.
+      cp :: FuelMonad m => Node a e x -> Mem2RegFact -> m (Maybe (Graph (Node a) e x))
+      cp node f = do { x <- badAss (lookup f) node
+                     ; return $ liftM {-Maybe-} nodeToGraph x
+                     }
+
+      lookup :: Mem2RegFact -> Value -> Maybe Value
+      lookup f x = do { x' <- case x of
+                           Val_ssa s -> Just $ Ref s
+                           -- Deref (Pointer (VgOl (GolL s))) -> Just $ Mem $ localIdToLstring s
+                           _ -> Nothing
+                       ;  case Dm.lookup x' f of
+                            Just (PElem v) -> Just v
+                            _ -> Nothing
+                       }
+
+
+
+
+mem2RegPass :: forall a. forall m. FuelMonad m => FwdPass m (Node a) Mem2RegFact
+mem2RegPass = FwdPass { fp_lattice = mem2RegLattice
+                      , fp_transfer = isReg
+                      , fp_rewrite = mem2Reg
+                      }
+
+
+mem2reg :: (CheckpointMonad m, FuelMonad m) => Ds.Set (Dtype, GlobalId) -> Label -> Graph (Node a) C C -> m (Graph (Node a) C C)
+mem2reg _ entry graph =
+  do { (graph', _, _) <- analyzeAndRewriteFwd fwd (JustC [entry]) graph
+                         (mapSingleton entry (Dm.empty)) -- initFact gs))
+     ; return graph'
+     }
+  where fwd = mem2RegPass -- debugFwdJoins trace (const True) mem2RegPas
diff --git a/src/Llvm/Pass/NormalGraph.hs b/src/Llvm/Pass/NormalGraph.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/NormalGraph.hs
@@ -0,0 +1,17 @@
+module Llvm.Pass.NormalGraph where
+import Compiler.Hoopl (Graph,C,analyzeAndRewriteFwd,MaybeC(..),mapInsert,mapEmpty,LabelMap,CheckpointMonad, FuelMonad) 
+import Llvm.Data.Ir
+import Llvm.Pass.PhiFixUp
+import Llvm.Pass.Dominator
+
+idom :: (CheckpointMonad m, FuelMonad m) => Label -> Graph (Node a) C C -> m (LabelMap Label)
+idom entry g = do { (_,fact,_) <- analyzeAndRewriteFwd domPass (JustC [entry]) g
+                                   (mapInsert entry domEntry mapEmpty)
+                  ; return $ immediateDominators fact
+                  }
+
+fixUpPhi :: (CheckpointMonad m, FuelMonad m) => () -> Label -> Graph (Node a) C C -> m (Graph (Node a) C C)
+fixUpPhi _ entry g = do { labelMap <- idom entry g
+                        ; g' <- phiFixUp labelMap entry g
+                        ; return g'
+                        }
diff --git a/src/Llvm/Pass/Optimizer.hs b/src/Llvm/Pass/Optimizer.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/Optimizer.hs
@@ -0,0 +1,36 @@
+module Llvm.Pass.Optimizer where
+
+import Llvm.Data.Ir
+import qualified Compiler.Hoopl as H 
+import qualified Data.Set as Ds
+
+type Optimization m a u = a -> H.Label -> H.Graph (Node u) H.C H.C -> m (H.Graph (Node u) H.C H.C)
+  
+opt :: (H.CheckpointMonad m, H.FuelMonad m) => a -> Optimization m a u -> (Toplevel u) -> m (Toplevel u)
+opt _ _ (ToplevelTriple s) = return $ ToplevelTriple s
+opt _ _ (ToplevelDataLayout s) = return $ ToplevelDataLayout s
+opt _ _ (ToplevelAlias s) = return $ ToplevelAlias s
+opt _ _ (ToplevelDbgInit s) = return $ ToplevelDbgInit s
+opt _ _ (ToplevelStandaloneMd s) = return $ ToplevelStandaloneMd s
+opt _ _ (ToplevelNamedMd v) = return $ ToplevelNamedMd v
+opt _ _ (ToplevelDeclare fn) = return $ ToplevelDeclare fn
+opt gs f (ToplevelDefine (TlDefine fn entry graph)) = do { graph' <- f gs entry graph
+                                                         ; return $ ToplevelDefine $ TlDefine fn entry graph'
+                                                         }
+opt _ _ (ToplevelGlobal s) = return $ ToplevelGlobal s
+opt _ _ (ToplevelTypeDef a) = return $ ToplevelTypeDef a
+opt _ _ (ToplevelDepLibs qs) = return $ ToplevelDepLibs qs
+opt _ _ (ToplevelUnamedType i) = return $ ToplevelUnamedType i
+opt _ _ (ToplevelModuleAsm s) = return $ ToplevelModuleAsm s
+opt _ _ (ToplevelComdat s) = return $ ToplevelComdat s
+opt _ _ (ToplevelAttribute s) = return $ ToplevelAttribute s
+
+
+optModule :: (H.CheckpointMonad m, H.FuelMonad m) => Optimization m (Ds.Set (Dtype, GlobalId)) u -> Module u -> m (Module u)
+optModule f (Module l) = 
+  let gs = globalIdOfModule (Module l)
+  in mapM (opt gs f) l >>= return . Module
+
+optModule1 :: (H.CheckpointMonad m, H.FuelMonad m) => a -> Optimization m a u -> Module u -> m (Module u)
+optModule1 a f (Module l) = 
+  mapM (opt a f) l >>= return . Module
diff --git a/src/Llvm/Pass/PassManager.hs b/src/Llvm/Pass/PassManager.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/PassManager.hs
@@ -0,0 +1,25 @@
+module Llvm.Pass.PassManager where
+
+import Llvm.Data.Ir
+import Llvm.Pass.Mem2Reg
+-- import Llvm.Pass.PrepareRw
+import Llvm.Pass.Liveness
+import qualified Data.Set as Ds
+import Llvm.Pass.Optimizer
+import Compiler.Hoopl
+
+data Step = Mem2Reg | Dce 
+          | PrepareRw
+          deriving (Show,Eq)
+
+toPass :: (CheckpointMonad m, FuelMonad m) => Step -> Optimization m (Ds.Set (Dtype, GlobalId)) a
+toPass Mem2Reg = mem2reg
+toPass Dce = dce
+
+applyPasses1 :: (CheckpointMonad m, FuelMonad m) => [Optimization m (Ds.Set (Dtype, GlobalId)) a] -> Module a -> m (Module a)
+applyPasses1 steps m = foldl (\p e -> p >>= optModule e) (return m) steps
+
+
+applySteps :: (CheckpointMonad m, FuelMonad m) => [Step] -> Module a -> m (Module a)
+applySteps steps m = let passes = map toPass steps
+                     in applyPasses1 passes m
diff --git a/src/Llvm/Pass/PassTester.hs b/src/Llvm/Pass/PassTester.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/PassTester.hs
@@ -0,0 +1,28 @@
+module Llvm.Pass.PassTester where
+
+import Llvm.Data.Ir
+import Llvm.Query.IrCxt
+import qualified Compiler.Hoopl as H 
+import qualified Data.Set as Ds
+
+type Optimization m a u x = IrCxt -> a -> H.Label -> H.Graph (Node u) H.C H.C -> m (H.Graph (Node u) H.C H.C, x)
+  
+opt :: (H.CheckpointMonad m, H.FuelMonad m) => IrCxt -> a -> Optimization m a u x -> Toplevel u -> m [(Toplevel u, (FunctionPrototype, x))]
+opt dl gs f (ToplevelDefine (TlDefine fn entry graph)) = do { (graph', x) <- f dl gs entry graph
+                                                            ; return [(ToplevelDefine $ TlDefine fn entry graph', (fn, x))]
+                                                            }
+opt _ _ _ _ = return []
+
+
+optModule :: (H.CheckpointMonad m, H.FuelMonad m) => Optimization m (Ds.Set (Dtype, GlobalId)) u x -> Module u -> m (Module u, [(FunctionPrototype, x)])
+optModule f (Module l) = 
+  let gs = globalIdOfModule (Module l)
+      dl = irCxtOfModule (Module l)
+  in mapM (opt dl gs f) l >>= \x -> let (lx, ly) = unzip $ concat x
+                                 in return (Module lx, ly)
+
+{-
+optModule1 :: (H.CheckpointMonad m, H.FuelMonad m) => a -> Optimization m a x -> Module -> m Module
+optModule1 a f (Module l) = 
+  mapM (opt a f) l >>= return . Module
+-}
diff --git a/src/Llvm/Pass/PhiFixUp.hs b/src/Llvm/Pass/PhiFixUp.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/PhiFixUp.hs
@@ -0,0 +1,93 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE GADTs #-}
+
+module Llvm.Pass.PhiFixUp (phiFixUp) where
+
+import Compiler.Hoopl
+import Llvm.Data.Ir
+import Control.Monad (liftM)
+
+import Llvm.Pass.Rewriter
+#ifdef DEBUG
+import Debug.Trace
+#endif 
+
+-- | this pass fix up Phi instructions that have the parameters from unreachable code
+type LiveLabel = LabelMap Label -- all the searchable labels
+lattice :: LiveLabel -> DataflowLattice LiveLabel
+lattice live = DataflowLattice { fact_name = "Live Label"
+                               , fact_bot = live
+                               , fact_join = add
+                               }
+    where add _ (OldFact old) (NewFact new) = (ch, j)
+              where 
+                j = new `mapUnion` old
+                ch= changeIf (mapSize j > mapSize old)
+
+
+fwdTransfer :: FwdTransfer (Node a) LiveLabel
+fwdTransfer = mkFTransfer live
+  where
+    live :: Node a e x -> LiveLabel -> Fact x LiveLabel
+    live (Nlabel _) f = f
+    live (Pinst _) f = f 
+    live (Cinst _) f = f 
+    live t@(Tinst n) f  = tinstft t n f
+    tinstft :: Node a O C -> TerminatorInstWithDbg -> LiveLabel -> Fact C LiveLabel
+    tinstft n (TerminatorInstWithDbg term _) f =  
+      let targets = successors n -- targetOf term
+      in case targets of
+        [] -> mapEmpty
+        l -> mkFactBase (lattice f) (map (\x -> (x, f)) l)
+                                                     
+
+fwdRewrite :: forall a.forall m. FuelMonad m => FwdRewrite m (Node a) LiveLabel
+fwdRewrite = mkFRewrite d
+   where
+     d :: Node a e x -> LiveLabel -> m (Maybe (Graph (Node a) e x))
+     d (Pinst n) f = removePhi n f 
+     d _ _ = return Nothing
+
+
+removePhi :: forall a. forall m. FuelMonad m => PhiInstWithDbg -> Fact O LiveLabel -> m (Maybe (Graph (Node a) O O))
+#ifdef DEBUG
+removePhi x live | trace ("removePhi is called over " ++ show x) False = undefined
+removePhi x live | trace ("removePhi is called with " ++ show live) False = undefined
+removePhi x live | trace ("removePhi is called with " ++ show live) False = undefined
+#endif
+removePhi (PhiInstWithDbg (PhiInst lhs t ins) dbgs) live = 
+  if liveOperands == ins then
+    return $ Nothing
+  else if liveOperands == [] then
+         return $ Just emptyGraph
+       else 
+         return $ Just $ nodeToGraph (Pinst $ PhiInstWithDbg (PhiInst lhs t liveOperands) dbgs)
+   where 
+#ifdef DEBUG
+     isAlive x s | trace ("isAlive is called with " ++ show x ++ "  " ++ show s) False = undefined
+     isAlive x s | trace ("isAlive result is " ++ show (hooplLabelOf x `mapMember` s)) False = undefined
+#endif                                                                                          
+     isAlive x s = x `mapMember` s
+     liveOperands = foldl (\p -> \x@(_, li) -> 
+                            if isAlive li live then x:p else p) [] (reverse ins)
+
+
+fwdPass :: forall a.forall m. FuelMonad m => LiveLabel -> FwdPass m (Node a) LiveLabel
+fwdPass f = FwdPass { fp_lattice = lattice f
+                    , fp_transfer = fwdTransfer
+                    , fp_rewrite = fwdRewrite
+                    }
+
+phiFixUp :: (CheckpointMonad m, FuelMonad m) => LabelMap Label -> Label -> Graph (Node a) C C -> m (Graph (Node a) C C)
+#ifdef DEBUG
+phiFixUp idom entry graph | trace ("phiFixUp with idom " ++ show idom) False = undefined
+phiFixUp idom entry graph | trace ("phiFixUp with entry " ++ show entry) False = undefined
+#endif
+phiFixUp idom entry graph = 
+  let idom0 = mapInsert entry entry idom
+      fwd = fwdPass idom0
+  in do { (graph0, _, _) <- analyzeAndRewriteFwd fwd (JustC [entry]) graph
+                            (mapInsert entry idom0 mapEmpty)
+        ; return graph0
+        }
diff --git a/src/Llvm/Pass/Rewriter.hs b/src/Llvm/Pass/Rewriter.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/Rewriter.hs
@@ -0,0 +1,245 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE GADTs #-}
+module Llvm.Pass.Rewriter where
+
+import Control.Monad
+import Data.Maybe
+import Prelude hiding (succ)
+
+import qualified Compiler.Hoopl as H
+
+import Llvm.Data.Ir
+import Llvm.Query.TypeConstValue
+import Llvm.Util.Monadic (maybeM)
+import Debug.Trace
+
+type MaybeChange a = a -> Maybe a
+
+{-
+f2t :: (a -> Maybe a) -> (Typed a, Typed a) -> Maybe (Typed a, Typed a) 
+f2t f ((TypedData t1 a1), (TypedData t2 a2)) = case (f a1, f a2) of
+  (Nothing, Nothing) -> Nothing
+  (a1', a2') -> Just (TypedData t1 $ fromMaybe a1 a1', TypedData t2 $ fromMaybe a2 a2')
+
+
+f2 :: (a -> Maybe a) -> (a, a) -> Maybe (a, a) 
+f2 f (a1, a2) = case (f a1, f a2) of
+  (Nothing, Nothing) -> Nothing
+  (a1', a2') -> Just (fromMaybe a1 a1', fromMaybe a2 a2')
+
+
+f3 :: (a -> Maybe a) -> (Typed a, Typed a, Typed a) -> Maybe (Typed a, Typed a, Typed a) 
+f3 f (TypedData t1 a1, TypedData t2 a2, TypedData t3 a3) = case (f a1, f a2, f a3) of
+  (Nothing, Nothing, Nothing) -> Nothing
+  (a1', a2', a3') -> Just (TypedData t1 $ fromMaybe a1 a1'
+                          , TypedData t2 $ fromMaybe a2 a2'
+                          , TypedData t3 $ fromMaybe a3 a3')
+
+
+fs :: Eq a => (a -> Maybe a) -> [Typed a] -> Maybe [Typed a]
+fs f ls = let ls' = map (\(TypedData t x) -> TypedData t (fromMaybe x (f x))) ls
+          in if ls == ls' then Nothing else Just ls'
+
+
+rwIbinExpr :: MaybeChange a -> MaybeChange (IbinExpr a)
+rwIbinExpr f e = let (v1, v2) = operandOfIbinExpr e
+                     t = typeOfIbinExpr e
+                 in do { (v1', v2') <- f2 f (v1, v2)
+                       ; return $ newBinExpr t v1' v2'
+                       }
+  where newBinExpr t v1 v2 = 
+          case e of 
+            Add nw _ _ _ -> Add nw t v1 v2
+            Sub nw _ _ _ -> Sub nw t v1 v2
+            Mul nw _ _ _ -> Mul nw t v1 v2
+            Udiv nw _ _ _ -> Udiv nw t v1 v2
+            Sdiv nw _ _ _ -> Sdiv nw t v1 v2
+            Urem _ _ _ -> Urem t v1 v2
+            Srem _ _ _ -> Srem t v1 v2
+            Shl nw _ _ _ -> Shl nw t v1 v2
+            Lshr nw _ _ _ -> Lshr nw t v1 v2
+            Ashr nw _ _ _ -> Ashr nw t v1 v2
+            And _ _ _ -> And t v1 v2
+            Or _ _ _ -> Or t v1 v2
+            Xor _ _ _ -> Xor t v1 v2
+                           
+
+rwFbinExpr :: MaybeChange a -> MaybeChange (FbinExpr a)
+rwFbinExpr f e = let (v1, v2) = operandOfFbinExpr e
+                     t = typeOfFbinExpr e
+                 in do { (v1', v2') <- f2 f (v1, v2)
+                       ; return $ newBinExpr t v1' v2'
+                       }
+  where newBinExpr t v1 v2 = 
+          case e of 
+            Fadd fg _ _ _ -> Fadd fg t v1 v2
+            Fsub fg _ _ _ -> Fsub fg t v1 v2
+            Fmul fg _ _ _ -> Fmul fg t v1 v2
+            Fdiv fg _ _ _ -> Fdiv fg t v1 v2
+            Frem fg _ _ _ -> Frem fg t v1 v2
+
+rwBinExpr :: MaybeChange a -> MaybeChange (BinExpr a)
+rwBinExpr f (Ie e) = liftM Ie (rwIbinExpr f e)
+rwBinExpr f (Fe e) = liftM Fe (rwFbinExpr f e)
+
+
+rwConversion :: MaybeChange a -> MaybeChange (Conversion a)
+rwConversion f (Conversion co (TypedData ts v) t) = 
+  do { v1 <- f v
+     ; return $ Conversion co (TypedData ts v1) t
+     }
+
+rwGetElemPtr :: Eq a => MaybeChange a -> MaybeChange (GetElemPtr a)
+rwGetElemPtr f (GetElemPtr b (TypedData ts (Pointer v)) indices) = 
+  do { v1 <- f v
+     -- ; indices1 <- fs f indices 
+     ; return $ GetElemPtr b (TypedData ts (Pointer v1)) indices
+     }
+
+rwSelect :: MaybeChange a -> MaybeChange (Select a)
+rwSelect f (Select tv1 tv2 tv3) = do { (tv1', tv2', tv3') <- f3 f (tv1, tv2, tv3)
+                                     ; return $ Select tv1' tv2' tv3'
+                                     }
+
+rwIcmp :: MaybeChange a -> MaybeChange (Icmp a)
+rwIcmp f (Icmp op t v1 v2) = do { (v1', v2') <- f2 f (v1, v2)
+                                ; return $ Icmp op t v1' v2'
+                                }
+rwFcmp :: MaybeChange a -> MaybeChange (Fcmp a)
+rwFcmp f (Fcmp op t v1 v2) = do { (v1', v2') <- f2 f (v1, v2)
+                                ; return $ Fcmp op t v1' v2'
+                                }
+
+tv2v :: MaybeChange Value -> MaybeChange (Typed Value)
+tv2v f (TypedData t x) = liftM (TypedData t) (f x)
+
+tp2p :: MaybeChange Value -> MaybeChange (Typed (Pointer Value))
+tp2p f x | trace ("tp2p " ++ (show x)) False = undefined
+tp2p f (TypedData t (Pointer x)) = liftM (\p -> TypedData t (Pointer p)) (f x)
+
+
+rwExpr :: MaybeChange Value -> MaybeChange Expr
+rwExpr f (EgEp gep) = rwGetElemPtr f gep >>= return . EgEp
+rwExpr f (EiC a) = rwIcmp f a >>= return . EiC
+rwExpr f (EfC a) = rwFcmp f a >>= return . EfC
+rwExpr f (Eb a) = rwBinExpr f a >>= return . Eb
+rwExpr f (Ec a) = rwConversion f a >>= return . Ec
+rwExpr f (Es a) = rwSelect f a >>= return . Es
+rwExpr f (Ev x) = (tv2v f x) >>= return . Ev
+                  
+
+rwMemOp :: MaybeChange Value -> MaybeChange Rhs 
+rwMemOp f x | trace ("rwMemOp " ++ (show x)) False = undefined
+rwMemOp f (RmO (Allocate m t ms ma)) = do { ms' <- maybeM (tv2v f) ms
+                                          ; return $ RmO $ Allocate m t ms' ma
+                                          }
+rwMemOp f (RmO (Load x ptr a1 a2 a3 a4)) = 
+  do { tp <- (tp2p f) ptr
+     ; traceM $ "tp:" ++ show tp
+     ; return $ RmO (Load x tp a1 a2 a3 a4)
+     }
+  {-
+rwMemOp f (RmO (LoadAtomic _ _ (TypedData (Tpointer t _) ptr) _)) = do { tv <- (tv2v f) (TypedData t (Deref ptr))
+                                                                       ; return $ Re $ Ev tv
+                                                                       }
+   -}
+-- rwMemOp f (RmO (Free tv)) = (tv2v f) tv >>= return . RmO . Free 
+rwMemOp f (RmO (Store a tv1 tv2 ma nt)) = do { tv1' <- (tv2v f) tv1
+                                             ; return $ RmO $ Store a tv1' tv2 ma nt
+                                             }
+rwMemOp f (RmO (StoreAtomic at a tv1 tv2 ma)) = do { tv1' <- (tv2v f) tv1
+                                                   ; return $ RmO $ StoreAtomic at a tv1' tv2 ma
+                                                   }                                          
+rwMemOp f (RmO (CmpXchg wk b ptr v1 v2 b2 fe ff)) = do { (v1', v2') <- f2 (tv2v f) (v1, v2)
+                                                       ; return $ RmO $ CmpXchg wk b ptr v1' v2' b2 fe ff
+                                                       }
+rwMemOp f (RmO (AtomicRmw b ao ptr v1 b2 fe)) = do { v1' <- (tv2v f) v1
+                                                   ; return $ RmO $ AtomicRmw b ao ptr v1' b2 fe
+                                                   }
+rwMemOp _ _ = error "impossible case"                                                
+
+rwShuffleVector :: MaybeChange a -> MaybeChange (ShuffleVector a)
+rwShuffleVector f (ShuffleVector tv1 tv2 tv3) = 
+  do { (tv1', tv2', tv3') <- f3 f (tv1, tv2, tv3)
+     ; return $ ShuffleVector tv1' tv2' tv3'
+     }
+                                                
+rwExtractValue :: MaybeChange a -> MaybeChange (ExtractValue a)
+rwExtractValue f (ExtractValue (TypedData t v) s) = 
+  f v >>= \v1 -> return $ ExtractValue (TypedData t v1) s
+
+rwInsertValue :: MaybeChange a -> MaybeChange (InsertValue a)
+rwInsertValue f (InsertValue tv1 tv2 s) = do { (tv1', tv2') <- f2t f (tv1, tv2)
+                                             ; return $ InsertValue tv1' tv2' s
+                                             }
+                                          
+rwExtractElem :: MaybeChange a -> MaybeChange (ExtractElem a)
+rwExtractElem f (ExtractElem tv1 tv2) = do { (tv1', tv2') <- f2t f (tv1, tv2)
+                                           ; return $ ExtractElem tv1' tv2'
+                                           }
+
+rwInsertElem :: MaybeChange a -> MaybeChange (InsertElem a)
+rwInsertElem f (InsertElem tv1 tv2 tv3) = do { (tv1', tv2', tv3') <- f3 f (tv1, tv2, tv3)
+                                             ; return $ InsertElem tv1' tv2' tv3'
+                                             }
+rwRhs :: MaybeChange Value -> MaybeChange Rhs
+rwRhs f (RmO a) = rwMemOp f (RmO a) 
+rwRhs _ (Call _ _) = Nothing
+rwRhs f (Re a) = rwExpr f a >>= return . Re
+rwRhs f (ReE a) = rwExtractElem f a >>= return . ReE
+rwRhs f (RiE a) = rwInsertElem f a >>= return . RiE
+rwRhs f (RsV a) = rwShuffleVector f a >>= return . RsV
+rwRhs f (ReV a) = rwExtractValue f a >>= return . ReV
+rwRhs f (RiV a) = rwInsertValue f a >>= return . RiV
+rwRhs f (VaArg tv t) = (tv2v f) tv >>= \tv' -> return $ VaArg tv' t
+rwRhs _ (LandingPad _ _ _ _ _) = Nothing
+
+
+rwComputingInst :: MaybeChange Value -> MaybeChange ComputingInst
+rwComputingInst f (ComputingInst lhs rhs) = rwRhs f rhs >>= return . (ComputingInst lhs)
+
+rwComputingInstWithDbg :: MaybeChange Value -> MaybeChange ComputingInstWithDbg
+rwComputingInstWithDbg f (ComputingInstWithDbg cinst dbgs) = 
+  rwComputingInst f cinst >>= \cinst' -> return $ ComputingInstWithDbg cinst' dbgs
+                                                                        
+rwCinst :: MaybeChange Value -> MaybeChange (Node e x)
+rwCinst f (Cinst c) = rwComputingInstWithDbg f c >>= return . Cinst
+rwCinst _ _ = Nothing
+
+
+rwTerminatorInst :: MaybeChange Value -> MaybeChange TerminatorInst
+rwTerminatorInst f (Return ls) = do { ls' <- fs f ls
+                                    ; return $ Return ls'
+                                    }
+rwTerminatorInst f (Cbr v tl fl) = do { v' <- f v
+                                      ; return $ Cbr v' tl fl
+                                      }
+rwTerminatorInst _ _  = Nothing                   
+-- rwTerminatorInst f e = error ("unhandled case " ++ (show e))
+                       
+
+rwTerminatorInstWithDbg :: MaybeChange Value -> MaybeChange TerminatorInstWithDbg
+rwTerminatorInstWithDbg f (TerminatorInstWithDbg cinst dbgs) = 
+  rwTerminatorInst f cinst >>= \cinst' -> return $ TerminatorInstWithDbg cinst' dbgs
+                                                                        
+rwTinst :: MaybeChange Value -> MaybeChange (Node e x)
+rwTinst f (Tinst c) = rwTerminatorInstWithDbg f c >>= return . Tinst
+rwTinst _ _ = Nothing
+-}
+
+rwNode :: MaybeChange Value -> MaybeChange (Node a e x)
+rwNode = undefined
+
+{-
+rwNode f n@(Cinst _) = rwCinst f n
+rwNode f n@(Tinst _) = rwTinst f n
+rwNode _ _  = Nothing
+-}
+
+nodeToGraph :: Node a e x -> H.Graph (Node a) e x
+nodeToGraph n@(Nlabel _) = H.mkFirst n
+nodeToGraph n@(Pinst _) = H.mkMiddle n
+nodeToGraph n@(Cinst _) = H.mkMiddle n
+nodeToGraph n@(Tinst _) = H.mkLast n
+
+
diff --git a/src/Llvm/Pass/Uda.hs b/src/Llvm/Pass/Uda.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Pass/Uda.hs
@@ -0,0 +1,166 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+#define FLC   (FileLoc $(srcLoc))
+{-
+  This module compute the use, def, and Addr of CoreIr
+-}
+module Llvm.Pass.Uda where
+import Llvm.Data.CoreIr
+import qualified Data.Set as Ds
+import Data.Monoid
+import Prelude (Show, Eq, Ord, fst, (.), ($), map, maybe, Maybe, (++), show, Bool(False), undefined, foldl,error
+               ,fmap)
+#ifdef DEBUG
+import Debug.Trace
+#endif
+
+import Llvm.Query.TypeConstValue
+import Llvm.Query.IrCxt
+import qualified Llvm.Query.TypeConstValue as Tc
+
+class Uda a where
+  use :: a -> Ds.Set GlobalOrLocalId
+  def :: a -> Ds.Set LocalId -- defined ssa variables
+  
+  storeTo :: a -> Ds.Set Value
+  storeTo _ = Ds.empty
+  
+  loadFrom :: a -> Ds.Set Value
+  loadFrom _ = Ds.empty 
+  
+instance Uda Const where
+  use c = case c of
+    C_globalAddr i -> Ds.insert (GolG i) Ds.empty
+    _ -> Ds.empty
+  def _ = Ds.empty
+
+instance Uda v => Uda (GetElementPtr s v) where
+  use (GetElementPtr _ (T _ ptr) indices) = use ptr `Ds.union` (foldl (\p e -> Ds.union p (use e)) Ds.empty indices)
+  def _ = Ds.empty
+  
+instance Uda v => Uda (Maybe v) where  
+  use x = maybe Ds.empty use x
+  def x = maybe Ds.empty def x
+  storeTo x = maybe Ds.empty storeTo x
+  
+instance Uda v => Uda (T t v) where  
+  use (T _ x) = use x
+  def (T _ x) = def x
+  storeTo (T _ x) = storeTo x
+  
+instance Uda LocalId where
+  use x = Ds.insert (GolL x) Ds.empty
+  def x = Ds.insert x Ds.empty
+  storeTo x = Ds.insert (Val_ssa x) Ds.empty
+  
+instance Uda Value where
+  use x = case x of
+    Val_ssa l -> Ds.insert (GolL l) Ds.empty
+    Val_const c -> use c
+  def _ = error $ "cannot happen"
+  storeTo x = Ds.insert x Ds.empty
+ 
+instance Uda ActualParam where
+  use ap = case ap of
+    ActualParamData _ _ _ v _ -> use v
+    ActualParamLabel _ _ _ v _ -> use v
+    ActualParamMeta _ -> Ds.empty
+  def _ = errorLoc FLC $ "cannot happen"
+  storeTo _ = errorLoc FLC $ "cannot happen"
+  loadFrom _ = errorLoc FLC $ "cannot happen"
+  
+  
+instance Uda x => Uda [x] where  
+  use l = Ds.unions (fmap use l)
+  def l = Ds.unions (fmap def l)
+  storeTo l = Ds.unions (fmap storeTo l)
+  loadFrom l = Ds.unions (fmap loadFrom l)
+
+instance Uda CallSite where
+  use x = case x of
+    CsFun _ _ _ _ l _ -> use l
+    CsAsm _ _ _ _ _ _ l _ -> use l
+    CsConversion _ _ _ l _ -> use l
+
+instance Uda CInst where 
+  use ci = case ci of
+    I_alloca{..} -> use size
+    I_load{..} -> use pointer
+    I_loadatomic{..} -> use pointer
+    I_store{..} -> Ds.union (use storedvalue) (use pointer)
+    I_storeatomic{..} -> Ds.union (use storedvalue) (use pointer)
+    I_fence{..} -> Ds.empty
+    I_cmpxchg_I{..} -> Ds.unions [use pointer,use cmpi,use newi]
+    I_cmpxchg_F{..} -> Ds.unions [use pointer,use cmpf,use newf]
+    I_cmpxchg_P{..} -> Ds.unions [use pointer,use cmpp,use newp]
+    I_atomicrmw{..} -> Ds.unions [use pointer,use val]
+    I_call_fun{..} -> use actualParams
+    I_call_other{..} -> use callSite
+    I_extractelement_I{..} -> Ds.unions [use vectorI, use index]
+    I_extractelement_F{..} -> Ds.unions [use vectorF, use index]
+    I_extractelement_P{..} -> Ds.unions [use vectorP, use index]
+    I_bitcast{..} -> use srcP
+    I_ptrtoint{..} -> use srcP
+    I_inttoptr{..} -> use srcI
+    I_add{..} -> use operand1 `mappend` use operand2
+    I_getelementptr{..} -> use pointer `mappend` (foldl (\p e -> p `mappend` (use e)) Ds.empty indices)
+    I_getelementptr_V{..} -> use vpointer `mappend` (foldl (\p e -> p `mappend` (use e)) Ds.empty vindices)
+    I_llvm_dbg_declare{..} -> Ds.empty
+    I_icmp{..} -> use operand1 `mappend` use operand2
+    I_icmp_V{..} -> use operand1 `mappend` use operand2
+    I_va_end{..} -> use pointer
+    I_va_start{..} -> use pointer
+    I_va_arg tv _ _ -> use tv
+    _ -> errorLoc FLC $ "unsupported " ++ show ci
+  def ci = case ci of
+    I_alloca{..} -> def result
+    I_load{..} -> def result
+    I_store{..} -> Ds.empty
+    I_bitcast{..} -> def result
+    I_ptrtoint{..} -> def result
+    I_inttoptr{..} -> def result
+    I_add{..} -> def result
+    I_sub{..} -> def result
+    I_mul{..} -> def result
+    I_udiv{..} -> def result
+    I_sdiv{..} -> def result
+    I_urem{..} -> def result
+    I_srem{..} -> def result
+    I_shl{..} -> def result
+    I_lshr{..} -> def result
+    I_ashr{..} -> def result    
+    I_and{..} -> def result    
+    I_or{..} -> def result        
+    I_xor{..} -> def result 
+    I_getelementptr{..} -> def result
+    I_llvm_dbg_declare{..} -> Ds.empty
+    I_icmp{..} -> def result
+    I_icmp_V{..} -> def result
+    I_trunc{..} -> def result
+    I_sext{..} -> def result
+    I_va_start{..} -> Ds.empty
+    I_va_arg{..} -> def result
+    I_va_end{..} -> Ds.empty
+    _ -> errorLoc FLC $ "unsupported " ++ show ci    
+  storeTo ci = case ci of
+    I_store{..} -> storeTo pointer
+    I_va_start tv -> storeTo tv
+    _ -> Ds.empty
+  loadFrom ci = case ci of
+    I_load{..} -> let T _ v = pointer
+                  in Ds.insert v Ds.empty
+    _ -> Ds.empty
+
+
+instance Uda CInstWithDbg where  
+  use (CInstWithDbg ci _) = use ci
+  def (CInstWithDbg ci _) = def ci
+  storeTo (CInstWithDbg ci _) = storeTo ci
+  loadFrom (CInstWithDbg ci _) = loadFrom ci
+  
+  
+                              
diff --git a/src/Llvm/Query/Conversion.hs b/src/Llvm/Query/Conversion.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Query/Conversion.hs
@@ -0,0 +1,59 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+module Llvm.Query.Conversion where
+import Llvm.Data.CoreIr
+import Llvm.Query.Qerror
+import Llvm.Data.IrType
+import Debug.Trace
+
+strToApInt :: String -> Integer
+-- strToApInt s | trace ("parsing " ++ show s ++ " as int") False = undefined
+strToApInt s = case ((reads s)::[(Integer,String)]) of
+  [(n,"")] -> n
+  _ -> error $ "is not integer " ++ s
+
+castTypedValueToTypedConst :: Show t => T t Value -> T t Const
+castTypedValueToTypedConst (T t (Val_const c)) = T t c
+castTypedValueToTypedConst x = error $ "is not const " ++ show x
+
+castTypedConstToTypedValue :: T t Const -> T t Value  
+castTypedConstToTypedValue (T t c) = T t (Val_const c) 
+
+
+zExtTo32or64 :: MonadError Qerror m => Integer -> m Integer
+zExtTo32or64 n = return n -- FIXME n should be less then or equal to uint64_t
+
+castToStructType :: MonadError Qerror m => Type x r -> m (Packing, [Dtype])
+castToStructType (Tstruct p ts) = return (p, ts)
+castToStructType x = throwError (QerrWithInfo $ (show x) ++ " is not a struct type")
+
+getUniqueInteger :: Show t => T t Const -> Integer
+getUniqueInteger (T _ (C_int s))  = strToApInt s
+getUniqueInteger (T _ (C_u8 s)) = fromIntegral s
+getUniqueInteger (T _ (C_u16 s)) = fromIntegral s
+getUniqueInteger (T _ (C_u32 s)) = fromIntegral s
+getUniqueInteger (T _ (C_s8 s)) = fromIntegral s
+getUniqueInteger (T _ (C_s16 s)) = fromIntegral s
+getUniqueInteger (T _ (C_s32 s)) = fromIntegral s
+getUniqueInteger x = error $ "is not integer " ++ show x
+
+
+type ExponentType = Int 
+data FloatingSemantics = FloatingSemantics { maxExponent :: ExponentType  
+                                           , minExponent :: ExponentType
+                                           , precision :: Integer
+                                           } deriving (Eq, Ord, Show)
+
+ieeeHalf = FloatingSemantics 15 (-14) 11
+ieeeSingle = FloatingSemantics 127 (-126) 24
+ieeeDouble = FloatingSemantics 1023 (-1022) 53
+ieeeQuad = FloatingSemantics 16383 (-16382) 113
+x87DoubleExtended = FloatingSemantics 16383 (-16382) 64
+pPcDoubleDouble = FloatingSemantics 1023 (-1022+53) (53+53)
+bogus = FloatingSemantics 0 0 0
+
+data InMemRep  = InMemRep (Type ScalarB I) SimpleConstant deriving (Eq, Ord, Show)
+{-
+castPointerToValue :: Typed Pointer -> Typed Value
+castPointerToValue (Typed (Tpointer _) (Pointer v)) = Ec (Conversion 
+-}
diff --git a/src/Llvm/Query/IrCxt.hs b/src/Llvm/Query/IrCxt.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Query/IrCxt.hs
@@ -0,0 +1,50 @@
+module Llvm.Query.IrCxt where
+import qualified Llvm.Data.CoreIr as Ci
+import qualified Data.Map as M
+import Llvm.Data.Ir
+
+data TypeEnv = TypeEnv { dataLayout :: Ci.DataLayoutInfo
+                       , targetTriple :: Ci.TargetTriple
+                       , typedefs :: M.Map Ci.LocalId Ci.Dtype
+                       } deriving (Eq, Ord, Show)
+
+data FunCxt = FunCxt { funName :: String 
+                     , funParameters :: M.Map Ci.LocalId Ci.Dtype
+                     } deriving (Eq, Ord, Show)
+
+data GlobalCxt = GlobalCxt { typeEnv :: TypeEnv
+                           , globals :: M.Map (Maybe Ci.GlobalId) (TlGlobal, Ci.Dtype)
+                           } deriving (Eq, Ord, Show)
+                                
+data IrCxt = IrCxt { globalCxt :: GlobalCxt
+                   , funCxt :: FunCxt
+                   } deriving (Eq, Ord, Show)
+
+irCxtOfModule :: Module a -> IrCxt
+irCxtOfModule (Module tl) = 
+  let [ToplevelDataLayout (TlDataLayout dl)] = filter (\x -> case x of
+                                                          ToplevelDataLayout _ -> True
+                                                          _ -> False
+                                                      ) tl
+      [ToplevelTriple (TlTriple tt)] = filter (\x -> case x of
+                                                  ToplevelTriple _ -> True
+                                                  _ -> False
+                                              ) tl
+      tdefs = fmap (\(ToplevelTypeDef (TlDatTypeDef lhs def)) -> (lhs, def)) $ filter (\x -> case x of
+                                                                                          ToplevelTypeDef _ -> True
+                                                                                          _ -> False
+                                                                                      ) tl
+      glbs = fmap (\(ToplevelGlobal g@(TlGlobalDtype lhs _ _ _ _ _ _ _ _ t _ _ _ _)) -> (lhs, (g,t))) $ filter (\x -> case x of
+                                                                                                                   ToplevelGlobal _ -> True
+                                                                                                                   _ -> False
+                                                                                                               ) tl
+  in IrCxt { globalCxt = GlobalCxt { typeEnv = TypeEnv { dataLayout = getDataLayoutInfo dl
+                                                       , targetTriple = tt
+                                                       , typedefs = M.fromList tdefs
+                                                       }
+                                   , globals = M.fromList glbs
+                                   }
+           , funCxt = FunCxt { funName = ""
+                             , funParameters = M.empty
+                             }
+           }
diff --git a/src/Llvm/Query/Qerror.hs b/src/Llvm/Query/Qerror.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Query/Qerror.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE  FlexibleContexts  #-}
+module Llvm.Query.Qerror 
+       (module Llvm.Query.Qerror
+       ,module Control.Monad.Error
+       ) where
+import Control.Monad.Error
+
+data Qerror = QerrIsNotInteger String
+            | QerrIsNotConst String
+            | QerrWithoutInfo
+            | QerrWithInfo String
+            deriving (Eq, Ord, Show)
+
+instance Error Qerror where
+  noMsg = QerrWithoutInfo
+  strMsg s = QerrWithInfo s
+  
+{-  
+suppressQerror :: MonadError Qerror m => m a -> a                        
+suppressQerror ma = case catchError ma (\err -> strMsg err) of
+  (Right a) -> a
+  (Left e) -> error $ show e  
+-}
diff --git a/src/Llvm/Query/TypeConstValue.hs b/src/Llvm/Query/TypeConstValue.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Query/TypeConstValue.hs
@@ -0,0 +1,364 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+module Llvm.Query.TypeConstValue where
+
+#define FLC   (FileLoc $(srcLoc))
+
+
+import Llvm.Data.Shared
+import Llvm.Data.IrType
+import qualified Data.Map as M
+import qualified Data.Bits as B
+import Llvm.Data.CoreIr
+import Llvm.Query.IrCxt 
+import Llvm.Query.Conversion
+import Debug.Trace
+import Llvm.Query.TypeDef
+import Data.Word
+
+eightBits :: Word32
+eightBits = 8
+
+data SizeInByte = SizeInByte Word32 deriving (Eq, Ord, Show)
+data OffsetInByte = OffsetInByte Word32 deriving (Eq, Ord, Show)
+data AlignInByte = AlignInByte Word32 deriving (Eq, Ord, Show)
+
+fromSizeInBit :: SizeInBit -> SizeInByte
+fromSizeInBit (SizeInBit n) = SizeInByte (n `div` eightBits)
+
+toSizeInBit :: SizeInByte -> SizeInBit
+toSizeInBit (SizeInByte n) = SizeInBit (n * eightBits)
+
+fromAlignInBit :: AlignInBit -> AlignInByte
+fromAlignInBit (AlignInBit n) = AlignInByte (n `div` eightBits)
+
+
+getTypeAlignment :: TypeEnv -> Dtype -> AlignType -> AlignInByte
+getTypeAlignment te@TypeEnv{..} t at = case t of
+  DtypeScalarI st -> fromAlignInBit $ getTpAlignment dataLayout st
+  DtypeScalarF st -> fromAlignInBit $ getTpAlignment dataLayout st  
+  DtypeRecordD st -> case st of
+    Tarray i et -> getTypeAlignment te et at
+    Tstruct p tys -> case (p, at) of
+      (Packed, AlignAbi)  -> AlignInByte 1
+      _ -> let aa = case M.lookup (Just $ SizeInBit 0) (aggregates dataLayout) of
+                 Just (aa, pa) -> selectAlignment at aa pa
+                 Nothing -> errorX
+               sl = getStructLayout te (p,tys)
+           in (max (fromAlignInBit aa) (structAlignment sl))
+  DtypeScalarP st -> case st of  
+    Tpointer t a -> case (uncurry lookupOr) (ta $ Just a) (pointers dataLayout) of
+      Just (s, aa, pa) -> (fromAlignInBit $ selectAlignment at aa pa)
+      Nothing -> errorX
+  where
+    errorX :: a
+    errorX = error $ "getTypedAlignment:unsupported " ++ show t
+    getTpAlignment :: DataLayoutInfo -> Type ScalarB x -> AlignInBit
+    getTpAlignment dl tp = case tp of
+      TpI n -> case M.lookup (SizeInBit n) (ints dl) of
+        Just (aa, pa) -> selectAlignment at aa pa
+        Nothing -> AlignInBit n
+      TpF n -> case M.lookup (SizeInBit n) (floats dl) of
+        Just (aa, pa) -> selectAlignment at aa pa
+        Nothing -> AlignInBit n
+      TpV n -> case M.lookup (SizeInBit n) (vectors dl) of
+        Just (aa, pa) -> selectAlignment at aa pa
+        Nothing ->AlignInBit n
+      TpHalf -> AlignInBit 16 
+      TpFloat -> let b = getTypeSizeInBits te (ucast tp)
+                 in case M.lookup b (floats dl) of
+                   Just (aa, pa) -> selectAlignment at aa pa
+                   Nothing -> AlignInBit 32
+      TpDouble -> let b = getTypeSizeInBits te (ucast tp)
+                  in case M.lookup b (floats dl) of
+                    Just (aa, pa) -> selectAlignment at aa pa
+                    Nothing -> AlignInBit 64
+      TpFp128 -> let b = getTypeSizeInBits te (ucast tp)
+                 in case M.lookup b (floats dl) of
+                   Just (aa, pa) -> selectAlignment at aa pa
+                   Nothing -> errorX
+      TpX86Fp80 -> let b = getTypeSizeInBits te (ucast tp)
+                   in case M.lookup b (floats dl) of
+                     Just (aa, pa) -> selectAlignment at aa pa
+                     Nothing -> errorX
+      TpPpcFp128 -> let b = getTypeSizeInBits te (ucast tp)
+                    in case M.lookup b (floats dl) of
+                      Just (aa, pa) -> selectAlignment at aa pa
+                      Nothing -> errorX
+      TpX86Mmx -> errorX
+
+ta :: Maybe AddrSpace -> (LayoutAddrSpace, LayoutAddrSpace)
+ta x = case x of
+  Just n | n == 0 -> (LayoutAddrSpaceUnspecified, LayoutAddrSpace n)
+  Just n -> (LayoutAddrSpace n, LayoutAddrSpace n)  
+  Nothing -> (LayoutAddrSpaceUnspecified, LayoutAddrSpace 0)
+
+
+getCallFrameTypeAlignment :: TypeEnv -> Dtype -> AlignInByte
+getCallFrameTypeAlignment te@TypeEnv{..} ty = case stackAlign dataLayout of
+  StackAlign n -> fromAlignInBit n
+  StackAlignUnspecified -> getTypeAlignment te ty AlignAbi
+
+lookupOr :: Ord a => a -> a -> M.Map a r -> Maybe r
+lookupOr a1 a2 m = maybe (M.lookup a2 m) Just (M.lookup a1 m)
+
+getTypeSizeInBits :: TypeEnv -> Dtype -> SizeInBit
+getTypeSizeInBits te@TypeEnv{..} dt = case dt of
+  (DtypeRecordD t) -> case t of
+    Tarray i et -> let SizeInBit n = getTypeAllocSizeInBits te et
+                   in SizeInBit (i * n)
+    Tstruct pk ts -> let sl = getStructLayout te (pk, ts)
+                     in toSizeInBit $ structSize sl
+    TnameRecordD n -> case getTypeByTname n typedefs of
+      Just d -> getTypeSizeInBits te d
+      Nothing -> errorLoc FLC ("undefined " ++ show n)
+    _ -> errorLoc FLC (show t)
+  (DtypeScalarP (Tpointer t a)) -> case (uncurry lookupOr) (ta $ Just a) (pointers dataLayout) of
+    Just (n, _, _) -> n
+    Nothing -> error $ "getTypeSizeInBits:unsupported type " ++ show t
+  (DtypeScalarI t) -> case t of  
+    TpI n -> SizeInBit n
+    TpV n -> SizeInBit n
+  (DtypeScalarF t) -> case t of  
+    TpF n -> SizeInBit n
+    TpHalf -> SizeInBit 16
+    TpFloat -> SizeInBit 32
+    TpDouble -> SizeInBit 64
+    TpFp128 -> SizeInBit 128
+    TpX86Fp80 -> SizeInBit 80
+    TpPpcFp128 -> SizeInBit 128
+  _ -> errorLoc FLC (show dt)
+      
+
+getTypeStoreSize :: TypeEnv ->  Dtype -> SizeInByte
+getTypeStoreSize te ty = let (SizeInBit tyBits) = getTypeSizeInBits te ty
+                         in fromSizeInBit (SizeInBit (tyBits + 7))
+
+getTypeStoreSizeInBits :: TypeEnv -> Dtype -> SizeInBit
+getTypeStoreSizeInBits te ty = toSizeInBit (getTypeStoreSize te ty)
+
+getTypeAllocSize :: TypeEnv -> Dtype -> SizeInByte
+getTypeAllocSize te ty = roundUpAlignment (getTypeStoreSize te ty) (getTypeAlignment te ty AlignAbi)
+
+getTypeAllocSizeInBits :: TypeEnv -> Dtype -> SizeInBit
+getTypeAllocSizeInBits te ty = toSizeInBit (getTypeAllocSize te ty)
+
+data StructLayout = StructLayout { structSize :: SizeInByte
+                                 , structAlignment :: AlignInByte
+                                 , numElements :: Integer
+                                 , memberOffsets :: [OffsetInByte]
+                                 } deriving (Eq, Ord, Show)
+
+roundUpAlignment :: SizeInByte -> AlignInByte -> SizeInByte
+roundUpAlignment (SizeInByte val) (AlignInByte align) = SizeInByte $ (val + (align -1)) B..&. (B.complement (align - 1))
+
+getStructLayout :: TypeEnv -> (Packing, [Dtype]) -> StructLayout
+getStructLayout te@TypeEnv{..} (pk, tys) = 
+  let (totalSize@(SizeInByte totalSizeByte), offsets, alignment@(AlignInByte alignmentByte)) =
+        foldl (\(curSize@(SizeInByte curSizeByte), offsets, AlignInByte structAlignment0) ty ->
+                let tyAlign@(AlignInByte tyAlignByte) = case pk of
+                      Packed -> AlignInByte 1
+                      Unpacked -> getTypeAlignment te ty AlignAbi
+                    (SizeInByte nextOffsetByte) = if curSizeByte B..&. (tyAlignByte - 1) /= 0 then roundUpAlignment curSize tyAlign
+                                                  else curSize
+                    (SizeInByte tySize) = getTypeAllocSize te ty
+                in (SizeInByte $ nextOffsetByte + tySize, (OffsetInByte nextOffsetByte):offsets, AlignInByte $ max tyAlignByte structAlignment0)
+              ) (SizeInByte 0, [], AlignInByte 1) tys
+  in StructLayout { structSize = if (totalSizeByte B..&. (alignmentByte - 1)) /= 0 then roundUpAlignment totalSize alignment
+                                 else totalSize
+                  , structAlignment = alignment
+                  , numElements = toInteger $ length tys
+                  , memberOffsets = reverse offsets
+                  }
+
+getPointerSizeInBits :: DataLayoutInfo -> Maybe AddrSpace -> SizeInBit
+getPointerSizeInBits dl mas = case (uncurry lookupOr) (ta mas) (pointers dl) of
+  Just (s, aa, pa) -> s
+  Nothing -> error $ "getPointerSizeInBits:unsupported " ++ show dl
+
+getPointerSize :: DataLayoutInfo -> Maybe AddrSpace -> SizeInByte
+getPointerSize dl mas = fromSizeInBit (getPointerSizeInBits dl mas)
+
+getPointerAlignment :: DataLayoutInfo -> Maybe AddrSpace -> AlignType -> AlignInByte
+getPointerAlignment dl mas at = case (uncurry lookupOr) (ta mas) (pointers dl) of
+  Just (s, aa, pa) -> fromAlignInBit $ selectAlignment at aa pa
+  Nothing -> error $ "getPointerAlignment:unsupported " ++ show dl
+
+
+
+getScalarTypeSizeInBits :: DataLayoutInfo -> ScalarType -> SizeInBit
+getScalarTypeSizeInBits dl x = 
+  SizeInBit (case x of
+                ScalarTypeI e -> case e of
+                  (TpI n) -> n
+                  (TpV n) -> n
+                  TpX86Mmx -> 64
+                ScalarTypeF e -> case e of
+                  (TpF n) -> n
+                  TpHalf -> 16
+                  TpFloat -> 32
+                  TpDouble -> 64
+                  TpFp128 -> 128
+                  TpX86Fp80 -> 80
+                  TpPpcFp128 -> 128
+                ScalarTypeP _ -> 32
+            )
+
+
+getGetElemtPtrIndexedType :: TypeEnv -> Dtype -> [T (Type ScalarB I) Value] -> Dtype
+getGetElemtPtrIndexedType te x is | trace ("getGetElemtPtrIndexedType : type:" ++ show x ++ ", " ++ show is) False = undefined
+getGetElemtPtrIndexedType te x is = case is of 
+  hd:tl -> case x of
+    DtypeScalarP (Tpointer et _) -> if tl == [] then dcast FLC et
+                                    else getGetElemtPtrIndexedType te (dcast FLC et) tl
+    DtypeRecordD (TnameRecordD _) -> getGetElemtPtrIndexedType te (getTypeDef te x) is
+    DtypeRecordD (TquoteNameRecordD _) -> getGetElemtPtrIndexedType te (getTypeDef te x) is    
+    DtypeRecordD (TnoRecordD _) -> getGetElemtPtrIndexedType te (getTypeDef te x) is
+    _ -> let ct = getTypeAtIndex te x (castTypedValueToTypedConst hd)
+         in if tl == [] then ct
+            else getGetElemtPtrIndexedType te ct tl
+
+getTypeAtIndex :: Show t => TypeEnv -> Dtype -> T t Const -> Dtype
+getTypeAtIndex _ x@(DtypeScalarP (Tpointer _ _)) _ = error $ "does not expect a pointer type: " ++ show x
+getTypeAtIndex te t idx = 
+  case (getTypeDef te t) of
+    DtypeRecordD (Tstruct _ ts) -> let (ii::Word32) = fromIntegral $ getUniqueInteger idx
+                                   in if ii < fromIntegral (length ts) then ts !! (fromIntegral ii)
+                                      else error ("Invalid structure index! " ++ show ii)
+    DtypeRecordD (Tarray n et) -> et 
+    x -> error $ "Invalid indexing of " ++ show x
+
+getTypeDef :: TypeEnv -> Dtype -> Dtype
+getTypeDef TypeEnv{..} t = case t of
+  DtypeRecordD (TnameRecordD n) -> maybe (error $ show t ++ " is not defined.") id (getTypeByTname n typedefs)
+  DtypeRecordD (TquoteNameRecordD n) -> maybe (error $ show t ++ " is not defined.") id (getTypeByTquoteName n typedefs)
+  DtypeRecordD (TnoRecordD n) -> maybe (error $ show t ++ " is not defined.") id (getTypeByTno n typedefs)
+  DtypeRecordD _ -> t
+  DtypeScalarI _ -> t
+  DtypeScalarP _ -> t 
+  DtypeScalarF _ -> t
+  DtypeVectorI _ -> t
+  DtypeVectorP _ -> t
+  DtypeVectorF _ -> t
+  DtypeFirstClassD _ -> t
+
+
+getElementType :: TypeEnv -> Dtype -> Dtype
+getElementType te t = case getTypeDef te t of
+  DtypeRecordD (Tarray _ t1) -> t1
+  DtypeScalarP (Tpointer t1 _) -> dcast FLC t1
+  _ -> error $ (show t) ++ " has not element type"
+
+{-
+getScalarType :: TypeEnv -> Dtype -> Dtype
+getScalarType te (DtypeAgg (Tvector _ t)) = t
+getScalarType te x = x
+-}
+
+castIsValid :: DataLayoutInfo -> Conversion ScalarB v -> Bool -- ConvertOp -> Dtype -> Dtype -> Bool
+-- castIsValid op src dest | vsize src == vsize dest = case op of
+castIsValid dl op = True 
+                    {-case op of  
+  Trunc (T src _) dest -> getScalarTypeSizeInBits dl src > getScalarTypeSizeInBits dl
+  Zext (T src _) dest -> getScalarTypeSizeInBits dl src < getScalarTypeSizeInBits dl
+  Sext (T src _) dest -> getScalarTypeSizeInBits dl src < getScalarTypeSizeInBits dl
+  FpTrunc (T src _) dest -> getScalarTypeSizeInBits dl src > getScalarTypeSizeInBits dl dest
+  FpExt (T src _) dest -> getScalarTypeSizeInBits dl src < getScalarTypeSizeInBits dl dest
+  UiToFp (T src _) dest -> vsize src == vsize dest && vmap isInt src && vmap isFp dest
+  SiToFp (T src _) dest -> vsize src == vsize dest && vmap isInt src && vmap isFp dest
+  FpToUi (T src _) dest -> vsize src == vsize dest && vmap isFp src && vmap isInt dest
+  FpToSi (T src _) dest -> vsize src == vsize dest && vmap isFp src && vmap isInt dest
+  PtrToInt (T src _) dest -> vsize src == vsize dest && vmap isInt src && vmap isPtr dest
+  IntToPtr (T src _) dest -> vsize src == vsize dest && vmap isPtr src && vmap isInt dest
+  Bitcast (T src _) dest -> vsize src == vsize dest &&  (vmap isPtr src && vmap isPtr dest && vmap addrSpace src == vmap addrSpace dest)  {- ptr to ptr -}
+                            || (vmap (not . isPtr) src) && (vmap (getScalarTypeSizeInBits dl) src == vmap (getScalarTypeSizeInBits dl) dest) {- non ptr to ptr -}
+  AddrSpaceCast (T src _) dest -> vsize src == vsize dest && vmap isPtr src && vmap isPtr dest && vmap addrSpace src == vmap addrSpace dest
+  where isValid f s d = vmap f s && vmap f d
+-}
+
+
+castable :: Show v => DataLayoutInfo -> Conversion ScalarB v -> Conversion ScalarB v
+castable dl op = if castIsValid dl op then op
+                 else error $ "Invalid cast:" ++ show op 
+
+
+
+getConstArray :: Dtype -> [T Dtype Const] -> T Dtype Const
+getConstArray t@(DtypeRecordD (Tarray n el)) [] = T t (C_array $ fmap (\x -> TypedConst $ T el C_zeroinitializer) [1..n])
+getConstArray t@(DtypeRecordD (Tarray n el)) l = if or $ fmap (\(T vt _) -> vt /= el) l then error "type mismatch"
+                                                 else T t (C_array (fmap TypedConst l))
+getConstArray t _ = error "type mismatch"
+
+
+getTypedConst :: TypeEnv -> (Type ScalarB x -> Const) -> Dtype -> T Dtype Const
+getTypedConst te f t = case (getTypeDef te t) of
+  (DtypeRecordD (Tarray n et)) -> let ev = getTypedConst te f et
+                                  in T t (C_arrayN n $ TypedConst ev)
+  (DtypeRecordD (Tstruct pk ts)) -> let evs = fmap (getTypedConst te f) ts
+                                    in T t (C_struct pk (fmap TypedConst evs))
+
+getNullValue :: Type ScalarB x -> Const
+getNullValue t = case t of
+--  TpVoid -> error $ show t ++ " has no null const value"
+--  TpNull -> error $ show t ++ " has no null const value"
+--  TpLabel -> error $ show t ++ " has no null const value"
+  _ -> C_zeroinitializer
+
+getUndefValue :: Type ScalarB x -> Const
+getUndefValue t = case t of
+--  TpVoid -> error $ show t ++ " has no undef const value"
+--  TpNull -> error $ show t ++ " has no undef const value"
+--  TpLabel -> error $ show t ++ " has no undef const value"
+  _ -> C_undef
+
+getPointerCast :: Show v => DataLayoutInfo -> T (Type ScalarB P) v -> Type ScalarB I -> Conversion ScalarB v
+getPointerCast dl (T ts v) td = castable dl (PtrToInt (T ts v) td)
+
+getBitCast :: Show v => DataLayoutInfo -> T Dtype v -> Dtype -> Conversion ScalarB v
+getBitCast dl (T t c) dt = castable dl (Bitcast (T t c) dt)
+
+getGetElementPtr :: T (Type ScalarB P) Const -> [T (Type ScalarB I) Const] -> IsOrIsNot InBounds -> GetElementPtr ScalarB Const
+getGetElementPtr (T t cv) indices isB = GetElementPtr isB (T t cv) indices
+
+
+getIntStoreTypeForPointer :: DataLayoutInfo -> Dtype
+getIntStoreTypeForPointer dl =  let (SizeInBit sizeInBits) = getPointerSizeInBits dl Nothing
+                                in DtypeScalarI $ TpI sizeInBits
+
+typeOfCallSite :: IrCxt -> CallSite -> Maybe Rtype
+typeOfCallSite = error "typeOfCallSite is not defined yet"
+
+typeOfExtractElem = undefined
+typeOfInsertElem _ = Nothing
+typeOfShuffleVector = undefined
+typeOfExtractValue = undefined
+typeOfInsertValue _ = Nothing
+
+{-
+castTcToTv :: T t Const -> T t Value
+castTcToTv (T t c) = (T t (Val_const c))
+-}
+
+
+class TypeOf a t | a -> t where  
+  typeof :: TypeEnv -> a -> t
+  
+  
+instance TypeOf CInst Dtype where
+  typeof te x = case x of
+    I_getelementptr{..} -> let (T bt _) = pointer
+                               et = getGetElemtPtrIndexedType te (ucast bt) indices
+                           in (ucast $ Tpointer (ucast et) 0)
+    I_add{..} -> ucast typeI
+    I_bitcast{..} -> ucast toP
+    I_ptrtoint{..} -> ucast toI
+    I_inttoptr{..} -> ucast toP
+    I_load{..} -> let (T (Tpointer et _) _) = pointer
+                  in dcast FLC et
+    I_llvm_dbg_declare{..} -> error $ show x ++ " has no type"
+    _ -> errorLoc FLC $ "unsupported " ++ show x 
diff --git a/src/Llvm/Query/TypeDef.hs b/src/Llvm/Query/TypeDef.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Query/TypeDef.hs
@@ -0,0 +1,13 @@
+module Llvm.Query.TypeDef where
+
+import Llvm.Data.Ir
+import qualified Data.Map as M
+  
+getTypeByTname :: String -> M.Map LocalId Dtype -> Maybe Dtype
+getTypeByTname tn mp = M.lookup (LocalIdAlphaNum tn) mp
+
+getTypeByTquoteName :: String -> M.Map LocalId Dtype -> Maybe Dtype
+getTypeByTquoteName tn mp = M.lookup (LocalIdDqString tn) mp
+
+getTypeByTno :: Word32 -> M.Map LocalId Dtype -> Maybe Dtype
+getTypeByTno n mp = M.lookup (LocalIdNum n) mp
diff --git a/src/Llvm/Syntax/Parser/Basic.hs b/src/Llvm/Syntax/Parser/Basic.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/Basic.hs
@@ -0,0 +1,491 @@
+module Llvm.Syntax.Parser.Basic
+    ( module Text.Parsec
+    , module Llvm.Syntax.Parser.Basic
+    , module Control.Monad
+    , module Text.Parsec.Perm
+    )
+    where
+
+import Text.Parsec 
+import Control.Monad
+import Llvm.Data.Ast
+import qualified Text.Parsec.Token as T
+import Text.Parsec.Language
+import Text.Parsec.Perm
+import Data.Char
+import Data.Functor.Identity (Identity)
+import qualified Data.Map as M
+import Data.Word (Word32)
+
+-- dummy state
+-- data DummyState = DummyState
+
+type DummyState = ()
+
+type P a = Parsec String DummyState a
+
+initState :: DummyState
+initState = () -- DummyState 
+
+lexer :: T.GenTokenParser String u Data.Functor.Identity.Identity
+lexer = T.makeTokenParser 
+        (emptyDef 
+         { T.commentLine = ";"
+         , T.reservedNames = 
+             [ "begin", "end", "true", "false", "declare", "define", "global", "constant"
+             , "dllimport", "dllexport"
+             , "extern_weak", "external", "thread_local", "zeroinitializer", "undef", "null", "to", "tail"
+             , "target", "triple", "deplibs", "datalayout", "volatile", "nuw", "nsw", "exact", "inbounds", "align"
+             , "addrspace", "section", "alias", "module", "asm", "sideeffect", "gc", "ccc", "cc", "fastcc"
+             , "coldcc", "x86_stdcallcc", "x86_fastcallcc", "x86_thiscallcc", "arm_apcscc", "arm_aapcscc", "arm_aapcs_vfpcc"
+             , "msp430_intrcc", "cc", "c", "signext", "zeroext", "inreg", "sret", "nounwind", "noreturn", "noalias"
+             , "nocapture", "byval", "nest", "type", "opaque", "eq", "ne", "slt", "sgt"
+             , "sle", "sge", "ult", "ugt", "ule", "uge", "oeq", "one", "olt", "ogt", "ole", "oge", "ord", "uno", "ueq"
+             , "une", "x", "blockaddress"
+             , "add",  "fadd", "sub",  "fsub", "mul",  "fmul", "udiv", "sdiv", "fdiv", "urem", "srem", "frem"
+             , "shl",  "lshr", "ashr", "and",  "or",   "xor", "icmp", "fcmp", "phi", "call", "trunc"
+             , "zext", "sext", "fptrunc", "fpext", "uitofp", "sitofp", "fptoui", "fptosi", "inttoptr", "ptrtoint"
+             , "bitcast", "addrspacecast", "select", "va_arg", "ret", "br", "switch", "indirectbr"
+             , "invoke", "unwind", "unreachable"
+             , "alloca", "malloc", "load", "store", "getelementptr", "extractelement", "insertelement", "shufflevector"
+             , "getresult", "extractvalue", "insertvalue", "free", "address_safety", "nonlazybind", "landingpad", "cleanup"
+             , "catch", "filter", "personality", "half", "unnamed_addr", "singlethread", "acquire"
+             , "release", "acq_rel", "seq_cst", "unordered", "monotonic", "atomic"
+             , "atomicrmw", "xchg", "nand", "max", "min", "umax", "umin", "x86_mmx"
+             , "call", "tail", "musttail"
+             -- Linkage Types                                                             
+             , "private", "internal", "available_externally", "linkonce", "weak", "common", "appending", "extern_weak"
+             , "linkonce_odr", "weak_odr", "external"
+             -- Calling Conventions
+             , "ccc", "fastcc", "coldcc", "cc", "webkit_jscc", "anyregcc", "preserve_mostcc", "preserve_allcc"
+             , "spir_kernel", "spir_func", "intel_ocl_bicc", "x86_stdcallcc", "x86_fastcallcc", "x86_thiscallcc"
+             , "arm_apcscc", "arm_aapcscc", "arm_aapcs_vfpcc", "msp430_intrcc", "ptx_kernel", "ptx_device"
+             , "x86_64_win64cc", "x86_64_sysvcc"
+             -- Visibility Styles                                                                             
+             , "default", "hidden", "protected"
+             -- Parameter Attributes                                                             
+             , "zeroext", "signext", "inreg", "byval", "inalloca", "sret", "noalias", "nocapture", "nest", "returned"
+             , "nonnull", "dereferenceable"
+             -- Function Attributes
+             , "alignstack", "alwaysinline", "builtin", "cold", "inlinehint", "jumptable", "minsize", "naked", "nobuiltin"
+             , "noduplicate", "noimplicitfloat", "noinline", "nonlazybind", "noredzone", "noreturn", "nounwind", "optnone"
+             , "optsize", "readnone", "readonly", "returns_twice", "sanitize_address", "sanitize_memory", "sanitize_thread"
+             , "ssp", "sspreq", "sspstrong", "uwtable"
+             -- Fast math flags
+             , "nnan", "ninf", "nsz", "arcp", "fast"
+             , "inteldialect"
+             , "<<label>>"
+             ]
+         })
+          
+
+integer :: P Integer
+integer = T.integer lexer
+
+unsignedInt :: P Word32
+unsignedInt = liftM fromIntegral integer
+
+decimal :: P Integer
+decimal = lexeme (T.decimal lexer)
+
+
+reserved :: String -> P ()
+reserved = T.reserved lexer
+
+
+symbol :: String -> P String
+symbol = T.symbol lexer
+
+
+lexeme :: P a -> P a
+lexeme = T.lexeme lexer
+
+
+intStrToken :: P String
+intStrToken = lexeme numericLit <?> "intStringToken"
+
+
+whiteSpace :: P ()
+whiteSpace = T.whiteSpace lexer
+
+ignore   :: P a -> P ()
+ignore p = do { _ <- p ; return () }
+
+chartok :: Char -> P Char
+chartok = lexeme . char
+
+complete :: P a -> P a
+complete p = do { whiteSpace; x <- p; eof; return x }
+
+-------------------------------------------------------------------------------
+comma :: P String
+comma = T.comma lexer
+
+colon :: P String
+colon = T.colon lexer
+
+braces :: P a  -> P a
+braces = T.braces lexer 
+
+brackets :: P a -> P a
+brackets = T.brackets lexer 
+
+parens :: P a -> P a
+parens = T.parens lexer
+
+angles :: P a -> P a
+angles = T.angles lexer
+
+anglebraces :: P a -> P a
+anglebraces p = between (symbol "<{") (symbol "}>") p
+
+
+-------------------------------------------------------------------
+idChar :: Char -> Bool
+idChar c = isAlphaNum c || c == '$' || c == '.' || c == '_' || c == '-'    
+
+startChar :: Char -> Bool
+startChar c = isAlpha c || c == '$' || c == '.' || c == '_' || c == '-'
+
+pAlphaNum :: P String
+pAlphaNum = do { h <- satisfy startChar
+               ; l <- many (satisfy idChar)
+               ; return (h:l)
+               }
+
+pLocalId :: P LocalId
+pLocalId = do { x <- lexeme (char '%' >> choice [ liftM LocalIdNum unsignedInt -- decimal
+                                                , try $ liftM (LocalIdAlphaNum) pAlphaNum
+                                                , try $ liftM (LocalIdAlphaNum) (lexeme (between (char '"') (char '"') pAlphaNum))
+                                                , liftM (LocalIdDqString) pQuoteStr
+                                                ])
+              ; return x
+              }
+
+pGlobalId :: P GlobalId
+pGlobalId = lexeme (char '@' >> choice [ liftM GlobalIdNum unsignedInt -- decimal
+                                       , try $ liftM (GlobalIdAlphaNum) pAlphaNum -- (many1 (satisfy idChar))
+                                       , try $ liftM GlobalIdAlphaNum (lexeme (between (char '"') (char '"') pAlphaNum))
+                                       , liftM GlobalIdDqString pQuoteStr
+                                       ])
+
+pDollarId :: P DollarId
+pDollarId = lexeme (char '$' >> choice [ liftM DollarIdNum unsignedInt -- decimal
+                                       , try $ liftM (DollarIdAlphaNum) pId 
+                                       , try $ liftM DollarIdAlphaNum (lexeme (between (char '"') (char '"') pId))
+                                       , liftM (DollarIdDqString) pQuoteStr
+                                       ])
+
+
+pMdVar :: P MdVar
+pMdVar = lexeme $ do { ignore (char '!')
+                     ; n <- choice [ liftM (\x -> [x]) (satisfy isAlpha)
+                                   , char '\\' >> numericLit ]
+                     ; l <- many (satisfy idChar)
+                     ; return $ MdVar (n++l)
+                     }
+
+pId :: P String
+pId = do { n <- (satisfy isAlpha)
+         ; l <- many (satisfy idChar)
+         ; return $ n:l
+         }
+    
+pGlobalOrLocalId :: P GlobalOrLocalId
+pGlobalOrLocalId = do { x <- choice [liftM GolL pLocalId
+                                    , liftM GolG pGlobalId ]
+                      ; return x
+                      }
+
+
+numericLit :: P String
+numericLit = many1 (satisfy isNumber)
+
+pQuoteStr :: P String
+pQuoteStr = lexeme ((char '"' >> (manyTill anyChar (char '"'))))
+
+readInteger :: String -> Either String Integer            
+readInteger x = case reads x :: [(Integer, String)] of
+                  [(i,s)] | s == "" -> Right i
+                  [] -> Left x                  
+                  _ -> Left x
+                        
+pLabelId :: P LabelId
+pLabelId = choice [ do { s <- (many1 (satisfy lblChar))
+                       ; case readInteger s of
+                            Right x -> return $ LabelNumber $ fromIntegral x
+                            Left x -> return $ LabelString x
+                       }
+                  , do { s <- pQuoteStr
+                       ; case readInteger s of
+                           Right x -> return $ LabelDqNumber $ fromIntegral x
+                           Left x -> return $ LabelDqString x
+                       }
+                  ]
+           where
+             lblChar c = isAlphaNum c || c == '.' || c == '_' || c == '-' 
+             
+             
+pLabelNumber :: P LabelId
+pLabelNumber = do { x <- many1 (satisfy isDigit)
+                  ; let i = read x:: Word32 -- Int 
+                  ; return $ LabelNumber i
+                  }
+             
+pAddrNaming :: P AddrNaming
+pAddrNaming = option NamedAddr (reserved "unnamed_addr" >> return UnnamedAddr)
+          
+pPercentLabel :: P PercentLabel
+pPercentLabel = lexeme (char '%' >> liftM PercentLabel pLabelId)
+
+pTargetLabel :: P TargetLabel
+pTargetLabel = reserved "label" >> liftM TargetLabel pPercentLabel
+
+pExplicitBlockLabel :: P BlockLabel
+pExplicitBlockLabel = lexeme (do { x <- pLabelId 
+                                 ; _ <- char ':'
+                                 ; return $ ExplicitBlockLabel x
+                                 })
+              
+pImplicitBlockLabel :: P BlockLabel              
+pImplicitBlockLabel = do { pos <- getPosition
+                         ; return $ ImplicitBlockLabel (sourceName pos, sourceLine pos, sourceColumn pos)
+                         }
+                      
+
+pBlockLabel :: P BlockLabel                      
+pBlockLabel = choice [ try pExplicitBlockLabel
+                     , pImplicitBlockLabel ]
+
+pParamAttr :: P ParamAttr
+pParamAttr = choice [ reserved "zeroext" >> return PaZeroExt
+                    , reserved "signext" >> return PaSignExt
+                    , reserved "inreg" >> return PaInReg
+                    , reserved "byval" >> return PaByVal
+                    , reserved "inalloca" >> return PaInAlloca
+                    , reserved "sret" >> return PaSRet
+                    , reserved "noalias" >> return PaNoAlias
+                    , reserved "nocapture" >> return PaNoCapture
+                    , reserved "nest" >> return PaNest
+                    , reserved "returned" >> return PaReturned
+                    , reserved "nonnull" >> return PaNonNull
+                    , reserved "dereferenceable" >> liftM PaDereferenceable (parens unsignedInt) -- decimal)
+                    , reserved "readonly" >> return PaReadOnly
+                    , reserved "readnone" >> return PaReadNone
+                    , reserved "align" >> liftM PaAlign unsignedInt -- decimal
+                    ]
+
+pConvertOp :: P ConvertOp
+pConvertOp = choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList convertOpMap
+
+pCallConv :: P CallConv
+pCallConv = choice [ try (reserved "ccc") >> return Ccc
+                   , try (string "cc" >> liftM Cc intStrToken)
+                   , reserved "cc" >> liftM Cc intStrToken
+                   , reserved "fastcc" >> return CcFast
+                   , reserved "coldcc" >> return CcCold
+                   , reserved "webkit_jscc" >> return CcWebkit_Js
+                   , reserved "anyregcc" >> return CcAnyReg
+                   , reserved "preserve_mostcc" >> return CcPreserveMost
+                   , reserved "preserve_allcc" >> return CcPreserveAll
+                   , reserved "spir_kernel" >> return CcSpir_Kernel
+                   , reserved "spir_func" >> return CcSpir_Func
+                   , reserved "intel_ocl_bicc" >> return CcIntel_Ocl_Bi
+                   , reserved "x86_stdcallcc" >> return CcX86_StdCall
+                   , reserved "x86_fastcallcc" >> return CcX86_FastCall
+                   , reserved "x86_thiscallcc" >> return CcX86_ThisCall
+                   , reserved "arm_apcscc" >> return CcArm_Apcs
+                   , reserved "arm_aapcscc" >> return CcArm_Aapcs
+                   , reserved "arm_aapcs_vfpcc" >> return CcArm_Aapcs_Vfp
+                   , reserved "msp430_intrcc" >> return CcMsp430_Intr
+                   , reserved "ptx_kernel" >> return CcPtx_Kernel
+                   , reserved "ptx_device" >> return CcPtx_Device
+                   , reserved "x86_64_win64cc" >> return CcX86_64_Win64
+                   , reserved "x86_64_sysvcc" >> return CcX86_64_SysV
+                   ]
+
+
+pVisibility :: P Visibility
+pVisibility = (reserved "default" >> return VisDefault)
+              <|> (reserved "hidden" >> return VisHidden)
+              <|> (reserved "protected" >> return VisProtected)
+
+
+pLinkage :: P Linkage
+pLinkage = choice [ reserved "linker_private_weak_def_auto" >> return LinkagePrivate
+                  , reserved "linker_private_weak" >> return LinkagePrivate
+                  , reserved "private" >> return LinkagePrivate
+                  , reserved "linker_private" >> return LinkagePrivate
+                  , reserved "internal" >> return LinkageInternal
+                  , reserved "external" >> return LinkageExternal
+                  , reserved "available_externally" >> return LinkageAvailableExternally
+                  , reserved "linkonce" >> return LinkageLinkonce
+                  , reserved "weak" >> return LinkageWeak
+                  , reserved "common" >> return LinkageCommon
+                  , reserved "appending" >> return LinkageAppending
+                  , reserved "extern_weak" >> return LinkageExternWeak
+                  , reserved "linkonce_odr" >> return LinkageLinkonceOdr
+                  , reserved "weak_odr" >> return LinkageWeakOdr
+                  ]
+
+
+opt :: P a -> P (Maybe a)
+opt p = option Nothing (liftM Just (try p))
+
+
+optCommaSep :: P a -> P (Maybe a)
+optCommaSep p = opt (try (comma >> p))
+
+
+
+pIbinaryOperator :: P IbinOp
+pIbinaryOperator = choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList ibinOpMap
+
+pFbinaryOperator :: P FbinOp
+pFbinaryOperator = choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList fbinOpMap
+
+pIcmpOp :: P IcmpOp
+pIcmpOp = choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList icmpOpMap
+
+pFcmpOp :: P FcmpOp
+pFcmpOp = choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList fcmpOpMap
+
+
+pAliasLinkage :: P Linkage
+pAliasLinkage = choice [ reserved "private" >> return LinkagePrivate
+                       , reserved "internal" >> return LinkageInternal
+                       , reserved "available_externally" >> return LinkageAvailableExternally
+                       , reserved "linkonce" >> return LinkageLinkonce
+                       , reserved "weak" >> return LinkageWeak
+                       , reserved "common" >> return LinkageCommon
+                       , reserved "appending" >> return LinkageAppending
+                       , reserved "extern_weak" >> return LinkageExternWeak
+                       , reserved "linkonce_odr" >> return LinkageLinkonceOdr
+                       , reserved "weak_odr" >> return LinkageWeakOdr
+                       , reserved "external" >> return LinkageExternal
+                       ]
+
+pDllStorageClass :: P DllStorageClass
+pDllStorageClass = choice [ reserved "dllimport" >> return DscImport
+                          , reserved "dllexport" >> return DscExport
+                          ] 
+pThreadLocalStorageClass :: P ThreadLocalStorage                   
+pThreadLocalStorageClass = reserved "thread_local" >> option TlsNone (parens (choice [ reserved "localdynamic" >> return TlsLocalDynamic
+                                                                                     , reserved "initialexec" >> return TlsInitialExec
+                                                                                     , reserved "localexec" >> return TlsLocalExec
+                                                                                     ]
+                                                                             ))
+
+pTailCall :: P TailCall
+pTailCall = choice [ reserved "tail" >> return TcTailCall
+                   , reserved "musttail" >> return TcMustTailCall
+                   ]
+pFunAttr :: P FunAttr
+pFunAttr =  choice [ reserved "alignstack" >> liftM FaAlignStack (parens unsignedInt) -- decimal)
+                   , reserved "alwaysinline" >> return FaAlwaysInline
+                   , reserved "builtin" >> return FaBuiltin
+                   , reserved "cold" >> return FaCold
+                   , reserved "inlinehint" >> return FaInlineHint
+                   , reserved "jumptable" >> return FaJumpTable
+                   , reserved "minsize" >> return FaMinSize
+                   , reserved "naked" >> return FaNaked
+                   , reserved "nobuiltin" >> return FaNoBuiltin
+                   , reserved "noduplicate" >> return FaNoDuplicate
+                   , reserved "noimplicitfloat" >> return FaNoImplicitFloat
+                   , reserved "noinline" >> return FaNoInline
+                   , reserved "nonlazybind" >> return FaNonLazyBind
+                   , reserved "noredzone" >> return FaNoRedZone
+                   , reserved "noreturn" >> return FaNoReturn
+                   , reserved "nounwind" >> return FaNoUnwind
+                   , reserved "optnone" >> return FaOptNone
+                   , reserved "optsize" >> return FaOptSize
+                   , reserved "readnone" >> return FaReadNone
+                   , reserved "readonly" >> return FaReadOnly
+                   , reserved "returns_twice" >> return FaReturnsTwice
+                   , reserved "sanitize_address" >> return FaSanitizeAddress
+                   , reserved "sanitize_memory" >> return FaSanitizeMemory
+                   , reserved "sanitize_thread" >> return FaSanitizeThread
+                   , reserved "ssp" >> return FaSsp
+                   , reserved "sspreq" >> return FaSspReq
+                   , reserved "sspstrong" >> return FaSspStrong
+                   , reserved "uwtable" >> return FaUwTable
+                   , reserved "align" >> liftM FaAlign unsignedInt -- integer
+                   , liftM DqString pQuoteStr >>= \s1 -> opt (symbol "=" >> liftM DqString pQuoteStr) >>= \s2 -> return (FaPair s1 s2)
+                   ]
+
+pCarry :: P TrapFlag
+pCarry = choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList trapFlagMap
+
+
+pAlign :: P Alignment
+pAlign = reserved "align" >> liftM Alignment unsignedInt -- decimal
+
+pComdat :: P Comdat
+pComdat = reserved "comdat" >> liftM Comdat (opt pDollarId)
+
+pNontemporal :: P Nontemporal
+pNontemporal =  char '!' >> reserved "nontemporal" >> char '!' >> liftM Nontemporal unsignedInt -- decimal 
+
+pInvariantLoad :: P InvariantLoad
+pInvariantLoad = char '!' >> reserved "invariant.load" >> char '!' >> liftM InvariantLoad unsignedInt -- decimal
+
+pNonnull :: P Nonnull
+pNonnull = char '!' >> reserved "nonnull" >> char '!' >> liftM Nonnull unsignedInt -- decimal
+
+pSection :: P Section
+pSection =  reserved "section" >> liftM (Section . DqString) pQuoteStr
+
+pSelectionKind :: P SelectionKind
+pSelectionKind = choice $ fmap (\(x, y) -> reserved y >> return x) $ M.toList selectionKindMap 
+
+pAddrSpace :: P AddrSpace
+pAddrSpace = reserved "addrspace" >> liftM (AddrSpace . fromIntegral) (parens decimal)
+             
+pGlobalType :: P GlobalType 
+pGlobalType = choice [ reserved "constant" >> return (GlobalType "constant")
+                     , reserved "global" >> return (GlobalType "global")
+                     ]
+
+pFenceOrder :: P AtomicMemoryOrdering
+pFenceOrder =  choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList atomicMemoryOrderingMap
+
+pAtomicOp :: P AtomicOp
+pAtomicOp = choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList atomicOpMap
+
+pFunAttrCollection :: P [FunAttr] -- Collection          
+pFunAttrCollection = many $ choice [ char '#' >> liftM FaGroup unsignedInt -- decimal
+                                   , pFunAttr
+                                   ]
+
+pTuple2 :: P a -> P b -> P (a, b)
+pTuple2 p1 p2 = do { a1 <- p1
+                   ; ignore comma
+                   ; a2 <- p2
+                   ; return (a1, a2)
+                   }
+
+pTriple3 :: P a -> P b -> P c -> P (a, b, c)
+pTriple3 p1 p2 p3 = do { a1 <- p1
+                       ; ignore comma
+                       ; a2 <- p2
+                       ; ignore comma
+                       ; a3 <- p3
+                       ; return (a1, a2, a3)
+                       }
+
+
+pTuple :: P a -> P (a, a)
+pTuple p = pTuple2 p p
+
+pTriple :: P a -> P (a, a, a)
+pTriple p = pTriple3 p p p
+
+uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d 
+uncurry3 f (a1, b1, c1) = f a1 b1 c1
+    
+                          
+pFastMathFlag :: P FastMathFlag
+pFastMathFlag =  choice $ fmap (\(x,y) -> reserved y >> return x) $ M.toList fastMathFlagMap
+                
+pFastMathFlags :: P FastMathFlags                
+pFastMathFlags = liftM FastMathFlags (many pFastMathFlag)
diff --git a/src/Llvm/Syntax/Parser/Block.hs b/src/Llvm/Syntax/Parser/Block.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/Block.hs
@@ -0,0 +1,26 @@
+{-# OPTIONS_GHC -Wall #-}
+module Llvm.Syntax.Parser.Block where
+import Llvm.Data.Ast
+import Llvm.Syntax.Parser.Basic
+import Llvm.Syntax.Parser.Instruction
+
+-------------------------------------------------------------------------------
+pBlocks :: P [Block]
+pBlocks = try (many block)
+ where
+   block :: P Block
+   block = do { n <- pBlockLabel
+              ; restInsts (Block n) [] []
+              }
+
+restInsts :: ([PhiInstWithDbg] -> [ComputingInstWithDbg] -> TerminatorInstWithDbg -> Block) -> 
+             [PhiInstWithDbg] -> [ComputingInstWithDbg] -> P Block 
+restInsts bf phis insts = do { instOrTerm <- pInstructionWithDbg
+                             ; case instOrTerm of
+                                 InstructionWithDbg (Phi inst) dbgs ->
+                                     restInsts bf ((PhiInstWithDbg inst dbgs):phis) insts
+                                 InstructionWithDbg (Comp inst) dbgs -> 
+                                     restInsts bf phis ((ComputingInstWithDbg inst dbgs):insts)
+                                 InstructionWithDbg (Term x) dbgs -> 
+                                     return $ bf (reverse phis) (reverse insts) (TerminatorInstWithDbg x dbgs)
+                             }
diff --git a/src/Llvm/Syntax/Parser/Const.hs b/src/Llvm/Syntax/Parser/Const.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/Const.hs
@@ -0,0 +1,230 @@
+{-# LANGUAGE GADTs #-}
+module Llvm.Syntax.Parser.Const where
+import Llvm.Data.Ast
+import Llvm.Syntax.Parser.Basic
+import Llvm.Syntax.Parser.Type
+
+
+pConst :: P Const
+pConst = choice [ liftM C_simple pSimpleConstant
+                , liftM C_complex pComplexConstant
+                , pBlockAddr
+                , liftM C_binexp pConstBinaryOperation
+                , liftM C_icmp pConstIcmp
+                , liftM C_fcmp pConstFcmp
+                , liftM C_extractelement pConstExtractElement
+                , liftM C_insertelement pConstInsertElement
+                , liftM C_shufflevector pConstShuffleVector
+                , liftM C_extractvalue pConstExtractValue
+                , liftM C_insertvalue pConstInsertValue
+                , liftM C_select pConstSelect
+                , liftM C_gep pConstGetElemPtr
+                , liftM C_conv pConstConversion
+                ]
+         
+pTypedConst :: P (TypedConstOrNull)
+pTypedConst = do { t <- pType
+                 ; case t of 
+                   (Tprimitive TpNull) -> return UntypedNull
+                   _ -> liftM (TypedConst . Typed t) pConst 
+                 }
+
+pSimpleConstant :: P SimpleConstant
+pSimpleConstant = choice [ pIntOrFloat 
+                         , (reserved "undef" >> return CpUndef) 
+                         , (reserved "null" >> return CpNull) 
+                         , (reserved "false" >> return CpFalse) 
+                         , (reserved "true" >> return CpTrue) 
+                         , (reserved "zeroinitializer" >> return CpZeroInitializer)
+                         , liftM CpGlobalAddr pGlobalId
+                         , (char 'c' >> liftM CpStr pQuoteStr)
+                         ]
+
+
+signedIntStr :: P String
+signedIntStr = do { sign <- option "" (string "-" <|> string "+")
+                  ; n <- numericLit
+                  ; return (sign ++ n)
+                  }
+
+pIntOrFloat :: P SimpleConstant
+pIntOrFloat = lexeme (choice [try k, try u, try s, intOrFloat])
+ where
+   k = do { hd <- string "0x"
+          ; t <- option "" (choice [ string "K", string "M", string "H", string "L"])
+          ; cs <- many1 hexDigit
+          ; return $ CpFloat (hd ++ t ++ cs)
+          }
+   u = do { ignore (string "u0x")
+          ; cs <- many1 hexDigit
+          ; return $ CpUhexInt cs
+          }
+   s = do { ignore (string "s0x")
+          ; cs <- many1 hexDigit
+          ; return $ CpShexInt cs
+          }
+   intOrFloat = do { i <- signedIntStr
+                   ; option (CpInt i) 
+                                (do { ignore (char '.')
+                                    ; ne <- option "" (do { n <- numericLit
+                                                         ; e <- option "" (do { e <- (string "E" <|> string "e")
+                                                                             ; x <- signedIntStr
+                                                                             ; return (e ++ x)
+                                                                             })
+                                                         ; return (n ++ e)
+                                                         })
+                                    ; return $ CpFloat (i ++ "." ++ ne)
+                                    })
+                   }
+
+
+pComplexConstant :: P ComplexConstant
+pComplexConstant = choice [ pConstStruct
+                          , (try pConstVector)
+                          , pPackedStructConst
+                          , pConstArray
+                          ]
+
+pConstStruct :: P ComplexConstant
+pConstStruct = liftM (Cstruct Unpacked) (braces (sepBy pTypedConst comma))
+
+
+
+pPackedStructConst :: P ComplexConstant
+pPackedStructConst = liftM (Cstruct Packed) (anglebraces (sepBy pTypedConst comma))
+                        
+pConstVector :: P ComplexConstant
+pConstVector = liftM Cvector (angles (sepBy pTypedConst comma))
+                  
+pConstArray :: P ComplexConstant
+pConstArray = liftM Carray (brackets (sepBy pTypedConst comma))
+
+
+pBlockAddr :: P Const
+pBlockAddr = reserved "blockaddress" >> parens (pTuple2 pGlobalId pPercentLabel) 
+             >>= return . (uncurry C_blockAddress)
+                
+pConstIbinaryOperation :: P (IbinExpr Const)
+pConstIbinaryOperation = do { op <- pIbinaryOperator
+                            ; l <- many pCarry
+                            ; (tc1, tc2) <- parens (pTuple pTypedConst)
+                            ; return $ IbinExpr op l (getType tc1 tc2) (getConst tc1) (getConst tc2)
+                            }
+                  
+
+pConstFbinaryOperation :: P (FbinExpr Const)
+pConstFbinaryOperation = do { op <- pFbinaryOperator
+                            ; l <- pFastMathFlags
+                            ; (tc1, tc2) <- parens (pTuple pTypedConst)
+                            ; return $ FbinExpr op l (getType tc1 tc2) (getConst tc1) (getConst tc2)
+                            }
+                         
+pConstBinaryOperation :: P (BinExpr Const)                         
+pConstBinaryOperation = choice [liftM Ie pConstIbinaryOperation, liftM Fe pConstFbinaryOperation]
+
+              
+getType :: TypedConstOrNull -> TypedConstOrNull -> Type
+getType (TypedConst (Typed t1 _)) (TypedConst (Typed t2 _)) = if t1 == t2 then t1 
+                                                                     else error "t1 != t2"
+getType UntypedNull (TypedConst (Typed t2 _)) = t2
+getType (TypedConst (Typed t1 _)) UntypedNull = t1
+getType UntypedNull UntypedNull = error "unexpected case"
+
+getConst :: TypedConstOrNull -> Const
+getConst UntypedNull = C_simple CpNull
+getConst (TypedConst (Typed _ c)) = c
+              
+pConstIcmp :: P (Icmp Const) 
+pConstIcmp = do { reserved "icmp"
+                ; op <- pIcmpOp
+                ; (tc1, tc2) <- parens (pTuple pTypedConst)
+                ; return (Icmp op (getType tc1 tc2) (getConst tc1) (getConst tc2))
+                }
+                
+pConstFcmp :: P (Fcmp Const)
+pConstFcmp = do { reserved "fcmp"
+                ; op <- pFcmpOp
+                ; (tc1, tc2) <- parens (pTuple pTypedConst)
+                ; return $ Fcmp op (getType tc1 tc2) (getConst tc1) (getConst tc2)
+                }
+                
+                
+extractTypedConst :: TypedConstOrNull -> Typed Const            
+extractTypedConst (TypedConst x) = x
+extractTypedConst _ = error " error rorooror"
+
+pConstExtractElement :: P (ExtractElement Const)
+pConstExtractElement = reserved "extractelement" >> parens (pTuple pTypedConst) >>= \(x,y) -> return $ ExtractElement (extractTypedConst x) (extractTypedConst y)
+                  
+pConstInsertElement :: P (InsertElement Const)
+pConstInsertElement = do { reserved "insertelement"
+                         ; (tc1, tc2, idx) <- parens (pTriple3 pTypedConst pTypedConst pConst)
+                         ; return $ InsertElement (extractTypedConst tc1) (extractTypedConst tc2) (Typed (Tprimitive $ TpI 32) idx)
+                         }
+
+pConstShuffleVector :: P (ShuffleVector Const)
+pConstShuffleVector = reserved "shufflevector" >> parens (pTriple pTypedConst) >>= \(x,y,z) -> return $  ShuffleVector (extractTypedConst x) (extractTypedConst y) (extractTypedConst z)
+                     
+pConstExtractValue :: P (ExtractValue Const)
+pConstExtractValue = reserved "extractvalue" >> parens (pTuple2 pTypedConst (sepBy unsignedInt comma)) >>= \(x, y) -> return $ ExtractValue (extractTypedConst x) y 
+                        
+pConstInsertValue :: P (InsertValue Const)
+pConstInsertValue = reserved "insertvalue" >> parens (pTriple3 pTypedConst pTypedConst (sepBy unsignedInt comma)) >>= \(x,y,z) -> return $ InsertValue (extractTypedConst x) (extractTypedConst y) z
+                        
+                        
+pConstSelect :: P (Select Const)
+pConstSelect = reserved "select" >> parens (pTriple pTypedConst) >>= \(x,y,z) -> return $ Select (extractTypedConst x) (extractTypedConst y) (extractTypedConst z)
+                  
+pConstConversion :: P (Conversion Const)
+pConstConversion = do { op <- pConvertOp
+                   ; ignore $ chartok '('
+                   ; tc <- pTypedConst
+                   ; reserved "to"
+                   ; t <- pType
+                   ; ignore $ chartok ')'
+                   ; return $ Conversion op (extractTypedConst tc) t
+                   }
+                   
+                   
+pConstGetElemPtr :: P (GetElementPtr Const)
+pConstGetElemPtr = do { reserved "getelementptr"
+                      ; ib <- option (IsNot InBounds) (reserved "inbounds" >> return (Is InBounds))
+                      ; ignore (chartok '(')
+                      ; (Typed t c) <- liftM extractTypedConst pTypedConst
+                      ; idx <- option [] (do { ignore comma
+                                            ; idx <- sepBy pTypedConst comma 
+                                            ; return $ fmap extractTypedConst idx
+                                            })
+                      ; ignore (chartok ')')
+                      ; return $ GetElementPtr ib (Pointer (Typed t c)) idx
+                      }
+                      
+{-
+pTypedConst1 :: P MetaConst -- (TypedConstOrNull)
+pTypedConst1 = do { t <- pType
+                  ; case t of
+                    (Tprimitive TpNull) -> return UntypedNull
+                    _ -> (choice [pConst, liftM CmL pLocalId] >>= return . (TypedConst . Typed t))
+                  }
+
+
+pMetaStruct :: P MetaConst -- [MetaConst] -- Const
+pMetaStruct = liftM McStruct (braces (sepBy pTypedConst1 comma))
+-}
+
+pMetaKindedConst :: P (MetaKindedConst)
+pMetaKindedConst = choice [ reserved "null" >> return UnmetaKindedNull
+                          , liftM2 MetaKindedConst pMetaKind pMetaConst
+                          ]
+
+
+pMetaConst :: P MetaConst
+pMetaConst = choice[ char '!' >> choice [ liftM McStruct (braces (sepBy pMetaKindedConst comma))
+                                        , liftM (McString . DqString) pQuoteStr
+                                        , liftM (McMn . MdNode) intStrToken
+                                        ]
+                    , liftM McSimple pConst
+                    , liftM McRef pLocalId 
+                    ]
+                                
+                    
diff --git a/src/Llvm/Syntax/Parser/DataLayout.hs b/src/Llvm/Syntax/Parser/DataLayout.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/DataLayout.hs
@@ -0,0 +1,93 @@
+module Llvm.Syntax.Parser.DataLayout where
+
+import Llvm.Syntax.Parser.Basic
+import Llvm.Data.Shared.DataLayout
+import Llvm.Data.Shared.AtomicEntity (TargetTriple(..), Arch(..), Vendor(..), Os(..), OsEnv(..))
+
+
+pLayoutSpec :: P LayoutSpec
+pLayoutSpec = choice [ char 'e' >> return (DlE LittleEndian)
+                     , char 'E' >> return (DlE BigEndian)
+                     , try (char 's' >> do { n <- option Nothing (liftM Just unsignedInt)
+                                           ; aa <- option Nothing (colon >> liftM Just unsignedInt)
+                                           ; pa <- option Nothing (colon >> liftM Just unsignedInt)
+                                           ; return (DlLittleS n aa pa)
+                                           })
+                     , char 'p' >> do { as <- option (LayoutAddrSpaceUnspecified) (liftM LayoutAddrSpace unsignedInt)
+                                      ; s <- colon >> liftM SizeInBit unsignedInt
+                                      ; aa <- colon >> liftM (AbiAlign . AlignInBit) unsignedInt
+                                      ; pa <- prefAlign
+                                      ; return (DlP as s aa pa) 
+                                      }
+                     , dlIVF
+                     , char 'a' >> do { s <- opt (liftM SizeInBit unsignedInt)
+                                      ; aa <- colon >> liftM (AbiAlign . AlignInBit) unsignedInt
+                                      ; pa <- prefAlign
+                                      ; return (DlA s aa pa)
+                                      }
+                     , char 'm' >> colon >> liftM DlM (choice [ char 'e' >> return ManglingE
+                                                              , char 'm' >> return ManglingM
+                                                              , char 'o' >> return ManglingO
+                                                              , char 'w' >> return ManglingW
+                                                              ])
+                     , char 'n' >> do { ls <- sepBy1 unsignedInt colon
+                                      ; return (DlN (fmap SizeInBit ls))
+                                      }
+                     , try (symbol "S0" >> return (DlS StackAlignUnspecified))
+                     , char 'S' >> liftM ((DlS . StackAlign . AlignInBit)) unsignedInt
+                     ]
+  where prefAlign = option Nothing (colon >> liftM (Just . PrefAlign . AlignInBit) unsignedInt)
+        dlIVF = do { df <- choice [ char 'i' >> return DlI
+                                  , char 'v' >> return DlV
+                                  , char 'f' >> return DlF
+                                  ]
+                   ; s <- liftM SizeInBit unsignedInt
+                   ; abi <- colon >> liftM (AbiAlign . AlignInBit) unsignedInt
+                   ; pa <- prefAlign
+                   ; return (df s abi pa)
+                   }
+              
+pDataLayout :: P DataLayout
+pDataLayout = liftM DataLayout (sepBy pLayoutSpec (char '-'))
+
+
+pTargetTriple :: P TargetTriple
+pTargetTriple = 
+  do { arch <- choice [ reserved "i386" >> return Arch_i386
+                      , reserved "i686" >> return Arch_i686
+                      , reserved "x86" >> return Arch_x86
+                      , reserved "x86_64" >> return Arch_x86_64
+                      , reserved "powerpc" >> return Arch_PowerPc
+                      , reserved "powerpc64" >> return Arch_PowerPc64
+                      , reserved "arm" >> liftM Arch_Arm pAnyString
+                      , reserved "thumbv7" >> return Arch_ThumbV7
+                      , reserved "mips" >> liftM Arch_Mips pAnyString
+                      , reserved "itanium" >> return Arch_Itanium 
+                      , liftM Arch_String pAnyString
+                      ]
+     ; vendor <- option Nothing (char '-' >> liftM Just
+                                 (choice [ reserved "pc" >> return Vendor_Pc
+                                         , reserved "apple" >> return Vendor_Apple
+                                         , reserved "unknown" >> return Vendor_Unknown
+                                         , liftM Vendor_String pAnyString
+                                         ]))
+     ; os <- option Nothing (char '-' >> liftM Just
+                             (choice [ reserved "linux" >> return Os_Linux
+                                     , reserved "windows" >> return Os_Windows
+                                     , reserved "win32" >> return Os_Win32
+                                     , reserved "mingw32" >> return Os_Mingw32
+                                     , reserved "unknown" >> return Os_Unknown
+                                     , reserved "darwin" >> liftM Os_Darwin pAnyString
+                                     , string "freebsd" >> liftM Os_FreeBsd pAnyString
+                                     , string "macosx" >> liftM Os_Macosx pAnyString
+                                     , string "ios" >> liftM Os_Ios pAnyString
+                                     , liftM Os_String pAnyString
+                                     ]))
+     ; env <- option Nothing (char '-' >> liftM Just (choice [ reserved "gnu" >> return OsEnv_Gnu
+                                                             , liftM OsEnv_String pAnyString
+                                                             ]))
+     ; return $ TargetTriple arch vendor os env
+     }
+  where 
+    pAnyString :: P String
+    pAnyString = (manyTill anyChar (lookAhead $ choice [char '"', char '-']))
diff --git a/src/Llvm/Syntax/Parser/Instruction.hs b/src/Llvm/Syntax/Parser/Instruction.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/Instruction.hs
@@ -0,0 +1,109 @@
+{-# OPTIONS_GHC -Wall #-}
+module Llvm.Syntax.Parser.Instruction where
+import Llvm.Data.Ast
+import Llvm.Syntax.Parser.Basic
+import Llvm.Syntax.Parser.Const
+import Llvm.Syntax.Parser.Type
+import Llvm.Syntax.Parser.Rhs
+
+pTerminatorInst :: P TerminatorInst
+pTerminatorInst = choice [ pRet
+                         , pBr
+                         , pSwitch
+                         , reserved "indirectbr" >> liftM (uncurry IndirectBr)
+                           (pTuple2 pTypedValue (brackets (sepBy pTargetLabel comma)))
+                         , reserved "unreachable" >> return Unreachable
+                         , reserved "resume" >> liftM Resume pTypedValue
+                         ]
+                  <?> "control instruction"
+
+pRet :: P TerminatorInst
+pRet = do { reserved "ret"
+          ; t <- pType
+          ; case t of
+              Tvoid -> return RetVoid
+              _  -> do { v <- pValue
+                       ; option (Return $ [Typed t v])
+                         (do { ls <- many (try (comma >> pTypedValue))
+                             ; return (Return ((Typed t v):ls))
+                             }
+                         )
+                       }
+          }
+
+
+
+pSwitch :: P TerminatorInst
+pSwitch = do { reserved "switch"
+             ; (tv,l) <- tvl
+             ; arms <- brackets (many tvl)
+             ; return $ Switch tv l arms
+             }
+ where
+   tvl = pTuple2 pTypedValue pTargetLabel
+
+
+pBr :: P TerminatorInst
+pBr = reserved "br" >> choice [ reserved "label" >> liftM (Br . TargetLabel) pPercentLabel
+                              , reserved "i1" >> liftM (uncurry3 Cbr) (pTriple3 pValue pTargetLabel pTargetLabel)
+                              ]
+
+
+data Instruction = Comp ComputingInst
+                 | Term TerminatorInst
+                 | Phi PhiInst
+
+data InstructionWithDbg = InstructionWithDbg Instruction [Dbg]
+
+pInstruction :: P Instruction
+pInstruction = do { lhs <- opt (do { x <- pLocalId
+                                   ; ignore (chartok '=')
+                                   ; return x
+                                   })
+                  ; choice [ try $ liftM Term $ pInvoke lhs
+                           , liftM Comp $ pComputingInst lhs
+                           , liftM Term pTerminatorInst
+                           , liftM Phi $ pPhiInst lhs
+                           ]
+                  }
+
+pDbg :: P Dbg
+pDbg = do { x <- pMdVar
+          ; mc <- pMetaConst
+          ; return $ Dbg x mc
+          }
+
+pInstructionWithDbg :: P InstructionWithDbg
+pInstructionWithDbg  = do { ins <- pInstruction
+                          ; l <- many (comma >> pDbg)
+                          ; return $ InstructionWithDbg ins l
+                          }
+
+
+
+pComputingInst ::  Maybe LocalId -> P ComputingInst
+pComputingInst lhs = do { rhs <- pRhs
+                        ; return $ ComputingInst lhs rhs
+                        }
+
+
+pInvoke :: Maybe LocalId -> P TerminatorInst
+pInvoke lhs = do { reserved "invoke"
+                 ; callSite <- pCallSite
+                 ; reserved "to"
+                 ; toLbl <- pTargetLabel
+                 ; reserved "unwind"
+                 ; unwindLbl <- pTargetLabel
+                 ; return $ Invoke lhs callSite toLbl unwindLbl
+                 }
+
+
+pPhiInst :: Maybe LocalId -> P PhiInst
+pPhiInst lhsOpt = do { reserved "phi"
+                     ; t <- pType
+                     ; one <- pair
+                     ; ls <- many (try (comma >> pair))
+                     ; return $ PhiInst lhsOpt t (one:ls)
+                     }
+  where pair = brackets (pTuple2 pValue pPercentLabel)
+
diff --git a/src/Llvm/Syntax/Parser/Module.hs b/src/Llvm/Syntax/Parser/Module.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/Module.hs
@@ -0,0 +1,224 @@
+module Llvm.Syntax.Parser.Module where
+import Llvm.Data.Ast
+import Llvm.Syntax.Parser.Basic
+import Llvm.Syntax.Parser.Type
+import Llvm.Syntax.Parser.Block
+import Llvm.Syntax.Parser.Const
+import Llvm.Syntax.Parser.Rhs
+import Llvm.Syntax.Parser.DataLayout
+
+
+pModule :: P Module
+pModule = do { l <- many toplevel
+             ; eof 
+             ; return $ Module l
+             }
+
+toplevel :: P Toplevel
+toplevel = choice [ try pNamedGlobal 
+                  , try pToplevelTypeDef
+                  , try pToplevelTarget
+                  , try pToplevelDepLibs
+                  , try pToplevelDeclare
+                  , try pToplevelDefine
+                  , pToplevelModuleAsm
+                  , pToplevelAttributeGroup
+                  , pToplevelComdat
+                  , pStandaloneMd
+                  ]
+
+
+-- GlobalVar '=' OptionalVisibility ALIAS ...
+-- GlobalVar '=' OptionalLinkage OptionalVisibility ... -> global variable
+pNamedGlobal :: P Toplevel
+pNamedGlobal = do { lhsOpt <- opt (pGlobalId >>= \x->chartok '=' >> return x)
+                  ; linkOpt <- opt pLinkage -- (choice [try pExternalLinkage, pLinkage])
+                  ; vis <- opt pVisibility
+                  ; dllStorage <- opt pDllStorageClass
+                  ; tlm <- opt pThreadLocalStorageClass
+                  ; na <- option NamedAddr (reserved "unnamed_addr" >> return UnnamedAddr)
+                  ; hasAlias <- option False (reserved "alias" >> return True)
+                  ; case (lhsOpt, linkOpt, hasAlias) of
+                    (Just lhs, Nothing, True) -> pAlias lhs vis dllStorage tlm na
+                    (_, _, False) -> pGlobal lhsOpt linkOpt vis dllStorage tlm na
+                  }
+
+-- ParseAlias:
+--   ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee
+-- Aliasee
+--   ::= TypeAndValue
+--   ::= 'bitcast' '(' TypeAndValue 'to' Type ')'
+--   ::= 'getelementptr' 'inbounds'? '(' ... ')'
+--
+-- Everything through visibility has already been parsed.
+--
+pAlias :: GlobalId -> Maybe Visibility -> Maybe DllStorageClass -> Maybe ThreadLocalStorage -> AddrNaming -> P Toplevel
+pAlias lhs vis dll tlm na = do { link <- option Nothing (liftM Just pAliasLinkage)
+                               ; aliasee <- pAliasee
+                               ; return $ ToplevelAlias (TlAlias lhs vis dll tlm na link aliasee)
+                               }
+    where pAliasee = 
+            choice [ liftM AtV pTypedValue
+                   , liftM Ac pConstConversion
+                   , liftM AgEp pConstGetElemPtr
+                   ]
+
+
+-- ParseGlobal
+--   ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal
+--       OptionalAddrSpace GlobalType Type Const
+--   ::= OptionalLinkage OptionalVisibility OptionalThreadLocal
+--       OptionalAddrSpace GlobalType Type Const
+--
+-- Everything through visibility has been parsed already.
+--
+pGlobal :: Maybe GlobalId -> Maybe Linkage -> Maybe Visibility -> Maybe DllStorageClass -> Maybe ThreadLocalStorage -> AddrNaming ->  P Toplevel
+pGlobal lhs link vis dll tls na = 
+  do { addrOpt <- opt pAddrSpace
+     ; exti <- option (IsNot ExternallyInitialized) (reserved "externally_initialized" >> return (Is ExternallyInitialized))
+     ; globalOpt <- pGlobalType
+     ; t <- pType
+     ; c <- if (hasInit link) then liftM Just pConst
+            else return Nothing
+     ; (s,cd,a) <- permute ((,,) <$?> (Nothing, try (comma >> liftM Just pSection))
+                            <|?> (Nothing, try (comma >> liftM Just pComdat))
+                            <|?> (Nothing, try (comma >> liftM Just pAlign))
+                           )
+     ; return $ ToplevelGlobal (TlGlobal lhs link vis dll tls na addrOpt exti
+                                globalOpt t c s cd a)
+     }
+  where hasInit x = case x of 
+          Just(LinkageExternWeak) -> False
+          Just(LinkageExternal) -> False
+          -- Just(DllImport) -> False
+          Just(_) -> True
+          Nothing -> True
+
+data LocalIdOrQuoteStr = L LocalId | Q DqString deriving (Eq,Show)
+
+pLhsType :: P LocalIdOrQuoteStr 
+pLhsType = do { lhs <- choice [ liftM L pLocalId
+                              , liftM (Q . DqString) pQuoteStr
+                              ] 
+              ; ignore (chartok '=')
+              ; reserved "type"              
+              ; return lhs
+              }
+           
+pToplevelTypeDef :: P Toplevel           
+pToplevelTypeDef = do { lhsOpt <- opt pLhsType
+                      ; case lhsOpt of
+                        Nothing -> liftM (ToplevelUnamedType . (TlUnamedType 1)) pType
+                        Just (L x) -> liftM (ToplevelTypeDef . (TlTypeDef x)) pType
+                        Just (Q _) -> error "irrefutable"
+                      }
+
+pToplevelTarget :: P Toplevel
+pToplevelTarget = do { reserved "target"
+                     ; choice [ do { reserved "triple"  
+                                   ; ignore $ chartok '=' 
+                                   ; tt <- lexeme (between (char '"') (char '"') pTargetTriple)
+                                   ; return $ ToplevelTriple (TlTriple tt)
+                                   }
+                              , do { reserved "datalayout" 
+                                   ; ignore $ chartok '='
+                                   ; ls <- lexeme (between (char '"') (char '"') pDataLayout) 
+                                   ; return $ ToplevelDataLayout (TlDataLayout ls) 
+                                   }
+                              ]
+                     }
+
+pToplevelDepLibs :: P Toplevel
+pToplevelDepLibs = do { reserved "deplibs"
+                      ; ignore (chartok '=')
+                      ; l <- brackets (sepBy pQuoteStr comma)
+                      ; return $ ToplevelDepLibs (TlDepLibs (fmap DqString l))
+                      }
+
+                     
+pFunctionPrototype :: P FunctionPrototype
+pFunctionPrototype = do { lopt <- opt pLinkage
+                        ; vopt <- opt pVisibility
+                        ; dllopt <- opt pDllStorageClass
+                        ; copt <- opt pCallConv
+                        ; as <- many pParamAttr
+                        ; ret <- pType
+                        ; name <- pGlobalId
+                        ; params <- pFormalParamList
+                        ; unnamed <- opt (reserved "unnamed_addr" >> return UnnamedAddr)
+                        ; attrs <- pFunAttrCollection
+                        ; sopt <- opt pSection
+                        ; cdopt <- opt pComdat
+                        ; aopt <- opt pAlign
+                        ; gopt <- opt (liftM (Gc . DqString) (reserved "gc" >> pQuoteStr))
+                        ; prefixOpt <- opt pPrefix
+                        ; prologueOpt <- opt pPrologue
+                        ; return (FunctionPrototype lopt vopt dllopt copt 
+                                  as ret name params unnamed attrs sopt cdopt aopt gopt 
+                                  prefixOpt prologueOpt)
+                        }
+                                          
+pPrefix :: P Prefix                     
+pPrefix = reserved "prefix" >> liftM Prefix pTypedConst
+
+pPrologue :: P Prologue
+pPrologue = reserved "prologue" >> liftM Prologue pTypedConst
+
+pToplevelDefine :: P Toplevel
+pToplevelDefine = do { reserved "define"
+                     ; fh <- pFunctionPrototype
+                     ; bs <- braces pBlocks
+                     ; return $ ToplevelDefine (TlDefine fh bs)
+                     }
+                  
+pToplevelAttributeGroup :: P Toplevel                  
+pToplevelAttributeGroup = do { reserved "attributes" 
+                             ; ignore (char '#')
+                             ; n <- unsignedInt -- decimal
+                             ; ignore (chartok '=')
+                             ; l <- braces $ many pFunAttr
+                             ; return $ ToplevelAttribute (TlAttribute n l)
+                             }
+                  
+pToplevelDeclare :: P Toplevel                  
+pToplevelDeclare = liftM ToplevelDeclare 
+                   (reserved "declare" >> liftM TlDeclare pFunctionPrototype)
+
+pToplevelModuleAsm :: P Toplevel
+pToplevelModuleAsm = do { reserved "module"
+                        ; reserved "asm"
+                        ; s <- pQuoteStr
+                        ; return $ ToplevelModuleAsm (TlModuleAsm (DqString s))
+                        }
+                     
+
+pToplevelComdat :: P Toplevel
+pToplevelComdat = do { l <- pDollarId
+                     ; ignore (chartok '=')
+                     ; reserved "comdat"
+                     ; s <- pSelectionKind
+                     ; return $ ToplevelComdat (TlComdat l s)
+                     }
+
+pMdNode :: P MdNode
+pMdNode = (char '!' >> liftM MdNode intStrToken)
+
+pStandaloneMd :: P Toplevel
+pStandaloneMd = do { ignore (char '!')
+                   ; choice [ do { n <- intStrToken
+                                 ; ignore (chartok '=')
+                                 ; choice [ do { t <- pMetaKindedConst -- Tmetadata
+                                               ; return (ToplevelStandaloneMd (TlStandaloneMd n t))
+                                               }
+                                          ]
+                                 }
+                            , do { i <- lexeme pId
+                                 ; ignore (chartok '=')
+                                 ; ignore (lexeme (string "!{"))
+                                 ; l <- sepBy pMdNode comma 
+                                 ; ignore (chartok '}')
+                                 ; return $ ToplevelNamedMd (TlNamedMd (MdVar i) l)
+                                 }
+                            ]
+                   }
+                   
diff --git a/src/Llvm/Syntax/Parser/Rhs.hs b/src/Llvm/Syntax/Parser/Rhs.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/Rhs.hs
@@ -0,0 +1,326 @@
+{-# LANGUAGE GADTs #-}
+module Llvm.Syntax.Parser.Rhs where
+import Llvm.Data.Ast
+import Llvm.Syntax.Parser.Basic
+import Llvm.Syntax.Parser.Type
+import Llvm.Syntax.Parser.Const
+
+
+pTmetadata :: P MetaConst
+pTmetadata = do { reserved "metadata" 
+                ; mc <- pMetaConst
+                ; return mc
+                }
+
+pTypedValue :: P (Typed Value)
+pTypedValue = liftM2 Typed pType pValue
+
+pValue :: P Value
+pValue = choice [ (liftM Val_const pConst)
+                , (liftM Val_local pLocalId) 
+                ]
+
+
+pTypedPointer :: P (Pointer (Typed Value))
+pTypedPointer = do { t <- pType
+                   ; v <- pValue
+                   ; return (Pointer (Typed t v))
+                   }
+                
+pAllocate :: P MemOp
+pAllocate = do { reserved "alloca"
+               ; ina <- option (IsNot InAllocaAttr) (reserved "inalloca" >> return (Is InAllocaAttr))
+               ; t <- pType 
+               ; n <- opt (comma >> pTypedValue)
+               ; a <- opt (comma >> pAlign)
+               ; return $ Alloca ina t n a
+               }
+
+pLoad :: P MemOp
+pLoad = do { reserved "load"
+           ; at <- option False (reserved "atomic" >> return True)
+           ; b <- option (IsNot Volatile) (reserved "volatile" >> return (Is Volatile))
+           ; tv <- pTypedPointer
+           ; if at then
+               do { st <- option (IsNot SingleThread) (reserved "singlethread" >> return (Is SingleThread))
+                  ; ord <- pFenceOrder
+                  ; a <- optCommaSep pAlign
+                  ; return $ LoadAtomic (Atomicity st ord) b tv a
+                  }
+             else
+               do { a <- optCommaSep pAlign
+                  ; nt <- optCommaSep pNontemporal
+                  ; inv <- optCommaSep pInvariantLoad
+                  ; nn <- optCommaSep pNonnull
+                  ; return $ Load b tv a nt inv nn
+                  }
+           }
+        
+pStore :: P MemOp
+pStore = do { reserved "store"
+            ; at <- option False (reserved "atomic" >> return True)
+            ; b <- option (IsNot Volatile) (reserved "volatile" >> return (Is Volatile))
+            ; tv <- pTypedValue
+            ; ignore comma
+            ; ptr <- pTypedPointer
+            ; if at then 
+                do { st <- option (IsNot SingleThread) (reserved "singlethread" >> return (Is SingleThread))
+                   ; ord <- pFenceOrder
+                   ; a <- optCommaSep pAlign
+                   ; return $ StoreAtomic (Atomicity st ord) b tv ptr a 
+                   }
+              else
+                do { a <- optCommaSep pAlign
+                   ; nt <- optCommaSep pNontemporal
+                   ; return $ Store b tv ptr a nt
+                   }
+            }
+         
+         
+pFence :: P MemOp
+pFence = do { reserved "fence"
+            ; st <- option (IsNot SingleThread) (reserved "singlethread" >> return (Is SingleThread))
+            ; ordering <- pFenceOrder
+            ; return $ Fence st ordering
+            }
+   
+pCmpXchg :: P MemOp
+pCmpXchg = do { reserved "cmpxchg"
+              ; wk <- option (IsNot Weak) (reserved "weak" >> return (Is Weak))
+              ; v <- option (IsNot Volatile) (reserved "volatile" >> return (Is Volatile))
+              ; p <- pTypedPointer
+              ; ignore comma
+              ; (c, n) <- pTuple pTypedValue
+              ; st <- option (IsNot SingleThread) (reserved "singlethread" >> return (Is SingleThread))
+              ; sord <- pFenceOrder
+              ; ford <- pFenceOrder
+              ; return $ CmpXchg wk v p c n st sord ford
+              }
+           
+pAtomicRmw :: P MemOp
+pAtomicRmw = do { reserved "atomicrmw"
+                ; v <- option (IsNot Volatile) (reserved "volatile" >> return (Is Volatile))
+                ; op <- pAtomicOp
+                ; p <- pTypedPointer
+                ; ignore comma
+                ; vl <- pTypedValue
+                ; st <- option (IsNot SingleThread) (reserved "singlethread" >> return (Is SingleThread))
+                ; ord <- pFenceOrder
+                ; return $ AtomicRmw v op p vl st ord
+                }    
+
+     
+          
+
+pMemOp :: P MemOp
+pMemOp = choice [ pAllocate
+                , pLoad
+                , pStore
+                , pFence
+                , pCmpXchg
+                , pAtomicRmw
+                ]
+
+
+pExpr :: P Expr 
+pExpr = choice [ liftM Eb pBinaryOperation
+               , liftM EiC pIcmp
+               , liftM EfC pFcmp        
+               , liftM Es pSelect
+               , liftM Ec pConversion
+               , liftM EgEp pGetElemPtr
+               ]
+
+pIbinaryOperation :: P (IbinExpr Value)
+pIbinaryOperation = do { op <- pIbinaryOperator
+                       ; l <- many pCarry
+                       ; t <- pType
+                       ; (v1, v2) <- pTuple pValue
+                       ; return $ IbinExpr op l t v1 v2
+                       }
+
+pFbinaryOperation :: P (FbinExpr Value)
+pFbinaryOperation = do { op <- pFbinaryOperator
+                       ; l <- pFastMathFlags 
+                       ; t <- pType
+                       ; (v1, v2) <- pTuple pValue
+                       ; return $ FbinExpr op l t v1 v2
+                       }
+                    
+pBinaryOperation :: P (BinExpr Value)                    
+pBinaryOperation = choice [ liftM Ie pIbinaryOperation, liftM Fe pFbinaryOperation]
+
+              
+pIcmp :: P (Icmp Value)
+pIcmp = do { reserved "icmp"
+           ; op <- pIcmpOp
+           ; t <- pType
+           ; (v1, v2) <- pTuple pValue
+           ; return (Icmp op t v1 v2)
+           }
+
+pFcmp :: P (Fcmp Value)
+pFcmp = do { reserved "fcmp"
+           ; op <- pFcmpOp
+           ; t <- pType
+           ; (v1, v2) <- pTuple pValue
+           ; return $ Fcmp op t v1 v2
+           }
+                
+                
+
+                        
+pSelect :: P (Select Value)
+pSelect = do { reserved "select"
+             ; t <- pSelTy
+             ; v <- pValue
+             ; ignore comma
+             ; (tv2, tv3) <- pTuple pTypedValue
+             ; return $ Select (Typed t v) tv2 tv3
+             }
+
+pConversion :: P (Conversion Value)
+pConversion = do { op <- pConvertOp
+              ; tv <- pTypedValue
+              ; reserved "to"
+              ; t <- pType
+              ; return $ Conversion op tv t
+              }
+
+pGetElemPtr :: P (GetElementPtr Value)
+pGetElemPtr = do { reserved "getelementptr"
+                 ; ib <- option (IsNot InBounds) (reserved "inbounds" >> return (Is InBounds))
+                 ; tc1 <- pTypedPointer -- AddrValue
+                 ; idx <- many (try (comma >> pTypedValue))
+                 ; return $ GetElementPtr ib tc1 idx
+                 }
+
+pExtractElement :: P (ExtractElement Value)
+pExtractElement = reserved "extractelement" >> pTuple pTypedValue >>= return . (uncurry ExtractElement)
+
+pInsertElement :: P (InsertElement Value)
+pInsertElement = reserved "insertelement" >> pTriple pTypedValue >>= return . (uncurry3 InsertElement)
+
+pShuffleVector :: P (ShuffleVector Value)
+pShuffleVector = reserved "shufflevector" >> pTriple pTypedValue >>= return . (uncurry3 ShuffleVector)
+                     
+pExtractValue :: P (ExtractValue Value)
+pExtractValue = do { reserved "extractvalue"
+                   ; tc1 <- pTypedValue
+                   ; ls <- many (try (comma >> unsignedInt))
+                   ; return $ ExtractValue tc1 ls
+                   }
+
+pInsertValue :: P (InsertValue Value)
+pInsertValue = do { reserved "insertvalue"
+                  ; (tv1, tv2) <- pTuple pTypedValue
+                  ; ls <- many (try (comma >> unsignedInt))
+                  ; return $ InsertValue tv1 tv2 ls
+                  }
+                  
+               
+pVaArg :: P Rhs
+pVaArg = reserved "va_arg" >> pTuple2 pTypedValue pType >>= return . (RvA . uncurry VaArg)
+         
+              
+pCallFun :: P CallSite
+pCallFun = do { cc <- opt pCallConv
+              ; atts0 <- many pParamAttr
+              ; t <- pType
+              ; i <- choice [ liftM FunNameString (choice [symbol "null", symbol "undef"])
+                            , liftM FunNameGlobal pGlobalOrLocalId
+                            ]
+              ; params <- parens (sepBy pActualParam comma)
+              ; atts1 <- pFunAttrCollection
+              ; return (CsFun cc atts0 t i params atts1)
+              }
+
+pCallAsm :: P CallSite
+pCallAsm = do { t <- pType
+              ; reserved "asm"
+              ; se <- opt (reserved "sideeffect" >> return SideEffect)
+              ; as <- opt (reserved "alignstack" >> return AlignStack)
+              ; dialect <- option AsmDialectAtt (reserved "inteldialect" >> return AsmDialectIntel)
+              ; (s1, s2) <- pTuple pQuoteStr
+              ; params <- parens (sepBy pActualParam comma)
+              ; atts1 <- pFunAttrCollection
+              ; return (CsAsm t se as dialect (DqString s1) (DqString s2) params atts1)
+              }
+
+pCallConversion :: P (CallSite)
+pCallConversion = do { a <- many pParamAttr
+                     ; t <- pType
+                     ; convert <- pConstConversion
+                     ; params <- parens (sepBy pActualParam comma)
+                     ; atts1 <- pFunAttrCollection
+                     ; return (CsConversion a t convert params atts1)
+                     }
+
+pCallSite :: P CallSite
+pCallSite = choice [ try pCallFun
+                   , try pCallAsm
+                   , pCallConversion
+                   ]
+         
+pCall :: P Rhs
+pCall = do { tl <- option TcNon pTailCall 
+           ; reserved "call"
+           ; liftM (Call tl) pCallSite
+           }
+
+pActualParam :: P ActualParam
+pActualParam = choice [do { t <- pType
+                          ; atts0 <- many pParamAttr
+                          ; a <- opt pAlign
+                          ; v <- pValue
+                          ; atts1 <- many pParamAttr
+                          ; return $ ActualParamData t atts0 a v atts1
+                          }
+                      ,liftM ActualParamMeta pMetaKindedConst
+                      ]
+                  
+pRhs :: P Rhs
+pRhs = choice [ liftM Re pExpr
+              , liftM RmO pMemOp
+              , liftM ReE pExtractElement
+              , liftM RiE pInsertElement
+              , liftM RsV pShuffleVector
+              , liftM ReV pExtractValue
+              , liftM RiV pInsertValue
+              , pVaArg
+              , pCall
+              , pLandingPad
+              ]
+       
+       
+
+
+pPersFn :: P PersFn
+pPersFn = choice [ liftM PersFnId pGlobalOrLocalId
+                 , do { op <- pConvertOp
+                      ; ignore (chartok '(')
+                      ; ot <- pType
+                      ; ix <- pGlobalOrLocalId
+                      ; reserved "to"
+                      ; dt <- pType
+                      ; ignore (chartok ')')
+                      ; return $ PersFnCast (Conversion op (Typed ot ix) dt)
+                      }
+                 , reserved "undef" >> return PersFnUndef
+                 , reserved "null" >> return PersFnNull
+                 , liftM PersFnConst pConst
+                 ]
+          
+pLandingPad :: P Rhs
+pLandingPad = do { reserved "landingpad"
+                 ; rt <- pType
+                 ; reserved "personality"
+                 ; ft <- pType
+                 ; ix <- pPersFn
+                 ; cl <- option Nothing (reserved "cleanup" >> return (Just Cleanup))
+                 ; c <- many pClause
+                 ; return $ RlP $ LandingPad rt ft ix cl c
+                 }
+    where pClause = choice [ reserved "catch" >> liftM Catch pTypedValue
+                           , reserved "filter" >> liftM Filter pTypedConst
+                           ]
diff --git a/src/Llvm/Syntax/Parser/Type.hs b/src/Llvm/Syntax/Parser/Type.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Parser/Type.hs
@@ -0,0 +1,153 @@
+module Llvm.Syntax.Parser.Type where
+import Llvm.Data.Ast
+import Llvm.Syntax.Parser.Basic
+
+
+pType :: P Type
+pType =
+    do { t <- choice [ try (liftM Tprimitive pPrimType)
+                     , pTypeName
+                     --, upref
+                     , array
+                     , try pstruct
+                     , vector
+                     , struct
+                     , pOther 
+                     ]
+       ; post t
+       }
+ where
+--   upref    = chartok '\\' >> liftM TupRef decimal
+   array    = brackets (avbody Tarray)
+   vector   = angles (avbody Tvector)
+   avbody f = do { n <- lexeme unsignedInt -- decimal
+                 ; ignore $ chartok 'x'
+                 ; t <- pType
+                 ; return (f n t)
+                 }
+   struct   = liftM (Tstruct Unpacked) (braces (sepBy pType comma))
+   pstruct  = do { ignore $ symbol "<{"
+                 ; v <- sepBy pType comma
+                 ; ignore $ symbol "}>"
+                 ; return (Tstruct Packed v)
+                 }
+   pOther = choice [ reserved "opaque" >> return Topaque
+                   , reserved "void" >> return Tvoid
+                   ]
+
+
+castTypeToMetaKind :: Type -> MetaKind
+castTypeToMetaKind t = Mtype t                       
+
+
+pMetaKind :: P MetaKind
+pMetaKind = choice [ try (liftM castTypeToMetaKind pType)
+                   , reserved "metadata" >> return Mmetadata
+                   ]
+
+pTypeName :: P Type
+pTypeName = do { x <- pLocalId 
+               ; case x of 
+                 LocalIdNum n -> return $ Tno n
+                 LocalIdAlphaNum s -> return $ Tname s
+                 LocalIdDqString s -> return $ TquoteName s
+               }
+
+
+pStar :: P AddrSpace
+pStar = option AddrSpaceUnspecified pAddrSpace >>= \x -> chartok '*' >> return x
+
+post :: Type -> P Type
+post t = do { pt <- option t (pStar >>= \x -> post (Tpointer t x))
+            ; option pt $ do { fp <- pTypeParamList
+                             ; fattrs <- many pFunAttr
+                             ; post (Tfunction pt fp fattrs)
+                             }
+            }
+
+pTypeI :: P TypePrimitive
+pTypeI = (char 'i' >> liftM TpI unsignedInt)
+
+pTypeF :: P TypePrimitive
+pTypeF = (char 'f' >> liftM TpF unsignedInt)
+
+pTypeV :: P TypePrimitive
+pTypeV = (char 'v' >> liftM TpV unsignedInt)
+
+
+pPrimType :: P TypePrimitive
+pPrimType = choice [ try pTypeI
+                   , reserved "half"      >> return TpHalf
+                   , reserved "float"     >> return TpFloat
+                   , reserved "fp128"     >> return TpFp128
+                   , pTypeF
+                   , reserved "label"     >> return TpLabel
+                   , reserved "double"    >> return TpDouble
+                   , reserved "x86_fp80"  >> return TpX86Fp80
+                   , reserved "x86_mmx"   >> return TpX86Mmx
+                   , reserved "ppc_fp128" >> return TpPpcFp128
+                   , pTypeV
+                   , reserved "null" >> return TpNull
+                   ]
+            
+            
+pTypeParamList :: P TypeParamList
+pTypeParamList = do { ignore $ chartok '('
+                    ; (l, f) <- args []
+                    ; return $ TypeParamList l f
+                    }
+ where
+   args :: [Type] -> P ([Type], Maybe VarArgParam)
+   args l =  choice [ do { p <- pType
+                         ; let l' = p:l
+                         ; choice [ comma >> args l'
+                                  , chartok ')' >> return (reverse l', Nothing)
+                                  ]
+                         }
+                    , symbol "..." >> chartok ')' >> return (reverse l, Just VarArgParam)
+                    , chartok ')' >> return (reverse l, Nothing)
+                    ]
+  
+
+pFormalParamList :: P FormalParamList
+pFormalParamList = do { ignore $ chartok '('
+                      ; (l, f) <- args []
+                      ; funAttrs <- many pFunAttr
+                      ; return $ FormalParamList l f funAttrs
+                      }
+ where
+   args :: [FormalParam] -> P ([FormalParam], Maybe VarArgParam)
+   args l =  choice [ do { p <- param
+                         ; let l' = p:l
+                         ; choice [ comma >> args l'
+                                  , chartok ')' >> return (reverse l', Nothing)
+                                  ]
+                         }
+                    , symbol "..." >> chartok ')' >> return (reverse l, Just VarArgParam)
+                    , chartok ')' >> return (reverse l, Nothing)
+                    ]
+    where
+        param = choice [do { at <- pType
+                           ; ar1 <- many pParamAttr
+                           ; an <- opt pAlign
+                           ; lv <- opt pLocalId
+                           ; let lv' = maybe FimplicitParam FexplicitParam lv 
+                           ; ar2 <- many pParamAttr
+                           ; return $ FormalParamData at  ar1 an lv' ar2
+                           }
+                       , do { mt <- pMetaKind
+                            ; lv <- opt pLocalId
+                            ; let lv1 = maybe FimplicitParam FexplicitParam lv
+                            ; return $ FormalParamMeta mt lv1
+                            }
+                       ]
+
+pSelTy :: P Type
+pSelTy = choice [ reserved "i1" >> return (Tprimitive $ TpI 1)
+                , angles $ do { n <- unsignedInt -- decimal
+                              ; ignore $ chartok 'x'
+                              ; reserved "i1"
+                              ; return $ Tvector n (Tprimitive $ TpI 1)
+                              }
+                , pTypeName
+                ]
diff --git a/src/Llvm/Syntax/Printer/Common.hs b/src/Llvm/Syntax/Printer/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Printer/Common.hs
@@ -0,0 +1,23 @@
+module Llvm.Syntax.Printer.Common 
+       (module Llvm.Syntax.Printer.Common
+       ,module Text.PrettyPrint
+       )
+       where
+
+import Text.PrettyPrint
+import Data.Monoid (mempty)
+import qualified Data.Map as M(Map, foldWithKey) 
+
+
+angleBrackets :: Doc -> Doc  
+angleBrackets x = char '<' <> x <> char '>'
+
+commaSepList :: [Doc] -> Doc
+commaSepList l = hsep $ punctuate comma l
+
+commaSepNonEmpty :: [Doc] -> Doc
+commaSepNonEmpty l = commaSepList (filter (not . isEmpty) l)
+
+sepMaybe :: (a -> Doc) -> (Doc -> Doc) -> Maybe a -> Doc
+sepMaybe f _  (Nothing) = empty
+sepMaybe f sep (Just x) = sep $ f x
diff --git a/src/Llvm/Syntax/Printer/IrPrint.hs b/src/Llvm/Syntax/Printer/IrPrint.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Printer/IrPrint.hs
@@ -0,0 +1,1041 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+module Llvm.Syntax.Printer.IrPrint 
+       (module Llvm.Syntax.Printer.IrPrint
+       ,module Llvm.Syntax.Printer.Common
+       ) where
+
+import Llvm.Data.Ir
+import Llvm.Query.IrCxt
+
+import Llvm.Syntax.Printer.Common
+import Llvm.Syntax.Printer.SharedEntityPrint (integral)
+import qualified Llvm.Syntax.Printer.SharedEntityPrint as P
+import qualified Compiler.Hoopl as H
+import qualified Data.Map as M (Map, toList)
+import qualified Data.Set as S (Set, toList)
+
+class IrPrint a where
+  printIr :: a -> Doc
+  
+instance IrPrint v => IrPrint (H.LabelMap v) where
+  printIr lm = let ls = H.mapToList lm
+               in vcat $ fmap (\(k,v) -> printIr k <+> text "::=>" <+> printIr v) ls
+  
+instance (IrPrint t1, IrPrint t2) => IrPrint (t1, t2) where
+  printIr (v1, v2) = parens (printIr v1 <> comma <+> printIr v2)
+  
+instance IrPrint x => IrPrint [x] where  
+  printIr l = vcat $ fmap printIr l
+  
+instance (IrPrint k, IrPrint v) => IrPrint (M.Map k v) where
+  printIr mp = let l = M.toList mp
+               in printIr l
+                                    
+instance IrPrint v => IrPrint (S.Set v) where
+  printIr s = let l = S.toList s
+              in printIr l
+  
+instance IrPrint () where  
+  printIr _ = text "()"
+  
+commaSepMaybe :: IrPrint a => Maybe a -> Doc
+commaSepMaybe = maybe empty ((comma <+>) . printIr)
+
+optSepToLlvm :: IrPrint a => Maybe a -> Doc -> Doc
+optSepToLlvm (Nothing) _ = empty
+optSepToLlvm (Just x) sep = printIr x <+> sep
+
+instance IrPrint a => IrPrint (Maybe a) where
+  printIr (Just x) = printIr x
+  printIr Nothing = empty
+  
+
+instance IrPrint TlTriple where  
+  printIr (TlTriple s) = hsep [text "target", text "triple", equals, printIr s]
+
+instance IrPrint TlDataLayout where
+  printIr (TlDataLayout s) = hsep [text "target", text "datalayout", equals, printIr s]
+
+instance IrPrint TlAlias where
+  printIr (TlAlias lhs vis dll tlm na link aliasee) = 
+    hsep [printIr lhs, equals, printIr vis, printIr dll, printIr tlm, printIr na, text "alias", printIr link, printIr aliasee]
+
+instance IrPrint TlDbgInit where
+  printIr (TlDbgInit s i) = hsep [text "dbginit", text s, integral i]
+
+instance IrPrint TlStandaloneMd where
+  printIr (TlStandaloneMd s t) = char '!'<>(text s) <+> equals <+> printIr t
+
+instance IrPrint TlNamedMd where                                 
+  printIr (TlNamedMd mv nds) = printIr mv <+> equals <+> char '!'<>(braces (hsep $ punctuate comma $ fmap printIr nds))
+
+instance IrPrint TlDeclare where
+  printIr (TlDeclare fproto) = text "declare" <+> printIr fproto
+  
+instance IrPrint a => IrPrint (TlDefine a) where  
+  printIr (TlDefine fproto entry graph) = text "define" <+> printIr fproto $$
+                                          text "; the entry label is" <+> 
+                                          printIr entry $$
+                                          printIr graph
+
+instance IrPrint TlGlobal where  
+  printIr x = case x of
+    (TlGlobalDtype lhs linkage vis dll tlm un addrspace externali gty ty c section comdat align) ->
+      hsep [optSepToLlvm lhs equals, printIr linkage, printIr vis, printIr dll, printIr tlm, printIr un, optSepToLlvm addrspace empty
+           , printIr externali, printIr gty, printIr ty, printIr c, commaSepNonEmpty [printIr section, printIr comdat, printIr align]]
+    (TlGlobalOpaque lhs linkage vis dll tlm un addrspace externali gty ty c section comdat align) ->
+      hsep [optSepToLlvm lhs equals, printIr linkage, printIr vis, printIr dll, printIr tlm, printIr un, optSepToLlvm addrspace empty
+           , printIr externali, printIr gty, printIr ty, printIr c, commaSepNonEmpty [printIr section, printIr comdat, printIr align]]      
+
+instance IrPrint TlTypeDef where    
+  printIr x = case x of
+    (TlDatTypeDef n t) -> hsep [printIr n, equals, text "data type", printIr t]
+    (TlOpqTypeDef n t) -> hsep [printIr n, equals, text "opaque type", printIr t]    
+    (TlFunTypeDef n t) -> hsep [printIr n, equals, text "function type", printIr t]      
+
+instance IrPrint TlDepLibs where
+  printIr (TlDepLibs l) = hsep [text "deplibs", equals, brackets (hsep $ punctuate comma $ fmap printIr l)]
+
+instance IrPrint TlUnamedType where
+  printIr (TlUnamedType x t) = text "type" <+> printIr t <+> text("; " ++ (show x))
+
+instance IrPrint TlModuleAsm where
+  printIr (TlModuleAsm qs) = hsep [text "module", text "asm", printIr qs]
+  
+instance IrPrint TlAttribute where
+  printIr (TlAttribute n l) = hsep [text "attributes", char '#' <> (integral n), braces (hsep $ fmap printIr l)]
+
+instance IrPrint TlComdat where
+  printIr (TlComdat l s) = hsep [printIr l, equals, printIr s]
+  
+instance IrPrint a => IrPrint (Toplevel a) where 
+  printIr (ToplevelTriple x) = printIr x
+  printIr (ToplevelDataLayout x) = printIr x
+  printIr (ToplevelAlias x) = printIr x
+  printIr (ToplevelDbgInit x) = printIr x
+  printIr (ToplevelStandaloneMd x) = printIr x
+  printIr (ToplevelNamedMd x) = printIr x
+  printIr (ToplevelDeclare x) = printIr x
+  printIr (ToplevelDefine x) = printIr x
+  printIr (ToplevelGlobal x) = printIr x
+  printIr (ToplevelTypeDef x) = printIr x
+  printIr (ToplevelDepLibs x) = printIr x
+  printIr (ToplevelUnamedType x) = printIr x
+  printIr (ToplevelModuleAsm x) = printIr x
+  printIr (ToplevelAttribute x) = printIr x
+  printIr (ToplevelComdat x) = printIr x
+
+instance IrPrint TypeEnv where
+  printIr (TypeEnv dl tt td) = text "datalayout:" <+> printIr dl
+                               $+$ text "triple:" <+> printIr tt
+                               $+$ text "typedefs:" <+> printIr td
+                               
+instance IrPrint GlobalCxt where
+  printIr (GlobalCxt te gl) = text "typeEnv:" <+> printIr te
+                              $+$ text "globals:" <+> printIr gl
+                                
+instance IrPrint FunCxt where
+  printIr (FunCxt fn p) = text "funName:" <+> text fn
+                          $+$ text "funParameters:" <+> printIr p
+                                
+instance IrPrint IrCxt where
+  printIr (IrCxt g l) = text "globalCxt:" <+> printIr g
+                        $+$ text "funCxt:" <+> printIr l
+
+instance IrPrint a => IrPrint (Module a) where 
+  printIr (Module tops) = fcat $ fmap printIr tops
+
+
+instance IrPrint a => IrPrint (Node a e x) where
+  printIr (Nlabel lbl) = printIr lbl
+  printIr (Pinst i) = printIr i
+  printIr (Cinst c) = printIr c
+  printIr (Tinst t) = printIr t
+  printIr (Comment s) = text s
+  printIr (Additional a) = printIr a
+    
+instance IrPrint a => IrPrint (H.Graph (Node a) H.C H.C) where
+  printIr g = braces (H.foldGraphNodes (\n -> \s -> s $$ (printIr n)) g empty)
+
+instance IrPrint Label where
+  printIr l = text (show l) 
+
+instance IrPrint Exact where
+  printIr Exact = text "exact"
+
+instance IrPrint NoWrap where
+    printIr Nsw = text "nsw"
+    printIr Nuw = text "nuw"
+    printIr Nsuw = text "nsw nuw"
+
+printX :: (String, Doc, T Utype Const, T Utype Const) -> Doc
+printX (op, cs, s1, s2) = text op <+> cs <+> parens (printIr s1 <> comma <+> printIr s2)
+
+printF :: (String, Doc, T Utype Const, T Utype Const) -> Doc                 
+printF (op, cs, s1, s2) = text op <+> cs <+> parens (printIr s1 <> comma <+> printIr s2)
+
+printConversion :: IrPrint x => Conversion s x -> (Doc -> Doc) -> Doc
+printConversion x p = case x of
+  Trunc fv dt -> text "trunc" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  Zext fv dt -> text "zext" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  Sext fv dt -> text "sext" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  FpTrunc fv dt -> text "fptrunc" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  FpExt fv dt -> text "fpext" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  FpToUi fv dt -> text "fptoui" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  FpToSi fv dt -> text "fptosi" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  UiToFp fv dt -> text "uitofp" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  SiToFp fv dt -> text "sitofp" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  PtrToInt fv dt -> text "ptrtoint" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  IntToPtr fv dt -> text "inttoptr" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  Bitcast fv dt -> text "bitcast" <+> p (printIr fv <+> text "to" <+> printIr dt)
+  AddrSpaceCast fv dt -> text "addrspacecast" <+> p (printIr fv <+> text "to" <+> printIr dt)
+
+instance IrPrint (Conversion s Const) where
+  printIr x = printConversion x parens
+
+instance IrPrint (GetElementPtr s Const) where
+  printIr (GetElementPtr b base indices) = 
+    hsep [text "getelementptr", printIr b, parens (commaSepList ((printIr base):fmap printIr indices))]
+                                       
+instance IrPrint (Select s r Const) where
+  printIr (Select cnd tc1 tc2) = text "select" <+> (parens (commaSepList [printIr cnd, printIr tc1, printIr tc2]))
+
+instance (IrPrint a, IrPrint b) => IrPrint (Either a b) where
+  printIr (Left a) = printIr a
+  printIr (Right b) = printIr b
+
+instance IrPrint (Icmp ScalarB Const) where
+  printIr (Icmp op t c1 c2) = 
+    text "icmp" <+> printIr op <+> parens (commaSepList [printIr (T t c1), printIr (T t c2)])
+
+instance IrPrint (Icmp VectorB Const) where
+  printIr (Icmp op t c1 c2) = 
+    text "icmp" <+> printIr op <+> parens (commaSepList [printIr (T t c1), printIr (T t c2)])
+
+instance IrPrint (Fcmp s Const) where
+  printIr (Fcmp op t c1 c2) = 
+    text "fcmp" <+> printIr op <+> parens (commaSepList [printIr (T t c1), printIr (T t c2)])
+  
+instance IrPrint (ShuffleVector r Const) where
+  printIr (ShuffleVector tc1 tc2 mask) = 
+    text "shufflevector" <+> parens (commaSepList [printIr tc1, printIr tc2, printIr mask])
+
+instance IrPrint (ExtractValue Const) where
+  printIr (ExtractValue tc indices) = 
+    hsep [text "extractvalue", parens (commaSepList ((printIr tc:(fmap integral indices))))]
+                                   
+instance IrPrint (InsertValue Const) where
+  printIr (InsertValue vect tc indices) = 
+    hsep [text "insertvalue", parens (commaSepList ((printIr vect:printIr tc:(fmap integral indices))))]
+                                       
+instance IrPrint (ExtractElement r Const) where
+  printIr (ExtractElement tc index) = 
+    hsep [text "extractelement", parens (printIr tc <> comma <+> printIr index)]
+                                
+instance IrPrint (InsertElement r Const) where
+  printIr (InsertElement tc1 tc2 index) = 
+    hsep [text "insertelement", parens (printIr tc1 <> comma <+> printIr tc2 <> comma <+> printIr index)]
+                                          
+instance IrPrint Const where
+  printIr cst = case cst of
+    C_u8 v -> integral v
+    C_u16 v -> integral v
+    C_u32 v -> integral v
+    C_u64 v -> integral v
+    C_u96 v -> integral v
+    C_u128 v -> integral v
+    C_s8 v -> integral v
+    C_s16 v -> integral v
+    C_s32 v -> integral v
+    C_s64 v -> integral v
+    C_s96 v -> integral v
+    C_s128 v -> integral v
+    C_int i -> text i
+    C_uhex_int i -> text "u0x" <> (text i)
+    C_shex_int i -> text "s0x" <> (text i)
+    C_float s -> text s
+    C_null -> text "null"
+    C_undef -> text "undef"
+    C_true -> text "true"
+    C_false -> text "false"
+    C_zeroinitializer -> text "zeroinitializer"
+    C_globalAddr g -> printIr g
+    C_str s -> char 'c'<> (doubleQuotes $ text s)
+
+    (C_struct b ts) -> let v = (braces (commaSepList $ fmap printIr ts))
+                       in case b of 
+                         Packed -> angleBrackets v
+                         Unpacked -> v
+    (C_vector ts) -> angleBrackets (commaSepList $ fmap printIr ts)
+    (C_array ts) -> brackets (commaSepList $ fmap printIr ts)
+    C_vectorN n e -> angleBrackets (commaSepList $ fmap (\x -> printIr e) [1..n])
+    C_arrayN n e -> brackets (commaSepList $ fmap (\x -> printIr e) [1..n])    
+    C_localId l -> printIr l
+    C_labelId l -> printIr l
+    C_block g a -> text "blockaddress" <+> parens (printIr g <> comma <+> printIr a)
+    
+    C_add x t v1 v2 -> printX ("add", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_sub x t v1 v2 -> printX ("sub", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_mul x t v1 v2 -> printX ("mul", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_udiv x t v1 v2 -> printX ("udiv", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_sdiv x t v1 v2 -> printX ("sdiv", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_urem t v1 v2 -> printX ("urem", empty, T (ucast t) v1, T (ucast t) v2)
+    C_srem t v1 v2 -> printX ("srem", empty, T (ucast t) v1, T (ucast t) v2)
+    C_shl x t v1 v2 -> printX ("shl", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_lshr x t v1 v2 -> printX ("lshr", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_ashr x t v1 v2 -> printX ("ashr", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_and  t v1 v2 -> printX ("and", empty, T (ucast t) v1, T (ucast t) v2)
+    C_or  t v1 v2 -> printX ("or", empty, T (ucast t) v1, T (ucast t) v2)
+    C_xor t v1 v2 -> printX ("xor", empty, T (ucast t) v1, T (ucast t) v2)
+
+    C_add_V x t v1 v2 -> printX ("add", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_sub_V x t v1 v2 -> printX ("sub", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_mul_V x t v1 v2 -> printX ("mul", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_udiv_V x t v1 v2 -> printX ("udiv", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_sdiv_V x t v1 v2 -> printX ("sdiv", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_urem_V t v1 v2 -> printX ("urem", empty, T (ucast t) v1, T (ucast t) v2)
+    C_srem_V t v1 v2 -> printX ("srem", empty, T (ucast t) v1, T (ucast t) v2)
+    C_shl_V x t v1 v2 -> printX ("shl", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_lshr_V x t v1 v2 -> printX ("lshr", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_ashr_V x t v1 v2 -> printX ("ashr", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_and_V  t v1 v2 -> printX ("and", empty, T (ucast t) v1, T (ucast t) v2)
+    C_or_V  t v1 v2 -> printX ("or", empty, T (ucast t) v1, T (ucast t) v2)
+    C_xor_V t v1 v2 -> printX ("xor", empty, T (ucast t) v1, T (ucast t) v2)
+
+    C_fadd x t v1 v2 -> printF ("fadd", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_fsub x t v1 v2 -> printF ("fsub", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_fmul x t v1 v2 -> printF ("fmul", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_fdiv x t v1 v2 -> printF ("fdiv", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_frem x t v1 v2 -> printF ("frem", printIr x, T (ucast t) v1, T (ucast t) v2)
+
+    C_fadd_V x t v1 v2 -> printF ("fadd", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_fsub_V x t v1 v2 -> printF ("fsub", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_fmul_V x t v1 v2 -> printF ("fmul", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_fdiv_V x t v1 v2 -> printF ("fdiv", printIr x, T (ucast t) v1, T (ucast t) v2)
+    C_frem_V x t v1 v2 -> printF ("frem", printIr x, T (ucast t) v1, T (ucast t) v2)
+
+    {- conversion -}
+    C_trunc fv dt -> text "trunc" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_zext fv dt -> text "zext" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_sext fv dt -> text "sext" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fptrunc fv dt -> text "fptrunc" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fpext fv dt -> text "fpext" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fptoui fv dt -> text "fptoui" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fptosi fv dt -> text "fptosi" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_uitofp fv dt -> text "uitofp" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_sitofp fv dt -> text "sitofp" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_ptrtoint fv dt -> text "ptrtoint" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_inttoptr fv dt -> text "inttoptr" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_addrspacecast fv dt -> text "addrspacecast" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+
+    C_bitcast fv dt -> text "bitcast" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+
+    C_trunc_V fv dt -> text "trunc" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_zext_V fv dt -> text "zext" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_sext_V fv dt -> text "sext" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fptrunc_V fv dt -> text "fptrunc" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fpext_V fv dt -> text "fpext" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fptoui_V fv dt -> text "fptoui" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_fptosi_V fv dt -> text "fptosi" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_uitofp_V fv dt -> text "uitofp" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_sitofp_V fv dt -> text "sitofp" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_ptrtoint_V fv dt -> text "ptrtoint" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_inttoptr_V fv dt -> text "inttoptr" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+    C_addrspacecast_V fv dt -> text "addrspacecast" <+> parens (printIr fv <+> text "to" <+> printIr dt)
+
+    C_getelementptr b base indices ->
+      hsep [text "getelementptr", printIr b, parens (commaSepList ((printIr base):fmap printIr indices))]
+      
+    C_getelementptr_V b base indices ->
+      hsep [text "getelementptr", printIr b, parens (commaSepList ((printIr base):fmap printIr indices))]
+
+    C_select_I a -> printIr a
+    C_select_F a -> printIr a    
+    C_select_P a -> printIr a    
+    C_select_First cnd t f -> hsep [text "select", printIr cnd, printIr t, printIr f]
+    C_select_VI a -> printIr a    
+    C_select_VF a -> printIr a    
+    C_select_VP a -> printIr a    
+    C_icmp a -> printIr a
+    C_icmp_V a -> printIr a    
+    C_fcmp a -> printIr a    
+    C_fcmp_V a -> printIr a
+    C_shufflevector_I a -> printIr a
+    C_shufflevector_F a -> printIr a    
+    C_shufflevector_P a -> printIr a    
+    C_extractelement_I a -> printIr a
+    C_extractelement_F a -> printIr a    
+    C_extractelement_P a -> printIr a    
+    C_insertelement_I a -> printIr a
+    C_insertelement_F a -> printIr a    
+    C_insertelement_P a -> printIr a    
+    C_extractvalue a -> printIr a
+    C_insertvalue a -> printIr a    
+
+instance IrPrint MdVar where 
+  printIr (MdVar s) = char '!' <> (text s)
+  
+instance IrPrint MdNode where
+  printIr (MdNode s) = char '!' <> (text s)
+  
+instance IrPrint MetaConst where
+  printIr (McStruct c) = char '!' <> braces (commaSepList (fmap printIr c))
+  printIr (McString s) = char '!' <> (printIr s)
+  printIr (McMn n) = printIr n
+  printIr (McMv v) = printIr v
+  printIr (McRef s) = text $ show s
+  printIr (McSimple sc) = printIr sc
+
+instance IrPrint (GetElementPtr s Value) where
+  printIr (GetElementPtr ib tv tcs) = 
+    hsep [text "getelementptr", printIr ib, printIr tv, (commaSepList $ fmap printIr tcs)]
+
+instance IrPrint (Icmp ScalarB Value) where  
+  printIr (Icmp op t v1 v2) = hsep [text "icmp", printIr op, printIr t, printIr v1 <> comma, printIr v2]
+  
+instance IrPrint (Icmp VectorB Value) where  
+  printIr (Icmp op t v1 v2) = hsep [text "icmp", printIr op, printIr t, printIr v1 <> comma, printIr v2]
+
+instance IrPrint (Fcmp s Value) where  
+  printIr (Fcmp op t v1 v2) = hsep [text "fcmp", printIr op, printIr t, printIr v1 <> comma, printIr v2]
+  
+instance IrPrint (Conversion s Value) where  
+  printIr x = printConversion x id
+  
+instance IrPrint (Select s r Value) where  
+  printIr (Select c t f) = text "select" <+> (commaSepList [printIr c, printIr t, printIr f])
+
+instance IrPrint Value where
+  printIr (Val_ssa i) = printIr i
+  printIr (Val_const c) = printIr c
+
+  
+instance IrPrint TypedConstOrNull where  
+  printIr (TypedConst tc) = printIr tc
+  printIr UntypedNull = text "null"
+
+
+instance (IrPrint t, IrPrint x) => IrPrint (T t x) where
+  printIr (T t v) = printIr t <+> printIr v
+  
+instance IrPrint FunName where
+  printIr (FunNameGlobal s) = printIr s
+  printIr (FunNameString s) = text s
+  
+
+instance IrPrint CallSiteType where
+  printIr (CallSiteRet e) = printIr e
+  printIr (CallSiteFun e as) = printIr (Tpointer (ucast e) as) 
+
+  
+instance IrPrint CallSite where
+  printIr (CsFun cc ra rt ident params fa) = 
+    hsep [printIr cc, hsep $ fmap printIr ra, printIr rt, printIr ident, parens (commaSepList $ fmap printIr params), hsep $ fmap printIr fa]
+  printIr (CsAsm t se as dia s1 s2 params fa) = 
+    hsep [printIr t, text "asm", printIr se, printIr as, printIr dia, printIr s1 <> comma
+         , printIr s2, parens (commaSepList $ fmap printIr params), hsep $ fmap printIr fa]
+  printIr (CsConversion ra t convert params fa) = 
+    hsep [hsep $ fmap printIr ra, printIr t, printIr convert, parens (hsep $ fmap printIr params), hsep $ fmap printIr fa]
+  printIr (CsConversionV ra t convert params fa) = 
+    hsep [hsep $ fmap printIr ra, printIr t, printIr convert, parens (hsep $ fmap printIr params), hsep $ fmap printIr fa]
+
+
+instance IrPrint Clause where
+  printIr (Catch tv) = text "catch" <+> printIr tv
+  printIr (Filter tc) = text "filter" <+> printIr tc
+  printIr (CcoS c) = printIr c
+  printIr (CcoV c) = printIr c  
+
+instance IrPrint (Conversion s GlobalOrLocalId) where
+  printIr x = printConversion x parens
+  
+instance IrPrint PersFn where
+    printIr (PersFnId g) = printIr g
+    printIr (PersFnCastS c) = printIr c
+    printIr (PersFnCastV c) = printIr c    
+    printIr PersFnUndef = text "undef"                                     
+    printIr PersFnNull = text "null"
+    printIr (PersFnConst c) = printIr c
+
+
+instance IrPrint (ExtractElement r Value) where
+  printIr (ExtractElement tv1 tv2) = hsep [text "extractelement", printIr tv1 <> comma, printIr tv2]
+  
+instance IrPrint (InsertElement r Value) where  
+  printIr (InsertElement vect tv idx) = 
+    hsep [text "insertelement", printIr vect <> comma, printIr tv <> comma, printIr idx]
+  
+instance IrPrint (ShuffleVector r Value) where  
+  printIr (ShuffleVector vect1 vect2 mask) = 
+    hsep [text "shufflevector", printIr vect1 <> comma, printIr vect2 <> comma, printIr mask]
+  
+instance IrPrint (ExtractValue Value) where  
+  printIr (ExtractValue tv idxs) = 
+    hsep [text "extractvalue", printIr tv <> comma, (commaSepList $ fmap integral idxs)]
+                                  
+instance IrPrint (InsertValue Value) where  
+  printIr (InsertValue vect tv idx) = text "insertvalue" <+> hsep (punctuate comma ((printIr vect):(printIr tv):(fmap integral idx)))
+
+instance IrPrint ActualParam where
+  printIr x = case x of
+    (ActualParamData t att1 align v att2) ->
+      hsep [printIr t, hsep $ fmap printIr att1, printIr align, printIr v, hsep $ fmap printIr att2]
+    (ActualParamMeta mc) -> printIr mc
+  
+
+instance IrPrint Dbg where
+  printIr (Dbg mv meta) = printIr mv <+> printIr meta
+
+
+instance IrPrint PhiInst where
+  printIr (PhiInst lhs t pairs) =  printIr lhs <+> equals <+> text "phi" 
+                                   <+> printIr t <+> (commaSepList $ fmap tvToLLvm pairs)
+    where tvToLLvm (h1,h2) = brackets (printIr h1 <+> comma <+> printIr h2)
+
+instance IrPrint CInst where
+  printIr x = case x of
+    (I_alloca ma t s a lhs) -> 
+      hsep [printIr lhs, equals, text "alloca", printIr ma, printIr t, commaSepMaybe s, commaSepMaybe a]
+    (I_load v ptr align nonterm invar nonull lhs) ->
+      hsep [printIr lhs, equals, text "load", printIr v, printIr ptr
+           , commaSepNonEmpty [printIr align, printIr nonterm, printIr invar, printIr nonull]]
+    (I_loadatomic (Atomicity st ord) v ptr align lhs) ->
+      hsep [printIr lhs, equals, text "load atomic", printIr v, printIr ptr, printIr st, printIr ord, commaSepMaybe align]
+    (I_store b v addr align nonterm) ->
+      hsep [text "store", printIr b, printIr v <> comma, printIr addr, commaSepMaybe align, commaSepMaybe nonterm]
+    (I_storeatomic (Atomicity st ord) b v ptr align) ->
+      hsep [text "store atomic", printIr b, printIr v <> comma, printIr ptr, printIr st, printIr ord <> commaSepMaybe align]
+    (I_fence b order) -> hsep [text "fence", printIr b, printIr order]
+    (I_cmpxchg_I wk v p c n st sord ford lhs) ->
+      hsep [printIr lhs, equals, text "cmpxchg", printIr wk, printIr v, printIr p <> comma
+           , printIr c <> comma, printIr n, printIr st, printIr sord, printIr ford]
+    (I_cmpxchg_F wk v p c n st sord ford lhs) ->
+      hsep [printIr lhs, equals, text "cmpxchg", printIr wk, printIr v, printIr p <> comma
+           , printIr c <> comma, printIr n, printIr st, printIr sord, printIr ford]
+    (I_cmpxchg_P wk v p c n st sord ford lhs) ->
+      hsep [printIr lhs, equals, text "cmpxchg", printIr wk, printIr v, printIr p <> comma
+           , printIr c <> comma, printIr n, printIr st, printIr sord, printIr ford]
+    
+    (I_atomicrmw v op p vl st ord lhs) ->
+      hsep [printIr lhs, equals, text "atomicrmw", printIr v, printIr op, printIr p <> comma, printIr vl, printIr st, printIr ord]
+    
+    (I_call_fun tc cc pa cstype callee actparams fna lhs) -> hsep [optSepToLlvm lhs equals, printIr tc, 
+                                                                   printIr (CsFun cc pa cstype callee actparams fna)]
+    (I_call_other tc cs lhs) -> hsep [optSepToLlvm lhs equals, printIr tc, printIr cs]    
+    
+    (I_extractelement_I tv idx lhs) -> hsep [printIr lhs, equals, text "extractelement_i", printIr tv, printIr idx]
+    (I_extractelement_F tv idx lhs) -> hsep [printIr lhs, equals, text "extractelement_f", printIr tv, printIr idx]
+    (I_extractelement_P tv idx lhs) -> hsep [printIr lhs, equals, text "extractelement_p", printIr tv, printIr idx]
+    
+    (I_insertelement_I tv v idx lhs) -> hsep [printIr lhs, equals, text "insertelement_i", printIr tv, printIr v, printIr idx]
+    (I_insertelement_F tv v idx lhs) -> hsep [printIr lhs, equals, text "insertelement_f", printIr tv, printIr v, printIr idx]
+    (I_insertelement_P tv v idx lhs) -> hsep [printIr lhs, equals, text "insertelement_p", printIr tv, printIr v, printIr idx]
+    
+    (I_shufflevector_I v1 v2 v3 lhs) -> hsep [printIr lhs, equals, text "shufflevector_i", printIr v1, printIr v2, printIr v3]
+    (I_shufflevector_F v1 v2 v3 lhs) -> hsep [printIr lhs, equals, text "shufflevector_f", printIr v1, printIr v2, printIr v3]
+    (I_shufflevector_P v1 v2 v3 lhs) -> hsep [printIr lhs, equals, text "shufflevector_p", printIr v1, printIr v2, printIr v3]
+    
+    (I_extractvalue v idx lhs) -> hsep ([printIr lhs, equals, text "extractvalue", printIr v] ++ fmap integral idx)
+    (I_insertvalue vv v idx lhs) -> hsep ([printIr lhs, equals, text "insertvalue", printIr vv, printIr v] ++ fmap integral idx)
+    
+    I_va_arg dv t lhs -> hsep [printIr lhs, equals, text "va_arg", printIr dv, printIr t]
+    I_va_start tv -> text "call" <+> text "void" <+> text "@llvm.va_start" <+> parens(printIr tv)
+    I_va_end tv -> text "call" <+> text "void" <+> text "@llvm.va_end" <+> parens(printIr tv)
+  
+    I_landingpad rt pt tgl b clauses lhs -> 
+      hsep ([printIr lhs, equals, text "landingpad", printIr rt, text "personality", printIr pt, printIr tgl, printIr b] ++ fmap printIr clauses)
+    
+    I_getelementptr b base indices lhs -> hsep [printIr lhs, equals, text "getelementptr", printIr b, parens (commaSepList ((printIr base):fmap printIr indices))]
+    I_getelementptr_V b base indices lhs -> hsep [printIr lhs, equals, text "getelementptr_v", printIr b, parens (commaSepList ((printIr base):fmap printIr indices))]
+    
+    (I_icmp op t v1 v2 lhs) -> hsep [printIr lhs, equals, text "icmp", printIr op, printIr t, printIr v1, printIr v2]
+    (I_icmp_V op t v1 v2 lhs) -> hsep [printIr lhs, equals, text "icmp_v", printIr op, printIr t, printIr v1, printIr v2]
+    
+    (I_fcmp op t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fcmp", printIr op, printIr t, printIr v1, printIr v2]
+    (I_fcmp_V op t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fcmp_v", printIr op, printIr t, printIr v1, printIr v2]
+    
+    (I_add n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "add", printIr n, printIr t, printIr v1, printIr v2]
+    (I_sub n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "sub", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_mul n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "mul", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_udiv n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "udiv", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_sdiv n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "sdiv", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_urem t v1 v2 lhs) -> hsep [printIr lhs, equals, text "urem", printIr t, printIr v1, printIr v2]  
+    (I_srem t v1 v2 lhs) -> hsep [printIr lhs, equals, text "sdiv", printIr t, printIr v1, printIr v2]      
+    (I_shl n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "shl", printIr n, printIr t, printIr v1, printIr v2]
+    (I_lshr n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "lshr", printIr n, printIr t, printIr v1, printIr v2]          
+    (I_ashr n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "ashr", printIr n, printIr t, printIr v1, printIr v2]          
+    (I_and t v1 v2 lhs) -> hsep [printIr lhs, equals, text "and", printIr t, printIr v1, printIr v2]
+    (I_or t v1 v2 lhs) -> hsep [printIr lhs, equals, text "or", printIr t, printIr v1, printIr v2]
+    (I_xor t v1 v2 lhs) -> hsep [printIr lhs, equals, text "xor", printIr t, printIr v1, printIr v2]
+    
+    (I_add_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "add_v", printIr n, printIr t, printIr v1, printIr v2]
+    (I_sub_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "sub_v", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_mul_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "mul_v", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_udiv_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "udiv_v", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_sdiv_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "sdiv_v", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_urem_V t v1 v2 lhs) -> hsep [printIr lhs, equals, text "urem_v", printIr t, printIr v1, printIr v2]  
+    (I_srem_V t v1 v2 lhs) -> hsep [printIr lhs, equals, text "sdiv_v", printIr t, printIr v1, printIr v2]      
+    (I_shl_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "shl_v", printIr n, printIr t, printIr v1, printIr v2]
+    (I_lshr_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "lshr_v", printIr n, printIr t, printIr v1, printIr v2]          
+    (I_ashr_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "ashr_v", printIr n, printIr t, printIr v1, printIr v2]          
+    (I_and_V t v1 v2 lhs) -> hsep [printIr lhs, equals, text "and_v", printIr t, printIr v1, printIr v2]
+    (I_or_V t v1 v2 lhs) -> hsep [printIr lhs, equals, text "or_v", printIr t, printIr v1, printIr v2]
+    (I_xor_V t v1 v2 lhs) -> hsep [printIr lhs, equals, text "xor_v", printIr t, printIr v1, printIr v2]
+    
+    
+    (I_fadd n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fadd", printIr n, printIr t, printIr v1, printIr v2]
+    (I_fsub n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fsub", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_fmul n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fmul", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_fdiv n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fdiv", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_frem n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "frem", printIr n, printIr t, printIr v1, printIr v2]
+    
+    (I_fadd_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fadd_v", printIr n, printIr t, printIr v1, printIr v2]
+    (I_fsub_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fsub_v", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_fmul_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fmul_v", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_fdiv_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "fdiv_v", printIr n, printIr t, printIr v1, printIr v2]    
+    (I_frem_V n t v1 v2 lhs) -> hsep [printIr lhs, equals, text "frem_v", printIr n, printIr t, printIr v1, printIr v2]
+    
+    (I_trunc tv dt lhs) -> hsep [printIr lhs, equals, text "trunc", printIr tv, text "to", printIr dt]
+    (I_zext tv dt lhs) -> hsep [printIr lhs, equals, text "zext", printIr tv, text "to", printIr dt]
+    (I_sext tv dt lhs) -> hsep [printIr lhs, equals, text "sext", printIr tv, text "to", printIr dt]
+    (I_fptrunc tv dt lhs) -> hsep [printIr lhs, equals, text "fptrunc", printIr tv, text "to", printIr dt]
+    (I_fpext tv dt lhs) -> hsep [printIr lhs, equals, text "fpext", printIr tv, text "to", printIr dt]
+    (I_fptoui tv dt lhs) -> hsep [printIr lhs, equals, text "fptoui", printIr tv, text "to", printIr dt]
+    (I_fptosi tv dt lhs) -> hsep [printIr lhs, equals, text "fptosi", printIr tv, text "to", printIr dt]
+    (I_uitofp tv dt lhs) -> hsep [printIr lhs, equals, text "uitofp", printIr tv, text "to", printIr dt]
+    (I_sitofp tv dt lhs) -> hsep [printIr lhs, equals, text "sitofp", printIr tv, text "to", printIr dt]
+    (I_ptrtoint tv dt lhs) -> hsep [printIr lhs, equals, text "ptrtoint", printIr tv, text "to", printIr dt]
+    (I_inttoptr tv dt lhs) -> hsep [printIr lhs, equals, text "inttoptr", printIr tv, text "to", printIr dt]
+    (I_addrspacecast tv dt lhs) -> hsep [printIr lhs, equals, text "addrspacecast", printIr tv, text "to", printIr dt]    
+    
+    (I_bitcast tv dt lhs) -> hsep [printIr lhs, equals, text "bitcast", printIr tv, text "to", printIr dt]
+    (I_bitcast_D tv dt lhs) -> hsep [printIr lhs, equals, text "bitcast_D", printIr tv, text "to", printIr dt]
+
+    (I_trunc_V tv dt lhs) -> hsep [printIr lhs, equals, text "trunc_v", printIr tv, text "to", printIr dt]
+    (I_zext_V tv dt lhs) -> hsep [printIr lhs, equals, text "zext_v", printIr tv, text "to", printIr dt]
+    (I_sext_V tv dt lhs) -> hsep [printIr lhs, equals, text "sext_v", printIr tv, text "to", printIr dt]
+    (I_fptrunc_V tv dt lhs) -> hsep [printIr lhs, equals, text "fptrunc_v", printIr tv, text "to", printIr dt]
+    (I_fpext_V tv dt lhs) -> hsep [printIr lhs, equals, text "fpext_v", printIr tv, text "to", printIr dt]
+    (I_fptoui_V tv dt lhs) -> hsep [printIr lhs, equals, text "fptoui_v", printIr tv, text "to", printIr dt]
+    (I_fptosi_V tv dt lhs) -> hsep [printIr lhs, equals, text "fptosi_v", printIr tv, text "to", printIr dt]
+    (I_uitofp_V tv dt lhs) -> hsep [printIr lhs, equals, text "uitofp_v", printIr tv, text "to", printIr dt]
+    (I_sitofp_V tv dt lhs) -> hsep [printIr lhs, equals, text "sitofp_v", printIr tv, text "to", printIr dt]
+    (I_ptrtoint_V tv dt lhs) -> hsep [printIr lhs, equals, text "ptrtoint_v", printIr tv, text "to", printIr dt]
+    (I_inttoptr_V tv dt lhs) -> hsep [printIr lhs, equals, text "inttoptr_v", printIr tv, text "to", printIr dt]
+    (I_addrspacecast_V tv dt lhs) -> hsep [printIr lhs, equals, text "addrspacecast_v", printIr tv, text "to", printIr dt]    
+    
+    (I_select_I cnd t f lhs) -> hsep [printIr lhs, equals, text "select", printIr cnd, printIr t, printIr f]
+    (I_select_F cnd t f lhs) -> hsep [printIr lhs, equals, text "select", printIr cnd, printIr t, printIr f]    
+    (I_select_P cnd t f lhs) -> hsep [printIr lhs, equals, text "select", printIr cnd, printIr t, printIr f]    
+    
+    (I_select_First cnd t f lhs) -> hsep [printIr lhs, equals, text "select", printIr cnd, printIr t, printIr f]    
+    
+    (I_select_VI cnd t f lhs) -> hsep [printIr lhs, equals, text "select", printIr cnd, printIr t, printIr f]
+    (I_select_VF cnd t f lhs) -> hsep [printIr lhs, equals, text "select", printIr cnd, printIr t, printIr f]    
+    (I_select_VP cnd t f lhs) -> hsep [printIr lhs, equals, text "select", printIr cnd, printIr t, printIr f]
+    
+    I_llvm_memcpy mod tv1 tv2 tv3 tv4 tv5 -> text "I_llvm_memcpy" <+> printIr mod  <+> parens (hsep [printIr tv1, printIr tv2, printIr tv3, printIr tv4, printIr tv5]) 
+    I_llvm_dbg_declare aps ->  text "I_llvm_dbg_declare" <> parens (hsep (fmap printIr aps))
+    I_llvm_dbg_value aps ->  text "I_llvm_dbg_value" <> parens (hsep (fmap printIr aps))    
+    {-
+    I_dbaseOf tv lhs -> hsep [printIr lhs, equals, text "dbaseOf", printIr tv]
+    I_dsizeOf tv lhs -> hsep [printIr lhs, equals, text "dsizeOf", printIr tv]
+    I_inspect_va_start_offset lhs -> hsep [printIr lhs, equals, text "inspect_va_start_offset"]
+    I_inspect_va_start_mbase lhs -> hsep [printIr lhs, equals, text "inspect_va_start_mbase"]    
+    I_inspect_va_start_msize lhs -> hsep [printIr lhs, equals, text "inspect_va_start_msize"]
+    -}
+    
+instance IrPrint MemLen where    
+  printIr m = case m of
+    MemLenI32 -> text "i32"
+    MemLenI64 -> text "i64"
+
+instance IrPrint TerminatorInst where
+  printIr RetVoid = text "ret" <+> text "void"
+  printIr (Return x) = text "ret" <+> (commaSepList $ fmap printIr x)
+  printIr (Br a) = text "br" <+> printIr a
+  printIr (Cbr v t f) = text "br i1" <+> (commaSepList [printIr v, printIr t, printIr f])
+  printIr (IndirectBr v l) = hsep [text "indirectbr", printIr v <> comma, brackets (commaSepList $ fmap printIr l)]
+  printIr (Switch v d tbl) = 
+    hsep [text "switch", printIr v <> comma, printIr d, brackets (hsep $ fmap (\(p1,p2) -> printIr p1 <> comma <+> printIr p2) tbl)]
+  printIr (Invoke callSite toL unwindL lhs) = 
+    hsep [optSepToLlvm lhs equals, text "invoke", printIr callSite, text "to", printIr toL, text "unwind", printIr unwindL]
+  printIr (InvokeCmd callSite toL unwindL) =  
+    hsep [text "invoke", printIr callSite, text "to", printIr toL, text "unwind", printIr unwindL]
+  printIr Unreachable = text "unreachable"
+  printIr (Resume a) = text "resume" <+> printIr a
+  printIr Unwind = text "unwind"
+             
+
+instance IrPrint PhiInstWithDbg where
+  printIr (PhiInstWithDbg ins dbgs) = commaSepList ((printIr ins):fmap printIr dbgs)
+
+instance IrPrint TerminatorInstWithDbg where
+  printIr (TerminatorInstWithDbg ins dbgs) = commaSepList ((printIr ins):fmap printIr dbgs)
+
+instance IrPrint CInstWithDbg where
+  printIr (CInstWithDbg ins dbgs) = commaSepList ((printIr ins):fmap printIr dbgs)
+
+
+instance IrPrint Aliasee where
+  printIr (AtV tv ) = printIr tv
+  printIr (Ac c) = printIr c
+  printIr (AcV c) = printIr c  
+  printIr (Agep a) = printIr a
+  printIr (AgepV a) = printIr a  
+                      
+
+instance IrPrint FunctionPrototype where
+  printIr (FunctionPrototype fhLinkage fhVisibility fhDllStorageClass fhCCoonc fhAttr fhRetType fhName fhParams 
+           fhd fhAttr1 fhSection fhCmd fhAlign fhGc fhPrefix fhPrologue) = 
+    hsep [printIr fhLinkage, printIr fhVisibility, printIr fhDllStorageClass, printIr fhCCoonc, hsep $ fmap printIr fhAttr
+         , printIr fhRetType, printIr fhName, printIr fhParams, printIr fhd, hsep $ fmap printIr fhAttr1
+         , printIr fhSection, printIr fhCmd, printIr fhAlign, printIr fhGc, printIr fhPrefix, printIr fhPrologue]
+
+
+instance IrPrint MetaKind where
+  printIr a = case a of
+    Mtype t -> printIr t
+    Mmetadata -> text "metadata"
+
+instance IrPrint MetaKindedConst where
+  printIr x = case x of
+    (MetaKindedConst mk mc) -> printIr mk <+> printIr mc
+    UnmetaKindedNull -> text "null"   
+
+instance IrPrint (Type s x) where
+  printIr a = case a of 
+    TpI i -> text "i" <> integral i
+    TpF f -> text "f" <> integral f
+    TpV v -> text "v" <> integral v
+    TpHalf -> text "half"
+    TpFloat -> text "float"
+    TpDouble -> text "double"
+    TpFp128 -> text "fp128"
+    TpX86Fp80 -> text "x86_fp80"
+    TpPpcFp128 -> text "ppc_fp128"
+    TpX86Mmx -> text "x86_mmx"
+    TpLabel -> text "label"
+    Tvoid -> text "void"
+    Topaque -> text "opaque"
+    TpNull -> text "null"
+    
+    TnameScalarI s -> char '%' <> text s
+    TquoteNameScalarI s -> char '%'<> (doubleQuotes $ text s)
+    TnoScalarI i -> char '%'<> integral i
+    
+    TnameScalarF s -> char '%' <> text s
+    TquoteNameScalarF s -> char '%'<> (doubleQuotes $ text s)
+    TnoScalarF i -> char '%'<> integral i
+
+    TnameScalarP s -> char '%' <> text s
+    TquoteNameScalarP s -> char '%'<> (doubleQuotes $ text s)
+    TnoScalarP i -> char '%'<> integral i
+
+    TnameVectorI s -> char '%' <> text s
+    TquoteNameVectorI s -> char '%'<> (doubleQuotes $ text s)
+    TnoVectorI i -> char '%'<> integral i
+
+    TnameVectorF s -> char '%' <> text s
+    TquoteNameVectorF s -> char '%'<> (doubleQuotes $ text s)
+    TnoVectorF i -> char '%'<> integral i
+
+    TnameVectorP s -> char '%' <> text s
+    TquoteNameVectorP s -> char '%'<> (doubleQuotes $ text s)
+    TnoVectorP i -> char '%'<> integral i
+
+    TnameRecordD s -> char '%' <> text s
+    TquoteNameRecordD s -> char '%'<> (doubleQuotes $ text s)
+    TnoRecordD i -> char '%'<> integral i
+
+    TnameCodeFunX s -> char '%' <> text s
+    TquoteNameCodeFunX s -> char '%'<> (doubleQuotes $ text s)
+    TnoCodeFunX i -> char '%'<> integral i
+
+    Tarray i t -> brackets (integral i <+> char 'x' <+> printIr t)
+    TvectorI i t -> char '<' <> integral i <+> char 'x' <+> printIr t <> char '>'
+    TvectorF i t -> char '<' <> integral i <+> char 'x' <+> printIr t <> char '>'    
+    TvectorP i t -> char '<' <> integral i <+> char 'x' <+> printIr t <> char '>'    
+    Tstruct b ts -> let (start, end) = case b of 
+                          Packed -> (char '<', char '>')
+                          Unpacked -> (empty, empty)
+                    in start <+> braces (hsep $ punctuate comma $ fmap printIr ts) <+> end
+    Tpointer t addr -> printIr t <+> integral addr <+> text "*"
+    Tfunction t fp atts -> printIr t <+> printIr fp <+> (hsep $ punctuate comma $ fmap printIr atts)
+
+instance IrPrint FormalParam where
+  printIr x = case x of
+    (FormalParamData t att1 align id att2) ->
+      (printIr t) <+> (hsep $ fmap printIr att1) <> (maybe empty ((comma <+>) . printIr) align)
+      <+> (printIr id) <+> (hsep $ fmap printIr att2)
+    (FormalParamMeta e lv) -> printIr e <+> printIr lv
+
+instance IrPrint FormalParamList where
+  printIr (FormalParamList params var atts) =
+    parens (commaSepNonEmpty ((fmap printIr params) ++ [maybe empty printIr var])) <+> (hsep $ fmap printIr atts)
+
+instance IrPrint TypeParamList where
+  printIr (TypeParamList params b) = parens (commaSepNonEmpty ((fmap printIr params) ++ [maybe empty printIr b]))
+
+
+
+instance IrPrint Utype where
+  printIr x = case x of
+    UtypeScalarI e -> printIr e
+    UtypeScalarF e -> printIr e    
+    UtypeScalarP e -> printIr e        
+    UtypeVectorI e -> printIr e
+    UtypeVectorF e -> printIr e    
+    UtypeVectorP e -> printIr e
+    UtypeFirstClassD e -> printIr e
+    UtypeRecordD e -> printIr e
+    UtypeOpaqueD e -> printIr e
+    UtypeVoidU e -> printIr e
+    UtypeFunX e -> printIr e
+
+
+instance IrPrint Etype where
+  printIr x = case x of
+    EtypeScalarI e -> printIr e
+    EtypeScalarF e -> printIr e    
+    EtypeScalarP e -> printIr e        
+    EtypeVectorI e -> printIr e
+    EtypeVectorF e -> printIr e    
+    EtypeVectorP e -> printIr e        
+    EtypeFirstClassD e -> printIr e
+    EtypeRecordD e -> printIr e
+    EtypeOpaqueD e -> printIr e
+    EtypeFunX e -> printIr e
+
+instance IrPrint Ftype where
+  printIr x = case x of
+    FtypeScalarI e -> printIr e
+    FtypeScalarF e -> printIr e    
+    FtypeScalarP e -> printIr e    
+    FtypeVectorI e -> printIr e
+    FtypeVectorF e -> printIr e    
+    FtypeVectorP e -> printIr e
+    FtypeFirstClassD e -> printIr e
+
+
+instance IrPrint Dtype where
+  printIr x = case x of
+    DtypeScalarI e -> printIr e
+    DtypeScalarF e -> printIr e    
+    DtypeScalarP e -> printIr e
+    DtypeVectorI e -> printIr e
+    DtypeVectorF e -> printIr e    
+    DtypeVectorP e -> printIr e    
+    DtypeFirstClassD e -> printIr e
+    DtypeRecordD e -> printIr e
+
+instance IrPrint Rtype where
+  printIr x = case x of
+    RtypeScalarI e -> printIr e
+    RtypeScalarF e -> printIr e    
+    RtypeScalarP e -> printIr e    
+    RtypeVectorI e -> printIr e
+    RtypeVectorF e -> printIr e    
+    RtypeVectorP e -> printIr e
+    RtypeFirstClassD e -> printIr e
+    RtypeRecordD e -> printIr e
+    RtypeVoidU e -> printIr e
+
+instance IrPrint ScalarType where
+  printIr x = case x of
+    ScalarTypeI e -> printIr e
+    ScalarTypeF e -> printIr e    
+    ScalarTypeP e -> printIr e    
+
+instance IrPrint (IntOrPtrType ScalarB) where
+  printIr x = case x of
+    IntOrPtrTypeI e -> printIr e
+    IntOrPtrTypeP e -> printIr e    
+
+instance IrPrint (IntOrPtrType VectorB) where
+  printIr x = case x of
+    IntOrPtrTypeI e -> printIr e
+    IntOrPtrTypeP e -> printIr e    
+
+instance IrPrint Prefix where
+  printIr (Prefix n) = text "prefix" <+> printIr n
+  
+instance IrPrint Prologue where  
+  printIr (Prologue n) = text "prologue" <+> printIr n
+
+
+instance IrPrint IcmpOp where
+  printIr = P.print 
+
+instance IrPrint FcmpOp where
+  printIr = P.print
+
+instance IrPrint Linkage where
+  printIr = P.print
+
+instance IrPrint CallConv where
+  printIr = P.print
+
+instance IrPrint Visibility where
+  printIr = P.print
+
+instance IrPrint DllStorageClass where
+  printIr = P.print
+  
+instance IrPrint ThreadLocalStorage where  
+  printIr = P.print
+
+instance IrPrint ParamAttr where
+  printIr = P.print
+
+instance IrPrint FunAttr where
+  printIr = P.print
+  
+instance IrPrint SelectionKind where  
+  printIr = P.print
+   
+instance IrPrint AddrNaming where
+  printIr = P.print
+
+instance IrPrint DqString where
+  printIr = P.print
+
+
+instance IrPrint Section where
+  printIr = P.print
+
+instance IrPrint Alignment where
+    printIr = P.print
+
+instance IrPrint Gc where
+    printIr = P.print
+
+instance IrPrint GlobalType where
+    printIr = P.print
+
+instance IrPrint GlobalOrLocalId where
+  printIr = P.print
+                    
+instance IrPrint LocalId where
+  printIr = P.print
+                      
+instance IrPrint GlobalId where
+  printIr = P.print
+
+instance IrPrint BinaryConstant where
+  printIr = P.print
+                          
+instance IrPrint AtomicMemoryOrdering where
+  printIr = P.print
+
+instance IrPrint AtomicOp where
+    printIr = P.print
+    
+instance IrPrint Integer where
+  printIr = integer
+
+instance IrPrint AddrSpace where
+  printIr = integral
+
+instance IrPrint Fparam where
+  printIr = P.print
+  
+instance IrPrint InAllocaAttr where
+  printIr = P.print
+    
+instance IrPrint Volatile where
+  printIr = P.print
+
+instance IrPrint Weak where
+  printIr = P.print
+  
+instance IrPrint SingleThread where
+  printIr = P.print
+
+instance IrPrint InBounds where
+  printIr = P.print
+  
+instance (P.Print a, IrPrint a) => IrPrint (IsOrIsNot a) where
+  printIr = P.print
+
+instance IrPrint Nontemporal where    
+  printIr = P.print
+  
+instance IrPrint InvariantLoad where
+  printIr = P.print
+  
+instance IrPrint Nonnull where
+  printIr = P.print
+  
+  
+instance IrPrint TailCall where
+  printIr = P.print
+
+instance IrPrint DollarId where
+  printIr = P.print
+
+
+instance IrPrint Comdat where
+  printIr = P.print
+
+instance IrPrint FastMathFlag where  
+  printIr = P.print
+                
+instance IrPrint FastMathFlags where                
+  printIr = P.print
+  
+instance IrPrint ExternallyInitialized where  
+  printIr = P.print
+  
+  
+instance IrPrint AsmDialect where  
+  printIr = P.print
+
+instance IrPrint Endianness where
+  printIr = P.print
+  
+instance IrPrint LayoutAddrSpace where  
+  printIr = P.print
+  
+instance IrPrint SizeInBit where  
+  printIr = P.print
+  
+instance IrPrint AlignInBit where  
+  printIr = P.print
+  
+instance IrPrint StackAlign where  
+  printIr = P.print
+  
+instance IrPrint Mangling where
+  printIr = P.print
+    
+instance IrPrint AbiAlign where    
+  printIr = P.print
+
+instance IrPrint PrefAlign where
+  printIr = P.print
+  
+instance IrPrint LayoutSpec where  
+  printIr = P.print
+  
+instance IrPrint DataLayout where
+  printIr = P.print
+  
+instance IrPrint SideEffect where  
+  printIr = P.print
+  
+instance IrPrint AlignStack where  
+  printIr = P.print
+
+instance IrPrint Cleanup where
+  printIr = P.print
+
+instance IrPrint TargetTriple where
+  printIr = P.print
+  
+instance IrPrint DataLayoutInfo where  
+  printIr = P.print
+  
+instance IrPrint VarArgParam where  
+  printIr = P.print
diff --git a/src/Llvm/Syntax/Printer/LlvmPrint.hs b/src/Llvm/Syntax/Printer/LlvmPrint.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Printer/LlvmPrint.hs
@@ -0,0 +1,592 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+module Llvm.Syntax.Printer.LlvmPrint
+       (module Llvm.Syntax.Printer.LlvmPrint
+       ,module Llvm.Syntax.Printer.Common
+       ) where
+
+import Llvm.Syntax.Printer.Common
+import Llvm.Data.Ast
+import qualified Llvm.Syntax.Printer.SharedEntityPrint as P
+import Llvm.Syntax.Printer.SharedEntityPrint (integral)
+import Llvm.Util.Mapping (getValOrImplError)
+
+class AsmPrint a where
+  toLlvm :: a -> Doc
+
+commaSepMaybe :: AsmPrint a => Maybe a -> Doc
+commaSepMaybe = maybe empty ((comma<+>) . toLlvm)
+
+maybeSepByEquals :: AsmPrint a => Maybe a -> Doc
+maybeSepByEquals = maybe empty ((<+>equals).toLlvm)
+
+instance AsmPrint a => AsmPrint (Maybe a) where
+  toLlvm (Just x) = toLlvm x
+  toLlvm Nothing = empty
+
+instance AsmPrint LabelId where
+  toLlvm (LabelString s) = text s
+  toLlvm (LabelNumber n) = integral n
+  toLlvm (LabelDqNumber n) = doubleQuotes $ integral n
+  toLlvm (LabelDqString s) = doubleQuotes $ text s
+
+instance AsmPrint PercentLabel where
+  toLlvm (PercentLabel li) = char '%' <> (toLlvm li)
+  
+instance AsmPrint TargetLabel where
+  toLlvm (TargetLabel x) = text "label" <+> toLlvm x
+  
+instance AsmPrint BlockLabel where
+  toLlvm (ImplicitBlockLabel (f, l, c)) = 
+    text ";<label>:? ;" <+> parens ((text f) <> comma <+> (integer $ toInteger l) <> comma <+> (integer $ toInteger c))
+  toLlvm (ExplicitBlockLabel l) = toLlvm l <> char ':'
+
+instance AsmPrint ComplexConstant where
+  toLlvm (Cstruct b ts) = 
+    let (start, end) = case b of 
+          Packed -> (char '<', char '>') 
+          Unpacked -> (empty, empty)
+    in start <> braces (commaSepList $ fmap toLlvm ts) <> end
+  toLlvm (Cvector ts) = char '<' <+> (commaSepList $ fmap toLlvm ts) <+> char '>'
+  toLlvm (Carray ts) = brackets $ commaSepList $ fmap toLlvm ts
+
+instance AsmPrint IbinOp where
+  toLlvm x = text $ getValOrImplError (ibinOpMap, "ibinOpMap") x 
+
+instance AsmPrint FbinOp where
+  toLlvm x = text $ getValOrImplError (fbinOpMap, "fbinOpMap") x
+
+instance AsmPrint (BinExpr Const) where
+  toLlvm (Ie v) = toLlvm v
+  toLlvm (Fe v) = toLlvm v
+
+instance AsmPrint (BinExpr Value) where
+  toLlvm (Ie v) = toLlvm v
+  toLlvm (Fe v) = toLlvm v
+
+instance AsmPrint (IbinExpr Const) where
+  toLlvm (IbinExpr op cs t c1 c2) = 
+    toLlvm op <+> (hsep $ fmap toLlvm cs) <+> parens (toLlvm (Typed t c1) <> comma <+> toLlvm (Typed t c2))
+  
+instance AsmPrint (FbinExpr Const) where
+  toLlvm (FbinExpr op cs t c1 c2) = 
+    toLlvm op <+> toLlvm cs <+> parens (toLlvm (Typed t c1) <> comma <+> toLlvm (Typed t c2))
+
+instance AsmPrint (Conversion Const) where
+  toLlvm (Conversion op tc t) = toLlvm op <+> parens (toLlvm tc <+> text "to" <+> toLlvm t)
+
+instance AsmPrint (GetElementPtr Const) where
+  toLlvm (GetElementPtr b base indices) = 
+    text "getelementptr" <+> toLlvm b <+> parens (commaSepList ((toLlvm base):fmap toLlvm indices))
+
+instance AsmPrint (Select Const) where
+  toLlvm (Select cnd tc1 tc2) = 
+    text "select" <+> parens (commaSepList [toLlvm cnd, toLlvm tc1, toLlvm tc2])
+
+instance AsmPrint (Icmp Const) where
+  toLlvm (Icmp op t c1 c2) = 
+    text "icmp" <+> toLlvm op <+> parens (toLlvm (Typed t c1) <> comma <+> toLlvm (Typed t c2))
+
+instance AsmPrint (Fcmp Const) where
+  toLlvm (Fcmp op t c1 c2) = 
+    text "fcmp" <+> toLlvm op <+> parens (toLlvm (Typed t c1) <> comma <+> toLlvm (Typed t c2))
+
+instance AsmPrint (ShuffleVector Const) where
+  toLlvm (ShuffleVector tc1 tc2 mask) = 
+    text "shufflevector" <+> parens (commaSepList [toLlvm tc1, toLlvm tc2, toLlvm mask])
+
+instance AsmPrint (ExtractValue Const) where
+  toLlvm (ExtractValue tc indices) = 
+    text "extractvalue" <+> parens (commaSepList ((toLlvm tc):fmap integral indices))
+                                   
+instance AsmPrint (InsertValue Const) where
+  toLlvm (InsertValue vect tc indices) = 
+    text "insertvalue" <+> parens (commaSepList ((toLlvm vect):(toLlvm tc):fmap integral indices)) 
+                                       
+instance AsmPrint (ExtractElement Const) where
+  toLlvm (ExtractElement tc index) = 
+    text "extractelement" <+> parens (toLlvm tc <> comma <+> toLlvm index)
+
+instance AsmPrint (InsertElement Const) where                                  
+  toLlvm (InsertElement tc1 tc2 index) = 
+    text "insertelement" <+> parens (commaSepList [toLlvm tc1, toLlvm tc2, toLlvm index])
+
+instance AsmPrint TrapFlag where
+  toLlvm Nuw = text "nuw"
+  toLlvm Nsw = text "nsw"
+  toLlvm Exact = text "exact"
+                                      
+instance AsmPrint Const where
+  toLlvm x = case x of
+    C_simple c -> toLlvm c
+    C_complex a -> toLlvm a
+    C_labelId l -> toLlvm l
+    C_blockAddress g a -> text "blockaddress" <+> parens (toLlvm g <> comma <+> toLlvm a)
+    C_binexp a -> toLlvm a
+    C_conv a -> toLlvm a 
+    C_gep a -> toLlvm a
+    C_select a -> toLlvm a
+    C_icmp a -> toLlvm a
+    C_fcmp a -> toLlvm a 
+    C_shufflevector a -> toLlvm a
+    C_extractvalue a -> toLlvm a
+    C_insertvalue a -> toLlvm a
+    C_extractelement a -> toLlvm a
+    C_insertelement a -> toLlvm a
+    C_localId v -> toLlvm v
+
+instance AsmPrint MdVar where 
+  toLlvm (MdVar s) = char '!'<> (text s)
+  
+instance AsmPrint MdNode where
+  toLlvm (MdNode s) = char '!' <> (text s)
+  
+instance AsmPrint MetaConst where
+  toLlvm (McStruct c) = char '!' <> braces (commaSepList (fmap toLlvm c))
+  toLlvm (McString s) = char '!' <> (toLlvm s)
+  toLlvm (McMn n) = toLlvm n
+  toLlvm (McMv v) = toLlvm v
+  toLlvm (McRef s) = toLlvm s
+  toLlvm (McSimple sc) = toLlvm sc
+
+instance AsmPrint MetaKindedConst where
+  toLlvm x = case x of
+    (MetaKindedConst mk mc) -> toLlvm mk <+> toLlvm mc
+    UnmetaKindedNull -> text "null"
+
+instance AsmPrint (GetElementPtr Value) where
+  toLlvm (GetElementPtr ib tv tcs) = 
+    text "getelementptr" <+> toLlvm ib <+> (commaSepList ((toLlvm tv):fmap toLlvm tcs))
+
+instance AsmPrint (IbinExpr Value) where
+  toLlvm (IbinExpr op cs t v1 v2) = hsep ((toLlvm op):(fmap toLlvm cs)++[toLlvm t, toLlvm v1 <> comma, toLlvm v2])
+
+instance AsmPrint (FbinExpr Value) where
+  toLlvm (FbinExpr op cs t v1 v2) = hsep [toLlvm op, toLlvm cs, toLlvm t, toLlvm v1 <> comma, toLlvm v2]
+
+instance AsmPrint (Icmp Value) where  
+  toLlvm (Icmp op t v1 v2) = hsep [text "icmp", toLlvm op, toLlvm t, toLlvm v1 <> comma, toLlvm v2]
+  
+instance AsmPrint (Fcmp Value) where  
+  toLlvm (Fcmp op t v1 v2) = hsep [text "fcmp", toLlvm op, toLlvm t, toLlvm v1 <> comma, toLlvm v2]
+  
+instance AsmPrint (Conversion Value) where
+  toLlvm (Conversion op tv t) = hsep [toLlvm op, toLlvm tv, text "to", toLlvm t]
+  
+instance AsmPrint (Select Value) where
+  toLlvm (Select c t f) = hsep [text "select", toLlvm c <> comma, toLlvm t <> comma, toLlvm f]
+
+instance AsmPrint Expr where
+  toLlvm (EgEp a) = toLlvm a
+  toLlvm (EiC a) = toLlvm a
+  toLlvm (EfC a) = toLlvm a
+  toLlvm (Eb a) = toLlvm a
+  toLlvm (Ec a) = toLlvm a
+  toLlvm (Es a) = toLlvm a
+
+instance AsmPrint MemOp where  
+  toLlvm (Alloca ma t s a) = hsep [text "alloca", toLlvm ma, hcat [toLlvm t, commaSepMaybe s, commaSepMaybe a]]
+  toLlvm (Load b ptr align noterm inv nonul) = 
+    hsep [text "load", toLlvm b, hcat [toLlvm ptr, commaSepMaybe align, commaSepMaybe noterm, commaSepMaybe inv, commaSepMaybe nonul]]
+  toLlvm (LoadAtomic (Atomicity st ord) b ptr align) = 
+    hsep [text "load", text "atomic", toLlvm b, toLlvm ptr, toLlvm st, toLlvm ord] <> (commaSepMaybe align)
+  toLlvm (Store b v addr align noterm) = 
+    hsep [text "store", toLlvm b, toLlvm v <> comma, toLlvm addr <> (commaSepMaybe align) <> (commaSepMaybe noterm)]
+  toLlvm (StoreAtomic (Atomicity st ord) b v ptr align) = 
+    hsep [text "store", text "atomic", toLlvm b, toLlvm v <> comma, toLlvm ptr, toLlvm st, toLlvm ord] <> (commaSepMaybe align)
+  toLlvm (Fence b order) = hsep [text "fence", toLlvm b, toLlvm order]
+  toLlvm (CmpXchg wk v p c n st sord ford) = 
+    hsep [text "cmpxchg", toLlvm wk, toLlvm v, toLlvm p <> comma, toLlvm c <> comma, toLlvm n, toLlvm st, toLlvm sord, toLlvm ford]
+  toLlvm (AtomicRmw v op p vl st ord) = 
+    hsep [text "atomicrmw", toLlvm v, toLlvm op, toLlvm p <> comma, toLlvm vl, toLlvm st, toLlvm ord]
+
+instance AsmPrint Value where
+  toLlvm (Val_local i) = toLlvm i
+  toLlvm (Val_const c) = toLlvm c
+
+instance AsmPrint v => AsmPrint (Typed v) where
+  toLlvm (Typed t v) = toLlvm t <+> toLlvm v
+
+instance AsmPrint a => AsmPrint (Pointer a) where
+  toLlvm (Pointer i) = toLlvm i
+
+instance AsmPrint FunName where
+  toLlvm (FunNameGlobal s) = toLlvm s
+  toLlvm (FunNameString s) = text s
+  
+instance AsmPrint CallSite where
+  toLlvm (CsFun cc ra rt ident params fa) = 
+    hsep [toLlvm cc, hsep $ fmap toLlvm ra, toLlvm rt, toLlvm ident, parens (commaSepList $ fmap toLlvm params), hsep $ fmap toLlvm fa]
+  toLlvm (CsAsm t se as dia s1 s2 params fa) = 
+    hsep [toLlvm t, text "asm", toLlvm se, toLlvm as, toLlvm dia, toLlvm s1 <> comma, toLlvm s2, parens (commaSepList $ fmap toLlvm params), hsep $ fmap toLlvm fa]
+  toLlvm (CsConversion ra t convert params fa) = 
+    hsep [hsep $ fmap toLlvm ra, toLlvm t, toLlvm convert, parens (commaSepList $ fmap toLlvm params), hsep $ fmap toLlvm fa]
+
+instance AsmPrint Clause where
+  toLlvm (Catch tv) = text "catch" <+> toLlvm tv
+  toLlvm (Filter tc) = text "filter" <+> toLlvm tc
+  toLlvm (Cco c) = toLlvm c
+
+instance AsmPrint (Conversion GlobalOrLocalId) where
+  toLlvm (Conversion op (Typed t g) dt) = toLlvm op <+> parens (hsep [toLlvm t, toLlvm g, text "to", toLlvm dt])
+  
+instance AsmPrint PersFn where
+    toLlvm (PersFnId g) = toLlvm g
+    toLlvm (PersFnCast c) = toLlvm c
+    toLlvm PersFnUndef = text "undef"
+    toLlvm PersFnNull = text "null"
+    toLlvm (PersFnConst c) = toLlvm c
+
+instance AsmPrint (ExtractElement Value) where
+  toLlvm (ExtractElement tv1 tv2) = 
+    text "extractelement" <+> (commaSepList [toLlvm tv1, toLlvm tv2])
+  
+instance AsmPrint (InsertElement Value) where  
+  toLlvm (InsertElement vect tv idx) = 
+    text "insertelement" <+> (commaSepList [toLlvm vect, toLlvm tv, toLlvm idx])
+  
+instance AsmPrint (ShuffleVector Value) where  
+  toLlvm (ShuffleVector vect1 vect2 mask) = 
+    text "shufflevector" <+> (commaSepList [toLlvm vect1, toLlvm vect2, toLlvm mask])
+  
+instance AsmPrint (ExtractValue Value) where  
+  toLlvm (ExtractValue tv idxs) = text "extractvalue" <+> (commaSepList ((toLlvm tv):(fmap integral idxs)))
+  
+instance AsmPrint (InsertValue Value) where  
+  toLlvm (InsertValue vect tv idxs) = 
+    text "insertvalue" <+> (commaSepList ((toLlvm vect):(toLlvm tv):(fmap integral idxs)))
+
+
+instance AsmPrint Rhs where
+  toLlvm (RmO a) = toLlvm a
+  toLlvm (Re a) = toLlvm a
+  toLlvm (Call tailc callSite) = hsep [toLlvm tailc, text "call", toLlvm callSite]
+  toLlvm (ReE a) = toLlvm a
+  toLlvm (RiE a) = toLlvm a
+  toLlvm (RsV a) = toLlvm a
+  toLlvm (ReV a) = toLlvm a
+  toLlvm (RiV a) = toLlvm a
+  toLlvm (RvA (VaArg tv t)) = hsep [text "va_arg", toLlvm tv <> comma, toLlvm t]
+  toLlvm (RlP (LandingPad rt pt tgl b clause)) = 
+    hsep ([text "landingpad", toLlvm rt, text "personality", toLlvm pt, toLlvm tgl, toLlvm b] ++ (fmap toLlvm clause))
+
+instance AsmPrint ActualParam where
+  toLlvm x = case x of
+    (ActualParamData t att1 align v att2) ->
+      hsep [toLlvm t, hsep $ fmap toLlvm att1, toLlvm align, toLlvm v, hsep $ fmap toLlvm att2]
+    (ActualParamMeta mc) -> toLlvm mc
+
+instance AsmPrint Dbg where
+  toLlvm (Dbg mv meta) = toLlvm mv <+> toLlvm meta
+
+instance AsmPrint PhiInst where
+  toLlvm (PhiInst lhs t pairs) =  hsep [maybe empty ((<+> equals) . toLlvm) lhs, text "phi", toLlvm t, commaSepList $ fmap tvToLLvm pairs]
+    where tvToLLvm (h1,h2) = brackets (toLlvm h1 <> comma <+> toLlvm h2)
+
+instance AsmPrint ComputingInst where
+  toLlvm (ComputingInst lhs rhs) = maybe empty ((<+> equals) . toLlvm) lhs <+> toLlvm rhs
+
+instance AsmPrint TerminatorInst where
+  toLlvm RetVoid = text "ret" <+> text "void"
+  toLlvm (Return x) = text "ret" <+> (commaSepList $ fmap toLlvm x)
+  toLlvm (Br a) = text "br" <+> toLlvm a
+  toLlvm (Cbr v t f) = hsep [text "br",  text "i1", toLlvm v <> comma, toLlvm t <> comma, toLlvm f]
+  toLlvm (IndirectBr v l) = hsep [text "indirectbr", toLlvm v <> comma, brackets (commaSepList $ fmap toLlvm l)]
+  toLlvm (Switch v d tbl) = 
+    hsep [text "switch", toLlvm v <> comma, toLlvm d, brackets (hsep $ fmap (\(p1,p2) -> toLlvm p1 <> comma <+> toLlvm p2) tbl)]
+  toLlvm (Invoke lhs callSite toL unwindL) = 
+    hsep [maybe empty ((<+> equals) . toLlvm) lhs, text "invoke", toLlvm callSite, text "to", toLlvm toL, text "unwind", toLlvm unwindL]
+  toLlvm Unreachable = text "unreachable"
+  toLlvm (Resume a) = text "resume" <+> toLlvm a
+             
+instance AsmPrint PhiInstWithDbg where
+  toLlvm (PhiInstWithDbg ins dbgs) = commaSepList ((toLlvm ins):fmap toLlvm dbgs)
+
+instance AsmPrint TerminatorInstWithDbg where
+  toLlvm (TerminatorInstWithDbg ins dbgs) = commaSepList ((toLlvm ins):fmap toLlvm dbgs)
+
+instance AsmPrint ComputingInstWithDbg where
+  toLlvm ci = case ci of
+    ComputingInstWithDbg ins dbgs -> commaSepList ((toLlvm ins):fmap toLlvm dbgs)
+    ComputingInstWithComment s -> char ';' <+> text s 
+
+instance AsmPrint Aliasee where
+  toLlvm (AtV tv ) = toLlvm tv
+  toLlvm (Ac c) = toLlvm c
+  toLlvm (AgEp a) = toLlvm a
+
+instance AsmPrint FunctionPrototype where
+  toLlvm (FunctionPrototype fhLinkage fhVisibility fhDllStorageClass fhCCoonc fhAttr fhRetType fhName fhParams fnd 
+          fhAttr1 fhSection fhcmd fhAlign fhGc fhPrefix fhPrologue) = 
+    hsep [toLlvm fhLinkage, toLlvm fhVisibility, toLlvm fhDllStorageClass, toLlvm fhCCoonc, hsep $ fmap toLlvm fhAttr 
+         , toLlvm fhRetType, toLlvm fhName, toLlvm fhParams, toLlvm fnd, hsep $ fmap toLlvm fhAttr1
+         , toLlvm fhSection, toLlvm fhcmd, toLlvm fhAlign, toLlvm fhGc, toLlvm fhPrefix, toLlvm fhPrologue]
+
+instance AsmPrint Block where
+  toLlvm (Block lbl phis ins end) = toLlvm lbl $$
+                                    (nest 2 
+                                     ((vcat $ fmap toLlvm phis) $$
+                                      (vcat $ fmap toLlvm ins) $$
+                                      toLlvm end))
+
+instance AsmPrint Toplevel where 
+  toLlvm (ToplevelTriple (TlTriple s)) = hsep [text "target", text "triple", equals, toLlvm s]
+  toLlvm (ToplevelDataLayout (TlDataLayout s)) = hsep [text "target", text "datalayout", equals, toLlvm s]
+  toLlvm (ToplevelAlias (TlAlias lhs vis dll tlm naddr link aliasee)) = 
+    hsep [toLlvm lhs, equals, toLlvm vis, toLlvm dll, toLlvm tlm, toLlvm naddr, text "alias", toLlvm link, toLlvm aliasee]
+  toLlvm (ToplevelDbgInit (TlDbgInit s i)) = error "DbgInit is not implemented"
+  toLlvm (ToplevelStandaloneMd smd) = toLlvm smd
+  toLlvm (ToplevelNamedMd (TlNamedMd mv nds)) = toLlvm mv <+> equals <+> char '!'<>(braces (commaSepList $ fmap toLlvm nds))
+  toLlvm (ToplevelDeclare (TlDeclare fproto)) = text "declare" <+> toLlvm fproto
+  toLlvm (ToplevelDefine (TlDefine fproto blocks)) = text "define" <+> toLlvm fproto <+> text "{" $$
+                                          (fcat $ fmap toLlvm blocks) $$ text "}"
+  toLlvm (ToplevelGlobal (TlGlobal lhs linkage vis dllStor threadLoc un addrspace externali gty ty const0 
+                          section comdat align)) = 
+    hsep [maybeSepByEquals lhs, toLlvm linkage, toLlvm vis, toLlvm dllStor, toLlvm threadLoc, toLlvm un
+         , toLlvm addrspace, toLlvm externali, toLlvm gty, toLlvm ty, toLlvm const0]
+    <> (hcat [commaSepMaybe section, commaSepMaybe comdat, commaSepMaybe align])
+
+  toLlvm (ToplevelTypeDef (TlTypeDef n t)) = toLlvm n <+> equals <+> text "type" <+> toLlvm t
+  toLlvm (ToplevelDepLibs (TlDepLibs l)) = text "deplibs" <+> equals <+> brackets (commaSepList $ fmap toLlvm l)
+  toLlvm (ToplevelUnamedType (TlUnamedType x t)) = text "type" <+> toLlvm t <+> text "; " <+> (integral x)
+  toLlvm (ToplevelModuleAsm (TlModuleAsm qs)) = text "module asm" <+> toLlvm qs
+  toLlvm (ToplevelAttribute (TlAttribute n l)) = 
+    hsep [text "attributes", char '#' <> (integral n), equals, braces (hsep $ fmap toLlvm l)]
+  toLlvm (ToplevelComdat (TlComdat l c)) = 
+    hsep [toLlvm l, equals, text "comdat", toLlvm c]
+
+instance AsmPrint TlStandaloneMd where
+  toLlvm (TlStandaloneMd lhs rhs) = char '!' <> (text lhs) <+> equals <+> toLlvm rhs
+
+instance AsmPrint FormalParam where
+  toLlvm x = case x of
+    (FormalParamData t att1 align id att2) ->
+      (toLlvm t) <+> (hsep $ fmap toLlvm att1) 
+      <> (maybe empty ((comma <+>) . toLlvm) align) <+> (toLlvm id) <+> (hsep $ fmap toLlvm att2)
+    (FormalParamMeta e lv) -> toLlvm e <+> toLlvm lv
+
+instance AsmPrint FormalParamList where
+  toLlvm (FormalParamList params var atts) =
+    parens (commaSepNonEmpty ((fmap toLlvm params) ++ [maybe empty toLlvm var])) <+> (hsep $ fmap toLlvm atts)
+
+instance AsmPrint TypeParamList where
+  toLlvm (TypeParamList params b) = parens (commaSepNonEmpty ((fmap toLlvm params) ++ [maybe empty toLlvm b]))
+
+instance AsmPrint TypePrimitive where
+  toLlvm a = case a of 
+    TpI i -> text "i" <> integral i
+    TpF f -> text "f" <> integral f
+    TpV v -> text "v" <> integral v
+    TpHalf -> text "half"
+    TpFloat -> text "float"
+    TpDouble -> text "double"
+    TpFp128 -> text "fp128"
+    TpX86Fp80 -> text "x86_fp80"
+    TpPpcFp128 -> text "ppc_fp128"
+    TpX86Mmx -> text "x86_mmx"
+    TpLabel -> text "label"                       
+    TpNull -> text "null"
+
+instance AsmPrint MetaKind where
+  toLlvm a = case a of
+    Mtype e -> toLlvm e
+    Mmetadata -> text "metadata"
+
+instance AsmPrint Type where
+  toLlvm a = case a of 
+    Tprimitive tp -> toLlvm tp
+    Tvoid -> text "void"
+    Topaque -> text "opaque"
+    Tname s -> char '%' <> text s 
+    TquoteName s -> char '%'<> (doubleQuotes $ text s)
+    Tno i -> char '%'<> integral i
+    Tarray i t -> brackets (integral i <+> char 'x' <+> toLlvm t)
+    Tvector i t -> char '<' <> integral i <+> char 'x' <+> toLlvm t <> char '>'
+    Tstruct b ts -> let (start, end) = case b of 
+                          Packed -> (char '<', char '>')
+                          Unpacked -> (empty, empty)
+                    in start <> braces (hsep $ punctuate comma $ fmap toLlvm ts) <> end
+    Tpointer t addr -> toLlvm t <+> toLlvm addr <> text "*"
+    Tfunction t fp atts -> toLlvm t <+> toLlvm fp <+> (hsep $ punctuate comma $ fmap toLlvm atts)
+
+instance AsmPrint AddrSpace where
+  toLlvm (AddrSpace n) = text "addrspace" <+> (parens $ integral n)
+  toLlvm AddrSpaceUnspecified = empty
+
+instance AsmPrint ConvertOp where
+  toLlvm x = text $ getValOrImplError (convertOpMap, "convertOpMap") x
+
+instance AsmPrint TypedConstOrNull where  
+  toLlvm (TypedConst tc) = toLlvm tc
+  toLlvm UntypedNull = text "null"
+
+instance AsmPrint Module where 
+  toLlvm (Module tops) = vcat $ fmap toLlvm tops
+
+instance AsmPrint Prefix where
+  toLlvm (Prefix n) = text "prefix" <+> toLlvm n
+  
+instance AsmPrint Prologue where  
+  toLlvm (Prologue n) = text "prologue" <+> toLlvm n
+
+instance AsmPrint IcmpOp where
+  toLlvm = P.print 
+
+instance AsmPrint FcmpOp where
+  toLlvm = P.print
+
+instance AsmPrint Linkage where
+  toLlvm = P.print
+
+instance AsmPrint CallConv where
+  toLlvm = P.print
+
+instance AsmPrint Visibility where
+  toLlvm = P.print
+
+instance AsmPrint DllStorageClass where
+  toLlvm = P.print
+  
+instance AsmPrint ThreadLocalStorage where  
+  toLlvm = P.print
+
+instance AsmPrint ParamAttr where
+  toLlvm = P.print
+
+instance AsmPrint FunAttr where
+  toLlvm = P.print
+  
+instance AsmPrint SelectionKind where  
+  toLlvm = P.print
+   
+instance AsmPrint AddrNaming where
+  toLlvm = P.print
+
+instance AsmPrint DqString where
+  toLlvm = P.print
+
+instance AsmPrint Section where
+  toLlvm = P.print
+
+instance AsmPrint Alignment where
+  toLlvm = P.print
+
+instance AsmPrint Gc where
+  toLlvm = P.print
+
+instance AsmPrint GlobalType where
+  toLlvm = P.print
+
+instance AsmPrint GlobalOrLocalId where
+  toLlvm = P.print
+                    
+instance AsmPrint LocalId where
+  toLlvm = P.print
+                      
+instance AsmPrint GlobalId where
+  toLlvm = P.print
+
+instance AsmPrint SimpleConstant where
+  toLlvm = P.print
+                          
+instance AsmPrint AtomicMemoryOrdering where
+  toLlvm = P.print
+
+instance AsmPrint AtomicOp where
+  toLlvm = P.print
+    
+instance AsmPrint Fparam where
+  toLlvm = P.print
+  
+instance AsmPrint VarArgParam where
+  toLlvm = P.print
+
+instance AsmPrint InAllocaAttr where
+  toLlvm = P.print
+    
+instance AsmPrint Volatile where
+  toLlvm = P.print
+
+instance AsmPrint Weak where
+  toLlvm = P.print
+  
+instance AsmPrint SingleThread where
+  toLlvm = P.print
+
+instance AsmPrint InBounds where
+  toLlvm = P.print
+  
+instance (P.Print a, AsmPrint a) => AsmPrint (IsOrIsNot a) where
+  toLlvm = P.print
+
+instance AsmPrint Nontemporal where    
+  toLlvm = P.print
+  
+instance AsmPrint InvariantLoad where
+  toLlvm = P.print
+  
+instance AsmPrint Nonnull where
+  toLlvm = P.print
+
+instance AsmPrint TailCall where
+  toLlvm = P.print
+
+instance AsmPrint DollarId where
+  toLlvm = P.print
+
+instance AsmPrint Comdat where
+  toLlvm = P.print
+
+instance AsmPrint FastMathFlag where  
+  toLlvm = P.print
+                
+instance AsmPrint FastMathFlags where                
+  toLlvm = P.print
+  
+instance AsmPrint ExternallyInitialized where  
+  toLlvm = P.print
+  
+instance AsmPrint AsmDialect where  
+  toLlvm = P.print
+
+instance AsmPrint Endianness where
+  toLlvm = P.print
+  
+instance AsmPrint LayoutAddrSpace where  
+  toLlvm = P.print
+  
+instance AsmPrint SizeInBit where  
+  toLlvm = P.print
+  
+instance AsmPrint AlignInBit where  
+  toLlvm = P.print
+  
+instance AsmPrint StackAlign where  
+  toLlvm = P.print
+  
+instance AsmPrint Mangling where
+  toLlvm = P.print
+    
+instance AsmPrint AbiAlign where    
+  toLlvm = P.print
+
+instance AsmPrint PrefAlign where
+  toLlvm = P.print
+  
+instance AsmPrint LayoutSpec where  
+  toLlvm = P.print
+  
+instance AsmPrint DataLayout where
+  toLlvm = P.print
+  
+instance AsmPrint SideEffect where  
+  toLlvm = P.print
+  
+instance AsmPrint AlignStack where  
+  toLlvm = P.print
+  
+instance AsmPrint Cleanup where  
+  toLlvm = P.print
+
+instance AsmPrint TargetTriple where
+  toLlvm = P.print
diff --git a/src/Llvm/Syntax/Printer/SharedEntityPrint.hs b/src/Llvm/Syntax/Printer/SharedEntityPrint.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Syntax/Printer/SharedEntityPrint.hs
@@ -0,0 +1,396 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE GADTs #-}
+module Llvm.Syntax.Printer.SharedEntityPrint where
+import Prelude (($),fmap, Maybe(..),maybe, (.),null,(++),error, show,fromIntegral,String,Integral)
+
+import Llvm.Syntax.Printer.Common 
+import Llvm.Data.Shared
+import Llvm.Util.Mapping (getValOrImplError)
+import qualified Data.Map as M
+
+class Print a where
+  print :: a -> Doc
+
+instance Print Endianness where
+  print LittleEndian = char 'e'
+  print BigEndian = char 'E'
+  
+instance Print LayoutAddrSpace where  
+  print (LayoutAddrSpace n) = integral n
+  print (LayoutAddrSpaceUnspecified) = empty
+  
+instance Print SizeInBit where  
+  print (SizeInBit n) = integral n
+  
+instance Print AlignInBit where  
+  print (AlignInBit n) = integral n
+  
+instance Print StackAlign where  
+  print (StackAlign n) = print n
+  print StackAlignUnspecified = char '0'
+  
+instance Print Mangling where
+  print x = case x of
+    ManglingE -> char 'e'
+    ManglingM -> char 'm'
+    ManglingO -> char 'o'
+    ManglingW -> char 'w'
+    
+instance Print AbiAlign where    
+  print (AbiAlign n) = print n
+
+instance Print PrefAlign where
+  print (PrefAlign n) = print n
+  
+
+integral :: Integral a => a -> Doc
+integral = integer . fromIntegral
+
+instance Print LayoutSpec where  
+  print ls = case ls of
+      DlE x -> print x
+      DlS x -> char 'S' <> (print x)
+      DlLittleS s1 s2 s3 -> char 's' <> (maybe empty integral s1) 
+                            <> sepMaybe integral colonSep s2
+                            <> sepMaybe integral colonSep s3
+      DlP as s a n -> char 'p' <> (print as) 
+                      <> colonSep (print s) 
+                      <> colonSep (print a) 
+                      <> sepMaybe print colonSep n
+      DlI s a n -> char 'i' <> (print s)
+                   <> colonSep (print a)
+                   <> sepMaybe print colonSep n
+      DlF s a n -> char 'f' <> (print s)
+                 <> colonSep (print a)
+                 <> sepMaybe print colonSep n
+      DlV s a n -> char 'v' <> (print s)
+                   <> colonSep (print a)
+                   <> sepMaybe print colonSep n
+      DlA s a n -> char 'a' <> (maybe empty print s)
+                   <> colonSep (print a)
+                   <> sepMaybe print colonSep n
+      DlM m -> char 'm' <> colonSep (print m)
+      DlN l -> char 'n' <> (hcat $ punctuate (char ':') $ fmap print l)
+    where 
+      colonSep = (char ':' <>)
+  
+instance Print DataLayout where
+  print (DataLayout l) = doubleQuotes (hcat $ punctuate (char '-') $ fmap print l)
+  
+instance Print IcmpOp where
+  print x = text $ getValOrImplError (icmpOpMap, "icmpOpMap") x
+
+instance Print FcmpOp where
+  print x = text $ getValOrImplError (fcmpOpMap, "fcmpOpMap") x
+
+{-
+instance Print ConvertOp where
+  print x = text $ getValOrImplError (convertOpMap, "convertOpMap") x
+-}
+
+instance Print Linkage where
+  print LinkagePrivate = text "private"
+  print LinkageInternal = text "internal"
+  print LinkageAvailableExternally = text "available_externally"
+  print LinkageExternal = text "external"
+  print LinkageLinkonce = text "linkonce"
+  print LinkageWeak = text "weak"
+  print LinkageCommon = text "common"
+  print LinkageAppending = text "appending"
+  print LinkageExternWeak = text "extern_weak"
+  print LinkageLinkonceOdr = text "linkonce_odr"
+  print LinkageWeakOdr = text "weak_odr"
+  
+instance Print CallConv where
+  print Ccc = text "ccc"
+  print CcFast = text "fastcc"
+  print CcCold = text "coldcc"
+  print CcWebkit_Js = text "webkit_jscc"
+  print CcAnyReg = text "anyregcc"
+  print CcPreserveMost = text "preserve_mostcc"
+  print CcPreserveAll = text "preserve_allcc"
+  print (Cc s) = text "cc" <> text s
+  print CcSpir_Kernel = text "spir_kernel"
+  print CcSpir_Func = text "spir_func"
+  print CcIntel_Ocl_Bi = text "intel_ocl_bicc"
+  print CcX86_StdCall = text "x86_stdcallcc"
+  print CcX86_FastCall = text "x86_fastcallcc"
+  print CcX86_ThisCall = text "x86_thiscallcc"
+  print CcArm_Apcs = text "arm_apcscc"
+  print CcArm_Aapcs = text "arm_aapcscc"
+  print CcArm_Aapcs_Vfp = text "arm_aapcs_vfpcc"
+  print CcMsp430_Intr = text "msp430_intrcc"
+  print CcPtx_Kernel = text "ptx_kernel"
+  print CcPtx_Device = text "ptx_device"
+  print CcX86_64_Win64 = text "x86_64_win64cc"
+  print CcX86_64_SysV = text "x86_64_sysvcc"
+
+instance Print Visibility where
+  print VisDefault = text "default"
+  print VisHidden = text "hidden"
+  print VisProtected = text "protected"
+
+
+instance Print DllStorageClass where
+  print DscImport = text "dllimport"
+  print DscExport = text "dllexport"
+  
+instance Print ThreadLocalStorage where  
+  print x = let d = case x of 
+                   TlsLocalDynamic -> text "localdynamic"
+                   TlsInitialExec -> text "initialexec"
+                   TlsLocalExec -> text "localexec"
+                   TlsNone -> empty
+             in if isEmpty d then text "thread_local"
+                else text "thread_local" <+> parens d 
+
+instance Print ParamAttr where
+  print PaZeroExt = text "zeroext"
+  print PaSignExt = text "signext"
+  print PaInReg = text "inreg"
+  print PaByVal = text "byval"
+  print PaInAlloca = text "inalloca"
+  print PaSRet = text "sret"
+  print PaNoAlias = text "noalias"
+  print PaNoCapture = text "nocapture"
+  print PaNest = text "nest"
+  print PaReturned = text "returned"
+  print PaNonNull = text "nonnull"
+  print (PaDereferenceable n) = (text "dereferenceable") <> (parens $ integral n)
+  print PaReadOnly = text "readonly"
+  print PaReadNone = text "readnone"
+  print (PaAlign n) = text "align" <+> integral n
+
+
+instance Print FunAttr where
+  print (FaAlignStack n) = (text "alignstack") <> (parens $ integral n)
+  print FaAlwaysInline = text "alwaysinline"
+  print FaBuiltin = text "builtin"
+  print FaCold = text "cold"
+  print FaInlineHint = text "inlinehint"
+  print FaJumpTable = text "jumptable"
+  print FaMinSize = text "minsize"
+  print FaNaked = text "naked"
+  print FaNoBuiltin = text "nobuiltin"
+  print FaNoDuplicate = text "noduplicate"
+  print FaNoImplicitFloat = text "noimplicitfloat"
+  print FaNoInline = text "noinline"
+  print FaNonLazyBind = text "nonlazybind"
+  print FaNoRedZone = text "noredzone"
+  print FaNoReturn = text "noreturn"
+  print FaNoUnwind = text "nounwind"
+  print FaOptNone = text "optnone"
+  print FaOptSize = text "optsize"
+  print FaReadNone = text "readnone"
+  print FaReadOnly = text "readonly"
+  print FaReturnsTwice = text "returns_twice"
+  print FaSanitizeAddress = text "sanitize_address"
+  print FaSanitizeMemory = text "sanitize_memory"
+  print FaSanitizeThread = text "sanitize_thread"
+  print FaSsp = text "ssp"
+  print FaSspReq = text "sspreq"
+  print FaSspStrong = text "sspstrong"
+  print FaUwTable = text "uwtable"
+  print (FaPair s1 s2) = print s1 <> (maybe empty ((equals<>) . print) s2)
+  print (FaAlign n) = text "align" <+> integral n
+  print (FaGroup n) = char '#'<> (integral n)
+  
+instance Print SelectionKind where  
+  print x = text $ getValOrImplError (selectionKindMap, "selectionKindMap") x
+   
+instance Print AddrNaming where
+  print UnnamedAddr = text "unnamed_addr"
+  print NamedAddr = empty
+
+instance Print DqString where
+  print (DqString x) = doubleQuotes $ text x
+
+instance Print Section where
+  print (Section s) = text "section" <+> (print s)
+
+instance Print Alignment where
+    print (Alignment s) = text "align" <+>  (integral s)
+
+instance Print Gc where
+    print (Gc s) = text "gc" <+> (print s)
+
+instance Print GlobalType where
+    print (GlobalType s) = text s
+
+
+instance Print GlobalOrLocalId where
+  print (GolG g) = print g
+  print (GolL l) = print l
+                    
+instance Print LocalId where
+  print (LocalIdNum s) = char '%'<>(integral s)
+  print (LocalIdAlphaNum s) = char '%' <> text s
+  print (LocalIdDqString s) = char '%' <> (doubleQuotes $ text s)
+                      
+instance Print GlobalId where
+  print (GlobalIdNum s) = char '@'<>(integral s)
+  print (GlobalIdAlphaNum s) = char '@'<> text s
+  print (GlobalIdDqString s) = char '@'<> (doubleQuotes $ text s)
+
+instance Print SimpleConstant where
+  print x = case x of
+    CpInt i -> text i
+    CpUhexInt i -> text "u0x" <> (text i)
+    CpShexInt i -> text "s0x" <> (text i)
+    CpFloat s -> text s
+    CpNull -> text "null"
+    CpUndef -> text "undef"
+    CpTrue -> text "true"
+    CpFalse -> text "false"
+    CpZeroInitializer -> text "zeroinitializer"
+    CpGlobalAddr g -> print g
+    CpStr s -> char 'c'<> (doubleQuotes $ text s)
+    CpBconst bc -> print bc
+                          
+instance Print BinaryConstant where
+  print x = case x of
+    BconstUint8 v -> integral v
+    BconstUint16 v -> integral v
+    BconstUint32 v -> integral v
+    BconstUint64 v -> integral v
+    BconstUint96 v -> integral v
+    BconstUint128 v -> integral v
+    BconstInt8 v -> integral v
+    BconstInt16 v -> integral v
+    BconstInt32 v -> integral v
+    BconstInt64 v -> integral v
+    BconstInt96 v -> integral v
+    BconstInt128 v -> integral v
+
+instance Print AtomicMemoryOrdering where
+  print x = text $ getValOrImplError (atomicMemoryOrderingMap, "atomicMemoryOrderingMap") x
+
+instance Print AtomicOp where
+  print x = text $ getValOrImplError (atomicOpMap, "atomicOpMap") x
+    
+instance Print Fparam where
+  print (FimplicitParam) = text "; implicit param\n"
+  print (FexplicitParam x) = print x
+  
+instance Print InAllocaAttr where
+  print s = case s of
+    InAllocaAttr -> text "inalloca"
+    
+    
+instance Print Volatile where
+  print Volatile = text "volatile"
+
+instance Print Weak where
+  print Weak = text "weak"
+  
+instance Print SingleThread where
+  print SingleThread = text "singlethread"
+
+instance Print InBounds where
+  print InBounds = text "inbounds"
+  
+instance Print a => Print (IsOrIsNot a) where
+  print s = case s of
+    Is x -> print x
+    IsNot _ -> empty
+
+instance Print Nontemporal where    
+  print (Nontemporal i) = char '!'<>(text "nontemporal") <+> char '!'<>(integral i)
+  
+instance Print InvariantLoad where
+  print (InvariantLoad i) = char '!'<>(text "invariant.load") <+> char '!'<>(integral i)
+  
+instance Print Nonnull where
+  print (Nonnull i) = char '!'<>(text "nonnull") <+> char '!'<>(integral i)
+  
+  
+instance Print TailCall where
+  print x = case x of
+    TcNon -> empty
+    TcTailCall -> text "tail"
+    TcMustTailCall -> text "musttail"
+    
+instance Print DollarId where
+  print (DollarIdNum n) = char '$' <> (integral n)
+  print (DollarIdAlphaNum s) = char '$' <> (text s)
+  print (DollarIdDqString s) = char '$' <> (doubleQuotes $ text s)
+                                    
+                        
+instance Print Comdat where
+  print (Comdat l) = text "comdat" <+> (maybe empty print l)
+    
+instance Print FastMathFlag where
+  print x = text $ getValOrImplError (fastMathFlagMap, "fastMathFlagMap") x 
+                
+instance Print FastMathFlags where                
+  print (FastMathFlags l) = hsep $ fmap print l
+  
+instance Print ExternallyInitialized where  
+  print ExternallyInitialized = text "externally_initialized"
+  
+  
+instance Print AsmDialect where  
+  print x = case x of
+    AsmDialectAtt -> empty
+    AsmDialectIntel -> text "inteldialect"
+  
+  
+instance Print SideEffect where
+  print SideEffect = text "sideeffect"
+  
+instance Print AlignStack where  
+  print AlignStack = text "alignstack"
+  
+instance Print VarArgParam where
+  print VarArgParam = text "..."
+  
+instance Print Cleanup where
+  print Cleanup = text "cleanup"
+
+instance Print Arch where
+  print arch = case arch of
+    Arch_i386 -> text "i386"
+    Arch_i686 -> text "i686"
+    Arch_x86 -> text "x86"
+    Arch_x86_64 -> text "x86_64"
+    Arch_PowerPc -> text "powerpc"
+    Arch_PowerPc64 -> text "powerpc64"
+    Arch_Arm s -> text "arm" <> text s
+    Arch_ThumbV7 -> text "thumbv7"
+    Arch_Itanium -> text "itanium"
+    Arch_Mips s -> text "mips" <> text s
+    Arch_String s -> text s
+    
+instance Print Vendor where
+  print v = case v of
+    Vendor_Pc -> text "pc"
+    Vendor_Apple -> text "apple"
+    Vendor_Unknown -> text "unknown"
+    Vendor_String s -> text s
+    
+instance Print Os where    
+  print v = case v of
+    Os_Linux -> text "linux"
+    Os_Windows -> text "windows"
+    Os_Win32 -> text "win32"
+    Os_Darwin s -> text "darwin" <> text s
+    Os_FreeBsd s -> text "freebsd" <> text s
+    Os_Macosx s -> text "macosx" <> text s
+    Os_Ios s -> text "ios" <> text s
+    Os_Mingw32 -> text "mingw32"
+    Os_Unknown -> text "unknown"
+    Os_String s -> text s
+    
+instance Print OsEnv where    
+  print v = case v of
+    OsEnv_Gnu -> text "gnu"
+    OsEnv_String s -> text s
+
+instance Print TargetTriple where
+  print (TargetTriple arch ven os env) = 
+    doubleQuotes (hcat $ punctuate (char '-') 
+                  ([print arch] ++ mb ven ++ mb os ++ mb env))
+    where mb v = maybe [] (\x -> [print x]) v
+
+instance Print DataLayoutInfo where
+  print (DataLayoutInfo e sa ptrs is fs as ni ml _) = text "datalayout"
diff --git a/src/Llvm/Util/Mapping.hs b/src/Llvm/Util/Mapping.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Util/Mapping.hs
@@ -0,0 +1,8 @@
+module Llvm.Util.Mapping where
+
+import qualified Data.Map as M
+
+getValOrImplError :: (Show a, Ord a) => (M.Map a k, String) -> a -> k
+getValOrImplError (mp, mn) x = case M.lookup x mp of
+  Just s -> s
+  Nothing -> error $ "implementation error: " ++ show x ++ " is not added to " ++ mn
diff --git a/src/Llvm/Util/Monadic.hs b/src/Llvm/Util/Monadic.hs
new file mode 100644
--- /dev/null
+++ b/src/Llvm/Util/Monadic.hs
@@ -0,0 +1,13 @@
+module Llvm.Util.Monadic where
+import Control.Monad ()
+
+maybeM :: Monad m => (a -> m b) -> Maybe a -> m (Maybe b)
+maybeM f a = case a of
+               Just a' -> f a' >>= return . Just
+               Nothing -> return Nothing
+
+pairM :: Monad m => (v -> m v1) -> (l -> m l1) -> (v, l) -> m (v1, l1)
+pairM c1 c2 (v, l) = do { v' <- c1 v
+                        ; l' <- c2 l
+                        ; return $ (v', l')
+                        }
diff --git a/src/LlvmTest.hs b/src/LlvmTest.hs
new file mode 100644
--- /dev/null
+++ b/src/LlvmTest.hs
@@ -0,0 +1,168 @@
+{-# OPTIONS_GHC -cpp #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+import System.IO
+import System.Console.CmdArgs
+import ParserTester
+import Llvm.Pass.Optimizer ()
+import qualified Llvm.Pass.Mem2Reg as M2R ()
+import qualified Llvm.Pass.Liveness as L ()
+import qualified Llvm.Data.Ir as I
+import Llvm.Query.IrCxt
+import Llvm.Pass.PassManager
+import qualified Compiler.Hoopl as H
+import qualified Llvm.Data.Conversion as Cv
+import qualified Llvm.Pass.NormalGraph as N
+import qualified Llvm.Pass.Optimizer as O
+import qualified Llvm.Pass.PassTester as T
+import qualified Llvm.Syntax.Printer.IrPrint as P
+import qualified Data.Map as M
+import qualified Data.Set as S
+
+toStep "mem2reg" = Just Mem2Reg
+toStep "dce" = Just Dce
+toStep _ = Nothing
+
+
+extractSteps :: [String] -> [Step]
+extractSteps l = map (\x -> case toStep x of
+                         Just s -> s
+                         Nothing -> error (x ++ " is not step")
+                     ) l
+
+data Sample = Dummy { input :: FilePath, output :: Maybe String }
+            | Parser { input :: FilePath, output :: Maybe String, showAst :: Bool }
+            | Ast2Ir { input :: FilePath, output :: Maybe String }
+            | Ir2Ast { input :: FilePath, output :: Maybe String }
+            | Pass { input :: FilePath, output :: Maybe String, step :: [String], fuel :: Int }
+            | PhiFixUp { input :: FilePath, output :: Maybe String, fuel :: Int }
+            | AstCanonic { input :: FilePath, output :: Maybe String }
+            deriving (Show, Data, Typeable, Eq)
+
+outFlags x = x &= help "Output file, stdout is used if it's not specified" &= typFile
+
+dummy = Dummy { input = def &= typ "<INPUT>"
+              , output = outFlags Nothing
+              } &= help "Test LLVM Parser"
+
+parser = Parser { input = def &= typ "<INPUT>"
+                , output = outFlags Nothing
+                , showAst = False
+                } &= help "Test LLVM Parser"
+
+ast2ir = Ast2Ir { input = def &= typ "<INPUT>"
+                , output = outFlags Nothing
+                } &= help "Test Ast to Ir conversion"
+
+ir2ast = Ir2Ast { input = def &= typ "<INPUT>"
+                , output = outFlags Nothing
+                } &= help "Test Ir to Ast conversion"
+
+astcanonic = AstCanonic { input = def &= typ "<INPUT>"
+                        , output = outFlags Nothing
+                        } &= help "Test Ir to Ast conversion"
+
+pass = Pass { input = def &= typ "<INPUT>"
+            , output = outFlags Nothing
+            , fuel = H.infiniteFuel &= typ "FUEL" &= help "The fuel used to run the pass"
+            , step = def &= typ "STEP" &= help "Supported steps : mem2reg, dce. Multiple passes are supported by specifying multiple --step s, e.g., --step=mem2reg --step=dce"
+            } &= help "Test Optimization pass"
+
+phifixup = PhiFixUp { input = def &= typ "<INPUT>"
+                    , output = outFlags Nothing
+                    , fuel = H.infiniteFuel &= typ "FUEL" &= help "The fuel used to run the pass"
+                    } &= help "Test PhiFixUp pass"
+
+mode = cmdArgsMode $ modes [dummy, parser, ast2ir, ir2ast, pass, astcanonic, phifixup] &= help "Test sub components"
+       &= program "Test" &= summary "Test driver v1.0"
+
+main :: IO ()
+main = do { sel <- cmdArgsRun mode
+#ifdef DEBUG
+          ; putStr $ show sel
+#endif
+          ; case sel of
+            Parser ix ox sh -> do { inh <- openFile ix ReadMode
+                                  ; m <- testParser ix inh
+                                  ; if sh then
+                                      do { swth <- openFileOrStdout (fmap (\x -> x ++ ".show") ox)                                    
+                                         ; writeOutShow m swth
+                                         ; closeFileOrStdout ox swth
+                                         }
+                                      else 
+                                      do { outh <- openFileOrStdout ox              
+                                         ; writeOutLlvm m outh
+                                         ; closeFileOrStdout ox outh
+                                         }
+                                  ; hClose inh
+                                  }
+            AstCanonic ix ox -> do { inh <- openFile ix ReadMode
+                                   ; outh <- openFileOrStdout ox
+                                   ; ast <- testParser ix inh
+                                   ; let ast' = Cv.simplify ast
+                                   ; writeOutLlvm ast' outh
+                                   ; hClose inh
+                                   ; closeFileOrStdout ox outh
+                                   }
+
+            Ast2Ir ix ox -> do { inh <- openFile ix ReadMode
+                               ; outh <- openFileOrStdout ox
+                               ; ast <- testParser ix inh
+                               ; let ast' = Cv.simplify ast
+                               ; let (m, ir) = H.runSimpleUniqueMonad ((Cv.astToIr ast')::H.SimpleUniqueMonad (Cv.IdLabelMap, I.Module ()))
+                               ; writeOutIr ir outh
+                               ; hClose inh
+                               ; closeFileOrStdout ox outh
+                               }
+            Ir2Ast ix ox -> do { inh <- openFile ix ReadMode
+                               ; outh <- openFileOrStdout ox
+                               ; ast <- testParser ix inh
+                               ; let ast' = Cv.simplify ast
+                               ; let (m, ir) = testAst2Ir ast'
+                                     ast'' = testIr2Ast m ir
+                               ; writeOutLlvm ast'' outh
+                               ; hClose inh
+                               ; closeFileOrStdout ox outh
+                               }
+            PhiFixUp ix ox f -> do { inh <- openFile ix ReadMode
+                                   ; outh <- openFileOrStdout ox
+                                   ; ast <- testParser ix inh
+                                   ; let ast1 = Cv.simplify ast
+                                   ; let (m, ir) = testAst2Ir ast1
+                                   ; let ir1 = H.runSimpleUniqueMonad $ H.runWithFuel f 
+                                               ((O.optModule1 () N.fixUpPhi ir):: H.SimpleFuelMonad (I.Module ()))
+                                   ; let ast2 = testIr2Ast m ir1
+                                   ; writeOutLlvm ast2 outh
+                                   ; hClose inh
+                                   ; closeFileOrStdout ox outh
+                                   }
+            Pass ix ox passes f -> do { inh <- openFile ix ReadMode
+                                      ; outh <- openFileOrStdout ox
+                                      ; ast <- testParser ix inh
+                                      ; let ast1 = Cv.simplify ast
+                                      ; let (m, ir) = testAst2Ir ast1
+                                      ; let applySteps' = applySteps (extractSteps passes) ir
+                                      ; let ir1 = H.runSimpleUniqueMonad $ H.runWithFuel f 
+                                                  (applySteps' :: H.SimpleFuelMonad (I.Module ()))
+                                      ; let ir2 = H.runSimpleUniqueMonad $ H.runWithFuel f 
+                                                  ((O.optModule1 () N.fixUpPhi ir1) :: H.SimpleFuelMonad (I.Module ()))
+                                      ; let ast2 = testIr2Ast m ir2
+                                      ; writeOutLlvm ast2 outh
+                                      ; hClose inh
+                                      ; closeFileOrStdout ox outh
+                                      }
+            _ -> error $ "unexpected option " ++ show sel
+          }
+   where
+      testAst2Ir e = H.runSimpleUniqueMonad $ Cv.astToIr e
+      testIr2Ast m e = Cv.irToAst (Cv.invertMap (Cv.a2h m)) e
+
+
+
+openFileOrStdout :: Maybe FilePath -> IO Handle
+openFileOrStdout Nothing = return stdout
+openFileOrStdout (Just x) = openFile x WriteMode
+
+
+closeFileOrStdout :: Maybe FilePath -> Handle -> IO ()
+closeFileOrStdout Nothing h = hFlush h
+closeFileOrStdout (Just _) h = hClose h
diff --git a/src/ParserTester.hs b/src/ParserTester.hs
new file mode 100644
--- /dev/null
+++ b/src/ParserTester.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module ParserTester (testParser, writeOutLlvm, writeOutIr, writeOutShow) where
+import System.IO
+import Llvm.Syntax.Parser.Basic
+import Llvm.Syntax.Parser.Module
+import Llvm.Data.Ast
+import Llvm.Syntax.Printer.LlvmPrint
+import Llvm.Syntax.Printer.IrPrint
+import Data.List
+import Llvm.Data.Conversion
+
+displayError f s = 
+  let sLine = sourceLine $ errorPos s
+  in do 
+    { hPutStrLn stderr (hackFile sLine (sourceColumn $ errorPos s) f) 
+    ; hPutStrLn stderr (show (sourceColumn $ errorPos s))
+    ; hPutStrLn stderr (show s)
+    ; error ""
+    }
+  where 
+    hackFile :: Int -> Int -> [Char] -> [Char] 
+    hackFile sLine sCol l = let (_,ls) = mapAccumL f (0,0) l
+                            in ls
+      where
+        printx lx c x fx fc = if (lx < sLine) then ((fx lx,c), x)
+                              else if (lx == sLine) then
+                                     if (c < sCol) 
+                                     then ((lx, c+1), '^')
+                                     else if (c == sCol) 
+                                          then ((lx, c+1), '\n')
+                                          else ((lx, c), x) 
+                                   else 
+                                     ((lx,c), fc x) 
+        f :: (Int,Int)-> Char -> ((Int,Int), Char)
+        f (lx,c) '\n' = printx lx c '\n' (+1) id
+        f (lx,c) x = printx lx c x id (\_ -> '_')
+   
+
+testParser :: FilePath -> Handle -> IO Module
+testParser fileName inh = do { inpStr <- hGetContents inh
+                             ; case runParser (complete pModule) initState fileName inpStr of
+                               Left s -> displayError inpStr s
+                               Right e -> return e
+                             }
+                                       
+                          
+writeOutLlvm :: AsmPrint a => a -> Handle -> IO ()
+writeOutLlvm m outh = hPutStr outh (render $ toLlvm m)
+
+writeOutShow :: Show a => a -> Handle -> IO ()
+writeOutShow m outh = hPutStr outh (show m)
+
+writeOutIr :: IrPrint a => a -> Handle -> IO ()
+writeOutIr m outh = hPutStr outh (render $ printIr m)
