From af4466197ea77bd2a6a3aee4a499ed3bde269dca Mon Sep 17 00:00:00 2001 From: Stella Laurenzo Date: Sun, 7 Jun 2020 14:29:39 -0700 Subject: [PATCH] Add lit test suite for python compiler. * Adds a test for simple constants and fixes issues. --- CMakeLists.txt | 1 + include/npcomp/Dialect/Basicpy/BasicpyOps.td | 7 ++ pytest/CMakeLists.txt | 20 +++++ pytest/Compiler/constants.py | 29 +++++++ pytest/lit.cfg.py | 82 ++++++++++++++++++++ pytest/lit.site.cfg.py.in | 49 ++++++++++++ python/npcomp/compiler/frontend.py | 4 +- python/npcomp/compiler/logging.py | 2 +- python/npcomp/dialect/Basicpy.py | 3 + test/lit.cfg.py | 2 +- 10 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 pytest/CMakeLists.txt create mode 100644 pytest/Compiler/constants.py create mode 100644 pytest/lit.cfg.py create mode 100644 pytest/lit.site.cfg.py.in diff --git a/CMakeLists.txt b/CMakeLists.txt index f9a85f803..7606d20eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ add_subdirectory(include/npcomp) add_subdirectory(lib) add_subdirectory(python) add_subdirectory(python_native) +add_subdirectory(pytest) add_subdirectory(runtime) add_subdirectory(tools) add_subdirectory(test) diff --git a/include/npcomp/Dialect/Basicpy/BasicpyOps.td b/include/npcomp/Dialect/Basicpy/BasicpyOps.td index 81289761f..2f80ccbaa 100644 --- a/include/npcomp/Dialect/Basicpy/BasicpyOps.td +++ b/include/npcomp/Dialect/Basicpy/BasicpyOps.td @@ -13,6 +13,13 @@ include "BasicpyDialect.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/SymbolInterfaces.td" +def Basicpy_UnknownCastOp : Basicpy_Op<"unknown_cast", [NoSideEffect]> { + let summary = "Casts to and from the UnknownType"; + let arguments = (ins AnyType:$input); + let results = (outs AnyType:$result); + let assemblyFormat = "operands attr-dict `:` type(operands) `->` type(results)"; +} + def Basicpy_SingletonOp : Basicpy_Op<"singleton", [ ConstantLike, NoSideEffect]> { let summary = "Constant value for a singleton type"; diff --git a/pytest/CMakeLists.txt b/pytest/CMakeLists.txt new file mode 100644 index 000000000..553723688 --- /dev/null +++ b/pytest/CMakeLists.txt @@ -0,0 +1,20 @@ +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py + MAIN_CONFIG + ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py +) + +set(NPCOMP_TEST_DEPENDS + FileCheck count not + npcomp-opt + NPCOMPNativePyExt +) + +add_lit_testsuite(check-npcomp-pytest "Running npcomp python lit tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${NPCOMP_TEST_DEPENDS} + ) +set_target_properties(check-npcomp-pytest PROPERTIES FOLDER "Tests") + +add_lit_testsuites(NPCOMP_PYTEST ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${NPCOMP_TEST_DEPENDS}) diff --git a/pytest/Compiler/constants.py b/pytest/Compiler/constants.py new file mode 100644 index 000000000..b292f2e8a --- /dev/null +++ b/pytest/Compiler/constants.py @@ -0,0 +1,29 @@ +# RUN: %PYTHON %s | npcomp-opt -split-input-file | FileCheck %s --dump-input=fail + +from npcomp.compiler.frontend import * + + +def import_global(f): + fe = ImportFrontend() + fe.import_global_function(f) + print("// -----") + print(fe.ir_module.to_asm()) + + +# CHECK: func @integer_constants +@import_global +def integer_constants(): + # CHECK: %[[A:.*]] = constant 100 : i64 + a = 100 + # CHECK: %[[A_CAST:.*]] = basicpy.unknown_cast %[[A]] : i64 -> !basicpy.UnknownType + # CHECK: return %[[A_CAST]] + return a + +# CHECK: func @float_constants +@import_global +def float_constants(): + # CHECK: %[[A:.*]] = constant 2.200000e+00 : f64 + a = 2.2 + # CHECK: %[[A_CAST:.*]] = basicpy.unknown_cast %[[A]] : f64 -> !basicpy.UnknownType + # CHECK: return %[[A_CAST]] + return a diff --git a/pytest/lit.cfg.py b/pytest/lit.cfg.py new file mode 100644 index 000000000..5858213b7 --- /dev/null +++ b/pytest/lit.cfg.py @@ -0,0 +1,82 @@ +# -*- Python -*- + +import os +import platform +import re +import subprocess +import sys +import tempfile + +import lit.formats +import lit.util + +from lit.llvm import llvm_config +from lit.llvm.subst import ToolSubst +from lit.llvm.subst import FindTool + +# Configuration file for the 'lit' test runner. + +# name: The name of this test suite. +config.name = 'NPCOMP_PYTEST' + +config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) + +# suffixes: A list of file extensions to treat as test files. +config.suffixes = ['.mlir', '.py'] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) + +# test_exec_root: The root path where tests should be run. +config.test_exec_root = os.path.join(config.npcomp_obj_root, 'pytest') + +config.substitutions.append(('%PATH%', config.environment['PATH'])) +config.substitutions.append(('%shlibext', config.llvm_shlib_ext)) +config.substitutions.append(('%PYTHON', config.python_executable)) + +llvm_config.with_system_environment( + ['HOME', 'INCLUDE', 'LIB', 'TMP', 'TEMP']) + +llvm_config.use_default_substitutions() + +# excludes: A list of files/directories to exclude from the testsuite. The +# 'Inputs'subdirectories contain auxiliary inputs for various tests in their +# parent directories. +config.excludes = [ + 'Inputs', 'Examples', + 'lit.cfg.py', + 'CMakeLists.txt', + 'README.txt', + 'LICENSE.txt'] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) + +# test_exec_root: The root path where tests should be run. +config.test_exec_root = os.path.join(config.npcomp_obj_root, 'pytest') +config.npcomp_tools_dir = os.path.join(config.npcomp_obj_root, 'tools') +config.npcomp_runtime_shlib = os.path.join( + config.npcomp_obj_root, + 'runtime', + 'libNPCOMPRuntime' + config.llvm_shlib_ext +) + +# Tweak the PATH and PYTHONPATH to include the tools dir. +llvm_config.with_environment('PATH', config.llvm_tools_dir, append_path=True) +llvm_config.with_environment('PYTHONPATH', [ + os.path.join(config.npcomp_obj_root, "python"), + os.path.join(config.npcomp_obj_root, "python_native")], + append_path=True) + +tool_dirs = [ + os.path.join(config.npcomp_tools_dir, 'npcomp-opt'), + os.path.join(config.npcomp_tools_dir, 'npcomp-run-mlir'), + config.llvm_tools_dir, +] +tools = [ + 'npcomp-opt', + 'npcomp-run-mlir', + ToolSubst('%npcomp_runtime_shlib', config.npcomp_runtime_shlib), +] + +llvm_config.add_tool_substitutions(tools, tool_dirs) diff --git a/pytest/lit.site.cfg.py.in b/pytest/lit.site.cfg.py.in new file mode 100644 index 000000000..c048d6af0 --- /dev/null +++ b/pytest/lit.site.cfg.py.in @@ -0,0 +1,49 @@ +@LIT_SITE_CFG_IN_HEADER@ + +import sys + +config.host_triple = "@LLVM_HOST_TRIPLE@" +config.target_triple = "@TARGET_TRIPLE@" +config.llvm_src_root = "@LLVM_SOURCE_DIR@" +config.llvm_obj_root = "@LLVM_BINARY_DIR@" +config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" +config.llvm_lib_dir = "@LLVM_LIBRARY_DIR@" +config.llvm_shlib_dir = "@SHLIBDIR@" +config.llvm_shlib_ext = "@SHLIBEXT@" +config.llvm_exe_ext = "@EXEEXT@" +config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" +config.python_executable = "@PYTHON_EXECUTABLE@" +config.gold_executable = "@GOLD_EXECUTABLE@" +config.ld64_executable = "@LD64_EXECUTABLE@" +config.enable_shared = @ENABLE_SHARED@ +config.enable_assertions = @ENABLE_ASSERTIONS@ +config.targets_to_build = "@TARGETS_TO_BUILD@" +config.native_target = "@LLVM_NATIVE_ARCH@" +config.llvm_bindings = "@LLVM_BINDINGS@".split(' ') +config.host_os = "@HOST_OS@" +config.host_cc = "@HOST_CC@" +config.host_cxx = "@HOST_CXX@" +# Note: ldflags can contain double-quoted paths, so must use single quotes here. +config.host_ldflags = '@HOST_LDFLAGS@' +config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@" +config.llvm_host_triple = '@LLVM_HOST_TRIPLE@' +config.host_arch = "@HOST_ARCH@" +config.npcomp_src_root = "@CMAKE_SOURCE_DIR@" +config.npcomp_obj_root = "@CMAKE_BINARY_DIR@" + +# Support substitution of the tools_dir with user parameters. This is +# used when we can't determine the tool dir at configuration time. +try: + config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params + config.llvm_shlib_dir = config.llvm_shlib_dir % lit_config.params +except KeyError: + e = sys.exc_info()[1] + key, = e.args + lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) + + +import lit.llvm +lit.llvm.initialize(lit_config, config) + +# Let the main config do the real work. +lit_config.load_config(config, "@CMAKE_SOURCE_DIR@/pytest/lit.cfg.py") diff --git a/python/npcomp/compiler/frontend.py b/python/npcomp/compiler/frontend.py index e4545a478..03c2facbb 100644 --- a/python/npcomp/compiler/frontend.py +++ b/python/npcomp/compiler/frontend.py @@ -166,7 +166,9 @@ class FunctionDefImporter(BaseNodeVisitor): ir_h = self.fctx.ir_h expr = ExpressionImporter(self.fctx) expr.visit(ast_node.value) - ir_h.return_op([expr.value]) + casted = ir_h.basicpy_unknown_cast(ir_h.basicpy_UnknownType, + expr.value).result + ir_h.return_op([casted]) class ExpressionImporter(BaseNodeVisitor): diff --git a/python/npcomp/compiler/logging.py b/python/npcomp/compiler/logging.py index b0270cf38..b115d3e22 100644 --- a/python/npcomp/compiler/logging.py +++ b/python/npcomp/compiler/logging.py @@ -5,7 +5,7 @@ import string import sys -_ENABLED = True +_ENABLED = False _formatter = string.Formatter() diff --git a/python/npcomp/dialect/Basicpy.py b/python/npcomp/dialect/Basicpy.py index f815817e5..eae2d3678 100644 --- a/python/npcomp/dialect/Basicpy.py +++ b/python/npcomp/dialect/Basicpy.py @@ -47,6 +47,9 @@ class DialectHelper(_BaseDialectHelper): """ + def basicpy_unknown_cast(self, result_type, operand): + return self.op("basicpy.unknown_cast", [result_type], [operand]) + def basicpy_singleton_op(self, singleton_type): return self.op("basicpy.singleton", [singleton_type], []) diff --git a/test/lit.cfg.py b/test/lit.cfg.py index 8ce822bb2..c7ad989eb 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -21,7 +21,7 @@ config.name = 'NPCOMP_OPT' config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) # suffixes: A list of file extensions to treat as test files. -config.suffixes = ['.mlir'] +config.suffixes = ['.mlir', '.mlir.py'] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__)