Skip to content

Commit

Permalink
[pybindings] add test
Browse files Browse the repository at this point in the history
  • Loading branch information
makslevental committed Nov 26, 2024
1 parent b9ba6af commit 8e3882b
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "Build EUDSL"
name: "Build and test EUDSL"

on:
workflow_dispatch:
Expand Down Expand Up @@ -32,7 +32,7 @@ concurrency:
cancel-in-progress: true

jobs:
build:
build-eudsl-tblgen:

strategy:
fail-fast: false
Expand All @@ -54,7 +54,7 @@ jobs:

runs-on: ${{ matrix.runs-on }}

name: ${{ matrix.name }}
name: "Build eudsl-tblgen ${{ matrix.name }}"

defaults:
run:
Expand Down Expand Up @@ -84,6 +84,7 @@ jobs:
cache-key: ${{ env.cache-key }}
restore-key: "eudsl_${{ matrix.name }}_clang"
os: ${{ matrix.os }}
arch: ${{ matrix.arch }}

- name: "Download MLIR"
env:
Expand All @@ -93,52 +94,23 @@ jobs:
RELEASE_URL=$(gh release view latest --json assets -q '.assets |= sort_by(.createdAt) | .assets | map(select(.name | contains(env.RELEASE_PREFIX))) | .[-1] | .url')
curl -sLO $RELEASE_URL
tar xf $RELEASE_PREFIX*.tar.gz
echo "LLVM_DIR=$PWD/llvm-install/lib/cmake/llvm" >> $GITHUB_ENV
- name: "Build eudsl-tblgen"
id: build
run: |
export CMAKE_PREFIX_PATH="$PWD/llvm-install"
export EUDSL_SRC_DIR="$PWD/projects/eudsl"
export EUDSL_BUILD_DIR="$PWD/eudsl-build"
export EUDSL_INSTALL_DIR="$PWD/eudsl-install"
ccache -z
cmake -GNinja \
-S "$EUDSL_SRC_DIR" \
-B "$EUDSL_BUILD_DIR" \
-DCMAKE_BUILD_TYPE=Release \
"-DCMAKE_PREFIX_PATH=$PWD/__w/eudsl/eudsl/llvm-install/llvm-install" \
"-DCMAKE_INSTALL_PREFIX=$EUDSL_INSTALL_DIR"
cmake --build "$EUDSL_BUILD_DIR" --target install
$python3_command -m pip wheel "$EUDSL_SRC_DIR/eudsl-tblgen" -w wheelhouse
ccache -s
echo "*********************** SMOKE TEST *********************************"
"$EUDSL_INSTALL_DIR/bin/eudsl-tblgen" --help
echo "*********************** SMOKE TEST *********************************"
SHA_SHORT=$(git rev-parse --short HEAD)
tar -czf eudsl_tblgen_${{ matrix.name }}_$(date +'%Y%m%d')_$SHA_SHORT.tar.gz -C "$EUDSL_INSTALL_DIR" bin
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: eudsl_${{ matrix.name }}_artifact
path: eudsl-install/bin
name: eudsl_tblgen_${{ matrix.name }}_artifact
path: wheelhouse/*.whl
if-no-files-found: warn

- name: Release current commit
if: ${{ !cancelled() && github.event_name == 'push' && github.ref_name == 'main' }}
uses: ncipollo/[email protected]
with:
artifacts: "*.tar.gz"
token: "${{ secrets.GITHUB_TOKEN }}"
tag: "latest"
name: "latest"
removeArtifacts: false
allowUpdates: true
replacesArtifacts: true
makeLatest: true

- name: "Save cache"
uses: actions/cache/save@v3
if: ${{ !cancelled() && github.event_name == 'push' && github.ref_name == 'main' }}
Expand All @@ -152,3 +124,65 @@ jobs:
with:
limit-access-to-actor: true
install-dependencies: ${{ startsWith(matrix.runs-on, 'macos') || startsWith(matrix.runs-on, 'windows') }}

test-eudsl-tblgen:

needs: [build-eudsl-tblgen]

strategy:
fail-fast: false
matrix:
include:
- name: "manylinux_x86_64"
runs-on: "ubuntu-22.04"
container: "quay.io/pypa/manylinux_2_28_x86_64"
os: "almalinux"
- name: "windows_x86_64"
runs-on: "windows-2019"
os: "windows"
- name: "macos_arm64"
runs-on: "macos-14"
os: "macos"
- name: "macos_x86_64"
runs-on: "macos-13"
os: "macos"

runs-on: ${{ matrix.runs-on }}

name: "Test eudsl-tblgen ${{ matrix.name }}"

defaults:
run:
shell: bash

container:
image: ${{ matrix.container }}

steps:
- name: "Check out repository"
uses: actions/[email protected]
with:
submodules: false

- name: "Install Python"
uses: actions/setup-python@v4
with:
python-version: '3.12'

- uses: actions/download-artifact@v3
with:
name: eudsl_tblgen_${{ matrix.name }}_artifact
path: wheelhouse

- name: "Install eudsl-tblgen"
run: |
pip install wheelhouse/eudsl_tblgen*.whl
pip install pytest
- name: "Test eudsl-tblgen"
run: |
if [ ${{ matrix.os }} == 'windows' ]; then
pytest -s projects/eudsl/eudsl-tblgen/tests
else
pytest --capture=tee-sys projects/eudsl/eudsl-tblgen/tests
fi
30 changes: 30 additions & 0 deletions projects/eudsl/eudsl-tblgen/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[build-system]
requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"]
build-backend = "scikit_build_core.build"

[project]
name = "eudsl-tblgen"
version = "0.0.1"
requires-python = ">=3.8"

[project.urls]
Homepage = "https://github.com/llvm/eudsl"

[tool.scikit-build]
minimum-version = "0.4"
build-dir = "build/{wheel_tag}"
wheel.py-api = "cp312"
cmake.source-dir = "src"

[tool.scikit-build.cmake.define]
LLVM_DIR = {env="LLVM_DIR", default="EMPTY"}
CMAKE_CXX_VISIBILITY_PRESET = "hidden"

[tool.cibuildwheel]
build-verbosity = 1
test-command = "pytest {project}/tests"
test-requires = "pytest"
test-skip="cp38-macosx_*:arm64"

[tool.cibuildwheel.macos.environment]
MACOSX_DEPLOYMENT_TARGET = "10.14"
72 changes: 40 additions & 32 deletions projects/eudsl/eudsl-tblgen/src/eudsl_tblgen_ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,6 @@ using namespace llvm;
namespace nb = nanobind;
using namespace nb::literals;

void parseTD(RecordKeeper &Records, const std::string &InputFilename,
const std::vector<std::string> &IncludeDirs,
const std::vector<std::string> &MacroNames,
bool NoWarnOnUnusedTemplateArgs) {
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
MemoryBuffer::getFileOrSTDIN(InputFilename, /*IsText=*/true);
if (std::error_code EC = FileOrErr.getError())
throw std::runtime_error("Could not open input file '" + InputFilename +
"': " + EC.message() + "\n");
Records.saveInputFilename(InputFilename);
SourceMgr SrcMgr;
SrcMgr.AddNewSourceBuffer(std::move(*FileOrErr), SMLoc());
SrcMgr.setIncludeDirs(IncludeDirs);
TGParser Parser(SrcMgr, MacroNames, Records, NoWarnOnUnusedTemplateArgs);
if (Parser.ParseFile())
throw std::runtime_error("Could not parse file '" + InputFilename);
}

