#ifndef ZAMALANG_SUPPORT_COMPILER_ENGINE_H #define ZAMALANG_SUPPORT_COMPILER_ENGINE_H #include #include #include #include #include #include #include #include namespace mlir { namespace zamalang { // Compilation context that acts as the root owner of LLVM and MLIR // data structures directly and indirectly referenced by artefacts // produced by the `CompilerEngine`. class CompilationContext { public: CompilationContext(); ~CompilationContext(); mlir::MLIRContext *getMLIRContext(); llvm::LLVMContext *getLLVMContext(); static std::shared_ptr createShared(); protected: mlir::MLIRContext *mlirContext; llvm::LLVMContext *llvmContext; }; class CompilerEngine { public: // Result of an invocation of the `CompilerEngine` with optional // fields for the results produced by different stages. class CompilationResult { public: CompilationResult(std::shared_ptr compilationContext = CompilationContext::createShared()) : compilationContext(compilationContext) {} llvm::Optional mlirModuleRef; llvm::Optional clientParameters; std::unique_ptr llvmModule; llvm::Optional fheContext; protected: std::shared_ptr compilationContext; }; class Library { std::string libraryPath; std::vector objectsPath; bool cleanUp; public: /** Create a library instance on which you can add compilation results. * Then you can emit a library file with the given path. * cleanUp at false keeps intermediate .obj files for later use. */ Library(std::string libraryPath, bool cleanUp = true) : libraryPath(libraryPath), cleanUp(cleanUp) {} /** Add a compilation result to the library */ llvm::Expected addCompilation(CompilationResult &compilation); /** Emit a shared library with the previously added compilation result */ llvm::Expected emitShared(); /** Emit a shared library with the previously added compilation result */ llvm::Expected emitStatic(); /** After a shared library has been emitted, its path is here */ std::string sharedLibraryPath; /** After a static library has been emitted, its path is here */ std::string staticLibraryPath; // For advanced use const static std::string OBJECT_EXT, LINKER, LINKER_SHARED_OPT, AR, AR_STATIC_OPT, DOT_STATIC_LIB_EXT, DOT_SHARED_LIB_EXT; void addExtraObjectFilePath(std::string objectFilePath); llvm::Expected emit(std::string dotExt, std::string linker); ~Library(); }; // Specification of the exit stage of the compilation pipeline enum class Target { // Only read sources and produce corresponding MLIR module ROUND_TRIP, // Read sources and exit before any lowering HLFHE, // Read sources and lower all HLFHE operations to MidLFHE // operations MIDLFHE, // Read sources and lower all HLFHE and MidLFHE operations to LowLFHE // operations LOWLFHE, // Read sources and lower all HLFHE, MidLFHE and LowLFHE // operations to canonical MLIR dialects. Cryptographic operations // are lowered to invocations of the concrete library. STD, // Read sources and lower all HLFHE, MidLFHE and LowLFHE // operations to operations from the LLVM dialect. Cryptographic // operations are lowered to invocations of the concrete library. LLVM, // Same as `LLVM`, but lowers to actual LLVM IR instead of the // LLVM dialect LLVM_IR, // Same as `LLVM_IR`, but invokes the LLVM optimization pipeline // to produce optimized LLVM IR OPTIMIZED_LLVM_IR, // Same as `OPTIMIZED_LLVM_IR`, but compiles and add an object file to a // futur library LIBRARY }; CompilerEngine(std::shared_ptr compilationContext) : overrideMaxEintPrecision(), overrideMaxMANP(), clientParametersFuncName(), verifyDiagnostics(false), generateClientParameters(false), enablePass([](mlir::Pass *pass) { return true; }), compilationContext(compilationContext) {} llvm::Expected compile(llvm::StringRef s, Target target, llvm::Optional> lib = {}); llvm::Expected compile(std::unique_ptr buffer, Target target, llvm::Optional> lib = {}); llvm::Expected compile(llvm::SourceMgr &sm, Target target, llvm::Optional> lib = {}); template llvm::Expected compile(std::vector inputs, std::string libraryPath); void setFHEConstraints(const mlir::zamalang::V0FHEConstraint &c); void setMaxEintPrecision(size_t v); void setMaxMANP(size_t v); void setVerifyDiagnostics(bool v); void setGenerateClientParameters(bool v); void setClientParametersFuncName(const llvm::StringRef &name); void setHLFHELinalgTileSizes(llvm::ArrayRef sizes); void setEnablePass(std::function enablePass); protected: llvm::Optional overrideMaxEintPrecision; llvm::Optional overrideMaxMANP; llvm::Optional clientParametersFuncName; llvm::Optional> hlfhelinalgTileSizes; bool verifyDiagnostics; bool generateClientParameters; std::function enablePass; std::shared_ptr compilationContext; private: llvm::Expected> getV0FHEConstraint(CompilationResult &res); llvm::Error determineFHEParameters(CompilationResult &res); }; } // namespace zamalang } // namespace mlir #endif