accelerate-llvm-1.4.0.0: src/LLVM/AST/Type/Constant.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_HADDOCK hide #-}
-- |
-- Module : LLVM.AST.Type.Constant
-- Copyright : [2015..2020] The Accelerate Team
-- License : BSD3
--
-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability : experimental
-- Portability : non-portable (GHC extensions)
--
module LLVM.AST.Type.Constant
where
import LLVM.AST.Type.Downcast
import LLVM.AST.Type.GetElementPtr
import LLVM.AST.Type.Name
import LLVM.AST.Type.Representation
import qualified Data.Array.Accelerate.LLVM.Internal.LLVMPretty as LLVM
import Data.Constraint
import Data.Primitive.ByteArray
import Data.Primitive.Types
import Data.Primitive.Vec
-- | Although constant expressions and instructions have many similarities,
-- there are important differences - so they're represented using different
-- types in this AST. At the cost of making it harder to move an code back and
-- forth between being constant and not, this approach embeds more of the rules
-- of what IR is legal into the Haskell types.
--
-- <http://llvm.org/docs/LangRef.html#constants>
--
-- <http://llvm.org/docs/LangRef.html#constant-expressions>
--
data Constant a where
ScalarConstant :: ScalarType a
-> a
-> Constant a
BooleanConstant :: Bool
-> Constant Bool
UndefConstant :: Type a
-> Constant a
NullPtrConstant :: Type (Ptr a)
-> Constant (Ptr a)
GlobalReference :: Type a
-> Name a
-> Constant a
ConstantGetElementPtr :: GetElementPtr Constant (Ptr a) (Ptr b)
-> Constant (Ptr b)
-- | Convert to llvm-pretty
--
instance Downcast (Constant a) (LLVM.Typed LLVM.Value) where
downcast = \case
UndefConstant t -> LLVM.Typed (downcast t) LLVM.ValUndef
GlobalReference t n -> LLVM.Typed (downcast t) (LLVM.ValSymbol (nameToPrettyS n))
instr@(ConstantGetElementPtr (GEP t n i1 path)) ->
LLVM.Typed (downcast (typeOf instr)) (LLVM.ValConstExpr (LLVM.ConstGEP inbounds Nothing (downcast t) (downcast n) (downcast i1 : downcast path)))
BooleanConstant x -> LLVM.Typed (LLVM.PrimType (LLVM.Integer 1)) (LLVM.ValInteger (toInteger (fromEnum x)))
NullPtrConstant t -> LLVM.Typed (downcast t) LLVM.ValNull
ScalarConstant t x -> scalar t x
where
scalar :: ScalarType s -> s -> LLVM.Typed LLVM.Value
scalar (SingleScalarType s) = single s
scalar (VectorScalarType s) = vector s
single :: SingleType s -> s -> LLVM.Typed LLVM.Value
single (NumSingleType s) = num s
vector :: VectorType s -> s -> LLVM.Typed LLVM.Value
vector (VectorType n s) (Vec ba#)
= LLVM.Typed (LLVM.Vector (fromIntegral n) (downcast s))
$ LLVM.ValVector (downcast s)
$ map (LLVM.typedValue . single s)
$ singlePrim s `withDict` foldrByteArray (:) [] (ByteArray ba#)
num :: NumType s -> s -> LLVM.Typed LLVM.Value
num (IntegralNumType s) v
| IntegralDict <- integralDict s
= LLVM.Typed (downcast s) (LLVM.ValInteger (fromIntegral v))
num (FloatingNumType s) v
= case s of
TypeFloat -> LLVM.Typed (LLVM.PrimType (LLVM.FloatType LLVM.Float)) (LLVM.ValFloat v)
TypeDouble -> LLVM.Typed (LLVM.PrimType (LLVM.FloatType LLVM.Double)) (LLVM.ValDouble v)
TypeHalf | Half (CUShort _u) <- v ->
-- LLVM.Typed (LLVM.PrimType (LLVM.FloatType LLVM.Half)) (_ _u)
error "TODO: Half floats unsupported by llvm-pretty"
singlePrim :: SingleType s -> Dict (Prim s)
singlePrim (NumSingleType s) = numPrim s
numPrim :: NumType s -> Dict (Prim s)
numPrim (IntegralNumType s) = integralPrim s
numPrim (FloatingNumType s) = floatingPrim s
integralPrim :: IntegralType s -> Dict (Prim s)
integralPrim TypeInt = Dict
integralPrim TypeInt8 = Dict
integralPrim TypeInt16 = Dict
integralPrim TypeInt32 = Dict
integralPrim TypeInt64 = Dict
integralPrim TypeWord = Dict
integralPrim TypeWord8 = Dict
integralPrim TypeWord16 = Dict
integralPrim TypeWord32 = Dict
integralPrim TypeWord64 = Dict
floatingPrim :: FloatingType s -> Dict (Prim s)
floatingPrim TypeHalf = Dict
floatingPrim TypeFloat = Dict
floatingPrim TypeDouble = Dict
inbounds :: [LLVM.GEPAttr]
inbounds = [LLVM.GEP_Inbounds]
instance TypeOf Constant where
typeOf (BooleanConstant _) = type'
typeOf (ScalarConstant t _) = PrimType (ScalarPrimType t)
typeOf (UndefConstant t) = t
typeOf (NullPtrConstant t) = t
typeOf (GlobalReference t _) = t
typeOf (ConstantGetElementPtr gep) = typeOf gep