template <typename NewReturn, typename Return, typename... Args>
constexpr auto coerceReturn(Return (*pf)(Args...)) noexcept {
return [&pf](Args &&...args) -> NewReturn {
Expand Down Expand Up @@ -96,8 +78,7 @@ NB_MODULE(eudsl_tblgen_ext, m) {
.value("StringRecTyKind", RecTy::RecTyKind::StringRecTyKind)
.value("ListRecTyKind", RecTy::RecTyKind::ListRecTyKind)
.value("DagRecTyKind", RecTy::RecTyKind::DagRecTyKind)
.value("RecordRecTyKind", RecTy::RecTyKind::RecordRecTyKind)
.export_values();
.value("RecordRecTyKind", RecTy::RecTyKind::RecordRecTyKind);

recty.def_prop_ro("rec_ty_kind", &RecTy::getRecTyKind)
.def_prop_ro("record_keeper", &RecTy::getRecordKeeper)
Expand All @@ -110,7 +91,8 @@ NB_MODULE(eudsl_tblgen_ext, m) {
.def_prop_ro(
"classes",
coerceReturn<std::vector<const Record *>, ArrayRef<const Record *>>(
&RecordRecTy::getClasses, nb::const_))
&RecordRecTy::getClasses, nb::const_),
nb::rv_policy::reference_internal)
.def("is_sub_class_of", &RecordRecTy::isSubClassOf);

nb::class_<RecordVal>(m, "RecordVal")
Expand All @@ -129,12 +111,14 @@ NB_MODULE(eudsl_tblgen_ext, m) {
// .def_prop_ro("value", &RecordVal::getValue)

nb::class_<Record>(m, "Record")
.def_prop_ro("direct_super_classes",
[](const Record &self) -> std::vector<const Record *> {
SmallVector<const Record *> Classes;
self.getDirectSuperClasses(Classes);
return {Classes.begin(), Classes.end()};
})
.def_prop_ro(
"direct_super_classes",
[](const Record &self) -> std::vector<const Record *> {
SmallVector<const Record *> Classes;
self.getDirectSuperClasses(Classes);
return {Classes.begin(), Classes.end()};
},
nb::rv_policy::reference_internal)
.def_prop_ro("id", &Record::getID)
.def_prop_ro("name", &Record::getName)
.def_prop_ro("name_init_as_string", &Record::getNameInitAsString)
Expand Down Expand Up @@ -219,14 +203,38 @@ NB_MODULE(eudsl_tblgen_ext, m) {

nb::class_<RecordKeeper>(m, "RecordKeeper")
.def(nb::init<>())
.def("parse_td", &parseTD, "input_filename"_a, "include_dirs"_a,
"macro_names"_a = nb::list(),
"no_warn_on_unused_template_args"_a = true)
.def(
"parse_td",
[](RecordKeeper &self, const std::string &inputFilename,
const std::vector<std::string> &includeDirs,
const std::vector<std::string> &macroNames,
bool noWarnOnUnusedTemplateArgs) {
ErrorOr<std::unique_ptr<MemoryBuffer>> fileOrErr =
MemoryBuffer::getFileOrSTDIN(inputFilename, /*IsText=*/true);
if (std::error_code EC = fileOrErr.getError())
throw std::runtime_error("Could not open input file '" +
inputFilename + "': " + EC.message() +
"\n");
self.saveInputFilename(inputFilename);
SourceMgr srcMgr;
srcMgr.AddNewSourceBuffer(std::move(*fileOrErr), SMLoc());
srcMgr.setIncludeDirs(includeDirs);
TGParser tgParser(srcMgr, macroNames, self,
noWarnOnUnusedTemplateArgs);
if (tgParser.ParseFile())
throw std::runtime_error("Could not parse file '" +
inputFilename);
return &self;
},
"input_filename"_a, "include_dirs"_a = nb::list(),
"macro_names"_a = nb::list(),
"no_warn_on_unused_template_args"_a = true)
.def_prop_ro("input_filename", &RecordKeeper::getInputFilename)
.def_prop_ro("classes", &RecordKeeper::getClasses)
.def_prop_ro("defs", &RecordKeeper::getDefs)
.def_prop_ro("globals", &RecordKeeper::getGlobals)
.def("get_all_derived_definitions",
coerceReturn<std::vector<const Record *>, ArrayRef<const Record *>>(
&RecordKeeper::getAllDerivedDefinitions, nb::const_));
&RecordKeeper::getAllDerivedDefinitions, nb::const_),
nb::rv_policy::reference_internal);
// .def_prop_ro("globals", &RecordKeeper::getGlobals)
}
50 changes: 50 additions & 0 deletions projects/eudsl/eudsl-tblgen/tests/JSON.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// adapted from llvm/test/TableGen/JSON.td

class Base {}
class Intermediate : Base {}
class Derived : Intermediate {}

def D : Intermediate {}

def ExampleDagOp;

def FieldKeywordTest {
int a;
field int b;
}

class Variables {
int i;
string s;
bit b;
bits<8> bs;
code c;
list<int> li;
Base base;
dag d;
}
def VarNull : Variables {}
def VarPrim : Variables {
int i = 3;
int enormous_pos = 9123456789123456789;
int enormous_neg = -9123456789123456789;
string s = "hello, world";
bit b = 0;
bits<8> bs = { 0,0,0,1,0,1,1,1 };
code c = [{ \" }];
list<int> li = [ 1, 2, 3, 4 ];
}
def VarObj : Variables {
Base base = D;
dag d = (ExampleDagOp 22, "hello":$foo);
int undef_int;
field int ref_int = undef_int;
bits<2> undef_bits;
bits<4> ref_bits;
let ref_bits{3...2} = 0b10;
let ref_bits{1...0} = undef_bits{1...0};
field int complex_ref_int = !add(undef_int, 2);
}

def Named { int AnonTestField = 1; }
def { int AnonTestField = 2; }
38 changes: 34 additions & 4 deletions projects/eudsl/eudsl-tblgen/tests/test_bindings.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
from pathlib import Path

import pytest
from eudsl_tblgen import RecordKeeper


@pytest.fixture(scope="function")
def record_keeper():
return RecordKeeper().parse_td(str(Path(__file__).parent / "JSON.td"))


def test_record_keeper(record_keeper):
assert record_keeper.input_filename == str(Path(__file__).parent / "JSON.td")

assert set(record_keeper.classes) == {
"Base",
"Derived",
"Intermediate",
"Variables",
}

assert set(record_keeper.defs.keys()) == {
"D",
"ExampleDagOp",
"FieldKeywordTest",
"Named",
"VarNull",
"VarObj",
"VarPrim",
"anonymous_0",
}

def test_RecTy():
from eudsl_tblgen import RecTyKind, RecTy
assert len(record_keeper.get_all_derived_definitions("Base")) == 1
assert len(record_keeper.get_all_derived_definitions("Intermediate")) == 1
assert len(record_keeper.get_all_derived_definitions("Derived")) == 0

r = RecTyKind(RecTyKind.BitRecTyKind)
print(r)
assert record_keeper.get_all_derived_definitions("Base")[0].name == "D"
assert record_keeper.get_all_derived_definitions("Intermediate")[0].name == "D"

0 comments on commit 8e3882b

Please sign in to comment.