{- CAO Compiler Copyright (C) 2014 Cryptography and Information Security Group, HASLab - INESC TEC and Universidade do Minho This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} {- | Module : $Header$ Description : Queries about the target platform. Copyright : (C) 2014 Cryptography and Information Security Group, HASLab - INESC TEC and Universidade do Minho License : GPL Maintainer : Paulo Silva Stability : experimental Portability : non-portable Query and utility functions about the target platform. -} module Language.CAO.Platform.Query where import Control.Monad import Data.Array import Data.Maybe import Language.CAO.Common.Error import Language.CAO.Common.Literal import Language.CAO.Common.Monad import Language.CAO.Common.Polynomial import Language.CAO.Common.SrcLoc import Language.CAO.Common.Var import Language.CAO.Index import Language.CAO.Platform.Literals import Language.CAO.Platform.Naming import Language.CAO.Platform.Specification import Language.CAO.Type -------------------------------------------------------------------------------- -- These are the main query function which are used to encapsulate all searches. queryTTS :: TypeTransSpec -> [TypeSpec] queryTTS tts = map snd (ubitsT tts) ++ map snd (sbitsT tts) ++ map snd (modT tts) ++ map snd (vectorT tts) ++ map snd (matrixT tts) ++ (catMaybes $ boolT tts : intT tts : rintT tts : structT tts : modpolT tts : []) {- - Translations for matrices with just one dimension specified? - Structs of differnt sizes -} query :: TranslationSpec -> Type Var -> Maybe TypeSpec query tspec typ = either id (uncurry sizedTypeQuery) (worker typ) $ typeTransSpec tspec where worker tp = case tp of Int -> Left intT RInt -> Left rintT Bool -> Left boolT Bits sg n -> let f = case sg of U -> ubitsT S -> sbitsT in Right (f, auxIndex n) Mod Nothing Nothing (Pol [Mon (CoefI m) EZero]) -> Right (modT, auxIndex m) Mod _ _ _ -> Left modpolT -- TODO: specific polynomial Vector n _ -> Right (vectorT, auxIndex n) Matrix n m _ -> Right (matrixT, combineM (auxIndex n) (auxIndex m)) Struct {} -> Left structT SField _ t -> worker t Index _ _ t -> worker t _ -> error "query: Not expectd type" auxIndex n = case n of IInt n' -> Simple n' IInd v -> case indConst v of Just (IInt n') -> Simple n' _ -> Generic _ -> Generic combineM (Simple n) (Simple m) = MSize n m combineM _ _ = Generic sizedTypeQuery :: (TypeTransSpec -> [(Size, TypeSpec)]) -> Size -> TypeTransSpec -> Maybe TypeSpec sizedTypeQuery typ size ttspec = let t = typ ttspec in maybe (lookup Generic t) Just $ lookup size t -------------------------------------------------------------------------------- -- Checks the query result, and raises an exception if the type is not supported. queryType :: CaoMonad m => TranslationSpec -> Type Var -> m TypeSpec queryType tspec typ = maybe (caoError defSrcLoc $ NotSupportedTypeErr typ) return $ query tspec typ queryOperation :: CaoMonad m => TranslationSpec -> Type Var -> OpCode -> m (OpReturn, Consts, SafetyConv) queryOperation tspec typ op = do m <- queryType tspec typ maybe (caoError defSrcLoc $ NotSupportedOp (operationNames ! op) typ) return $ operations m ! op -------------------------------------------------------------------------------- varOrMacroDecl :: CaoMonad m => TranslationSpec -> Type Var -> m a -> m a -> m a varOrMacroDecl tspec typ f1 f2 = queryType tspec typ >>= aux . declConv where aux VarDecl = f1 aux MacroDecl = f2 autoOrAlloc :: CaoMonad m => TranslationSpec -> Type Var -> m a -> m a -> m a autoOrAlloc tspec typ f1 f2 = queryType tspec typ >>= aux . memoryConv where aux Auto = f1 aux AutoRef = f1 aux Alloc = f2 valOrRef :: CaoMonad m => TranslationSpec -> Type Var -> m a -> m a -> m a valOrRef tspec typ f1 f2 = queryType tspec typ >>= aux . memoryConv where aux Auto = f1 aux AutoRef = f2 aux Alloc = f2 valOrRefFuncReturn :: CaoMonad m => TranslationSpec -> Type Var -> m a -> m a -> m a valOrRefFuncReturn tspec typ f1 f2 = queryType tspec typ >>= aux . funcCall where aux FFuncReturn = f1 aux FFuncRef = f2 valOrRefOpReturn :: CaoMonad m => TranslationSpec -> Type Var -> OpCode -> m a -> m a -> m a valOrRefOpReturn tspec typ op f1 f2 = queryOperation tspec typ op >>= aux where aux (rc, _, _) = case rc of OMacroReturn -> f1 OFuncReturn -> f1 OMacroRef -> f2 OFuncRef -> f2 opReturnKind' :: CaoMonad m => TranslationSpec -> Type Var -> OpCode -> m a -> m a -> m a -> m a -> m a opReturnKind' tspec typ op f1 f2 f3 f4 = queryOperation tspec typ op >>= aux where aux (rc, _, _) = case rc of OFuncReturn -> f1 OFuncRef -> f2 OMacroReturn -> f3 OMacroRef -> f4 valOrRefOpMacroReturn :: CaoMonad m => TranslationSpec -> Type Var -> OpCode -> m a -> m a -> m a valOrRefOpMacroReturn tspec typ op f1 f2 = queryOperation tspec typ op >>= aux where aux (rc, _, _) = case rc of OMacroReturn -> f1 OMacroRef -> f2 _ -> caoError defSrcLoc $ NotSupportedOp (operationNames ! op) typ globalOrInlinedField :: CaoMonad m => TranslationSpec -> m a -> m a -> m a globalOrInlinedField tspec f1 f2 = case structFields $ globalTransSpec tspec of GlobalF -> f1 InlinedF -> f2 safeOfUnsafe :: CaoMonad m => TranslationSpec -> Type Var -> OpCode -> m a -> m a -> m a -> m a safeOfUnsafe tspec typ op f1 f2 f3 = queryOperation tspec typ op >>= aux where aux (_,_, saf) = case saf of Safe -> f1 Unsafe -> f2 ArgSafe -> f3 safeOrUnsafeDefault :: CaoMonad m => TranslationSpec -> m a -> m a -> m a -> m a safeOrUnsafeDefault tspec f1 f2 f3 = case defaultSafety $ globalTransSpec tspec of Safe -> f1 Unsafe -> f2 ArgSafe -> f3 checkLiteral :: CaoMonad m => TranslationSpec -> Type Var -> m a -> (LitCheck -> m a) -> m a checkLiteral tspec typ f1 f2 = queryType tspec typ >>= maybe f1 f2 . literal -------------------------------------------------------------------------------- -- Encapsulated queries -- How to deal with literals operandKind :: CaoMonad m => TranslationSpec -> Type Var -> OpCode -> m Consts operandKind tspec typ op = queryOperation tspec typ op >>= aux where aux (_, rc, _) = return rc operandKindGeneral :: CaoMonad m => TranslationSpec -> Type Var -> m Consts operandKindGeneral tspec typ = liftM operands $ queryType tspec typ codes :: CaoMonad m => TranslationSpec -> Type Var -> m String codes tspec typ = liftM code $ queryType tspec typ typeName :: CaoMonad m => TranslationSpec -> Type Var -> m String typeName tspec typ = liftM nameInPlat $ queryType tspec typ existsModWithBase :: TranslationSpec -> Integer -> Bool existsModWithBase tspec n = maybe False (const True) $ lookup (Simple n) $ modT $ typeTransSpec tspec