diff --git a/.gitignore b/.gitignore index 1eb22f5..41d393a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ devenv.local.nix /target /.envrc /result +*.snap.new diff --git a/Cargo.lock b/Cargo.lock index a83ba85..6926cac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,55 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.83" @@ -68,6 +117,71 @@ dependencies = [ "serde", ] +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap-stdin" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc126d12a0930c94c3548581294d5f19360ac02e408600b4d7619d7234e8b505" +dependencies = [ + "thiserror", +] + +[[package]] +name = "clap-verbosity-flag" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb9b20c0dd58e4c2e991c8d203bbeb76c11304d1011659686b5b644bc29aa478" +dependencies = [ + "clap", + "log", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.63", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "console" version = "0.15.8" @@ -287,6 +401,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "html-escape" version = "0.2.13" @@ -298,9 +418,33 @@ dependencies = [ [[package]] name = "hugr" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e15eaffd64f1cceac13429e5ceaf20017691e647cc56b8b7c53d73ad9f8714" +checksum = "a20246e5f1a0aae160b80b71bc4d5c1dcccc5605dbe6458ac6f9af73137339c3" +dependencies = [ + "hugr-core", + "hugr-passes", +] + +[[package]] +name = "hugr-cli" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d973149618f24c966ea90cfaf5955c184b670d38b18f3114a66a20dc5b712b" +dependencies = [ + "clap", + "clap-stdin", + "clap-verbosity-flag", + "hugr-core", + "serde_json", + "thiserror", +] + +[[package]] +name = "hugr-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd64c708ba21cedae58e37f3557d139ee6eaeaaa7df0ab9541385249c1ee6065" dependencies = [ "bitvec", "cgmath", @@ -310,7 +454,7 @@ dependencies = [ "downcast-rs", "enum_dispatch", "html-escape", - "itertools", + "itertools 0.13.0", "lazy_static", "num-rational", "paste", @@ -332,16 +476,36 @@ name = "hugr-llvm" version = "0.1.0" dependencies = [ "anyhow", + "clap", + "clap-verbosity-flag", "delegate", "downcast-rs", "hugr", + "hugr-cli", "inkwell", "insta", - "itertools", + "insta-cmd", + "itertools 0.12.1", "lazy_static", "llvm-sys", + "pathsearch", "petgraph", "rstest", + "serde_json", + "thiserror", +] + +[[package]] +name = "hugr-passes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7522d3a5299a49ee453f6d0e3c3a6e8e7ed08a38cbd11e1d19163b97098ce9be" +dependencies = [ + "hugr-core", + "itertools 0.13.0", + "lazy_static", + "paste", + "thiserror", ] [[package]] @@ -388,15 +552,33 @@ dependencies = [ "console", "lazy_static", "linked-hash-map", + "serde", "similar", ] +[[package]] +name = "insta-cmd" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffeeefa927925cced49ccb01bf3e57c9d4cd132df21e576eb9415baeab2d3de6" +dependencies = [ + "insta", + "serde", + "serde_json", +] + [[package]] name = "inventory" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.12.1" @@ -406,6 +588,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -443,6 +634,12 @@ dependencies = [ "semver", ] +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "memchr" version = "2.7.2" @@ -501,6 +698,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pathsearch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da983bc5e582ab17179c190b4b66c7d76c5943a69c6d34df2a2b6bf8a2977b05" +dependencies = [ + "anyhow", + "libc", +] + [[package]] name = "petgraph" version = "0.6.5" @@ -525,9 +732,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portgraph" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad1ebc029f8dfab4f023f14c7e41b3b3a257cf28b2928949153e563c9bf02c" +checksum = "0d83271bd5c2249831ff13227e6b3a968e115b6d4f4a2027a8ce02838b789ff8" dependencies = [ "bitvec", "context-iterators", @@ -720,6 +927,12 @@ dependencies = [ "serde", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "strum" version = "0.26.2" @@ -732,7 +945,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -769,18 +982,18 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -835,6 +1048,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index c58118a..b7c3771 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,16 +12,23 @@ llvm14 = ["dep:llvm-sys-140", "inkwell/llvm14-0"] [dependencies] inkwell = { version = "0.4.0", default-features=false } llvm-sys-140 = { package = "llvm-sys", version = "140.1.3", features = ["prefer-static"], optional = true} -hugr = "0.4.0" +hugr = "0.5.1" +hugr-cli = "0.1.1" anyhow = "1.0.83" itertools = "0.12.1" delegate = "0.12.0" petgraph = "*" lazy_static = "*" downcast-rs= "1.2.1" +pathsearch = "0.2.0" +thiserror = "1.0.61" +clap = "4.5.7" +clap-verbosity-flag = "2.2.0" +serde_json = "1.0.117" [dev-dependencies] insta = "1.39.0" +insta-cmd = "0.6.0" rstest = "0.19.0" [profile.dev.package] diff --git a/devenv.nix b/devenv.nix index 16ef269..dd0fa6d 100644 --- a/devenv.nix +++ b/devenv.nix @@ -26,5 +26,13 @@ in { enable = true; channel = "stable"; }; + + languages.python = { + enable = true; + poetry = { + enable = true; + activate.enable = true; + }; + }; }; } diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..99ff22b --- /dev/null +++ b/poetry.lock @@ -0,0 +1,208 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "graphviz" +version = "0.20.3" +description = "Simple Python interface for Graphviz" +optional = false +python-versions = ">=3.8" +files = [ + {file = "graphviz-0.20.3-py3-none-any.whl", hash = "sha256:81f848f2904515d8cd359cc611faba817598d2feaac4027b266aa3eda7b3dde5"}, + {file = "graphviz-0.20.3.zip", hash = "sha256:09d6bc81e6a9fa392e7ba52135a9d49f1ed62526f96499325930e87ca1b5925d"}, +] + +[package.extras] +dev = ["flake8", "pep8-naming", "tox (>=3)", "twine", "wheel"] +docs = ["sphinx (>=5,<7)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"] +test = ["coverage", "pytest (>=7,<8.1)", "pytest-cov", "pytest-mock (>=3)"] + +[[package]] +name = "guppylang" +version = "0.5.1" +description = "Pythonic quantum-classical programming language" +optional = false +python-versions = "^3.10" +files = [] +develop = false + +[package.dependencies] +graphviz = "^0.20.1" +hugr = "~0.2.1" +networkx = "^3.2.1" +pydantic = "^2.7.0b1" +typing-extensions = "^4.9.0" + +[package.source] +type = "git" +url = "https://github.com/CQCL/guppylang.git" +reference = "fix/input-order" +resolved_reference = "33fb1fc12e7d80d4fb21647ce517176a4ce984bc" + +[[package]] +name = "hugr" +version = "0.2.1" +description = "Quantinuum's common representation for quantum programs" +optional = false +python-versions = ">=3.10" +files = [ + {file = "hugr-0.2.1-py3-none-any.whl", hash = "sha256:9bed349f342740d1f7e92859f8c12553d494f39ff26216eadbbdfd92513f64e6"}, + {file = "hugr-0.2.1.tar.gz", hash = "sha256:899203ee02000a0ed3fe36ae1bf3f3ec5e06bddfa4d53bea15ab06aa8b452de5"}, +] + +[package.dependencies] +pydantic = ">=2.7.0,<2.8.0" + +[[package]] +name = "networkx" +version = "3.3" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.10" +files = [ + {file = "networkx-3.3-py3-none-any.whl", hash = "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2"}, + {file = "networkx-3.3.tar.gz", hash = "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9"}, +] + +[package.extras] +default = ["matplotlib (>=3.6)", "numpy (>=1.23)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"] +developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] +doc = ["myst-nb (>=1.0)", "numpydoc (>=1.7)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"] +extra = ["lxml (>=4.6)", "pydot (>=2.0)", "pygraphviz (>=1.12)", "sympy (>=1.10)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] + +[[package]] +name = "pydantic" +version = "2.7.4" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.7.4-py3-none-any.whl", hash = "sha256:ee8538d41ccb9c0a9ad3e0e5f07bf15ed8015b481ced539a1759d8cc89ae90d0"}, + {file = "pydantic-2.7.4.tar.gz", hash = "sha256:0c84efd9548d545f63ac0060c1e4d39bb9b14db8b3c0652338aecc07b5adec52"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.18.4" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.4" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"}, + {file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"}, + {file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"}, + {file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"}, + {file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"}, + {file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"}, + {file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"}, + {file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"}, + {file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"}, + {file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"}, + {file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"}, + {file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"}, + {file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"}, + {file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "typing-extensions" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "4756960c8f3667b802b3c8e271d959e1cc03bd980418df5f693c554e8f45cb88" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..2dddd7e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "hugr-llvm" +version = "0.1.0" +description = "" +authors = ["Douglas Wilson"] +readme = "README.md" +package-mode = false + +[tool.poetry.dependencies] +python = "^3.11" +guppylang= { git = "https://github.com/CQCL/guppylang.git", branch = "fix/input-order" } + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..25f8e40 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,150 @@ +//! Provides a command line interface to tket2-hseries +use std::rc::Rc; + +use clap::{ArgMatches, Args, Command, FromArgMatches, Parser}; +use hugr::std_extensions::arithmetic::{ + conversions::EXTENSION as CONVERSIONS_EXTENSION, float_ops::EXTENSION as FLOAT_OPS_EXTENSION, + float_types::EXTENSION as FLOAT_TYPES_EXTENSION, int_ops::EXTENSION as INT_OPS_EXTENSION, + int_types::EXTENSION as INT_TYPES_EXTENSION, +}; +use hugr::std_extensions::logic::EXTENSION as LOGICS_EXTENSION; +use hugr::Hugr; +use inkwell::module::Module; +use inkwell::passes::PassManager; +use thiserror::Error; + +use anyhow::Result; +use hugr::extension::{ExtensionRegistry, PRELUDE}; +use lazy_static::lazy_static; + +use crate::custom::CodegenExtsMap; +use crate::emit::{EmitHugr, Namer}; +use crate::fat::FatExt as _; + +lazy_static! { + /// A registry suitable for passing to `run`. Use this unless you have a + /// good reason not to do so. + pub static ref REGISTRY: ExtensionRegistry = ExtensionRegistry::try_new([ + PRELUDE.to_owned(), + INT_OPS_EXTENSION.to_owned(), + INT_TYPES_EXTENSION.to_owned(), + CONVERSIONS_EXTENSION.to_owned(), + FLOAT_OPS_EXTENSION.to_owned(), + FLOAT_TYPES_EXTENSION.to_owned(), + LOGICS_EXTENSION.to_owned(), + ]) + .unwrap(); +} + +#[derive(Debug)] +pub struct HugrCliCmdLineArgs(hugr_cli::CmdLineArgs); + +impl FromArgMatches for HugrCliCmdLineArgs { + fn from_arg_matches(matches: &ArgMatches) -> Result { + Ok(HugrCliCmdLineArgs(hugr_cli::CmdLineArgs::from_arg_matches( + matches, + )?)) + } + + fn update_from_arg_matches(&mut self, matches: &clap::ArgMatches) -> Result<(), clap::Error> { + self.0.update_from_arg_matches(matches) + } +} + +impl Args for HugrCliCmdLineArgs { + fn augment_args(cmd: Command) -> Command { + hugr_cli::CmdLineArgs::augment_args(cmd).mut_arg("mermaid", |x| x.hide(true)) + } + + fn augment_args_for_update(cmd: Command) -> Command { + hugr_cli::CmdLineArgs::augment_args_for_update(cmd).mut_arg("mermaid", |x| x.hide(true)) + } +} + +/// Arguments for `run`. +#[derive(Parser, Debug)] +#[command(version, about)] +pub struct CmdLineArgs { + #[command(flatten)] + base: HugrCliCmdLineArgs, + #[arg(long, default_value = "module")] + module_name: String, + + #[arg(short='p',long,default_value=crate::emit::NAMER_DEFAULT_PREFIX)] + mangle_prefix: String, + #[arg(short = 's', long, default_value_t = true)] + mangle_node_suffix: bool, + + #[arg(long, default_value_t = false)] + no_opt: bool, +} + +#[derive(Error, Debug)] +pub enum CliError { + #[error(transparent)] + HugrCliError(#[from] hugr_cli::CliError), + #[error(transparent)] + Other(#[from] anyhow::Error), +} + +pub fn emit_module<'c>( + context: &'c inkwell::context::Context, + hugr: &'c Hugr, + module_name: impl AsRef, + namer: Rc, + exts: Rc>, +) -> Result> { + let module = context.create_module(module_name.as_ref()); + let emit = EmitHugr::new(context, module, namer, exts); + Ok(emit.emit_module(hugr.fat_root().unwrap())?.finish()) +} + +impl CmdLineArgs { + /// Run the ngrte preparation and validation workflow with the given + /// registry. + pub fn run(&self, registry: &ExtensionRegistry) -> Result<()> { + let hugr = self.base.0.run(registry)?; + + let context = inkwell::context::Context::create(); + let module = emit_module( + &context, + &hugr, + &self.module_name, + self.namer(), + self.codegenexts(), + )?; + + module + .verify() + .map_err(|e| anyhow::anyhow!(e.to_string()))?; + + if !self.no_opt { + let pb = PassManager::create(()); + pb.add_promote_memory_to_register_pass(); + pb.add_scalar_repl_aggregates_pass(); + pb.add_cfg_simplification_pass(); + pb.run_on(&module); + } + + println!("{}", module.print_to_string().to_str().unwrap()); + Ok(()) + } + + /// Test whether a `level` message should be output. + pub fn verbosity(&self, level: hugr_cli::Level) -> bool { + self.base.0.verbosity(level) + } + + fn namer(&self) -> Rc { + Namer::new(self.mangle_prefix.clone(), self.mangle_node_suffix).into() + } + + fn codegenexts<'c>(&self) -> Rc> { + CodegenExtsMap::new() + .add_int_extensions() + .add_prelude_extensions() + .add_float_extensions() + .add_tket2_extensions() + .into() + } +} diff --git a/src/custom.rs b/src/custom.rs index a683919..63edc2d 100644 --- a/src/custom.rs +++ b/src/custom.rs @@ -21,7 +21,10 @@ use crate::{ use super::emit::EmitOp; +pub mod float; pub mod int; +pub mod prelude; +pub mod tket2; // pub mod float_ops; // pub mod logic_ops; diff --git a/src/custom/float.rs b/src/custom/float.rs new file mode 100644 index 0000000..874dd78 --- /dev/null +++ b/src/custom/float.rs @@ -0,0 +1,72 @@ +use std::{any::TypeId, collections::HashSet}; + +use anyhow::{anyhow, Result}; +use hugr::{ + ops::constant::CustomConst, + std_extensions::arithmetic::float_types::{self, ConstF64}, + HugrView, +}; +use inkwell::{ + types::{BasicType, FloatType}, + values::{BasicValue, BasicValueEnum}, +}; + +use crate::emit::func::EmitFuncContext; + +use super::{CodegenExtension, CodegenExtsMap}; + +struct FloatCodegenExtension; + +impl<'c, H: HugrView> CodegenExtension<'c, H> for FloatCodegenExtension { + fn extension(&self) -> hugr::extension::ExtensionId { + return float_types::EXTENSION_ID; + } + + fn llvm_type( + &self, + context: &crate::types::TypingSession<'c, H>, + hugr_type: &hugr::types::CustomType, + ) -> anyhow::Result> { + match hugr_type.name().as_str() { + "float64" => Ok(context.iw_context().f64_type().as_basic_type_enum()), + _ => todo!(), + } + } + + fn emitter<'a>( + &self, + _context: &'a mut crate::emit::func::EmitFuncContext<'c, H>, + ) -> Box + 'a> { + todo!() + } + + fn supported_consts(&self) -> HashSet { + [TypeId::of::()].into_iter().collect() + } + + fn load_constant( + &self, + context: &mut EmitFuncContext<'c, H>, + konst: &dyn hugr::ops::constant::CustomConst, + ) -> Result>> { + let Some(k) = konst.downcast_ref::() else { + return Ok(None); + }; + let ty: FloatType<'c> = context + .llvm_type(&k.get_type())? + .try_into() + .map_err(|_| anyhow!("Failed to get ConstInt as IntType"))?; + // TODO we don't know whether this is signed or unsigned + Ok(Some(ty.const_float(k.value()).as_basic_value_enum())) + } +} + +pub fn add_float_extensions(cem: CodegenExtsMap<'_, H>) -> CodegenExtsMap<'_, H> { + cem.add_cge(FloatCodegenExtension) +} + +impl CodegenExtsMap<'_, H> { + pub fn add_float_extensions(self) -> Self { + add_float_extensions(self) + } +} diff --git a/src/custom/int.rs b/src/custom/int.rs index fef9283..c1a4712 100644 --- a/src/custom/int.rs +++ b/src/custom/int.rs @@ -2,9 +2,9 @@ use std::{any::TypeId, collections::HashSet}; use hugr::{ extension::{simple_op::MakeExtensionOp, ExtensionId}, - ops::{constant::CustomConst, CustomOp, NamedOp}, + ops::{constant::CustomConst, CustomOp, NamedOp, Value}, std_extensions::arithmetic::{ - int_ops::{self, IntOpType}, + int_ops::{self, ConcreteIntOp}, int_types::{self, ConstInt}, }, types::{CustomType, TypeArg}, @@ -16,7 +16,7 @@ use inkwell::{ }; use crate::{ - emit::{func::EmitFuncContext, EmitOp, EmitOpArgs, NullEmitLlvm}, + emit::{emit_value, func::EmitFuncContext, EmitOp, EmitOpArgs, NullEmitLlvm}, types::TypingSession, }; @@ -25,9 +25,23 @@ use anyhow::{anyhow, Result}; struct IntOpEmitter<'c, 'd, H: HugrView>(&'d mut EmitFuncContext<'c, H>); +fn emit_icmp<'c, H: HugrView>( + context: &mut EmitFuncContext<'c, H>, + args: EmitOpArgs<'c, CustomOp, H>, + pred: inkwell::IntPredicate, +) -> Result<()> { + let true_val = emit_value(context, &Value::true_val())?; + let false_val = emit_value(context, &Value::false_val())?; + let builder = context.builder(); + let [lhs, rhs] = TryInto::<[_; 2]>::try_into(args.inputs).unwrap(); + let a = builder.build_int_compare(pred, lhs.into_int_value(), rhs.into_int_value(), "")?; + let a = builder.build_select(a, true_val, false_val, "")?; + args.outputs.finish(builder, [a.into()]) +} + impl<'c, H: HugrView> EmitOp<'c, CustomOp, H> for IntOpEmitter<'c, '_, H> { fn emit(&mut self, args: EmitOpArgs<'c, CustomOp, H>) -> Result<()> { - let iot = IntOpType::from_optype(&args.node().generalise()) + let iot = ConcreteIntOp::from_optype(&args.node().generalise()) .ok_or(anyhow!("IntOpEmitter from_optype_failed"))?; match iot.name().as_str() { "iadd" => { @@ -36,7 +50,19 @@ impl<'c, H: HugrView> EmitOp<'c, CustomOp, H> for IntOpEmitter<'c, '_, H> { let a = builder.build_int_add(lhs.into_int_value(), rhs.into_int_value(), "")?; args.outputs.finish(builder, [a.into()]) } - _ => Err(anyhow!("IntOpEmitter: unknown name")), + "ieq" => { + emit_icmp(self.0, args, inkwell::IntPredicate::EQ) + } + "ilt_s" => { + emit_icmp(self.0, args, inkwell::IntPredicate::SLT) + } + "isub" => { + let builder = self.0.builder(); + let [lhs, rhs] = TryInto::<[_; 2]>::try_into(args.inputs).unwrap(); + let a = builder.build_int_sub(lhs.into_int_value(), rhs.into_int_value(), "")?; + args.outputs.finish(builder, [a.into()]) + } + n => Err(anyhow!("IntOpEmitter: unknown name: {n}")), } } } @@ -153,3 +179,9 @@ pub fn add_int_extensions(cem: CodegenExtsMap<'_, H>) -> CodegenExt cem.add_cge(IntOpsCodegenExtension) .add_cge(IntTypesCodegenExtension) } + +impl CodegenExtsMap<'_, H> { + pub fn add_int_extensions(self) -> Self { + add_int_extensions(self) + } +} diff --git a/src/custom/prelude.rs b/src/custom/prelude.rs new file mode 100644 index 0000000..d287228 --- /dev/null +++ b/src/custom/prelude.rs @@ -0,0 +1,40 @@ +use hugr::{extension::prelude, HugrView}; +use inkwell::types::BasicType; + +use super::{CodegenExtension, CodegenExtsMap}; + +struct PreludeCodegenExtension; + +impl<'c, H: HugrView> CodegenExtension<'c, H> for PreludeCodegenExtension { + fn extension(&self) -> hugr::extension::ExtensionId { + return prelude::PRELUDE_ID; + } + + fn llvm_type( + &self, + context: &crate::types::TypingSession<'c, H>, + hugr_type: &hugr::types::CustomType, + ) -> anyhow::Result> { + match hugr_type.name().as_str() { + "qubit" => Ok(context.iw_context().i32_type().as_basic_type_enum()), + _ => todo!(), + } + } + + fn emitter<'a>( + &self, + _context: &'a mut crate::emit::func::EmitFuncContext<'c, H>, + ) -> Box + 'a> { + todo!() + } +} + +pub fn add_prelude_extensions(cem: CodegenExtsMap<'_, H>) -> CodegenExtsMap<'_, H> { + cem.add_cge(PreludeCodegenExtension) +} + +impl CodegenExtsMap<'_, H> { + pub fn add_prelude_extensions(self) -> Self { + add_prelude_extensions(self) + } +} diff --git a/src/custom/tket2.rs b/src/custom/tket2.rs new file mode 100644 index 0000000..8450d54 --- /dev/null +++ b/src/custom/tket2.rs @@ -0,0 +1,214 @@ +use anyhow::{anyhow, Result}; +use hugr::{ + extension::{ + prelude::{BOOL_T, QB_T}, + ExtensionId, + }, + ops::CustomOp, + std_extensions::arithmetic::float_types::FLOAT64_TYPE, + type_row, + types::FunctionType, + HugrView, +}; +use inkwell::module::Linkage; +use itertools::Itertools as _; +use std::ops::Deref; + +use crate::emit::{func::EmitFuncContext, EmitOp, EmitOpArgs}; + +use super::{CodegenExtension, CodegenExtsMap}; + +struct Tket2CodegenExtension; + +impl<'c, H: HugrView> CodegenExtension<'c, H> for Tket2CodegenExtension { + fn extension(&self) -> hugr::extension::ExtensionId { + return ExtensionId::new("quantum.tket2".to_string()).unwrap(); + } + + fn llvm_type( + &self, + _context: &crate::types::TypingSession<'c, H>, + hugr_type: &hugr::types::CustomType, + ) -> anyhow::Result> { + match hugr_type.name().as_str() { + _ => todo!(), + } + } + + fn emitter<'a>( + &self, + context: &'a mut crate::emit::func::EmitFuncContext<'c, H>, + ) -> Box + 'a> { + Box::new(Tket2Emitter(context)) + } +} + +struct Tket2Emitter<'c, 'd, H: HugrView>(&'d mut EmitFuncContext<'c, H>); + +impl<'c, H: HugrView> EmitOp<'c, CustomOp, H> for Tket2Emitter<'c, '_, H> { + fn emit(&mut self, args: EmitOpArgs<'c, CustomOp, H>) -> Result<()> { + let node = args.node().generalise(); + let custom = node.deref().as_custom_op().unwrap().clone(); + let opaque = custom.into_opaque(); + match opaque.name().as_str() { + "H" => { + let func_type = self.0.llvm_func_type(&FunctionType::new(QB_T, QB_T))?; + let h_func = + self.0 + .module() + .add_function("___h", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(h_func, inputs.as_ref(), "h_call")?; + args.outputs + .finish(builder, [call.try_as_basic_value().unwrap_left()])?; + Ok(()) + } + "Z" => { + let func_type = self.0.llvm_func_type(&FunctionType::new(QB_T, QB_T))?; + let z_func = + self.0 + .module() + .add_function("___z", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(z_func, inputs.as_ref(), "z_call")?; + args.outputs + .finish(builder, [call.try_as_basic_value().unwrap_left()])?; + Ok(()) + } + "X" => { + let func_type = self.0.llvm_func_type(&FunctionType::new(QB_T, QB_T))?; + let x_func = + self.0 + .module() + .add_function("___x", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(x_func, inputs.as_ref(), "x_call")?; + args.outputs + .finish(builder, [call.try_as_basic_value().unwrap_left()])?; + Ok(()) + } + "Tdg" => { + let func_type = self.0.llvm_func_type(&FunctionType::new(QB_T, QB_T))?; + let x_func = + self.0 + .module() + .add_function("___tdg", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(x_func, inputs.as_ref(), "tdg_call")?; + args.outputs + .finish(builder, [call.try_as_basic_value().unwrap_left()])?; + Ok(()) + } + "T" => { + let func_type = self.0.llvm_func_type(&FunctionType::new(QB_T, QB_T))?; + let x_func = + self.0 + .module() + .add_function("___t", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(x_func, inputs.as_ref(), "t_call")?; + args.outputs + .finish(builder, [call.try_as_basic_value().unwrap_left()])?; + Ok(()) + } + "RzF64" => { + let func_type = self + .0 + .llvm_func_type(&FunctionType::new(type_row![QB_T, FLOAT64_TYPE], QB_T))?; + let h_func = + self.0 + .module() + .add_function("___rz", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(h_func, inputs.as_ref(), "rz_call")?; + args.outputs + .finish(builder, [call.try_as_basic_value().unwrap_left()])?; + Ok(()) + } + "CX" => { + let func_type = self.0.llvm_func_type(&FunctionType::new( + type_row![QB_T, QB_T], + type_row![QB_T, QB_T], + ))?; + let cx_func = + self.0 + .module() + .add_function("___cx", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + + let call = builder.build_call(cx_func, inputs.as_ref(), "rz_call")?; + let call_r = call.try_as_basic_value().unwrap_left(); + + let r1 = builder.build_extract_value(call_r.into_struct_value(), 0, "")?; + let r2 = builder.build_extract_value(call_r.into_struct_value(), 1, "")?; + + args.outputs.finish(builder, [r1, r2])?; + Ok(()) + } + "QAlloc" => { + let func_type = self + .0 + .llvm_func_type(&FunctionType::new(type_row![], QB_T))?; + let h_func = + self.0 + .module() + .add_function("___qalloc", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(h_func, inputs.as_ref(), "qalloc_call")?; + args.outputs + .finish(builder, [call.try_as_basic_value().unwrap_left()])?; + Ok(()) + } + "QFree" => { + let func_type = self + .0 + .llvm_func_type(&FunctionType::new(QB_T, type_row![]))?; + let h_func = + self.0 + .module() + .add_function("___qfree", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let _call = builder.build_call(h_func, inputs.as_ref(), "qfree_call")?; + args.outputs.finish(builder, [])?; + Ok(()) + } + "Measure" => { + let func_type = self + .0 + .llvm_func_type(&FunctionType::new(QB_T, type_row![QB_T, BOOL_T]))?; + let h_func = + self.0 + .module() + .add_function("___measure", func_type, Some(Linkage::External)); + let inputs = args.inputs.into_iter().map_into().collect_vec(); + let builder = self.0.builder(); + let call = builder.build_call(h_func, inputs.as_ref(), "measure_call")?; + let call_r = call.try_as_basic_value().unwrap_left(); + let r1 = builder.build_extract_value(call_r.into_struct_value(), 0, "")?; + let r2 = builder.build_extract_value(call_r.into_struct_value(), 1, "")?; + args.outputs.finish(builder, [r1, r2])?; + Ok(()) + } + n => Err(anyhow!("Unknown op {}", n)), + } + } +} + +pub fn add_tket2_extensions(cem: CodegenExtsMap<'_, H>) -> CodegenExtsMap<'_, H> { + cem.add_cge(Tket2CodegenExtension) +} + +impl CodegenExtsMap<'_, H> { + pub fn add_tket2_extensions(self) -> Self { + add_tket2_extensions(self) + } +} diff --git a/src/emit.rs b/src/emit.rs index 63f7b26..eb48099 100644 --- a/src/emit.rs +++ b/src/emit.rs @@ -24,6 +24,7 @@ use self::func::{EmitFuncContext, RowPromise}; pub mod func; mod ops; +pub use ops::emit_value; /// A type used whenever emission is delegated to a function pub struct EmitOpArgs<'c, OT, H> { @@ -117,27 +118,39 @@ impl EmitOp<'_, OT, H> for NullEmitLlvm { #[derive(Clone)] pub struct Namer { prefix: String, + node_suffix: bool, } impl Namer { /// Create a new `Namer` that for each symbol: /// * prefix `prefix` /// * postfixes ".{node.index()}" - pub fn new(prefix: impl Into) -> Self { + pub fn new(prefix: impl Into, node_suffix: bool) -> Self { Self { prefix: prefix.into(), + node_suffix, } } /// Mangle the the name of a [FuncDefn] or [FuncDecl]. pub fn name_func(&self, name: impl AsRef, node: Node) -> String { - format!("{}{}.{}", &self.prefix, name.as_ref(), node.index()) + let suffix = if self.node_suffix { + format!(".{}", node.index()) + } else { + "".to_string() + }; + format!("{}{}{}", &self.prefix, name.as_ref(), suffix) } } +pub const NAMER_DEFAULT_PREFIX: &str = "_hl."; + impl Default for Namer { fn default() -> Self { - Self::new("_hl.") + Self { + prefix: NAMER_DEFAULT_PREFIX.into(), + node_suffix: true, + } } } @@ -321,6 +334,7 @@ impl<'c, H: HugrView> EmitHugr<'c, H> { pub fn new( iw_context: &'c Context, module: Module<'c>, + namer: Rc, exts: Rc>, ) -> Self { assert_eq!(iw_context, &module.get_context()); @@ -329,7 +343,7 @@ impl<'c, H: HugrView> EmitHugr<'c, H> { emitted: Default::default(), module_context: EmitModuleContext::new( module, - Default::default(), + namer, exts, TypeConverter::new(iw_context), ), @@ -369,9 +383,7 @@ impl<'c, H: HugrView> EmitHugr<'c, H> { /// are not emitted directly, but instead by [hugr::ops::LoadConstant] emission. So /// [FuncDefn] and [FuncDecl] are the only interesting children. pub fn emit_module(mut self, node: FatNode<'c, hugr::ops::Module, H>) -> Result { - println!("emit module"); for c in node.children() { - println!("emit child: {}", &c); match c.get() { OpType::FuncDefn(ref fd) => { self = self.emit_global(c.into_ot(fd))?; diff --git a/src/emit/func.rs b/src/emit/func.rs index 0dbbaad..0be8a18 100644 --- a/src/emit/func.rs +++ b/src/emit/func.rs @@ -7,12 +7,13 @@ use anyhow::{anyhow, Result}; use hugr::{ ops::{FuncDecl, FuncDefn}, types::Type, - HugrView, NodeIndex, PortIndex, Wire, + HugrView, NodeIndex, OutgoingPort, PortIndex, Wire, }; use inkwell::{ basic_block::BasicBlock, builder::Builder, context::Context, + module::Module, types::{BasicTypeEnum, FunctionType}, values::FunctionValue, }; @@ -61,6 +62,9 @@ impl<'c, H: HugrView> EmitFuncContext<'c, H> { to self.emit_context { fn iw_context(&self) -> &'c Context; /// Returns the internal [CodegenExtsMap] . + + pub fn module(&self) -> &Module<'c>; + /// Returns the internal [CodegenExtsMap] . pub fn extensions(&self) -> Rc>; /// Returns a new [TypingSession]. pub fn typing_session(&self) -> TypingSession<'c,H>; @@ -249,7 +253,7 @@ impl<'c, H: HugrView> EmitFuncContext<'c, H> { fn map_wire( &mut self, node: FatNode<'c, OT, H>, - port: hugr::OutgoingPort, + port: OutgoingPort, hugr_type: &Type, ) -> Result> { let wire = Wire::new(node.node(), port); diff --git a/src/emit/func/mailbox.rs b/src/emit/func/mailbox.rs index 06bb727..70d1713 100644 --- a/src/emit/func/mailbox.rs +++ b/src/emit/func/mailbox.rs @@ -93,6 +93,10 @@ impl<'c> ValuePromise<'c> { pub struct RowMailBox<'c>(Rc>>, Cow<'static, str>); impl<'c> RowMailBox<'c> { + pub fn new_empty() -> Self { + Self::new(std::iter::empty(), None) + } + pub(super) fn new( mbs: impl IntoIterator>, name: Option, @@ -144,7 +148,9 @@ impl<'c> RowMailBox<'c> { builder: &Builder<'c>, vs: impl IntoIterator>, ) -> Result<()> { - zip_eq(self.0.iter(), vs).try_for_each(|(mb, v)| mb.write(builder, v)) + let values = vs.into_iter().collect_vec(); + // println!("rowmailbox write {:?} \n -> {:?}", values.clone(), self.get_types().collect_vec()); + zip_eq(self.0.iter(), values.into_iter()).try_for_each(|(mb, v)| mb.write(builder, v)) } fn mailboxes(&'_ self) -> impl Iterator> + '_ { diff --git a/src/emit/ops.rs b/src/emit/ops.rs index ea51b7d..c9e9914 100644 --- a/src/emit/ops.rs +++ b/src/emit/ops.rs @@ -1,9 +1,9 @@ -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, ensure, Result}; use hugr::{ hugr::views::SiblingGraph, ops::{ Call, Case, Conditional, Const, Input, LoadConstant, MakeTuple, NamedOp, OpTag, OpTrait, - OpType, Output, Tag, UnpackTuple, Value, + OpType, Output, Tag, UnpackTuple, Value, CFG, }, types::{SumType, Type, TypeEnum}, HugrView, NodeIndex, @@ -20,6 +20,8 @@ use super::{ EmitOp, EmitOpArgs, }; +mod cfg; + struct SumOpEmitter<'c, 'd, H: HugrView>(&'d mut EmitFuncContext<'c, H>, LLVMSumType<'c>); impl<'c, 'd, H: HugrView> SumOpEmitter<'c, 'd, H> { @@ -38,8 +40,10 @@ impl<'c, 'd, H: HugrView> SumOpEmitter<'c, 'd, H> { impl<'c, H: HugrView> EmitOp<'c, MakeTuple, H> for SumOpEmitter<'c, '_, H> { fn emit(&mut self, args: EmitOpArgs<'c, MakeTuple, H>) -> Result<()> { let builder = self.0.builder(); - args.outputs - .finish(builder, [self.1.build_tag(builder, 0, args.inputs)?]) + let r = args + .outputs + .finish(builder, [self.1.build_tag(builder, 0, args.inputs)?])?; + Ok(r) } } @@ -59,12 +63,13 @@ impl<'c, H: HugrView> EmitOp<'c, UnpackTuple, H> for SumOpEmitter<'c, '_, H> { impl<'c, H: HugrView> EmitOp<'c, Tag, H> for SumOpEmitter<'c, '_, H> { fn emit(&mut self, args: EmitOpArgs<'c, Tag, H>) -> Result<()> { let builder = self.0.builder(); - args.outputs.finish( + let r = args.outputs.finish( builder, [self .1 .build_tag(builder, args.node.tag as u32, args.inputs)?], - ) + )?; + Ok(r) } } @@ -228,7 +233,7 @@ impl<'c, H: HugrView> EmitOp<'c, Conditional, H> for ConditionalEmitter<'c, '_, }) .collect::>>()?; - builder.build_switch(tag.into_int_value(), switches[0].1, &switches[1..])?; + builder.build_switch(tag, switches[0].1, &switches[1..])?; builder.position_at_end(exit_block); Ok(()) } @@ -246,14 +251,16 @@ fn get_exactly_one_sum_type(ts: impl IntoIterator) -> Result( +pub fn emit_value<'c, H: HugrView>( context: &mut EmitFuncContext<'c, H>, v: &Value, ) -> Result> { match v { Value::Extension { e } => { let exts = context.extensions(); - exts.load_constant(context, e.value()) + let val = exts.load_constant(context, e.value())?; + ensure!(val.get_type() == context.llvm_type(&v.get_type())?); + Ok(val) } Value::Function { .. } => todo!(), Value::Tuple { vs } => { @@ -263,7 +270,8 @@ fn emit_value<'c, H: HugrView>( .iter() .map(|x| emit_value(context, x)) .collect::>>()?; - llvm_st.build_tag(context.builder(), 0, llvm_vs) + let r = llvm_st.build_tag(context.builder(), 0, llvm_vs)?; + Ok(r) } Value::Sum { tag, @@ -275,7 +283,8 @@ fn emit_value<'c, H: HugrView>( .iter() .map(|x| emit_value(context, x)) .collect::>>()?; - llvm_st.build_tag(context.builder(), *tag as u32, vs) + let r = llvm_st.build_tag(context.builder(), *tag as u32, vs)?; + Ok(r) } } } @@ -370,6 +379,13 @@ fn emit_call<'c, H: HugrView>( args.outputs.finish(builder, rets) } +fn emit_cfg<'c, H: HugrView>( + context: &mut EmitFuncContext<'c, H>, + args: EmitOpArgs<'c, CFG, H>, +) -> Result<()> { + cfg::CfgEmitter::new(context, args)?.emit_children() +} + fn emit_optype<'c, H: HugrView>( context: &mut EmitFuncContext<'c, H>, args: EmitOpArgs<'c, OpType, H>, @@ -381,7 +397,6 @@ fn emit_optype<'c, H: HugrView>( OpType::Tag(ref tag) => emit_tag(context, args.into_ot(tag)), OpType::DFG(_) => emit_dataflow_parent(context, args), - // TODO Test cases OpType::CustomOp(ref co) => { let extensions = context.extensions(); extensions.emit(context, args.into_ot(co)) @@ -390,6 +405,7 @@ fn emit_optype<'c, H: HugrView>( OpType::LoadConstant(ref lc) => emit_load_constant(context, args.into_ot(lc)), OpType::Call(ref cl) => emit_call(context, args.into_ot(cl)), OpType::Conditional(ref co) => emit_conditional(context, args.into_ot(co)), + OpType::CFG(ref cfg) => emit_cfg(context, args.into_ot(cfg)), // OpType::FuncDefn(fd) => self.emit(ot.into_ot(fd), context, inputs, outputs), _ => todo!("Unimplemented OpTypeEmitter: {}", args.node().name()), diff --git a/src/emit/ops/cfg.rs b/src/emit/ops/cfg.rs new file mode 100644 index 0000000..3903e7f --- /dev/null +++ b/src/emit/ops/cfg.rs @@ -0,0 +1,208 @@ +use std::collections::HashMap; + +use anyhow::{anyhow, Result}; +use hugr::{ + ops::{DataflowBlock, ExitBlock, OpType, CFG}, + types::SumType, + HugrView, NodeIndex, +}; +use inkwell::{basic_block::BasicBlock, values::BasicValueEnum}; +use itertools::Itertools as _; + +use crate::{ + emit::{ + func::{EmitFuncContext, RowMailBox, RowPromise}, + EmitOp, EmitOpArgs, + }, + fat::FatNode, +}; + +use super::emit_dataflow_parent; + +pub struct CfgEmitter<'c, 'd, H: HugrView> { + context: &'d mut EmitFuncContext<'c, H>, + bbs: HashMap, (BasicBlock<'c>, RowMailBox<'c>)>, + inputs: Option>>, + outputs: Option>, + node: FatNode<'c, CFG, H>, + entry_node: FatNode<'c, DataflowBlock, H>, + exit_node: FatNode<'c, ExitBlock, H>, +} + +impl<'c, 'd, H: HugrView> CfgEmitter<'c, 'd, H> { + // Constructs a new CfgEmitter. Creates a basic block for each of + // the children in the llvm function. Note that this does not move the + // position of the builder. + pub fn new( + context: &'d mut EmitFuncContext<'c, H>, + args: EmitOpArgs<'c, CFG, H>, + ) -> Result { + let node = args.node(); + let (inputs, outputs) = (Some(args.inputs), Some(args.outputs)); + + // create this now so that it will be the last block and we can use it + // to crate the other blocks immediately before it. This is just for + // nice block ordering. + let exit_block = context.new_basic_block("", None); + let bbs = node + .children() + .map(|child| { + if child.is_exit_block() { + let output_row = { + let out_types = node.out_value_types().map(|x| x.1).collect_vec(); + context.new_row_mail_box(out_types.iter(), "")? + }; + Ok((child, (exit_block, output_row))) + } else { + let bb = context.new_basic_block("", Some(exit_block)); + let (i, _) = child.get_io().unwrap(); + Ok((child, (bb, context.node_outs_rmb(i)?))) + } + }) + .collect::>>()?; + let (entry_node, exit_node) = node.get_entry_exit().unwrap(); + Ok(CfgEmitter { + context, + bbs, + node, + inputs, + outputs, + entry_node, + exit_node, + }) + } + + fn take_inputs(&mut self) -> Result>> { + self.inputs.take().ok_or(anyhow!("Couldn't take inputs")) + } + + fn take_outputs(&mut self) -> Result> { + self.outputs.take().ok_or(anyhow!("Couldn't take inputs")) + } + + fn get_block_data( + &self, + node: &FatNode<'c, OT, H>, + ) -> Result<&(BasicBlock<'c>, RowMailBox<'c>)> + where + OT: Into + 'c, + { + self.bbs + .get(&node.clone().generalise()) + .ok_or(anyhow!("Couldn't get block data for: {}", node.index())) + } + + /// Consume the emitter by emitting each child of the node. + /// After returning the builder will be at the end of the exit block. + pub fn emit_children(mut self) -> Result<()> { + // write the inputs of the cfg node into the inputs of the entry + // dataflowblock node, and then branch to the basic block of that entry + // node. + let inputs = self.take_inputs()?; + let (entry_bb, inputs_rmb) = self.get_block_data(&self.entry_node).cloned()?; + let builder = self.context.builder(); + inputs_rmb.write(builder, inputs)?; + builder.build_unconditional_branch(entry_bb)?; + + // emit each child by delegating to the `impl EmitOp<_>` of self. + for c in self.node.children() { + let (inputs, outputs) = (vec![], RowMailBox::new_empty().promise()); + if let Some(node) = c.try_into_ot::() { + self.emit(EmitOpArgs { + node, + inputs, + outputs, + })?; + } else if let Some(node) = c.try_into_ot::() { + self.emit(EmitOpArgs { + node, + inputs, + outputs, + })?; + } else { + Err(anyhow!("unknown optype: {c}"))?; + } + } + + // move the builder to the end of the exit block + let (exit_bb, _) = self.get_block_data(&self.exit_node).cloned()?; + self.context.builder().position_at_end(exit_bb); + Ok(()) + } +} + +impl<'c, H: HugrView> EmitOp<'c, DataflowBlock, H> for CfgEmitter<'c, '_, H> { + fn emit( + &mut self, + EmitOpArgs { + node, + inputs: _, + outputs: _, + }: EmitOpArgs<'c, DataflowBlock, H>, + ) -> Result<()> { + // our entry basic block and our input RowMailBox + let (bb, inputs_rmb) = self.bbs.get(&node.clone().generalise()).unwrap(); + // the basic block and mailbox of each of our successors + let successor_data = node + .output_neighbours() + .map(|succ| self.get_block_data(&succ).map(|x| x.clone())) + .collect::>>()?; + + self.context.build_positioned(*bb, |context| { + let (_, o) = node.get_io().unwrap(); + // get the rowmailbox for our output node + let outputs_rmb = context.node_ins_rmb(o)?; + // read the values from our input node + let inputs = inputs_rmb.read_vec(context.builder(), [])?; + + // emit all our children and read the values from the rowmailbox of our output node + emit_dataflow_parent( + context, + EmitOpArgs { + node: node.clone(), + inputs, + outputs: outputs_rmb.promise(), + }, + )?; + let outputs = outputs_rmb.read_vec(context.builder(), [])?; + + let branch_sum_type = SumType::new(node.sum_rows.clone()); + let llvm_sum_type = context.llvm_sum_type(branch_sum_type)?; + let tag_bbs = successor_data + .into_iter() + .enumerate() + .map(|(tag, (target_bb, target_rmb))| { + let bb = context.build_positioned_new_block("", Some(*bb), |context, bb| { + let builder = context.builder(); + let mut vals = + llvm_sum_type.build_untag(builder, tag as u32, outputs[0])?; + vals.extend(&outputs[1..]); + target_rmb.write(builder, vals)?; + builder.build_unconditional_branch(target_bb)?; + Ok::<_, anyhow::Error>(bb) + })?; + Ok(( + llvm_sum_type.get_tag_type().const_int(tag as u64, false), + bb, + )) + }) + .collect::>>()?; + let tag_v = llvm_sum_type.build_get_tag(context.builder(), outputs[0])?; + context + .builder() + .build_switch(tag_v, tag_bbs[0].1, &tag_bbs[1..])?; + Ok(()) + }) + } +} + +impl<'c, H: HugrView> EmitOp<'c, ExitBlock, H> for CfgEmitter<'c, '_, H> { + fn emit(&mut self, args: EmitOpArgs<'c, ExitBlock, H>) -> Result<()> { + let outputs = self.take_outputs()?; + let (bb, inputs_rmb) = self.bbs.get(&args.node().generalise()).unwrap(); + self.context.build_positioned(*bb, |context| { + let builder = context.builder(); + outputs.finish(builder, inputs_rmb.read_vec(builder, [])?) + }) + } +} diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@llvm14.snap index 10e5d44..7d3eebb 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@llvm14.snap @@ -14,24 +14,24 @@ entry_block: ; preds = %alloca_block ret void } -define { {}, {} } @_hl.main_unary.5({ {}, {} } %0) { +define { i32, {}, {} } @_hl.main_unary.5({ i32, {}, {} } %0) { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - %1 = call { {}, {} } @_hl.main_unary.5({ {}, {} } %0) - ret { {}, {} } %1 + %1 = call { i32, {}, {} } @_hl.main_unary.5({ i32, {}, {} } %0) + ret { i32, {}, {} } %1 } -define { { {}, {} }, { {}, {} } } @_hl.main_binary.9({ {}, {} } %0, { {}, {} } %1) { +define { { i32, {}, {} }, { i32, {}, {} } } @_hl.main_binary.9({ i32, {}, {} } %0, { i32, {}, {} } %1) { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - %2 = call { { {}, {} }, { {}, {} } } @_hl.main_binary.9({ {}, {} } %0, { {}, {} } %1) - %3 = extractvalue { { {}, {} }, { {}, {} } } %2, 0 - %4 = extractvalue { { {}, {} }, { {}, {} } } %2, 1 - %mrv = insertvalue { { {}, {} }, { {}, {} } } undef, { {}, {} } %3, 0 - %mrv7 = insertvalue { { {}, {} }, { {}, {} } } %mrv, { {}, {} } %4, 1 - ret { { {}, {} }, { {}, {} } } %mrv7 + %2 = call { { i32, {}, {} }, { i32, {}, {} } } @_hl.main_binary.9({ i32, {}, {} } %0, { i32, {}, {} } %1) + %3 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %2, 0 + %4 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %2, 1 + %mrv = insertvalue { { i32, {}, {} }, { i32, {}, {} } } undef, { i32, {}, {} } %3, 0 + %mrv7 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } %mrv, { i32, {}, {} } %4, 1 + ret { { i32, {}, {} }, { i32, {}, {} } } %mrv7 } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@pre-mem2reg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@pre-mem2reg@llvm14.snap index 6d95704..7cd0aa2 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@pre-mem2reg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_call@pre-mem2reg@llvm14.snap @@ -14,51 +14,51 @@ entry_block: ; preds = %alloca_block ret void } -define { {}, {} } @_hl.main_unary.5({ {}, {} } %0) { +define { i32, {}, {} } @_hl.main_unary.5({ i32, {}, {} } %0) { alloca_block: - %"0" = alloca { {}, {} }, align 8 - %"6_0" = alloca { {}, {} }, align 8 - %"8_0" = alloca { {}, {} }, align 8 + %"0" = alloca { i32, {}, {} }, align 8 + %"6_0" = alloca { i32, {}, {} }, align 8 + %"8_0" = alloca { i32, {}, {} }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { {}, {} } %0, { {}, {} }* %"6_0", align 1 - %"6_01" = load { {}, {} }, { {}, {} }* %"6_0", align 1 - %1 = call { {}, {} } @_hl.main_unary.5({ {}, {} } %"6_01") - store { {}, {} } %1, { {}, {} }* %"8_0", align 1 - %"8_02" = load { {}, {} }, { {}, {} }* %"8_0", align 1 - store { {}, {} } %"8_02", { {}, {} }* %"0", align 1 - %"03" = load { {}, {} }, { {}, {} }* %"0", align 1 - ret { {}, {} } %"03" + store { i32, {}, {} } %0, { i32, {}, {} }* %"6_0", align 4 + %"6_01" = load { i32, {}, {} }, { i32, {}, {} }* %"6_0", align 4 + %1 = call { i32, {}, {} } @_hl.main_unary.5({ i32, {}, {} } %"6_01") + store { i32, {}, {} } %1, { i32, {}, {} }* %"8_0", align 4 + %"8_02" = load { i32, {}, {} }, { i32, {}, {} }* %"8_0", align 4 + store { i32, {}, {} } %"8_02", { i32, {}, {} }* %"0", align 4 + %"03" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"03" } -define { { {}, {} }, { {}, {} } } @_hl.main_binary.9({ {}, {} } %0, { {}, {} } %1) { +define { { i32, {}, {} }, { i32, {}, {} } } @_hl.main_binary.9({ i32, {}, {} } %0, { i32, {}, {} } %1) { alloca_block: - %"0" = alloca { {}, {} }, align 8 - %"1" = alloca { {}, {} }, align 8 - %"10_0" = alloca { {}, {} }, align 8 - %"10_1" = alloca { {}, {} }, align 8 - %"12_0" = alloca { {}, {} }, align 8 - %"12_1" = alloca { {}, {} }, align 8 + %"0" = alloca { i32, {}, {} }, align 8 + %"1" = alloca { i32, {}, {} }, align 8 + %"10_0" = alloca { i32, {}, {} }, align 8 + %"10_1" = alloca { i32, {}, {} }, align 8 + %"12_0" = alloca { i32, {}, {} }, align 8 + %"12_1" = alloca { i32, {}, {} }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { {}, {} } %0, { {}, {} }* %"10_0", align 1 - store { {}, {} } %1, { {}, {} }* %"10_1", align 1 - %"10_01" = load { {}, {} }, { {}, {} }* %"10_0", align 1 - %"10_12" = load { {}, {} }, { {}, {} }* %"10_1", align 1 - %2 = call { { {}, {} }, { {}, {} } } @_hl.main_binary.9({ {}, {} } %"10_01", { {}, {} } %"10_12") - %3 = extractvalue { { {}, {} }, { {}, {} } } %2, 0 - %4 = extractvalue { { {}, {} }, { {}, {} } } %2, 1 - store { {}, {} } %3, { {}, {} }* %"12_0", align 1 - store { {}, {} } %4, { {}, {} }* %"12_1", align 1 - %"12_03" = load { {}, {} }, { {}, {} }* %"12_0", align 1 - %"12_14" = load { {}, {} }, { {}, {} }* %"12_1", align 1 - store { {}, {} } %"12_03", { {}, {} }* %"0", align 1 - store { {}, {} } %"12_14", { {}, {} }* %"1", align 1 - %"05" = load { {}, {} }, { {}, {} }* %"0", align 1 - %"16" = load { {}, {} }, { {}, {} }* %"1", align 1 - %mrv = insertvalue { { {}, {} }, { {}, {} } } undef, { {}, {} } %"05", 0 - %mrv7 = insertvalue { { {}, {} }, { {}, {} } } %mrv, { {}, {} } %"16", 1 - ret { { {}, {} }, { {}, {} } } %mrv7 + store { i32, {}, {} } %0, { i32, {}, {} }* %"10_0", align 4 + store { i32, {}, {} } %1, { i32, {}, {} }* %"10_1", align 4 + %"10_01" = load { i32, {}, {} }, { i32, {}, {} }* %"10_0", align 4 + %"10_12" = load { i32, {}, {} }, { i32, {}, {} }* %"10_1", align 4 + %2 = call { { i32, {}, {} }, { i32, {}, {} } } @_hl.main_binary.9({ i32, {}, {} } %"10_01", { i32, {}, {} } %"10_12") + %3 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %2, 0 + %4 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %2, 1 + store { i32, {}, {} } %3, { i32, {}, {} }* %"12_0", align 4 + store { i32, {}, {} } %4, { i32, {}, {} }* %"12_1", align 4 + %"12_03" = load { i32, {}, {} }, { i32, {}, {} }* %"12_0", align 4 + %"12_14" = load { i32, {}, {} }, { i32, {}, {} }* %"12_1", align 4 + store { i32, {}, {} } %"12_03", { i32, {}, {} }* %"0", align 4 + store { i32, {}, {} } %"12_14", { i32, {}, {} }* %"1", align 4 + %"05" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + %"16" = load { i32, {}, {} }, { i32, {}, {} }* %"1", align 4 + %mrv = insertvalue { { i32, {}, {} }, { i32, {}, {} } } undef, { i32, {}, {} } %"05", 0 + %mrv7 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } %mrv, { i32, {}, {} } %"16", 1 + ret { { i32, {}, {} }, { i32, {}, {} } } %mrv7 } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@llvm14.snap index a7d9b52..a113570 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@llvm14.snap @@ -5,40 +5,41 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } @_hl.main.1({ { { i32 } }, { { i32, {} } }, { { {}, {} } } } %0, { i32, {} } %1) { +define { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } @_hl.main.1({ i32, { {} }, { { {} } }, { { i32, {}, {} } } } %0, { {} } %1) { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - %2 = extractvalue { { { i32 } }, { { i32, {} } }, { { {}, {} } } } %0, 0 - %3 = extractvalue { { i32 } } %2, 0 - %4 = extractvalue { { { i32 } }, { { i32, {} } }, { { {}, {} } } } %0, 1 - %5 = extractvalue { { i32, {} } } %4, 0 - %6 = extractvalue { { { i32 } }, { { i32, {} } }, { { {}, {} } } } %0, 2 - %7 = extractvalue { { {}, {} } } %6, 0 - switch i32 0, label %cond_4_case_0 [ + %2 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %0, 0 + %3 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %0, 1 + %4 = extractvalue { {} } %3, 0 + %5 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %0, 2 + %6 = extractvalue { { {} } } %5, 0 + %7 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %0, 3 + %8 = extractvalue { { i32, {}, {} } } %7, 0 + switch i32 %2, label %cond_4_case_0 [ i32 1, label %cond_4_case_1 i32 2, label %cond_4_case_2 ] cond_4_case_0: ; preds = %entry_block - %8 = insertvalue { { i32 } } undef, { i32 } %3, 0 - %9 = insertvalue { { { {}, {} } }, { { i32, {} } }, { { i32 } } } poison, { { i32 } } %8, 2 + %9 = insertvalue { {} } undef, {} %4, 0 + %10 = insertvalue { i32, { { i32, {}, {} } }, { { {} } }, { {} } } { i32 2, { { i32, {}, {} } } poison, { { {} } } poison, { {} } poison }, { {} } %9, 3 br label %cond_exit_4 cond_4_case_1: ; preds = %entry_block - %10 = insertvalue { { i32, {} } } undef, { i32, {} } %5, 0 - %11 = insertvalue { { { {}, {} } }, { { i32, {} } }, { { i32 } } } poison, { { i32, {} } } %10, 1 + %11 = insertvalue { { {} } } undef, { {} } %6, 0 + %12 = insertvalue { i32, { { i32, {}, {} } }, { { {} } }, { {} } } { i32 1, { { i32, {}, {} } } poison, { { {} } } poison, { {} } poison }, { { {} } } %11, 2 br label %cond_exit_4 cond_4_case_2: ; preds = %entry_block - %12 = insertvalue { { {}, {} } } undef, { {}, {} } %7, 0 - %13 = insertvalue { { { {}, {} } }, { { i32, {} } }, { { i32 } } } poison, { { {}, {} } } %12, 0 + %13 = insertvalue { { i32, {}, {} } } undef, { i32, {}, {} } %8, 0 + %14 = insertvalue { i32, { { i32, {}, {} } }, { { {} } }, { {} } } { i32 0, { { i32, {}, {} } } poison, { { {} } } poison, { {} } poison }, { { i32, {}, {} } } %13, 1 br label %cond_exit_4 cond_exit_4: ; preds = %cond_4_case_2, %cond_4_case_1, %cond_4_case_0 - %"03.0" = phi { { { {}, {} } }, { { i32, {} } }, { { i32 } } } [ %9, %cond_4_case_0 ], [ %13, %cond_4_case_2 ], [ %11, %cond_4_case_1 ] - %mrv = insertvalue { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } undef, { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %"03.0", 0 - %mrv32 = insertvalue { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } %mrv, { i32, {} } %1, 1 - ret { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } %mrv32 + %"03.0" = phi { i32, { { i32, {}, {} } }, { { {} } }, { {} } } [ %10, %cond_4_case_0 ], [ %14, %cond_4_case_2 ], [ %12, %cond_4_case_1 ] + %mrv = insertvalue { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } undef, { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %"03.0", 0 + %mrv32 = insertvalue { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } %mrv, { {} } %1, 1 + ret { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } %mrv32 } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@pre-mem2reg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@pre-mem2reg@llvm14.snap index fda29c1..423b25f 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@pre-mem2reg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_conditional@pre-mem2reg@llvm14.snap @@ -5,112 +5,113 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } @_hl.main.1({ { { i32 } }, { { i32, {} } }, { { {}, {} } } } %0, { i32, {} } %1) { +define { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } @_hl.main.1({ i32, { {} }, { { {} } }, { { i32, {}, {} } } } %0, { {} } %1) { alloca_block: - %"0" = alloca { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, align 8 - %"1" = alloca { i32, {} }, align 8 - %"2_0" = alloca { { { i32 } }, { { i32, {} } }, { { {}, {} } } }, align 8 - %"2_1" = alloca { i32, {} }, align 8 - %"4_0" = alloca { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, align 8 - %"4_1" = alloca { i32, {} }, align 8 - %"03" = alloca { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, align 8 - %"14" = alloca { i32, {} }, align 8 - %"07" = alloca { i32 }, align 8 - %"18" = alloca { i32, {} }, align 8 - %"6_0" = alloca { i32 }, align 8 - %"6_1" = alloca { i32, {} }, align 8 - %"8_0" = alloca { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, align 8 - %"014" = alloca { i32, {} }, align 8 - %"115" = alloca { i32, {} }, align 8 - %"10_0" = alloca { i32, {} }, align 8 - %"10_1" = alloca { i32, {} }, align 8 - %"12_0" = alloca { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, align 8 - %"021" = alloca { {}, {} }, align 8 - %"122" = alloca { i32, {} }, align 8 - %"14_0" = alloca { {}, {} }, align 8 - %"14_1" = alloca { i32, {} }, align 8 - %"16_0" = alloca { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, align 8 + %"0" = alloca { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, align 8 + %"1" = alloca { {} }, align 8 + %"2_0" = alloca { i32, { {} }, { { {} } }, { { i32, {}, {} } } }, align 8 + %"2_1" = alloca { {} }, align 8 + %"4_0" = alloca { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, align 8 + %"4_1" = alloca { {} }, align 8 + %"03" = alloca { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, align 8 + %"14" = alloca { {} }, align 8 + %"07" = alloca {}, align 8 + %"18" = alloca { {} }, align 8 + %"6_0" = alloca {}, align 8 + %"6_1" = alloca { {} }, align 8 + %"8_0" = alloca { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, align 8 + %"014" = alloca { {} }, align 8 + %"115" = alloca { {} }, align 8 + %"10_0" = alloca { {} }, align 8 + %"10_1" = alloca { {} }, align 8 + %"12_0" = alloca { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, align 8 + %"021" = alloca { i32, {}, {} }, align 8 + %"122" = alloca { {} }, align 8 + %"14_0" = alloca { i32, {}, {} }, align 8 + %"14_1" = alloca { {} }, align 8 + %"16_0" = alloca { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { { { i32 } }, { { i32, {} } }, { { {}, {} } } } %0, { { { i32 } }, { { i32, {} } }, { { {}, {} } } }* %"2_0", align 4 - store { i32, {} } %1, { i32, {} }* %"2_1", align 4 - %"2_01" = load { { { i32 } }, { { i32, {} } }, { { {}, {} } } }, { { { i32 } }, { { i32, {} } }, { { {}, {} } } }* %"2_0", align 4 - %"2_12" = load { i32, {} }, { i32, {} }* %"2_1", align 4 - %2 = extractvalue { { { i32 } }, { { i32, {} } }, { { {}, {} } } } %"2_01", 0 - %3 = extractvalue { { i32 } } %2, 0 - store { i32 } %3, { i32 }* %"07", align 4 - store { i32, {} } %"2_12", { i32, {} }* %"18", align 4 - %4 = extractvalue { { { i32 } }, { { i32, {} } }, { { {}, {} } } } %"2_01", 1 - %5 = extractvalue { { i32, {} } } %4, 0 - store { i32, {} } %5, { i32, {} }* %"014", align 4 - store { i32, {} } %"2_12", { i32, {} }* %"115", align 4 - %6 = extractvalue { { { i32 } }, { { i32, {} } }, { { {}, {} } } } %"2_01", 2 - %7 = extractvalue { { {}, {} } } %6, 0 - store { {}, {} } %7, { {}, {} }* %"021", align 1 - store { i32, {} } %"2_12", { i32, {} }* %"122", align 4 - switch i32 0, label %cond_4_case_0 [ + store { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %0, { i32, { {} }, { { {} } }, { { i32, {}, {} } } }* %"2_0", align 4 + store { {} } %1, { {} }* %"2_1", align 1 + %"2_01" = load { i32, { {} }, { { {} } }, { { i32, {}, {} } } }, { i32, { {} }, { { {} } }, { { i32, {}, {} } } }* %"2_0", align 4 + %"2_12" = load { {} }, { {} }* %"2_1", align 1 + %2 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %"2_01", 0 + %3 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %"2_01", 1 + %4 = extractvalue { {} } %3, 0 + store {} %4, {}* %"07", align 1 + store { {} } %"2_12", { {} }* %"18", align 1 + %5 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %"2_01", 2 + %6 = extractvalue { { {} } } %5, 0 + store { {} } %6, { {} }* %"014", align 1 + store { {} } %"2_12", { {} }* %"115", align 1 + %7 = extractvalue { i32, { {} }, { { {} } }, { { i32, {}, {} } } } %"2_01", 3 + %8 = extractvalue { { i32, {}, {} } } %7, 0 + store { i32, {}, {} } %8, { i32, {}, {} }* %"021", align 4 + store { {} } %"2_12", { {} }* %"122", align 1 + switch i32 %2, label %cond_4_case_0 [ i32 1, label %cond_4_case_1 i32 2, label %cond_4_case_2 ] cond_4_case_0: ; preds = %entry_block - %"09" = load { i32 }, { i32 }* %"07", align 4 - %"110" = load { i32, {} }, { i32, {} }* %"18", align 4 - store { i32 } %"09", { i32 }* %"6_0", align 4 - store { i32, {} } %"110", { i32, {} }* %"6_1", align 4 - %"6_011" = load { i32 }, { i32 }* %"6_0", align 4 - %8 = insertvalue { { i32 } } undef, { i32 } %"6_011", 0 - %9 = insertvalue { { { {}, {} } }, { { i32, {} } }, { { i32 } } } poison, { { i32 } } %8, 2 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %9, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"8_0", align 4 - %"8_012" = load { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"8_0", align 4 - %"6_113" = load { i32, {} }, { i32, {} }* %"6_1", align 4 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %"8_012", { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"03", align 4 - store { i32, {} } %"6_113", { i32, {} }* %"14", align 4 + %"09" = load {}, {}* %"07", align 1 + %"110" = load { {} }, { {} }* %"18", align 1 + store {} %"09", {}* %"6_0", align 1 + store { {} } %"110", { {} }* %"6_1", align 1 + %"6_011" = load {}, {}* %"6_0", align 1 + %9 = insertvalue { {} } undef, {} %"6_011", 0 + %10 = insertvalue { i32, { { i32, {}, {} } }, { { {} } }, { {} } } { i32 2, { { i32, {}, {} } } poison, { { {} } } poison, { {} } poison }, { {} } %9, 3 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %10, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"8_0", align 4 + %"8_012" = load { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"8_0", align 4 + %"6_113" = load { {} }, { {} }* %"6_1", align 1 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %"8_012", { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"03", align 4 + store { {} } %"6_113", { {} }* %"14", align 1 br label %cond_exit_4 cond_4_case_1: ; preds = %entry_block - %"016" = load { i32, {} }, { i32, {} }* %"014", align 4 - %"117" = load { i32, {} }, { i32, {} }* %"115", align 4 - store { i32, {} } %"016", { i32, {} }* %"10_0", align 4 - store { i32, {} } %"117", { i32, {} }* %"10_1", align 4 - %"10_018" = load { i32, {} }, { i32, {} }* %"10_0", align 4 - %10 = insertvalue { { i32, {} } } undef, { i32, {} } %"10_018", 0 - %11 = insertvalue { { { {}, {} } }, { { i32, {} } }, { { i32 } } } poison, { { i32, {} } } %10, 1 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %11, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"12_0", align 4 - %"12_019" = load { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"12_0", align 4 - %"10_120" = load { i32, {} }, { i32, {} }* %"10_1", align 4 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %"12_019", { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"03", align 4 - store { i32, {} } %"10_120", { i32, {} }* %"14", align 4 + %"016" = load { {} }, { {} }* %"014", align 1 + %"117" = load { {} }, { {} }* %"115", align 1 + store { {} } %"016", { {} }* %"10_0", align 1 + store { {} } %"117", { {} }* %"10_1", align 1 + %"10_018" = load { {} }, { {} }* %"10_0", align 1 + %11 = insertvalue { { {} } } undef, { {} } %"10_018", 0 + %12 = insertvalue { i32, { { i32, {}, {} } }, { { {} } }, { {} } } { i32 1, { { i32, {}, {} } } poison, { { {} } } poison, { {} } poison }, { { {} } } %11, 2 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %12, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"12_0", align 4 + %"12_019" = load { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"12_0", align 4 + %"10_120" = load { {} }, { {} }* %"10_1", align 1 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %"12_019", { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"03", align 4 + store { {} } %"10_120", { {} }* %"14", align 1 br label %cond_exit_4 cond_4_case_2: ; preds = %entry_block - %"023" = load { {}, {} }, { {}, {} }* %"021", align 1 - %"124" = load { i32, {} }, { i32, {} }* %"122", align 4 - store { {}, {} } %"023", { {}, {} }* %"14_0", align 1 - store { i32, {} } %"124", { i32, {} }* %"14_1", align 4 - %"14_025" = load { {}, {} }, { {}, {} }* %"14_0", align 1 - %12 = insertvalue { { {}, {} } } undef, { {}, {} } %"14_025", 0 - %13 = insertvalue { { { {}, {} } }, { { i32, {} } }, { { i32 } } } poison, { { {}, {} } } %12, 0 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %13, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"16_0", align 4 - %"16_026" = load { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"16_0", align 4 - %"14_127" = load { i32, {} }, { i32, {} }* %"14_1", align 4 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %"16_026", { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"03", align 4 - store { i32, {} } %"14_127", { i32, {} }* %"14", align 4 + %"023" = load { i32, {}, {} }, { i32, {}, {} }* %"021", align 4 + %"124" = load { {} }, { {} }* %"122", align 1 + store { i32, {}, {} } %"023", { i32, {}, {} }* %"14_0", align 4 + store { {} } %"124", { {} }* %"14_1", align 1 + %"14_025" = load { i32, {}, {} }, { i32, {}, {} }* %"14_0", align 4 + %13 = insertvalue { { i32, {}, {} } } undef, { i32, {}, {} } %"14_025", 0 + %14 = insertvalue { i32, { { i32, {}, {} } }, { { {} } }, { {} } } { i32 0, { { i32, {}, {} } } poison, { { {} } } poison, { {} } poison }, { { i32, {}, {} } } %13, 1 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %14, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"16_0", align 4 + %"16_026" = load { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"16_0", align 4 + %"14_127" = load { {} }, { {} }* %"14_1", align 1 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %"16_026", { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"03", align 4 + store { {} } %"14_127", { {} }* %"14", align 1 br label %cond_exit_4 cond_exit_4: ; preds = %cond_4_case_2, %cond_4_case_1, %cond_4_case_0 - %"05" = load { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"03", align 4 - %"16" = load { i32, {} }, { i32, {} }* %"14", align 4 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %"05", { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"4_0", align 4 - store { i32, {} } %"16", { i32, {} }* %"4_1", align 4 - %"4_028" = load { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"4_0", align 4 - %"4_129" = load { i32, {} }, { i32, {} }* %"4_1", align 4 - store { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %"4_028", { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"0", align 4 - store { i32, {} } %"4_129", { i32, {} }* %"1", align 4 - %"030" = load { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { { { {}, {} } }, { { i32, {} } }, { { i32 } } }* %"0", align 4 - %"131" = load { i32, {} }, { i32, {} }* %"1", align 4 - %mrv = insertvalue { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } undef, { { { {}, {} } }, { { i32, {} } }, { { i32 } } } %"030", 0 - %mrv32 = insertvalue { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } %mrv, { i32, {} } %"131", 1 - ret { { { { {}, {} } }, { { i32, {} } }, { { i32 } } }, { i32, {} } } %mrv32 + %"05" = load { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"03", align 4 + %"16" = load { {} }, { {} }* %"14", align 1 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %"05", { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"4_0", align 4 + store { {} } %"16", { {} }* %"4_1", align 1 + %"4_028" = load { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"4_0", align 4 + %"4_129" = load { {} }, { {} }* %"4_1", align 1 + store { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %"4_028", { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"0", align 4 + store { {} } %"4_129", { {} }* %"1", align 1 + %"030" = load { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { i32, { { i32, {}, {} } }, { { {} } }, { {} } }* %"0", align 4 + %"131" = load { {} }, { {} }* %"1", align 1 + %mrv = insertvalue { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } undef, { i32, { { i32, {}, {} } }, { { {} } }, { {} } } %"030", 0 + %mrv32 = insertvalue { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } %mrv, { {} } %"131", 1 + ret { { i32, { { i32, {}, {} } }, { { {} } }, { {} } }, { {} } } %mrv32 } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@llvm14.snap index af6800c..8ca5d26 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@llvm14.snap @@ -5,10 +5,10 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { i32, {} } @_hl.main.1({ i32, {} } %0) { +define { {} } @_hl.main.1({ {} } %0) { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - ret { i32, {} } %0 + ret { {} } %0 } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@pre-mem2reg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@pre-mem2reg@llvm14.snap index 38902a2..04f627a 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@pre-mem2reg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_dfg@pre-mem2reg@llvm14.snap @@ -5,22 +5,22 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { i32, {} } @_hl.main.1({ i32, {} } %0) { +define { {} } @_hl.main.1({ {} } %0) { alloca_block: - %"0" = alloca { i32, {} }, align 8 - %"2_0" = alloca { i32, {} }, align 8 - %"4_0" = alloca { i32, {} }, align 8 - %"5_0" = alloca { i32, {} }, align 8 + %"0" = alloca { {} }, align 8 + %"2_0" = alloca { {} }, align 8 + %"4_0" = alloca { {} }, align 8 + %"5_0" = alloca { {} }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { i32, {} } %0, { i32, {} }* %"2_0", align 4 - %"2_01" = load { i32, {} }, { i32, {} }* %"2_0", align 4 - store { i32, {} } %"2_01", { i32, {} }* %"5_0", align 4 - %"5_02" = load { i32, {} }, { i32, {} }* %"5_0", align 4 - store { i32, {} } %"5_02", { i32, {} }* %"4_0", align 4 - %"4_03" = load { i32, {} }, { i32, {} }* %"4_0", align 4 - store { i32, {} } %"4_03", { i32, {} }* %"0", align 4 - %"04" = load { i32, {} }, { i32, {} }* %"0", align 4 - ret { i32, {} } %"04" + store { {} } %0, { {} }* %"2_0", align 1 + %"2_01" = load { {} }, { {} }* %"2_0", align 1 + store { {} } %"2_01", { {} }* %"5_0", align 1 + %"5_02" = load { {} }, { {} }* %"5_0", align 1 + store { {} } %"5_02", { {} }* %"4_0", align 1 + %"4_03" = load { {} }, { {} }* %"4_0", align 1 + store { {} } %"4_03", { {} }* %"0", align 1 + %"04" = load { {} }, { {} }* %"0", align 1 + ret { {} } %"04" } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@llvm14.snap index dd875de..df80ecc 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@llvm14.snap @@ -5,10 +5,10 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { i32, { { {}, {}, {}, {} }, i16 } } @_hl.main.1() { +define { { { i32, {}, {}, {}, {} }, i16 } } @_hl.main.1() { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - ret { i32, { { {}, {}, {}, {} }, i16 } } { i32 0, { { {}, {}, {}, {} }, i16 } { { {}, {}, {}, {} } { {} poison, {} poison, {} undef, {} poison }, i16 -24 } } + ret { { { i32, {}, {}, {}, {} }, i16 } } { { { i32, {}, {}, {}, {} }, i16 } { { i32, {}, {}, {}, {} } { i32 2, {} poison, {} poison, {} undef, {} poison }, i16 -24 } } } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@pre-mem2reg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@pre-mem2reg@llvm14.snap index 32235d4..e8424cf 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@pre-mem2reg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_load_constant@pre-mem2reg@llvm14.snap @@ -5,16 +5,16 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { i32, { { {}, {}, {}, {} }, i16 } } @_hl.main.1() { +define { { { i32, {}, {}, {}, {} }, i16 } } @_hl.main.1() { alloca_block: - %"0" = alloca { i32, { { {}, {}, {}, {} }, i16 } }, align 8 - %"5_0" = alloca { i32, { { {}, {}, {}, {} }, i16 } }, align 8 + %"0" = alloca { { { i32, {}, {}, {}, {} }, i16 } }, align 8 + %"5_0" = alloca { { { i32, {}, {}, {}, {} }, i16 } }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { i32, { { {}, {}, {}, {} }, i16 } } { i32 0, { { {}, {}, {}, {} }, i16 } { { {}, {}, {}, {} } { {} poison, {} poison, {} undef, {} poison }, i16 -24 } }, { i32, { { {}, {}, {}, {} }, i16 } }* %"5_0", align 4 - %"5_01" = load { i32, { { {}, {}, {}, {} }, i16 } }, { i32, { { {}, {}, {}, {} }, i16 } }* %"5_0", align 4 - store { i32, { { {}, {}, {}, {} }, i16 } } %"5_01", { i32, { { {}, {}, {}, {} }, i16 } }* %"0", align 4 - %"02" = load { i32, { { {}, {}, {}, {} }, i16 } }, { i32, { { {}, {}, {}, {} }, i16 } }* %"0", align 4 - ret { i32, { { {}, {}, {}, {} }, i16 } } %"02" + store { { { i32, {}, {}, {}, {} }, i16 } } { { { i32, {}, {}, {}, {} }, i16 } { { i32, {}, {}, {}, {} } { i32 2, {} poison, {} poison, {} undef, {} poison }, i16 -24 } }, { { { i32, {}, {}, {}, {} }, i16 } }* %"5_0", align 4 + %"5_01" = load { { { i32, {}, {}, {}, {} }, i16 } }, { { { i32, {}, {}, {}, {} }, i16 } }* %"5_0", align 4 + store { { { i32, {}, {}, {}, {} }, i16 } } %"5_01", { { { i32, {}, {}, {}, {} }, i16 } }* %"0", align 4 + %"02" = load { { { i32, {}, {}, {}, {} }, i16 } }, { { { i32, {}, {}, {}, {} }, i16 } }* %"0", align 4 + ret { { { i32, {}, {}, {}, {} }, i16 } } %"02" } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@llvm14.snap index 567330b..ad60ef4 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@llvm14.snap @@ -5,13 +5,13 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { i32, { { {}, {} }, { {}, {} } } } @_hl.main.1({ {}, {} } %0, { {}, {} } %1) { +define { { { i32, {}, {} }, { i32, {}, {} } } } @_hl.main.1({ i32, {}, {} } %0, { i32, {}, {} } %1) { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - %2 = insertvalue { { {}, {} }, { {}, {} } } undef, { {}, {} } %0, 0 - %3 = insertvalue { { {}, {} }, { {}, {} } } %2, { {}, {} } %1, 1 - %4 = insertvalue { i32, { { {}, {} }, { {}, {} } } } { i32 0, { { {}, {} }, { {}, {} } } poison }, { { {}, {} }, { {}, {} } } %3, 1 - ret { i32, { { {}, {} }, { {}, {} } } } %4 + %2 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } undef, { i32, {}, {} } %0, 0 + %3 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } %2, { i32, {}, {} } %1, 1 + %4 = insertvalue { { { i32, {}, {} }, { i32, {}, {} } } } poison, { { i32, {}, {} }, { i32, {}, {} } } %3, 0 + ret { { { i32, {}, {} }, { i32, {}, {} } } } %4 } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@pre-mem2reg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@pre-mem2reg@llvm14.snap index d0ba060..51a81e2 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@pre-mem2reg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_make_tuple@pre-mem2reg@llvm14.snap @@ -5,25 +5,25 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { i32, { { {}, {} }, { {}, {} } } } @_hl.main.1({ {}, {} } %0, { {}, {} } %1) { +define { { { i32, {}, {} }, { i32, {}, {} } } } @_hl.main.1({ i32, {}, {} } %0, { i32, {}, {} } %1) { alloca_block: - %"0" = alloca { i32, { { {}, {} }, { {}, {} } } }, align 8 - %"2_0" = alloca { {}, {} }, align 8 - %"2_1" = alloca { {}, {} }, align 8 - %"4_0" = alloca { i32, { { {}, {} }, { {}, {} } } }, align 8 + %"0" = alloca { { { i32, {}, {} }, { i32, {}, {} } } }, align 8 + %"2_0" = alloca { i32, {}, {} }, align 8 + %"2_1" = alloca { i32, {}, {} }, align 8 + %"4_0" = alloca { { { i32, {}, {} }, { i32, {}, {} } } }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { {}, {} } %0, { {}, {} }* %"2_0", align 1 - store { {}, {} } %1, { {}, {} }* %"2_1", align 1 - %"2_01" = load { {}, {} }, { {}, {} }* %"2_0", align 1 - %"2_12" = load { {}, {} }, { {}, {} }* %"2_1", align 1 - %2 = insertvalue { { {}, {} }, { {}, {} } } undef, { {}, {} } %"2_01", 0 - %3 = insertvalue { { {}, {} }, { {}, {} } } %2, { {}, {} } %"2_12", 1 - %4 = insertvalue { i32, { { {}, {} }, { {}, {} } } } { i32 0, { { {}, {} }, { {}, {} } } poison }, { { {}, {} }, { {}, {} } } %3, 1 - store { i32, { { {}, {} }, { {}, {} } } } %4, { i32, { { {}, {} }, { {}, {} } } }* %"4_0", align 4 - %"4_03" = load { i32, { { {}, {} }, { {}, {} } } }, { i32, { { {}, {} }, { {}, {} } } }* %"4_0", align 4 - store { i32, { { {}, {} }, { {}, {} } } } %"4_03", { i32, { { {}, {} }, { {}, {} } } }* %"0", align 4 - %"04" = load { i32, { { {}, {} }, { {}, {} } } }, { i32, { { {}, {} }, { {}, {} } } }* %"0", align 4 - ret { i32, { { {}, {} }, { {}, {} } } } %"04" + store { i32, {}, {} } %0, { i32, {}, {} }* %"2_0", align 4 + store { i32, {}, {} } %1, { i32, {}, {} }* %"2_1", align 4 + %"2_01" = load { i32, {}, {} }, { i32, {}, {} }* %"2_0", align 4 + %"2_12" = load { i32, {}, {} }, { i32, {}, {} }* %"2_1", align 4 + %2 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } undef, { i32, {}, {} } %"2_01", 0 + %3 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } %2, { i32, {}, {} } %"2_12", 1 + %4 = insertvalue { { { i32, {}, {} }, { i32, {}, {} } } } poison, { { i32, {}, {} }, { i32, {}, {} } } %3, 0 + store { { { i32, {}, {} }, { i32, {}, {} } } } %4, { { { i32, {}, {} }, { i32, {}, {} } } }* %"4_0", align 4 + %"4_03" = load { { { i32, {}, {} }, { i32, {}, {} } } }, { { { i32, {}, {} }, { i32, {}, {} } } }* %"4_0", align 4 + store { { { i32, {}, {} }, { i32, {}, {} } } } %"4_03", { { { i32, {}, {} }, { i32, {}, {} } } }* %"0", align 4 + %"04" = load { { { i32, {}, {} }, { i32, {}, {} } } }, { { { i32, {}, {} }, { i32, {}, {} } } }* %"0", align 4 + ret { { { i32, {}, {} }, { i32, {}, {} } } } %"04" } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@llvm14.snap index 3860a43..10a6b33 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@llvm14.snap @@ -5,10 +5,10 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { {}, {}, {} } @_hl.main.1() { +define { i32, {}, {}, {} } @_hl.main.1() { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - ret { {}, {}, {} } { {} poison, {} undef, {} poison } + ret { i32, {}, {}, {} } { i32 1, {} poison, {} undef, {} poison } } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@pre-mem2reg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@pre-mem2reg@llvm14.snap index 58f5b08..3dbc925 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@pre-mem2reg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_tag@pre-mem2reg@llvm14.snap @@ -5,16 +5,16 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { {}, {}, {} } @_hl.main.1() { +define { i32, {}, {}, {} } @_hl.main.1() { alloca_block: - %"0" = alloca { {}, {}, {} }, align 8 - %"4_0" = alloca { {}, {}, {} }, align 8 + %"0" = alloca { i32, {}, {}, {} }, align 8 + %"4_0" = alloca { i32, {}, {}, {} }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { {}, {}, {} } { {} poison, {} undef, {} poison }, { {}, {}, {} }* %"4_0", align 1 - %"4_01" = load { {}, {}, {} }, { {}, {}, {} }* %"4_0", align 1 - store { {}, {}, {} } %"4_01", { {}, {}, {} }* %"0", align 1 - %"02" = load { {}, {}, {} }, { {}, {}, {} }* %"0", align 1 - ret { {}, {}, {} } %"02" + store { i32, {}, {}, {} } { i32 1, {} poison, {} undef, {} poison }, { i32, {}, {}, {} }* %"4_0", align 4 + %"4_01" = load { i32, {}, {}, {} }, { i32, {}, {}, {} }* %"4_0", align 4 + store { i32, {}, {}, {} } %"4_01", { i32, {}, {}, {} }* %"0", align 4 + %"02" = load { i32, {}, {}, {} }, { i32, {}, {}, {} }* %"0", align 4 + ret { i32, {}, {}, {} } %"02" } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@llvm14.snap index 12116d0..c7e8d1d 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@llvm14.snap @@ -5,15 +5,15 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { { {}, {} }, { {}, {} } } @_hl.main.1({ i32, { { {}, {} }, { {}, {} } } } %0) { +define { { i32, {}, {} }, { i32, {}, {} } } @_hl.main.1({ { { i32, {}, {} }, { i32, {}, {} } } } %0) { alloca_block: br label %entry_block entry_block: ; preds = %alloca_block - %1 = extractvalue { i32, { { {}, {} }, { {}, {} } } } %0, 1 - %2 = extractvalue { { {}, {} }, { {}, {} } } %1, 0 - %3 = extractvalue { { {}, {} }, { {}, {} } } %1, 1 - %mrv = insertvalue { { {}, {} }, { {}, {} } } undef, { {}, {} } %2, 0 - %mrv6 = insertvalue { { {}, {} }, { {}, {} } } %mrv, { {}, {} } %3, 1 - ret { { {}, {} }, { {}, {} } } %mrv6 + %1 = extractvalue { { { i32, {}, {} }, { i32, {}, {} } } } %0, 0 + %2 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %1, 0 + %3 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %1, 1 + %mrv = insertvalue { { i32, {}, {} }, { i32, {}, {} } } undef, { i32, {}, {} } %2, 0 + %mrv6 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } %mrv, { i32, {}, {} } %3, 1 + ret { { i32, {}, {} }, { i32, {}, {} } } %mrv6 } diff --git a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@pre-mem2reg@llvm14.snap b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@pre-mem2reg@llvm14.snap index b1141c8..fc3d28d 100644 --- a/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@pre-mem2reg@llvm14.snap +++ b/src/emit/snapshots/hugr_llvm__emit__test__emit_hugr_unpack_tuple@pre-mem2reg@llvm14.snap @@ -5,30 +5,30 @@ expression: module.to_string() ; ModuleID = 'test_context' source_filename = "test_context" -define { { {}, {} }, { {}, {} } } @_hl.main.1({ i32, { { {}, {} }, { {}, {} } } } %0) { +define { { i32, {}, {} }, { i32, {}, {} } } @_hl.main.1({ { { i32, {}, {} }, { i32, {}, {} } } } %0) { alloca_block: - %"0" = alloca { {}, {} }, align 8 - %"1" = alloca { {}, {} }, align 8 - %"2_0" = alloca { i32, { { {}, {} }, { {}, {} } } }, align 8 - %"4_0" = alloca { {}, {} }, align 8 - %"4_1" = alloca { {}, {} }, align 8 + %"0" = alloca { i32, {}, {} }, align 8 + %"1" = alloca { i32, {}, {} }, align 8 + %"2_0" = alloca { { { i32, {}, {} }, { i32, {}, {} } } }, align 8 + %"4_0" = alloca { i32, {}, {} }, align 8 + %"4_1" = alloca { i32, {}, {} }, align 8 br label %entry_block entry_block: ; preds = %alloca_block - store { i32, { { {}, {} }, { {}, {} } } } %0, { i32, { { {}, {} }, { {}, {} } } }* %"2_0", align 4 - %"2_01" = load { i32, { { {}, {} }, { {}, {} } } }, { i32, { { {}, {} }, { {}, {} } } }* %"2_0", align 4 - %1 = extractvalue { i32, { { {}, {} }, { {}, {} } } } %"2_01", 1 - %2 = extractvalue { { {}, {} }, { {}, {} } } %1, 0 - %3 = extractvalue { { {}, {} }, { {}, {} } } %1, 1 - store { {}, {} } %2, { {}, {} }* %"4_0", align 1 - store { {}, {} } %3, { {}, {} }* %"4_1", align 1 - %"4_02" = load { {}, {} }, { {}, {} }* %"4_0", align 1 - %"4_13" = load { {}, {} }, { {}, {} }* %"4_1", align 1 - store { {}, {} } %"4_02", { {}, {} }* %"0", align 1 - store { {}, {} } %"4_13", { {}, {} }* %"1", align 1 - %"04" = load { {}, {} }, { {}, {} }* %"0", align 1 - %"15" = load { {}, {} }, { {}, {} }* %"1", align 1 - %mrv = insertvalue { { {}, {} }, { {}, {} } } undef, { {}, {} } %"04", 0 - %mrv6 = insertvalue { { {}, {} }, { {}, {} } } %mrv, { {}, {} } %"15", 1 - ret { { {}, {} }, { {}, {} } } %mrv6 + store { { { i32, {}, {} }, { i32, {}, {} } } } %0, { { { i32, {}, {} }, { i32, {}, {} } } }* %"2_0", align 4 + %"2_01" = load { { { i32, {}, {} }, { i32, {}, {} } } }, { { { i32, {}, {} }, { i32, {}, {} } } }* %"2_0", align 4 + %1 = extractvalue { { { i32, {}, {} }, { i32, {}, {} } } } %"2_01", 0 + %2 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %1, 0 + %3 = extractvalue { { i32, {}, {} }, { i32, {}, {} } } %1, 1 + store { i32, {}, {} } %2, { i32, {}, {} }* %"4_0", align 4 + store { i32, {}, {} } %3, { i32, {}, {} }* %"4_1", align 4 + %"4_02" = load { i32, {}, {} }, { i32, {}, {} }* %"4_0", align 4 + %"4_13" = load { i32, {}, {} }, { i32, {}, {} }* %"4_1", align 4 + store { i32, {}, {} } %"4_02", { i32, {}, {} }* %"0", align 4 + store { i32, {}, {} } %"4_13", { i32, {}, {} }* %"1", align 4 + %"04" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + %"15" = load { i32, {}, {} }, { i32, {}, {} }* %"1", align 4 + %mrv = insertvalue { { i32, {}, {} }, { i32, {}, {} } } undef, { i32, {}, {} } %"04", 0 + %mrv6 = insertvalue { { i32, {}, {} }, { i32, {}, {} } } %mrv, { i32, {}, {} } %"15", 1 + ret { { i32, {}, {} }, { i32, {}, {} } } %mrv6 } diff --git a/src/fat.rs b/src/fat.rs index b9971d1..87f8152 100644 --- a/src/fat.rs +++ b/src/fat.rs @@ -5,10 +5,11 @@ use std::{cmp::Ordering, hash::Hash, marker::PhantomData, ops::Deref}; use hugr::{ - ops::{Input, NamedOp, OpType, Output}, + ops::{DataflowBlock, ExitBlock, Input, NamedOp, OpType, Output, CFG}, types::Type, Hugr, HugrView, IncomingPort, Node, NodeIndex, OutgoingPort, }; +use itertools::Itertools as _; /// A Fat Node is a [Node] along with a reference to the [HugrView] whence it /// originates. It carries a type `OT`, the [OpType] of that node. `OT` may be @@ -155,11 +156,20 @@ impl<'c, OT, H: HugrView + ?Sized> FatNode<'c, OT, H> { )) } + pub fn node_outputs(&self) -> impl Iterator + '_ { + self.hugr.node_outputs(self.node) + } + + pub fn output_neighbours(&self) -> impl Iterator> + '_ { + self.hugr + .output_neighbours(self.node) + .map(|n| FatNode::new_optype(self.hugr, n)) + } + /// Create a general `FatNode` from a specific one. pub fn generalise(self) -> FatNode<'c, OpType, H> where - &'c OpType: TryInto<&'c OT>, - OT: 'c, + OT: Into + 'c, { // guaranteed to be valid becasue self is valid FatNode { @@ -170,6 +180,25 @@ impl<'c, OT, H: HugrView + ?Sized> FatNode<'c, OT, H> { } } +impl<'c, H: HugrView> FatNode<'c, CFG, H> { + /// TODO it would be reasonable to remove Option and panic on failure here + pub fn get_entry_exit( + &self, + ) -> Option<(FatNode<'c, DataflowBlock, H>, FatNode<'c, ExitBlock, H>)> { + let [i, o] = self + .hugr + .children(self.node) + .take(2) + .collect_vec() + .try_into() + .ok()?; + Some(( + FatNode::try_new(self.hugr, i)?, + FatNode::try_new(self.hugr, o)?, + )) + } +} + impl<'c, OT, H> PartialEq for FatNode<'c, OT, H> { fn eq(&self, other: &Node) -> bool { &self.node == other @@ -271,6 +300,12 @@ impl<'c, OT, H> NodeIndex for FatNode<'c, OT, H> { } } +impl<'c, OT, H> NodeIndex for &FatNode<'c, OT, H> { + fn index(self) -> usize { + self.node.index() + } +} + /// An extension trait for [HugrView] which provides methods that delegate to /// [HugrView] and then return the result in [FatNode] form. See for example /// [FatExt::fat_io]. diff --git a/src/lib.rs b/src/lib.rs index 14683a9..ab0ba90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,7 @@ //! //! [BasicValueEnum]: [inkwell::values::BasicValueEnum] //! [BasicValue]: [inkwell::values::BasicValue] -//! +pub mod cli; pub mod custom; pub mod emit; pub mod fat; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..63b4404 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,34 @@ +use hugr::std_extensions::arithmetic::{ + conversions::EXTENSION as CONVERSIONS_EXTENSION, float_ops::EXTENSION as FLOAT_OPS_EXTENSION, + float_types::EXTENSION as FLOAT_TYPES_EXTENSION, int_ops::EXTENSION as INT_OPS_EXTENSION, + int_types::EXTENSION as INT_TYPES_EXTENSION, +}; +use hugr::std_extensions::logic::EXTENSION as LOGICS_EXTENSION; + +use hugr::extension::{ExtensionRegistry, PRELUDE}; + +use hugr_cli::{Level, Parser}; +use hugr_llvm::cli::CmdLineArgs; + +fn main() { + let opts = CmdLineArgs::parse(); + + // validate with all std extensions + let reg = ExtensionRegistry::try_new([ + PRELUDE.to_owned(), + INT_OPS_EXTENSION.to_owned(), + INT_TYPES_EXTENSION.to_owned(), + CONVERSIONS_EXTENSION.to_owned(), + FLOAT_OPS_EXTENSION.to_owned(), + FLOAT_TYPES_EXTENSION.to_owned(), + LOGICS_EXTENSION.to_owned(), + ]) + .unwrap(); + + if let Err(e) = opts.run(®) { + if opts.verbosity(Level::Error) { + eprintln!("{}", e); + } + std::process::exit(1); + } +} diff --git a/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_0.snap b/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_0.snap index cb69ce0..1a79773 100644 --- a/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_0.snap +++ b/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_0.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: "[[]+[]] -> [[]][]" --- -"void ({ {}, {} })" +"void ({ i32, {}, {} })" diff --git a/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_1.snap b/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_1.snap index b1fbcb6..5b3ba60 100644 --- a/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_1.snap +++ b/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_1.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: "[[]] -> [[]][[]+[]+[]]" --- -"{ {}, {}, {} } ({ i32, {} })" +"{ i32, {}, {}, {} } ({ {} })" diff --git a/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_2.snap b/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_2.snap index b609c7f..ed12608 100644 --- a/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_2.snap +++ b/src/snapshots/hugr_llvm__types__test__func_type_to_llvm@llvm14_2.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: "[[]][[], []]" --- -"{ { i32, {} }, { i32, {} } } ()" +"{ { {} }, { {} } } ()" diff --git a/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_0.snap b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_0.snap index d1b68be..88ae221 100644 --- a/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_0.snap +++ b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_0.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: ⊥ --- -"{ i32 }" +"{}" diff --git a/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_1.snap b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_1.snap index 9be4e63..73de345 100644 --- a/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_1.snap +++ b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_1.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: "[]" --- -"{ i32, {} }" +"{ {} }" diff --git a/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_2.snap b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_2.snap index 5683db0..786cbd1 100644 --- a/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_2.snap +++ b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_2.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: "[⊥, []]+[[]+[], []+[]+[]]" --- -"{ { { i32 }, { i32, {} } }, { { {}, {} }, { {}, {}, {} } } }" +"{ i32, { {}, { {} } }, { { i32, {}, {} }, { i32, {}, {}, {} } } }" diff --git a/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_3.snap b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_3.snap new file mode 100644 index 0000000..695c5e8 --- /dev/null +++ b/src/snapshots/hugr_llvm__types__test__sum_type_to_llvm@llvm14_3.snap @@ -0,0 +1,5 @@ +--- +source: src/types.rs +expression: "[]+[]" +--- +"{ i32, {}, {} }" diff --git a/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_5.snap b/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_5.snap index f1ecb14..ddf37e9 100644 --- a/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_5.snap +++ b/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_5.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: "[int([BoundedNat { n: 2 }])]" --- -"{ i32, { i8 } }" +"{ { i8 } }" diff --git a/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_6.snap b/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_6.snap index f0ec71a..7ff728a 100644 --- a/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_6.snap +++ b/src/snapshots/hugr_llvm__types__test__type_to_llvm@llvm14_6.snap @@ -2,4 +2,4 @@ source: src/types.rs expression: "[int([BoundedNat { n: 6 }]), []]+[[]+[], int([BoundedNat { n: 2 }])]" --- -"{ { i64, { i32, {} } }, { { {}, {} }, i8 } }" +"{ i32, { i64, { {} } }, { { i32, {}, {} }, i8 } }" diff --git a/src/test.rs b/src/test.rs index 5ea1731..3ce8cab 100644 --- a/src/test.rs +++ b/src/test.rs @@ -11,7 +11,7 @@ use rstest::fixture; use crate::{ custom::CodegenExtsMap, - emit::EmitHugr, + emit::{EmitHugr, Namer}, types::{TypeConverter, TypingSession}, }; @@ -116,7 +116,8 @@ impl TestContext { self.with_context(|ctx| { let m = ctx.create_module("test_context"); let exts = self.extensions(); - let (r, ectx) = f(EmitHugr::new(ctx, m, exts)); + let namer = Namer::default().into(); + let (r, ectx) = f(EmitHugr::new(ctx, m, namer, exts)); (r, ectx.finish()) }) } diff --git a/src/types.rs b/src/types.rs index d6469c2..fdc95eb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,7 +8,7 @@ use hugr::types::SumType; use hugr::{types::TypeRow, HugrView}; use inkwell::builder::Builder; use inkwell::types::{self as iw, AnyType, AsTypeRef, IntType}; -use inkwell::values::{BasicValue, BasicValueEnum, StructValue}; +use inkwell::values::{BasicValue, BasicValueEnum, IntValue, StructValue}; use inkwell::{ context::Context, types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, StructType}, @@ -52,13 +52,10 @@ impl<'c, H: HugrView> TypingSession<'c, H> { use hugr::types::TypeEnum; match hugr_type.as_type_enum() { TypeEnum::Extension(ref custom_type) => self.extensions.llvm_type(self, custom_type), - TypeEnum::Alias(ref alias) => Err(anyhow!("Invalid type: {:?}", alias)), - + TypeEnum::Sum(sum) => self.llvm_sum_type(sum.clone()).map(Into::into), // TODO Function Types are fine TypeEnum::Function(ref func_ty) => Err(anyhow!("Invalid type: {:?}", func_ty)), - - x @ TypeEnum::Variable(_, _) => Err(anyhow!("Invalid type: {:?}", x)), - TypeEnum::Sum(sum) => self.llvm_sum_type(sum.clone()).map(Into::into), + x => Err(anyhow!("Invalid type: {:?}", x)), } } @@ -199,13 +196,15 @@ impl<'c> LLVMSumType<'c> { &self, builder: &Builder<'c>, v: impl BasicValue<'c>, - ) -> Result> { + ) -> Result> { let struct_value: StructValue<'c> = v .as_basic_value_enum() .try_into() .map_err(|_| anyhow!("Not a struct type"))?; if self.has_tag_field() { - Ok(builder.build_extract_value(struct_value, 0, "")?) + Ok(builder + .build_extract_value(struct_value, 0, "")? + .into_int_value()) } else { Ok(self.get_tag_type().const_int(0, false).into()) } @@ -247,7 +246,7 @@ impl<'c> LLVMSumType<'c> { ) -> Result> { let expected_num_fields = self.num_fields(tag)?; if expected_num_fields != vs.len() { - Err(anyhow!("LLVMSumType::build: wrong number of fields: expected: {expected_num_fields} actual: {}", vs.len()))? + Err(anyhow!("LLVMSumType::build_tag: wrong number of fields: expected: {expected_num_fields} actual: {} sumtype: {} llvm_type {} vs: {:?}", vs.len(), &self.1, &self.0, vs.clone()))? } let variant_index = self.get_variant_index(tag); let row_t = self @@ -290,7 +289,7 @@ impl<'c> LLVMSumType<'c> { } fn sum_type_has_tag_field(st: &SumType) -> bool { - st.num_variants() < 2 + st.num_variants() >= 2 } fn has_tag_field(&self) -> bool { @@ -364,6 +363,7 @@ pub mod test { #[case(0, SumType::new_unary(0))] #[case(1, SumType::new_unary(1))] #[case(2,SumType::new([vec![Type::new_unit_sum(0), Type::new_unit_sum(1)], vec![Type::new_unit_sum(2), Type::new_unit_sum(3)]]))] + #[case(3, SumType::new_unary(2))] fn sum_types(#[case] _id: i32, #[with(_id)] llvm_ctx: TestContext, #[case] st: SumType) { llvm_ctx.with_tsesh(|tsesh| { assert_snapshot!( diff --git a/tests/guppy.rs b/tests/guppy.rs new file mode 100644 index 0000000..ec1930f --- /dev/null +++ b/tests/guppy.rs @@ -0,0 +1,105 @@ +use std::{ + env, + fmt::Display, + path::{Path, PathBuf}, + process::{Command, Stdio}, +}; + +use insta_cmd::assert_cmd_snapshot; +use rstest::{fixture, rstest}; + +struct TestConfig { + python_bin: PathBuf, + hugr_llvm_bin: PathBuf, + test_dir: PathBuf, + pub opt: bool, +} + +impl TestConfig { + pub fn new() -> TestConfig { + let python_bin = env::var("HUGR_LLVM_PYTHON_BIN") + .map(Into::into) + .ok() + .or_else(|| pathsearch::find_executable_in_path("python")) + .unwrap_or_else(|| panic!("Could not find python in PATH or HUGR_LLVM_PYTHON_BIN")); + let hugr_llvm_bin = env!("CARGO_BIN_EXE_hugr-llvm").into(); + let test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("tests/guppy_test_cases") + .into(); + TestConfig { + python_bin, + hugr_llvm_bin, + test_dir, + opt: true, + } + } +} + +impl TestConfig { + fn get_guppy_output(&self, path: impl AsRef) -> Command { + let mut cmd = Command::new(&self.python_bin); + cmd.arg(self.test_dir.join(path.as_ref())); + cmd + } + + fn hugr_llvm(&self) -> Command { + let mut cmd = Command::new(&self.hugr_llvm_bin); + if !self.opt { + cmd.arg("--no-opt"); + } + cmd + } + + fn run(&self, path: impl AsRef, go: impl FnOnce(Command) -> T) -> T { + let mut guppy_cmd = self.get_guppy_output(path); + guppy_cmd.stdout(Stdio::piped()); + let mut guppy_proc = guppy_cmd.spawn().expect("Failed to start guppy"); + + let mut hugr_llvm = self.hugr_llvm(); + hugr_llvm.stdin(guppy_proc.stdout.take().unwrap()).arg("-"); + let r = go(hugr_llvm); + assert!(guppy_proc.wait().unwrap().success()); + r + } +} +#[fixture] +fn test_config() -> TestConfig { + TestConfig::new() +} + +#[rstest] +fn test_dir_exists(test_config: TestConfig) { + assert!(test_config.test_dir.is_dir()) +} + +fn with_suffix(s: impl Display, go: impl FnOnce() -> R) -> R { + let mut settings = insta::Settings::clone_current(); + let old_suffix = settings + .snapshot_suffix() + .map_or("".to_string(), |s| format!("{s}.")); + let llvm_str = hugr_llvm::llvm_version(); + settings.set_snapshot_suffix(format!("{old_suffix}{llvm_str}.{s}")); + settings.bind(go) +} + +macro_rules! guppy_test { + ($filename:expr, $testname:ident) => { + #[rstest] + fn $testname(mut test_config: TestConfig) { + with_suffix("noopt", || { + test_config.opt = false; + test_config.run($filename, |mut cmd| assert_cmd_snapshot!(cmd)); + }); + with_suffix("opt", || { + test_config.opt = true; + test_config.run($filename, |mut cmd| assert_cmd_snapshot!(cmd)); + }); + } + }; +} + +guppy_test!("even_odd.py", even_odd); +guppy_test!("even_odd2.py", even_odd2); +guppy_test!("planqc-1.py", planqc1); +guppy_test!("planqc-2.py", planqc2); +guppy_test!("planqc-3.py", planqc3); diff --git a/tests/guppy_test_cases/even_odd.py b/tests/guppy_test_cases/even_odd.py new file mode 100644 index 0000000..7f3469e --- /dev/null +++ b/tests/guppy_test_cases/even_odd.py @@ -0,0 +1,21 @@ +from guppylang.decorator import guppy +from guppylang.module import GuppyModule + +main = GuppyModule("main") + + +@guppy(main) +def is_even(x: int) -> bool: + if x == 0: + return True + return is_odd(x - 1) + + +@guppy(main) +def is_odd(x: int) -> bool: + if x == 0: + return False + return is_even(x - 1) + +if __name__ == "__main__": + print(main.compile().serialize()) diff --git a/tests/guppy_test_cases/even_odd2.py b/tests/guppy_test_cases/even_odd2.py new file mode 100644 index 0000000..3dfd5a5 --- /dev/null +++ b/tests/guppy_test_cases/even_odd2.py @@ -0,0 +1,22 @@ +from guppylang.decorator import guppy +from guppylang.module import GuppyModule +from guppylang.prelude import quantum +from guppylang.prelude.quantum import measure, phased_x, qubit + +mod = GuppyModule("main") +mod.load(quantum) + +@guppy(mod) +def is_even(x: int) -> bool: + q = qubit() + return measure(h(q)) + + +@guppy(mod) +def is_odd(x: int) -> bool: + if x == 0: + return False + return is_even(x - 1) + +if __name__ == "__main__": + print(mod.compile().serialize()) diff --git a/tests/guppy_test_cases/planqc-1.py b/tests/guppy_test_cases/planqc-1.py new file mode 100644 index 0000000..1023a3f --- /dev/null +++ b/tests/guppy_test_cases/planqc-1.py @@ -0,0 +1,23 @@ +from guppylang.decorator import guppy +from guppylang.module import GuppyModule +from guppylang.prelude import quantum +from guppylang.prelude.quantum import measure, qubit, h, rz + +mod = GuppyModule("main") +mod.load(quantum) + +@guppy(mod) +def rx(q: qubit, x: float) -> qubit: + # Implement Rx via Rz rotation + return h(rz(h(q), x)) + + +@guppy(mod) +def main() -> bool: + q = qubit() + z = rx(q,1.5) + return measure(z) + +if __name__ == "__main__": + print(mod.compile().serialize()) + diff --git a/tests/guppy_test_cases/planqc-2.py b/tests/guppy_test_cases/planqc-2.py new file mode 100644 index 0000000..f02f371 --- /dev/null +++ b/tests/guppy_test_cases/planqc-2.py @@ -0,0 +1,29 @@ +from guppylang.decorator import guppy +from guppylang.module import GuppyModule +from guppylang.prelude import quantum +from guppylang.prelude.quantum import measure, qubit, cx, h, z, x + +mod = GuppyModule("main") +mod.load(quantum) + +@guppy(mod) +def teleport( + src: qubit, tgt: qubit +) -> qubit: + # Entangle qubits with ancilla + tmp, tgt = cx(h(qubit()), tgt) + src, tmp = cx(src, tmp) + # Apply classical corrections + if measure(h(src)): + tgt = z(tgt) + if measure(tmp): + tgt = x(tgt) + return tgt + +@guppy(mod) +def main() -> bool: + q1,q2 = qubit(), qubit() # TODO initialise into some interesting state + return measure(teleport(q1,q2)) + +if __name__ == "__main__": + print(mod.compile().serialize()) diff --git a/tests/guppy_test_cases/planqc-3.py b/tests/guppy_test_cases/planqc-3.py new file mode 100644 index 0000000..d0ef399 --- /dev/null +++ b/tests/guppy_test_cases/planqc-3.py @@ -0,0 +1,39 @@ +from guppylang.decorator import guppy +from guppylang.module import GuppyModule +from guppylang.prelude import quantum +from guppylang.prelude.quantum import measure, qubit, cx, h, z, x, t, tdg, discard + +mod = GuppyModule("main") +mod.load(quantum) + +@guppy(mod) +def rus(q: qubit, tries: int) -> qubit: + i = 0; + while i < tries: + # Prepare ancillary qubits + a, b = h(qubit()), h(qubit()) + + b, a = cx(b, tdg(a)) + if not measure(t(a)): + # First part failed; try again + discard(b) + continue + + q, b = cx(z(t(q)), b) + if measure(t(b)): + # Success, we are done + break + + # Otherwise, apply correction + q = x(q) + i = i + 1 + + return q + +@guppy(mod) +def main() -> bool: + q = qubit() # todo initialise into an interesting state + return measure(rus(q,100)) + +if __name__ == "__main__": + print(mod.compile().serialize()) diff --git a/tests/snapshots/guppy__even_odd.snap b/tests/snapshots/guppy__even_odd.snap new file mode 100644 index 0000000..94b40fb --- /dev/null +++ b/tests/snapshots/guppy__even_odd.snap @@ -0,0 +1,17 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - /tmp/.tmpggqcJI +--- +success: false +exit_code: 101 +----- stdout ----- +emit module module + +----- stderr ----- +HUGR valid! +thread 'main' panicked at src/emit/ops.rs:395:14: +not yet implemented: Unimplemented OpTypeEmitter: CFG +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/snapshots/guppy__even_odd2@llvm14.noopt.snap b/tests/snapshots/guppy__even_odd2@llvm14.noopt.snap new file mode 100644 index 0000000..5d59df4 --- /dev/null +++ b/tests/snapshots/guppy__even_odd2@llvm14.noopt.snap @@ -0,0 +1,218 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "--no-opt" + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define { i32, {}, {} } @_hl.is_even.21(i64 %0) { +alloca_block: + %"0" = alloca { i32, {}, {} }, align 8 + %"5_0" = alloca i64, align 8 + %"23_0" = alloca { i32, {}, {} }, align 8 + %"6_0" = alloca i64, align 8 + %"02" = alloca { i32, {}, {} }, align 8 + %"28_0" = alloca { {} }, align 8 + %"26_1" = alloca { i32, {}, {} }, align 8 + %"24_0" = alloca i32, align 4 + %"25_0" = alloca i32, align 4 + %"26_0" = alloca i32, align 4 + br label %entry_block + +entry_block: ; preds = %alloca_block + store i64 %0, i64* %"5_0", align 4 + %"5_01" = load i64, i64* %"5_0", align 4 + store i64 %"5_01", i64* %"6_0", align 4 + br label %3 + +1: ; preds = %3 + %2 = extractvalue { {} } %"28_09", 0 + store { i32, {}, {} } %"26_110", { i32, {}, {} }* %"02", align 4 + br label %6 + +3: ; preds = %entry_block + %"6_03" = load i64, i64* %"6_0", align 4 + store { {} } undef, { {} }* %"28_0", align 1 + %qalloc_call = call i32 @___qalloc() + store i32 %qalloc_call, i32* %"24_0", align 4 + %"24_04" = load i32, i32* %"24_0", align 4 + %h_call = call i32 @___h(i32 %"24_04") + store i32 %h_call, i32* %"25_0", align 4 + %"25_05" = load i32, i32* %"25_0", align 4 + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %"25_05") + %4 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %5 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + store i32 %4, i32* %"26_0", align 4 + store { i32, {}, {} } %5, { i32, {}, {} }* %"26_1", align 4 + %"28_06" = load { {} }, { {} }* %"28_0", align 1 + %"26_17" = load { i32, {}, {} }, { i32, {}, {} }* %"26_1", align 4 + store { {} } %"28_06", { {} }* %"28_0", align 1 + store { i32, {}, {} } %"26_17", { i32, {}, {} }* %"26_1", align 4 + %"26_08" = load i32, i32* %"26_0", align 4 + call void @___qfree(i32 %"26_08") + store i64 %"6_03", i64* %"6_0", align 4 + %"28_09" = load { {} }, { {} }* %"28_0", align 1 + %"26_110" = load { i32, {}, {} }, { i32, {}, {} }* %"26_1", align 4 + switch i32 0, label %1 [ + ] + +6: ; preds = %1 + %"011" = load { i32, {}, {} }, { i32, {}, {} }* %"02", align 4 + store { i32, {}, {} } %"011", { i32, {}, {} }* %"23_0", align 4 + %"23_012" = load { i32, {}, {} }, { i32, {}, {} }* %"23_0", align 4 + store { i32, {}, {} } %"23_012", { i32, {}, {} }* %"0", align 4 + %"013" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"013" +} + +declare i32 @___qalloc() + +declare i32 @___h(i32) + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + +define { i32, {}, {} } @_hl.is_odd.22(i64 %0) { +alloca_block: + %"0" = alloca { i32, {}, {} }, align 8 + %"7_0" = alloca i64, align 8 + %"29_0" = alloca { i32, {}, {} }, align 8 + %"8_0" = alloca i64, align 8 + %"02" = alloca { i32, {}, {} }, align 8 + %"12_0" = alloca i64, align 8 + %"33_0" = alloca { i32, { i64 }, {} }, align 8 + %"31_0" = alloca i64, align 8 + %"32_0" = alloca { i32, {}, {} }, align 8 + %"07" = alloca { i32, { i64 }, {} }, align 8 + %"35_0" = alloca { i32, { i64 }, {} }, align 8 + %"37_0" = alloca { i32, { i64 }, {} }, align 8 + %"41_0" = alloca { {} }, align 8 + %"40_0" = alloca { i32, {}, {} }, align 8 + %"47_0" = alloca { {} }, align 8 + %"46_0" = alloca { i32, {}, {} }, align 8 + %"44_0" = alloca i64, align 8 + %"45_0" = alloca i64, align 8 + br label %entry_block + +entry_block: ; preds = %alloca_block + store i64 %0, i64* %"7_0", align 4 + %"7_01" = load i64, i64* %"7_0", align 4 + store i64 %"7_01", i64* %"8_0", align 4 + br label %6 + +1: ; preds = %cond_exit_33 + %2 = extractvalue { i32, { i64 }, {} } %"33_013", 1 + %3 = extractvalue { i64 } %2, 0 + store i64 %3, i64* %"12_0", align 4 + br label %17 + +4: ; preds = %cond_exit_33 + %5 = extractvalue { i32, { i64 }, {} } %"33_013", 2 + br label %14 + +6: ; preds = %entry_block + %"8_03" = load i64, i64* %"8_0", align 4 + store i64 0, i64* %"31_0", align 4 + store i64 %"8_03", i64* %"8_0", align 4 + %"8_04" = load i64, i64* %"8_0", align 4 + %"31_05" = load i64, i64* %"31_0", align 4 + %7 = icmp eq i64 %"8_04", %"31_05" + %8 = select i1 %7, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + store { i32, {}, {} } %8, { i32, {}, {} }* %"32_0", align 4 + %"32_06" = load { i32, {}, {} }, { i32, {}, {} }* %"32_0", align 4 + %9 = extractvalue { i32, {}, {} } %"32_06", 0 + %10 = extractvalue { i32, {}, {} } %"32_06", 1 + %11 = extractvalue { i32, {}, {} } %"32_06", 2 + switch i32 %9, label %cond_33_case_0 [ + i32 1, label %cond_33_case_1 + ] + +12: ; preds = %14 + %13 = extractvalue { {} } %"41_017", 0 + store { i32, {}, {} } %"40_018", { i32, {}, {} }* %"02", align 4 + br label %20 + +14: ; preds = %4 + store { {} } undef, { {} }* %"41_0", align 1 + store { i32, {}, {} } { i32 0, {} undef, {} poison }, { i32, {}, {} }* %"40_0", align 4 + %"41_015" = load { {} }, { {} }* %"41_0", align 1 + %"40_016" = load { i32, {}, {} }, { i32, {}, {} }* %"40_0", align 4 + store { {} } %"41_015", { {} }* %"41_0", align 1 + store { i32, {}, {} } %"40_016", { i32, {}, {} }* %"40_0", align 4 + %"41_017" = load { {} }, { {} }* %"41_0", align 1 + %"40_018" = load { i32, {}, {} }, { i32, {}, {} }* %"40_0", align 4 + switch i32 0, label %12 [ + ] + +15: ; preds = %17 + %16 = extractvalue { {} } %"47_025", 0 + store { i32, {}, {} } %"46_026", { i32, {}, {} }* %"02", align 4 + br label %20 + +17: ; preds = %1 + %"12_019" = load i64, i64* %"12_0", align 4 + store { {} } undef, { {} }* %"47_0", align 1 + store i64 1, i64* %"44_0", align 4 + store i64 %"12_019", i64* %"12_0", align 4 + %"12_020" = load i64, i64* %"12_0", align 4 + %"44_021" = load i64, i64* %"44_0", align 4 + %18 = sub i64 %"12_020", %"44_021" + store i64 %18, i64* %"45_0", align 4 + %"45_022" = load i64, i64* %"45_0", align 4 + %19 = call { i32, {}, {} } @_hl.is_even.21(i64 %"45_022") + store { i32, {}, {} } %19, { i32, {}, {} }* %"46_0", align 4 + %"47_023" = load { {} }, { {} }* %"47_0", align 1 + %"46_024" = load { i32, {}, {} }, { i32, {}, {} }* %"46_0", align 4 + store { {} } %"47_023", { {} }* %"47_0", align 1 + store { i32, {}, {} } %"46_024", { i32, {}, {} }* %"46_0", align 4 + %"47_025" = load { {} }, { {} }* %"47_0", align 1 + %"46_026" = load { i32, {}, {} }, { i32, {}, {} }* %"46_0", align 4 + switch i32 0, label %15 [ + ] + +20: ; preds = %15, %12 + %"014" = load { i32, {}, {} }, { i32, {}, {} }* %"02", align 4 + store { i32, {}, {} } %"014", { i32, {}, {} }* %"29_0", align 4 + %"29_027" = load { i32, {}, {} }, { i32, {}, {} }* %"29_0", align 4 + store { i32, {}, {} } %"29_027", { i32, {}, {} }* %"0", align 4 + %"028" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"028" + +cond_33_case_0: ; preds = %6 + %"8_09" = load i64, i64* %"8_0", align 4 + %21 = insertvalue { i64 } undef, i64 %"8_09", 0 + %22 = insertvalue { i32, { i64 }, {} } { i32 0, { i64 } poison, {} poison }, { i64 } %21, 1 + store { i32, { i64 }, {} } %22, { i32, { i64 }, {} }* %"35_0", align 4 + %"35_010" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"35_0", align 4 + store { i32, { i64 }, {} } %"35_010", { i32, { i64 }, {} }* %"07", align 4 + br label %cond_exit_33 + +cond_33_case_1: ; preds = %6 + store { i32, { i64 }, {} } { i32 1, { i64 } poison, {} undef }, { i32, { i64 }, {} }* %"37_0", align 4 + %"37_011" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"37_0", align 4 + store { i32, { i64 }, {} } %"37_011", { i32, { i64 }, {} }* %"07", align 4 + br label %cond_exit_33 + +cond_exit_33: ; preds = %cond_33_case_1, %cond_33_case_0 + %"08" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"07", align 4 + store { i32, { i64 }, {} } %"08", { i32, { i64 }, {} }* %"33_0", align 4 + %"33_012" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"33_0", align 4 + store { i32, { i64 }, {} } %"33_012", { i32, { i64 }, {} }* %"33_0", align 4 + %"33_013" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"33_0", align 4 + %23 = extractvalue { i32, { i64 }, {} } %"33_013", 0 + switch i32 %23, label %1 [ + i32 1, label %4 + ] +} + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__even_odd2@llvm14.opt.snap b/tests/snapshots/guppy__even_odd2@llvm14.opt.snap new file mode 100644 index 0000000..f0ee89f --- /dev/null +++ b/tests/snapshots/guppy__even_odd2@llvm14.opt.snap @@ -0,0 +1,69 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define { i32, {}, {} } @_hl.is_even.21(i64 %0) { +alloca_block: + %qalloc_call = call i32 @___qalloc() + %h_call = call i32 @___h(i32 %qalloc_call) + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %h_call) + %1 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %2 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + call void @___qfree(i32 %1) + %3 = extractvalue { {} } undef, 0 + ret { i32, {}, {} } %2 +} + +declare i32 @___qalloc() + +declare i32 @___h(i32) + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + +define { i32, {}, {} } @_hl.is_odd.22(i64 %0) { +alloca_block: + %1 = icmp eq i64 %0, 0 + %2 = select i1 %1, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + %3 = extractvalue { i32, {}, {} } %2, 0 + %4 = extractvalue { i32, {}, {} } %2, 1 + %5 = extractvalue { i32, {}, {} } %2, 2 + %cond = icmp eq i32 %3, 1 + %6 = insertvalue { i64 } undef, i64 %0, 0 + %7 = insertvalue { i32, { i64 }, {} } { i32 0, { i64 } poison, {} poison }, { i64 } %6, 1 + %"07.0" = select i1 %cond, { i32, { i64 }, {} } { i32 1, { i64 } poison, {} undef }, { i32, { i64 }, {} } %7 + %8 = extractvalue { i32, { i64 }, {} } %"07.0", 0 + %cond29 = icmp eq i32 %8, 1 + br i1 %cond29, label %15, label %9 + +9: ; preds = %alloca_block + %10 = extractvalue { i32, { i64 }, {} } %"07.0", 1 + %11 = extractvalue { i64 } %10, 0 + %12 = sub i64 %11, 1 + %13 = call { i32, {}, {} } @_hl.is_even.21(i64 %12) + %14 = extractvalue { {} } undef, 0 + br label %18 + +15: ; preds = %alloca_block + %16 = extractvalue { i32, { i64 }, {} } %"07.0", 2 + %17 = extractvalue { {} } undef, 0 + br label %18 + +18: ; preds = %9, %15 + %"02.0" = phi { i32, {}, {} } [ %13, %9 ], [ { i32 0, {} undef, {} poison }, %15 ] + ret { i32, {}, {} } %"02.0" +} + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__even_odd@llvm14.noopt.snap b/tests/snapshots/guppy__even_odd@llvm14.noopt.snap new file mode 100644 index 0000000..5b4c54c --- /dev/null +++ b/tests/snapshots/guppy__even_odd@llvm14.noopt.snap @@ -0,0 +1,283 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "--no-opt" + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define { i32, {}, {} } @_hl.is_even.29(i64 %0) { +alloca_block: + %"0" = alloca { i32, {}, {} }, align 8 + %"5_0" = alloca i64, align 8 + %"31_0" = alloca { i32, {}, {} }, align 8 + %"6_0" = alloca i64, align 8 + %"02" = alloca { i32, {}, {} }, align 8 + %"10_0" = alloca i64, align 8 + %"35_0" = alloca { i32, { i64 }, {} }, align 8 + %"33_0" = alloca i64, align 8 + %"34_0" = alloca { i32, {}, {} }, align 8 + %"07" = alloca { i32, { i64 }, {} }, align 8 + %"37_0" = alloca { i32, { i64 }, {} }, align 8 + %"39_0" = alloca { i32, { i64 }, {} }, align 8 + %"43_0" = alloca { {} }, align 8 + %"42_0" = alloca { i32, {}, {} }, align 8 + %"49_0" = alloca { {} }, align 8 + %"48_0" = alloca { i32, {}, {} }, align 8 + %"46_0" = alloca i64, align 8 + %"47_0" = alloca i64, align 8 + br label %entry_block + +entry_block: ; preds = %alloca_block + store i64 %0, i64* %"5_0", align 4 + %"5_01" = load i64, i64* %"5_0", align 4 + store i64 %"5_01", i64* %"6_0", align 4 + br label %6 + +1: ; preds = %cond_exit_35 + %2 = extractvalue { i32, { i64 }, {} } %"35_013", 1 + %3 = extractvalue { i64 } %2, 0 + store i64 %3, i64* %"10_0", align 4 + br label %17 + +4: ; preds = %cond_exit_35 + %5 = extractvalue { i32, { i64 }, {} } %"35_013", 2 + br label %14 + +6: ; preds = %entry_block + %"6_03" = load i64, i64* %"6_0", align 4 + store i64 0, i64* %"33_0", align 4 + store i64 %"6_03", i64* %"6_0", align 4 + %"6_04" = load i64, i64* %"6_0", align 4 + %"33_05" = load i64, i64* %"33_0", align 4 + %7 = icmp eq i64 %"6_04", %"33_05" + %8 = select i1 %7, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + store { i32, {}, {} } %8, { i32, {}, {} }* %"34_0", align 4 + %"34_06" = load { i32, {}, {} }, { i32, {}, {} }* %"34_0", align 4 + %9 = extractvalue { i32, {}, {} } %"34_06", 0 + %10 = extractvalue { i32, {}, {} } %"34_06", 1 + %11 = extractvalue { i32, {}, {} } %"34_06", 2 + switch i32 %9, label %cond_35_case_0 [ + i32 1, label %cond_35_case_1 + ] + +12: ; preds = %14 + %13 = extractvalue { {} } %"43_017", 0 + store { i32, {}, {} } %"42_018", { i32, {}, {} }* %"02", align 4 + br label %20 + +14: ; preds = %4 + store { {} } undef, { {} }* %"43_0", align 1 + store { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} }* %"42_0", align 4 + %"43_015" = load { {} }, { {} }* %"43_0", align 1 + %"42_016" = load { i32, {}, {} }, { i32, {}, {} }* %"42_0", align 4 + store { {} } %"43_015", { {} }* %"43_0", align 1 + store { i32, {}, {} } %"42_016", { i32, {}, {} }* %"42_0", align 4 + %"43_017" = load { {} }, { {} }* %"43_0", align 1 + %"42_018" = load { i32, {}, {} }, { i32, {}, {} }* %"42_0", align 4 + switch i32 0, label %12 [ + ] + +15: ; preds = %17 + %16 = extractvalue { {} } %"49_025", 0 + store { i32, {}, {} } %"48_026", { i32, {}, {} }* %"02", align 4 + br label %20 + +17: ; preds = %1 + %"10_019" = load i64, i64* %"10_0", align 4 + store { {} } undef, { {} }* %"49_0", align 1 + store i64 1, i64* %"46_0", align 4 + store i64 %"10_019", i64* %"10_0", align 4 + %"10_020" = load i64, i64* %"10_0", align 4 + %"46_021" = load i64, i64* %"46_0", align 4 + %18 = sub i64 %"10_020", %"46_021" + store i64 %18, i64* %"47_0", align 4 + %"47_022" = load i64, i64* %"47_0", align 4 + %19 = call { i32, {}, {} } @_hl.is_odd.30(i64 %"47_022") + store { i32, {}, {} } %19, { i32, {}, {} }* %"48_0", align 4 + %"49_023" = load { {} }, { {} }* %"49_0", align 1 + %"48_024" = load { i32, {}, {} }, { i32, {}, {} }* %"48_0", align 4 + store { {} } %"49_023", { {} }* %"49_0", align 1 + store { i32, {}, {} } %"48_024", { i32, {}, {} }* %"48_0", align 4 + %"49_025" = load { {} }, { {} }* %"49_0", align 1 + %"48_026" = load { i32, {}, {} }, { i32, {}, {} }* %"48_0", align 4 + switch i32 0, label %15 [ + ] + +20: ; preds = %15, %12 + %"014" = load { i32, {}, {} }, { i32, {}, {} }* %"02", align 4 + store { i32, {}, {} } %"014", { i32, {}, {} }* %"31_0", align 4 + %"31_027" = load { i32, {}, {} }, { i32, {}, {} }* %"31_0", align 4 + store { i32, {}, {} } %"31_027", { i32, {}, {} }* %"0", align 4 + %"028" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"028" + +cond_35_case_0: ; preds = %6 + %"6_09" = load i64, i64* %"6_0", align 4 + %21 = insertvalue { i64 } undef, i64 %"6_09", 0 + %22 = insertvalue { i32, { i64 }, {} } { i32 0, { i64 } poison, {} poison }, { i64 } %21, 1 + store { i32, { i64 }, {} } %22, { i32, { i64 }, {} }* %"37_0", align 4 + %"37_010" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"37_0", align 4 + store { i32, { i64 }, {} } %"37_010", { i32, { i64 }, {} }* %"07", align 4 + br label %cond_exit_35 + +cond_35_case_1: ; preds = %6 + store { i32, { i64 }, {} } { i32 1, { i64 } poison, {} undef }, { i32, { i64 }, {} }* %"39_0", align 4 + %"39_011" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"39_0", align 4 + store { i32, { i64 }, {} } %"39_011", { i32, { i64 }, {} }* %"07", align 4 + br label %cond_exit_35 + +cond_exit_35: ; preds = %cond_35_case_1, %cond_35_case_0 + %"08" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"07", align 4 + store { i32, { i64 }, {} } %"08", { i32, { i64 }, {} }* %"35_0", align 4 + %"35_012" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"35_0", align 4 + store { i32, { i64 }, {} } %"35_012", { i32, { i64 }, {} }* %"35_0", align 4 + %"35_013" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"35_0", align 4 + %23 = extractvalue { i32, { i64 }, {} } %"35_013", 0 + switch i32 %23, label %1 [ + i32 1, label %4 + ] +} + +define { i32, {}, {} } @_hl.is_odd.30(i64 %0) { +alloca_block: + %"0" = alloca { i32, {}, {} }, align 8 + %"11_0" = alloca i64, align 8 + %"50_0" = alloca { i32, {}, {} }, align 8 + %"12_0" = alloca i64, align 8 + %"02" = alloca { i32, {}, {} }, align 8 + %"16_0" = alloca i64, align 8 + %"54_0" = alloca { i32, { i64 }, {} }, align 8 + %"52_0" = alloca i64, align 8 + %"53_0" = alloca { i32, {}, {} }, align 8 + %"07" = alloca { i32, { i64 }, {} }, align 8 + %"56_0" = alloca { i32, { i64 }, {} }, align 8 + %"58_0" = alloca { i32, { i64 }, {} }, align 8 + %"62_0" = alloca { {} }, align 8 + %"61_0" = alloca { i32, {}, {} }, align 8 + %"68_0" = alloca { {} }, align 8 + %"67_0" = alloca { i32, {}, {} }, align 8 + %"65_0" = alloca i64, align 8 + %"66_0" = alloca i64, align 8 + br label %entry_block + +entry_block: ; preds = %alloca_block + store i64 %0, i64* %"11_0", align 4 + %"11_01" = load i64, i64* %"11_0", align 4 + store i64 %"11_01", i64* %"12_0", align 4 + br label %6 + +1: ; preds = %cond_exit_54 + %2 = extractvalue { i32, { i64 }, {} } %"54_013", 1 + %3 = extractvalue { i64 } %2, 0 + store i64 %3, i64* %"16_0", align 4 + br label %17 + +4: ; preds = %cond_exit_54 + %5 = extractvalue { i32, { i64 }, {} } %"54_013", 2 + br label %14 + +6: ; preds = %entry_block + %"12_03" = load i64, i64* %"12_0", align 4 + store i64 0, i64* %"52_0", align 4 + store i64 %"12_03", i64* %"12_0", align 4 + %"12_04" = load i64, i64* %"12_0", align 4 + %"52_05" = load i64, i64* %"52_0", align 4 + %7 = icmp eq i64 %"12_04", %"52_05" + %8 = select i1 %7, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + store { i32, {}, {} } %8, { i32, {}, {} }* %"53_0", align 4 + %"53_06" = load { i32, {}, {} }, { i32, {}, {} }* %"53_0", align 4 + %9 = extractvalue { i32, {}, {} } %"53_06", 0 + %10 = extractvalue { i32, {}, {} } %"53_06", 1 + %11 = extractvalue { i32, {}, {} } %"53_06", 2 + switch i32 %9, label %cond_54_case_0 [ + i32 1, label %cond_54_case_1 + ] + +12: ; preds = %14 + %13 = extractvalue { {} } %"62_017", 0 + store { i32, {}, {} } %"61_018", { i32, {}, {} }* %"02", align 4 + br label %20 + +14: ; preds = %4 + store { {} } undef, { {} }* %"62_0", align 1 + store { i32, {}, {} } { i32 0, {} undef, {} poison }, { i32, {}, {} }* %"61_0", align 4 + %"62_015" = load { {} }, { {} }* %"62_0", align 1 + %"61_016" = load { i32, {}, {} }, { i32, {}, {} }* %"61_0", align 4 + store { {} } %"62_015", { {} }* %"62_0", align 1 + store { i32, {}, {} } %"61_016", { i32, {}, {} }* %"61_0", align 4 + %"62_017" = load { {} }, { {} }* %"62_0", align 1 + %"61_018" = load { i32, {}, {} }, { i32, {}, {} }* %"61_0", align 4 + switch i32 0, label %12 [ + ] + +15: ; preds = %17 + %16 = extractvalue { {} } %"68_025", 0 + store { i32, {}, {} } %"67_026", { i32, {}, {} }* %"02", align 4 + br label %20 + +17: ; preds = %1 + %"16_019" = load i64, i64* %"16_0", align 4 + store { {} } undef, { {} }* %"68_0", align 1 + store i64 1, i64* %"65_0", align 4 + store i64 %"16_019", i64* %"16_0", align 4 + %"16_020" = load i64, i64* %"16_0", align 4 + %"65_021" = load i64, i64* %"65_0", align 4 + %18 = sub i64 %"16_020", %"65_021" + store i64 %18, i64* %"66_0", align 4 + %"66_022" = load i64, i64* %"66_0", align 4 + %19 = call { i32, {}, {} } @_hl.is_even.29(i64 %"66_022") + store { i32, {}, {} } %19, { i32, {}, {} }* %"67_0", align 4 + %"68_023" = load { {} }, { {} }* %"68_0", align 1 + %"67_024" = load { i32, {}, {} }, { i32, {}, {} }* %"67_0", align 4 + store { {} } %"68_023", { {} }* %"68_0", align 1 + store { i32, {}, {} } %"67_024", { i32, {}, {} }* %"67_0", align 4 + %"68_025" = load { {} }, { {} }* %"68_0", align 1 + %"67_026" = load { i32, {}, {} }, { i32, {}, {} }* %"67_0", align 4 + switch i32 0, label %15 [ + ] + +20: ; preds = %15, %12 + %"014" = load { i32, {}, {} }, { i32, {}, {} }* %"02", align 4 + store { i32, {}, {} } %"014", { i32, {}, {} }* %"50_0", align 4 + %"50_027" = load { i32, {}, {} }, { i32, {}, {} }* %"50_0", align 4 + store { i32, {}, {} } %"50_027", { i32, {}, {} }* %"0", align 4 + %"028" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"028" + +cond_54_case_0: ; preds = %6 + %"12_09" = load i64, i64* %"12_0", align 4 + %21 = insertvalue { i64 } undef, i64 %"12_09", 0 + %22 = insertvalue { i32, { i64 }, {} } { i32 0, { i64 } poison, {} poison }, { i64 } %21, 1 + store { i32, { i64 }, {} } %22, { i32, { i64 }, {} }* %"56_0", align 4 + %"56_010" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"56_0", align 4 + store { i32, { i64 }, {} } %"56_010", { i32, { i64 }, {} }* %"07", align 4 + br label %cond_exit_54 + +cond_54_case_1: ; preds = %6 + store { i32, { i64 }, {} } { i32 1, { i64 } poison, {} undef }, { i32, { i64 }, {} }* %"58_0", align 4 + %"58_011" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"58_0", align 4 + store { i32, { i64 }, {} } %"58_011", { i32, { i64 }, {} }* %"07", align 4 + br label %cond_exit_54 + +cond_exit_54: ; preds = %cond_54_case_1, %cond_54_case_0 + %"08" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"07", align 4 + store { i32, { i64 }, {} } %"08", { i32, { i64 }, {} }* %"54_0", align 4 + %"54_012" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"54_0", align 4 + store { i32, { i64 }, {} } %"54_012", { i32, { i64 }, {} }* %"54_0", align 4 + %"54_013" = load { i32, { i64 }, {} }, { i32, { i64 }, {} }* %"54_0", align 4 + %23 = extractvalue { i32, { i64 }, {} } %"54_013", 0 + switch i32 %23, label %1 [ + i32 1, label %4 + ] +} + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__even_odd@llvm14.opt.snap b/tests/snapshots/guppy__even_odd@llvm14.opt.snap new file mode 100644 index 0000000..55cde7d --- /dev/null +++ b/tests/snapshots/guppy__even_odd@llvm14.opt.snap @@ -0,0 +1,82 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - /tmp/.tmp6o3Oz1 +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define { i32, {}, {} } @_hl.is_even.29(i64 %0) { +alloca_block: + %1 = icmp eq i64 %0, 0 + %2 = select i1 %1, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + %3 = extractvalue { i32, {}, {} } %2, 0 + %4 = extractvalue { i32, {}, {} } %2, 1 + %5 = extractvalue { i32, {}, {} } %2, 2 + %cond = icmp eq i32 %3, 1 + %6 = insertvalue { i64 } undef, i64 %0, 0 + %7 = insertvalue { i32, { i64 }, {} } { i32 0, { i64 } poison, {} poison }, { i64 } %6, 1 + %"07.0" = select i1 %cond, { i32, { i64 }, {} } { i32 1, { i64 } poison, {} undef }, { i32, { i64 }, {} } %7 + %8 = extractvalue { i32, { i64 }, {} } %"07.0", 0 + %cond29 = icmp eq i32 %8, 1 + br i1 %cond29, label %15, label %9 + +9: ; preds = %alloca_block + %10 = extractvalue { i32, { i64 }, {} } %"07.0", 1 + %11 = extractvalue { i64 } %10, 0 + %12 = sub i64 %11, 1 + %13 = call { i32, {}, {} } @_hl.is_odd.30(i64 %12) + %14 = extractvalue { {} } undef, 0 + br label %18 + +15: ; preds = %alloca_block + %16 = extractvalue { i32, { i64 }, {} } %"07.0", 2 + %17 = extractvalue { {} } undef, 0 + br label %18 + +18: ; preds = %9, %15 + %"02.0" = phi { i32, {}, {} } [ %13, %9 ], [ { i32 1, {} poison, {} undef }, %15 ] + ret { i32, {}, {} } %"02.0" +} + +define { i32, {}, {} } @_hl.is_odd.30(i64 %0) { +alloca_block: + %1 = icmp eq i64 %0, 0 + %2 = select i1 %1, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + %3 = extractvalue { i32, {}, {} } %2, 0 + %4 = extractvalue { i32, {}, {} } %2, 1 + %5 = extractvalue { i32, {}, {} } %2, 2 + %cond = icmp eq i32 %3, 1 + %6 = insertvalue { i64 } undef, i64 %0, 0 + %7 = insertvalue { i32, { i64 }, {} } { i32 0, { i64 } poison, {} poison }, { i64 } %6, 1 + %"07.0" = select i1 %cond, { i32, { i64 }, {} } { i32 1, { i64 } poison, {} undef }, { i32, { i64 }, {} } %7 + %8 = extractvalue { i32, { i64 }, {} } %"07.0", 0 + %cond29 = icmp eq i32 %8, 1 + br i1 %cond29, label %15, label %9 + +9: ; preds = %alloca_block + %10 = extractvalue { i32, { i64 }, {} } %"07.0", 1 + %11 = extractvalue { i64 } %10, 0 + %12 = sub i64 %11, 1 + %13 = call { i32, {}, {} } @_hl.is_even.29(i64 %12) + %14 = extractvalue { {} } undef, 0 + br label %18 + +15: ; preds = %alloca_block + %16 = extractvalue { i32, { i64 }, {} } %"07.0", 2 + %17 = extractvalue { {} } undef, 0 + br label %18 + +18: ; preds = %9, %15 + %"02.0" = phi { i32, {}, {} } [ %13, %9 ], [ { i32 0, {} undef, {} poison }, %15 ] + ret { i32, {}, {} } %"02.0" +} + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__planqc1@llvm14.noopt.snap b/tests/snapshots/guppy__planqc1@llvm14.noopt.snap new file mode 100644 index 0000000..0350347 --- /dev/null +++ b/tests/snapshots/guppy__planqc1@llvm14.noopt.snap @@ -0,0 +1,148 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "--no-opt" + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define i32 @_hl.rx.13(i32 %0, double %1) { +alloca_block: + %"0" = alloca i32, align 4 + %"5_0" = alloca i32, align 4 + %"5_1" = alloca double, align 8 + %"15_0" = alloca i32, align 4 + %"6_0" = alloca i32, align 4 + %"6_1" = alloca double, align 8 + %"03" = alloca i32, align 4 + %"19_0" = alloca { {} }, align 8 + %"18_0" = alloca i32, align 4 + %"16_0" = alloca i32, align 4 + %"17_0" = alloca i32, align 4 + br label %entry_block + +entry_block: ; preds = %alloca_block + store i32 %0, i32* %"5_0", align 4 + store double %1, double* %"5_1", align 8 + %"5_01" = load i32, i32* %"5_0", align 4 + %"5_12" = load double, double* %"5_1", align 8 + store i32 %"5_01", i32* %"6_0", align 4 + store double %"5_12", double* %"6_1", align 8 + br label %4 + +2: ; preds = %4 + %3 = extractvalue { {} } %"19_013", 0 + store i32 %"18_014", i32* %"03", align 4 + br label %5 + +4: ; preds = %entry_block + %"6_04" = load i32, i32* %"6_0", align 4 + %"6_15" = load double, double* %"6_1", align 8 + store { {} } undef, { {} }* %"19_0", align 1 + store i32 %"6_04", i32* %"6_0", align 4 + store double %"6_15", double* %"6_1", align 8 + %"6_06" = load i32, i32* %"6_0", align 4 + %h_call = call i32 @___h(i32 %"6_06") + store i32 %h_call, i32* %"16_0", align 4 + %"16_07" = load i32, i32* %"16_0", align 4 + %"6_18" = load double, double* %"6_1", align 8 + %rz_call = call i32 @___rz(i32 %"16_07", double %"6_18") + store i32 %rz_call, i32* %"17_0", align 4 + %"17_09" = load i32, i32* %"17_0", align 4 + %h_call10 = call i32 @___h.1(i32 %"17_09") + store i32 %h_call10, i32* %"18_0", align 4 + %"19_011" = load { {} }, { {} }* %"19_0", align 1 + %"18_012" = load i32, i32* %"18_0", align 4 + store { {} } %"19_011", { {} }* %"19_0", align 1 + store i32 %"18_012", i32* %"18_0", align 4 + %"19_013" = load { {} }, { {} }* %"19_0", align 1 + %"18_014" = load i32, i32* %"18_0", align 4 + switch i32 0, label %2 [ + ] + +5: ; preds = %2 + %"015" = load i32, i32* %"03", align 4 + store i32 %"015", i32* %"15_0", align 4 + %"15_016" = load i32, i32* %"15_0", align 4 + store i32 %"15_016", i32* %"0", align 4 + %"017" = load i32, i32* %"0", align 4 + ret i32 %"017" +} + +declare i32 @___h(i32) + +declare i32 @___rz(i32, double) + +declare i32 @___h.1(i32) + +define { i32, {}, {} } @_hl.main.14() { +alloca_block: + %"0" = alloca { i32, {}, {} }, align 8 + %"20_0" = alloca { i32, {}, {} }, align 8 + %"01" = alloca { i32, {}, {} }, align 8 + %"27_0" = alloca { {} }, align 8 + %"25_1" = alloca { i32, {}, {} }, align 8 + %"23_0" = alloca double, align 8 + %"21_0" = alloca i32, align 4 + %"24_0" = alloca i32, align 4 + %"25_0" = alloca i32, align 4 + br label %entry_block + +entry_block: ; preds = %alloca_block + br label %2 + +0: ; preds = %2 + %1 = extractvalue { {} } %"27_08", 0 + store { i32, {}, {} } %"25_19", { i32, {}, {} }* %"01", align 4 + br label %6 + +2: ; preds = %entry_block + store { {} } undef, { {} }* %"27_0", align 1 + store double 1.500000e+00, double* %"23_0", align 8 + %qalloc_call = call i32 @___qalloc() + store i32 %qalloc_call, i32* %"21_0", align 4 + %"21_02" = load i32, i32* %"21_0", align 4 + %"23_03" = load double, double* %"23_0", align 8 + %3 = call i32 @_hl.rx.13(i32 %"21_02", double %"23_03") + store i32 %3, i32* %"24_0", align 4 + %"24_04" = load i32, i32* %"24_0", align 4 + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %"24_04") + %4 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %5 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + store i32 %4, i32* %"25_0", align 4 + store { i32, {}, {} } %5, { i32, {}, {} }* %"25_1", align 4 + %"27_05" = load { {} }, { {} }* %"27_0", align 1 + %"25_16" = load { i32, {}, {} }, { i32, {}, {} }* %"25_1", align 4 + store { {} } %"27_05", { {} }* %"27_0", align 1 + store { i32, {}, {} } %"25_16", { i32, {}, {} }* %"25_1", align 4 + %"25_07" = load i32, i32* %"25_0", align 4 + call void @___qfree(i32 %"25_07") + %"27_08" = load { {} }, { {} }* %"27_0", align 1 + %"25_19" = load { i32, {}, {} }, { i32, {}, {} }* %"25_1", align 4 + switch i32 0, label %0 [ + ] + +6: ; preds = %0 + %"010" = load { i32, {}, {} }, { i32, {}, {} }* %"01", align 4 + store { i32, {}, {} } %"010", { i32, {}, {} }* %"20_0", align 4 + %"20_011" = load { i32, {}, {} }, { i32, {}, {} }* %"20_0", align 4 + store { i32, {}, {} } %"20_011", { i32, {}, {} }* %"0", align 4 + %"012" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"012" +} + +declare i32 @___qalloc() + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__planqc1@llvm14.opt.snap b/tests/snapshots/guppy__planqc1@llvm14.opt.snap new file mode 100644 index 0000000..37bb61e --- /dev/null +++ b/tests/snapshots/guppy__planqc1@llvm14.opt.snap @@ -0,0 +1,49 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define i32 @_hl.rx.13(i32 %0, double %1) { +alloca_block: + %h_call = call i32 @___h(i32 %0) + %rz_call = call i32 @___rz(i32 %h_call, double %1) + %h_call10 = call i32 @___h.1(i32 %rz_call) + %2 = extractvalue { {} } undef, 0 + ret i32 %h_call10 +} + +declare i32 @___h(i32) + +declare i32 @___rz(i32, double) + +declare i32 @___h.1(i32) + +define { i32, {}, {} } @_hl.main.14() { +alloca_block: + %qalloc_call = call i32 @___qalloc() + %0 = call i32 @_hl.rx.13(i32 %qalloc_call, double 1.500000e+00) + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %0) + %1 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %2 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + call void @___qfree(i32 %1) + %3 = extractvalue { {} } undef, 0 + ret { i32, {}, {} } %2 +} + +declare i32 @___qalloc() + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__planqc2@llvm14.noopt.snap b/tests/snapshots/guppy__planqc2@llvm14.noopt.snap new file mode 100644 index 0000000..8ab5626 --- /dev/null +++ b/tests/snapshots/guppy__planqc2@llvm14.noopt.snap @@ -0,0 +1,408 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "--no-opt" + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define i32 @_hl.teleport.25(i32 %0, i32 %1) { +alloca_block: + %"0" = alloca i32, align 4 + %"5_0" = alloca i32, align 4 + %"5_1" = alloca i32, align 4 + %"27_0" = alloca i32, align 4 + %"6_0" = alloca i32, align 4 + %"6_1" = alloca i32, align 4 + %"03" = alloca i32, align 4 + %"7_0" = alloca i32, align 4 + %"7_1" = alloca i32, align 4 + %"8_0" = alloca i32, align 4 + %"8_1" = alloca i32, align 4 + %"9_0" = alloca i32, align 4 + %"9_1" = alloca i32, align 4 + %"10_0" = alloca i32, align 4 + %"11_0" = alloca i32, align 4 + %"12_0" = alloca i32, align 4 + %"37_1" = alloca { i32, {}, {} }, align 8 + %"32_1" = alloca i32, align 4 + %"35_1" = alloca i32, align 4 + %"28_0" = alloca i32, align 4 + %"29_0" = alloca i32, align 4 + %"30_0" = alloca i32, align 4 + %"30_1" = alloca i32, align 4 + %"31_0" = alloca { { i32, i32 } }, align 8 + %"32_0" = alloca i32, align 4 + %"33_0" = alloca i32, align 4 + %"33_1" = alloca i32, align 4 + %"34_0" = alloca { { i32, i32 } }, align 8 + %"35_0" = alloca i32, align 4 + %"36_0" = alloca i32, align 4 + %"37_0" = alloca i32, align 4 + %"41_0" = alloca { {} }, align 8 + %"40_0" = alloca i32, align 4 + %"43_0" = alloca { {} }, align 8 + %"45_1" = alloca { i32, {}, {} }, align 8 + %"45_0" = alloca i32, align 4 + %"49_0" = alloca { {} }, align 8 + %"48_0" = alloca i32, align 4 + %"51_0" = alloca { {} }, align 8 + %"53_0" = alloca { {} }, align 8 + br label %entry_block + +entry_block: ; preds = %alloca_block + store i32 %0, i32* %"5_0", align 4 + store i32 %1, i32* %"5_1", align 4 + %"5_01" = load i32, i32* %"5_0", align 4 + %"5_12" = load i32, i32* %"5_1", align 4 + store i32 %"5_01", i32* %"6_0", align 4 + store i32 %"5_12", i32* %"6_1", align 4 + br label %6 + +2: ; preds = %6 + %3 = extractvalue { i32, {}, {} } %"37_125", 1 + store i32 %"32_126", i32* %"8_0", align 4 + store i32 %"35_127", i32* %"8_1", align 4 + br label %31 + +4: ; preds = %6 + %5 = extractvalue { i32, {}, {} } %"37_125", 2 + store i32 %"32_126", i32* %"7_0", align 4 + store i32 %"35_127", i32* %"7_1", align 4 + br label %28 + +6: ; preds = %entry_block + %"6_04" = load i32, i32* %"6_0", align 4 + %"6_15" = load i32, i32* %"6_1", align 4 + %qalloc_call = call i32 @___qalloc() + store i32 %qalloc_call, i32* %"28_0", align 4 + %"28_06" = load i32, i32* %"28_0", align 4 + %h_call = call i32 @___h(i32 %"28_06") + store i32 %h_call, i32* %"29_0", align 4 + store i32 %"6_04", i32* %"6_0", align 4 + store i32 %"6_15", i32* %"6_1", align 4 + %"29_07" = load i32, i32* %"29_0", align 4 + %"6_18" = load i32, i32* %"6_1", align 4 + %rz_call = call { i32, i32 } @___cx(i32 %"29_07", i32 %"6_18") + %7 = extractvalue { i32, i32 } %rz_call, 0 + %8 = extractvalue { i32, i32 } %rz_call, 1 + store i32 %7, i32* %"30_0", align 4 + store i32 %8, i32* %"30_1", align 4 + %"30_09" = load i32, i32* %"30_0", align 4 + %"30_110" = load i32, i32* %"30_1", align 4 + %9 = insertvalue { i32, i32 } undef, i32 %"30_09", 0 + %10 = insertvalue { i32, i32 } %9, i32 %"30_110", 1 + %11 = insertvalue { { i32, i32 } } poison, { i32, i32 } %10, 0 + store { { i32, i32 } } %11, { { i32, i32 } }* %"31_0", align 4 + %"31_011" = load { { i32, i32 } }, { { i32, i32 } }* %"31_0", align 4 + %12 = extractvalue { { i32, i32 } } %"31_011", 0 + %13 = extractvalue { i32, i32 } %12, 0 + %14 = extractvalue { i32, i32 } %12, 1 + store i32 %13, i32* %"32_0", align 4 + store i32 %14, i32* %"32_1", align 4 + %"6_012" = load i32, i32* %"6_0", align 4 + %"32_013" = load i32, i32* %"32_0", align 4 + %rz_call14 = call { i32, i32 } @___cx.1(i32 %"6_012", i32 %"32_013") + %15 = extractvalue { i32, i32 } %rz_call14, 0 + %16 = extractvalue { i32, i32 } %rz_call14, 1 + store i32 %15, i32* %"33_0", align 4 + store i32 %16, i32* %"33_1", align 4 + %"33_015" = load i32, i32* %"33_0", align 4 + %"33_116" = load i32, i32* %"33_1", align 4 + %17 = insertvalue { i32, i32 } undef, i32 %"33_015", 0 + %18 = insertvalue { i32, i32 } %17, i32 %"33_116", 1 + %19 = insertvalue { { i32, i32 } } poison, { i32, i32 } %18, 0 + store { { i32, i32 } } %19, { { i32, i32 } }* %"34_0", align 4 + %"34_017" = load { { i32, i32 } }, { { i32, i32 } }* %"34_0", align 4 + %20 = extractvalue { { i32, i32 } } %"34_017", 0 + %21 = extractvalue { i32, i32 } %20, 0 + %22 = extractvalue { i32, i32 } %20, 1 + store i32 %21, i32* %"35_0", align 4 + store i32 %22, i32* %"35_1", align 4 + %"35_018" = load i32, i32* %"35_0", align 4 + %h_call19 = call i32 @___h.2(i32 %"35_018") + store i32 %h_call19, i32* %"36_0", align 4 + %"36_020" = load i32, i32* %"36_0", align 4 + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %"36_020") + %23 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %24 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + store i32 %23, i32* %"37_0", align 4 + store { i32, {}, {} } %24, { i32, {}, {} }* %"37_1", align 4 + %"37_121" = load { i32, {}, {} }, { i32, {}, {} }* %"37_1", align 4 + %"32_122" = load i32, i32* %"32_1", align 4 + %"35_123" = load i32, i32* %"35_1", align 4 + store { i32, {}, {} } %"37_121", { i32, {}, {} }* %"37_1", align 4 + store i32 %"32_122", i32* %"32_1", align 4 + store i32 %"35_123", i32* %"35_1", align 4 + %"37_024" = load i32, i32* %"37_0", align 4 + call void @___qfree(i32 %"37_024") + %"37_125" = load { i32, {}, {} }, { i32, {}, {} }* %"37_1", align 4 + %"32_126" = load i32, i32* %"32_1", align 4 + %"35_127" = load i32, i32* %"35_1", align 4 + %25 = extractvalue { i32, {}, {} } %"37_125", 0 + switch i32 %25, label %2 [ + i32 1, label %4 + ] + +26: ; preds = %28 + %27 = extractvalue { {} } %"41_035", 0 + store i32 %"40_036", i32* %"9_0", align 4 + store i32 %"7_137", i32* %"9_1", align 4 + br label %36 + +28: ; preds = %4 + %"7_029" = load i32, i32* %"7_0", align 4 + %"7_130" = load i32, i32* %"7_1", align 4 + store { {} } undef, { {} }* %"41_0", align 1 + store i32 %"7_029", i32* %"7_0", align 4 + store i32 %"7_130", i32* %"7_1", align 4 + %"7_031" = load i32, i32* %"7_0", align 4 + %z_call = call i32 @___z(i32 %"7_031") + store i32 %z_call, i32* %"40_0", align 4 + %"41_032" = load { {} }, { {} }* %"41_0", align 1 + %"40_033" = load i32, i32* %"40_0", align 4 + %"7_134" = load i32, i32* %"7_1", align 4 + store { {} } %"41_032", { {} }* %"41_0", align 1 + store i32 %"40_033", i32* %"40_0", align 4 + store i32 %"7_134", i32* %"7_1", align 4 + %"41_035" = load { {} }, { {} }* %"41_0", align 1 + %"40_036" = load i32, i32* %"40_0", align 4 + %"7_137" = load i32, i32* %"7_1", align 4 + switch i32 0, label %26 [ + ] + +29: ; preds = %31 + %30 = extractvalue { {} } %"43_043", 0 + store i32 %"8_044", i32* %"9_0", align 4 + store i32 %"8_145", i32* %"9_1", align 4 + br label %36 + +31: ; preds = %2 + %"8_038" = load i32, i32* %"8_0", align 4 + %"8_139" = load i32, i32* %"8_1", align 4 + store { {} } undef, { {} }* %"43_0", align 1 + store i32 %"8_038", i32* %"8_0", align 4 + store i32 %"8_139", i32* %"8_1", align 4 + %"43_040" = load { {} }, { {} }* %"43_0", align 1 + %"8_041" = load i32, i32* %"8_0", align 4 + %"8_142" = load i32, i32* %"8_1", align 4 + store { {} } %"43_040", { {} }* %"43_0", align 1 + store i32 %"8_041", i32* %"8_0", align 4 + store i32 %"8_142", i32* %"8_1", align 4 + %"43_043" = load { {} }, { {} }* %"43_0", align 1 + %"8_044" = load i32, i32* %"8_0", align 4 + %"8_145" = load i32, i32* %"8_1", align 4 + switch i32 0, label %29 [ + ] + +32: ; preds = %36 + %33 = extractvalue { i32, {}, {} } %"45_153", 1 + store i32 %"9_054", i32* %"11_0", align 4 + br label %45 + +34: ; preds = %36 + %35 = extractvalue { i32, {}, {} } %"45_153", 2 + store i32 %"9_054", i32* %"10_0", align 4 + br label %42 + +36: ; preds = %29, %26 + %"9_046" = load i32, i32* %"9_0", align 4 + %"9_147" = load i32, i32* %"9_1", align 4 + store i32 %"9_046", i32* %"9_0", align 4 + store i32 %"9_147", i32* %"9_1", align 4 + %"9_148" = load i32, i32* %"9_1", align 4 + %measure_call49 = call { i32, { i32, {}, {} } } @___measure.3(i32 %"9_148") + %37 = extractvalue { i32, { i32, {}, {} } } %measure_call49, 0 + %38 = extractvalue { i32, { i32, {}, {} } } %measure_call49, 1 + store i32 %37, i32* %"45_0", align 4 + store { i32, {}, {} } %38, { i32, {}, {} }* %"45_1", align 4 + %"45_150" = load { i32, {}, {} }, { i32, {}, {} }* %"45_1", align 4 + %"9_051" = load i32, i32* %"9_0", align 4 + store { i32, {}, {} } %"45_150", { i32, {}, {} }* %"45_1", align 4 + store i32 %"9_051", i32* %"9_0", align 4 + %"45_052" = load i32, i32* %"45_0", align 4 + call void @___qfree.4(i32 %"45_052") + %"45_153" = load { i32, {}, {} }, { i32, {}, {} }* %"45_1", align 4 + %"9_054" = load i32, i32* %"9_0", align 4 + %39 = extractvalue { i32, {}, {} } %"45_153", 0 + switch i32 %39, label %32 [ + i32 1, label %34 + ] + +40: ; preds = %42 + %41 = extractvalue { {} } %"49_059", 0 + store i32 %"48_060", i32* %"12_0", align 4 + br label %48 + +42: ; preds = %34 + %"10_055" = load i32, i32* %"10_0", align 4 + store { {} } undef, { {} }* %"49_0", align 1 + store i32 %"10_055", i32* %"10_0", align 4 + %"10_056" = load i32, i32* %"10_0", align 4 + %x_call = call i32 @___x(i32 %"10_056") + store i32 %x_call, i32* %"48_0", align 4 + %"49_057" = load { {} }, { {} }* %"49_0", align 1 + %"48_058" = load i32, i32* %"48_0", align 4 + store { {} } %"49_057", { {} }* %"49_0", align 1 + store i32 %"48_058", i32* %"48_0", align 4 + %"49_059" = load { {} }, { {} }* %"49_0", align 1 + %"48_060" = load i32, i32* %"48_0", align 4 + switch i32 0, label %40 [ + ] + +43: ; preds = %45 + %44 = extractvalue { {} } %"51_064", 0 + store i32 %"11_065", i32* %"12_0", align 4 + br label %48 + +45: ; preds = %32 + %"11_061" = load i32, i32* %"11_0", align 4 + store { {} } undef, { {} }* %"51_0", align 1 + store i32 %"11_061", i32* %"11_0", align 4 + %"51_062" = load { {} }, { {} }* %"51_0", align 1 + %"11_063" = load i32, i32* %"11_0", align 4 + store { {} } %"51_062", { {} }* %"51_0", align 1 + store i32 %"11_063", i32* %"11_0", align 4 + %"51_064" = load { {} }, { {} }* %"51_0", align 1 + %"11_065" = load i32, i32* %"11_0", align 4 + switch i32 0, label %43 [ + ] + +46: ; preds = %48 + %47 = extractvalue { {} } %"53_069", 0 + store i32 %"12_070", i32* %"03", align 4 + br label %49 + +48: ; preds = %43, %40 + %"12_066" = load i32, i32* %"12_0", align 4 + store { {} } undef, { {} }* %"53_0", align 1 + store i32 %"12_066", i32* %"12_0", align 4 + %"53_067" = load { {} }, { {} }* %"53_0", align 1 + %"12_068" = load i32, i32* %"12_0", align 4 + store { {} } %"53_067", { {} }* %"53_0", align 1 + store i32 %"12_068", i32* %"12_0", align 4 + %"53_069" = load { {} }, { {} }* %"53_0", align 1 + %"12_070" = load i32, i32* %"12_0", align 4 + switch i32 0, label %46 [ + ] + +49: ; preds = %46 + %"028" = load i32, i32* %"03", align 4 + store i32 %"028", i32* %"27_0", align 4 + %"27_071" = load i32, i32* %"27_0", align 4 + store i32 %"27_071", i32* %"0", align 4 + %"072" = load i32, i32* %"0", align 4 + ret i32 %"072" +} + +declare i32 @___qalloc() + +declare i32 @___h(i32) + +declare { i32, i32 } @___cx(i32, i32) + +declare { i32, i32 } @___cx.1(i32, i32) + +declare i32 @___h.2(i32) + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + +declare i32 @___z(i32) + +declare { i32, { i32, {}, {} } } @___measure.3(i32) + +declare void @___qfree.4(i32) + +declare i32 @___x(i32) + +define { i32, {}, {} } @_hl.main.26() { +alloca_block: + %"0" = alloca { i32, {}, {} }, align 8 + %"54_0" = alloca { i32, {}, {} }, align 8 + %"01" = alloca { i32, {}, {} }, align 8 + %"62_0" = alloca { {} }, align 8 + %"60_1" = alloca { i32, {}, {} }, align 8 + %"56_0" = alloca i32, align 4 + %"55_0" = alloca i32, align 4 + %"57_0" = alloca { { i32, i32 } }, align 8 + %"58_0" = alloca i32, align 4 + %"58_1" = alloca i32, align 4 + %"59_0" = alloca i32, align 4 + %"60_0" = alloca i32, align 4 + br label %entry_block + +entry_block: ; preds = %alloca_block + br label %2 + +0: ; preds = %2 + %1 = extractvalue { {} } %"62_012", 0 + store { i32, {}, {} } %"60_113", { i32, {}, {} }* %"01", align 4 + br label %12 + +2: ; preds = %entry_block + store { {} } undef, { {} }* %"62_0", align 1 + %qalloc_call = call i32 @___qalloc.5() + store i32 %qalloc_call, i32* %"56_0", align 4 + %qalloc_call2 = call i32 @___qalloc.6() + store i32 %qalloc_call2, i32* %"55_0", align 4 + %"55_03" = load i32, i32* %"55_0", align 4 + %"56_04" = load i32, i32* %"56_0", align 4 + %3 = insertvalue { i32, i32 } undef, i32 %"55_03", 0 + %4 = insertvalue { i32, i32 } %3, i32 %"56_04", 1 + %5 = insertvalue { { i32, i32 } } poison, { i32, i32 } %4, 0 + store { { i32, i32 } } %5, { { i32, i32 } }* %"57_0", align 4 + %"57_05" = load { { i32, i32 } }, { { i32, i32 } }* %"57_0", align 4 + %6 = extractvalue { { i32, i32 } } %"57_05", 0 + %7 = extractvalue { i32, i32 } %6, 0 + %8 = extractvalue { i32, i32 } %6, 1 + store i32 %7, i32* %"58_0", align 4 + store i32 %8, i32* %"58_1", align 4 + %"58_06" = load i32, i32* %"58_0", align 4 + %"58_17" = load i32, i32* %"58_1", align 4 + %9 = call i32 @_hl.teleport.25(i32 %"58_06", i32 %"58_17") + store i32 %9, i32* %"59_0", align 4 + %"59_08" = load i32, i32* %"59_0", align 4 + %measure_call = call { i32, { i32, {}, {} } } @___measure.7(i32 %"59_08") + %10 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %11 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + store i32 %10, i32* %"60_0", align 4 + store { i32, {}, {} } %11, { i32, {}, {} }* %"60_1", align 4 + %"62_09" = load { {} }, { {} }* %"62_0", align 1 + %"60_110" = load { i32, {}, {} }, { i32, {}, {} }* %"60_1", align 4 + store { {} } %"62_09", { {} }* %"62_0", align 1 + store { i32, {}, {} } %"60_110", { i32, {}, {} }* %"60_1", align 4 + %"60_011" = load i32, i32* %"60_0", align 4 + call void @___qfree.8(i32 %"60_011") + %"62_012" = load { {} }, { {} }* %"62_0", align 1 + %"60_113" = load { i32, {}, {} }, { i32, {}, {} }* %"60_1", align 4 + switch i32 0, label %0 [ + ] + +12: ; preds = %0 + %"014" = load { i32, {}, {} }, { i32, {}, {} }* %"01", align 4 + store { i32, {}, {} } %"014", { i32, {}, {} }* %"54_0", align 4 + %"54_015" = load { i32, {}, {} }, { i32, {}, {} }* %"54_0", align 4 + store { i32, {}, {} } %"54_015", { i32, {}, {} }* %"0", align 4 + %"016" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"016" +} + +declare i32 @___qalloc.5() + +declare i32 @___qalloc.6() + +declare { i32, { i32, {}, {} } } @___measure.7(i32) + +declare void @___qfree.8(i32) + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__planqc2@llvm14.opt.snap b/tests/snapshots/guppy__planqc2@llvm14.opt.snap new file mode 100644 index 0000000..ce888a7 --- /dev/null +++ b/tests/snapshots/guppy__planqc2@llvm14.opt.snap @@ -0,0 +1,134 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define i32 @_hl.teleport.25(i32 %0, i32 %1) { +alloca_block: + %qalloc_call = call i32 @___qalloc() + %h_call = call i32 @___h(i32 %qalloc_call) + %rz_call = call { i32, i32 } @___cx(i32 %h_call, i32 %1) + %2 = extractvalue { i32, i32 } %rz_call, 0 + %3 = extractvalue { i32, i32 } %rz_call, 1 + %4 = insertvalue { i32, i32 } undef, i32 %2, 0 + %5 = insertvalue { i32, i32 } %4, i32 %3, 1 + %6 = insertvalue { { i32, i32 } } poison, { i32, i32 } %5, 0 + %7 = extractvalue { { i32, i32 } } %6, 0 + %8 = extractvalue { i32, i32 } %7, 0 + %9 = extractvalue { i32, i32 } %7, 1 + %rz_call14 = call { i32, i32 } @___cx.1(i32 %0, i32 %8) + %10 = extractvalue { i32, i32 } %rz_call14, 0 + %11 = extractvalue { i32, i32 } %rz_call14, 1 + %12 = insertvalue { i32, i32 } undef, i32 %10, 0 + %13 = insertvalue { i32, i32 } %12, i32 %11, 1 + %14 = insertvalue { { i32, i32 } } poison, { i32, i32 } %13, 0 + %15 = extractvalue { { i32, i32 } } %14, 0 + %16 = extractvalue { i32, i32 } %15, 0 + %17 = extractvalue { i32, i32 } %15, 1 + %h_call19 = call i32 @___h.2(i32 %16) + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %h_call19) + %18 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %19 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + call void @___qfree(i32 %18) + %20 = extractvalue { i32, {}, {} } %19, 0 + %cond = icmp eq i32 %20, 1 + br i1 %cond, label %24, label %21 + +21: ; preds = %alloca_block + %22 = extractvalue { i32, {}, {} } %19, 1 + %23 = extractvalue { {} } undef, 0 + br label %33 + +24: ; preds = %alloca_block + %25 = extractvalue { i32, {}, {} } %19, 2 + %z_call = call i32 @___z(i32 %9) + %26 = extractvalue { {} } undef, 0 + br label %33 + +27: ; preds = %33 + %28 = extractvalue { i32, {}, {} } %35, 1 + %29 = extractvalue { {} } undef, 0 + br label %37 + +30: ; preds = %33 + %31 = extractvalue { i32, {}, {} } %35, 2 + %x_call = call i32 @___x(i32 %"9_0.0") + %32 = extractvalue { {} } undef, 0 + br label %37 + +33: ; preds = %21, %24 + %"9_0.0" = phi i32 [ %9, %21 ], [ %z_call, %24 ] + %measure_call49 = call { i32, { i32, {}, {} } } @___measure.3(i32 %17) + %34 = extractvalue { i32, { i32, {}, {} } } %measure_call49, 0 + %35 = extractvalue { i32, { i32, {}, {} } } %measure_call49, 1 + call void @___qfree.4(i32 %34) + %36 = extractvalue { i32, {}, {} } %35, 0 + %cond73 = icmp eq i32 %36, 1 + br i1 %cond73, label %30, label %27 + +37: ; preds = %27, %30 + %"12_0.0" = phi i32 [ %"9_0.0", %27 ], [ %x_call, %30 ] + %38 = extractvalue { {} } undef, 0 + ret i32 %"12_0.0" +} + +declare i32 @___qalloc() + +declare i32 @___h(i32) + +declare { i32, i32 } @___cx(i32, i32) + +declare { i32, i32 } @___cx.1(i32, i32) + +declare i32 @___h.2(i32) + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + +declare i32 @___z(i32) + +declare { i32, { i32, {}, {} } } @___measure.3(i32) + +declare void @___qfree.4(i32) + +declare i32 @___x(i32) + +define { i32, {}, {} } @_hl.main.26() { +alloca_block: + %qalloc_call = call i32 @___qalloc.5() + %qalloc_call2 = call i32 @___qalloc.6() + %0 = insertvalue { i32, i32 } undef, i32 %qalloc_call2, 0 + %1 = insertvalue { i32, i32 } %0, i32 %qalloc_call, 1 + %2 = insertvalue { { i32, i32 } } poison, { i32, i32 } %1, 0 + %3 = extractvalue { { i32, i32 } } %2, 0 + %4 = extractvalue { i32, i32 } %3, 0 + %5 = extractvalue { i32, i32 } %3, 1 + %6 = call i32 @_hl.teleport.25(i32 %4, i32 %5) + %measure_call = call { i32, { i32, {}, {} } } @___measure.7(i32 %6) + %7 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %8 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + call void @___qfree.8(i32 %7) + %9 = extractvalue { {} } undef, 0 + ret { i32, {}, {} } %8 +} + +declare i32 @___qalloc.5() + +declare i32 @___qalloc.6() + +declare { i32, { i32, {}, {} } } @___measure.7(i32) + +declare void @___qfree.8(i32) + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__planqc3@llvm14.noopt.snap b/tests/snapshots/guppy__planqc3@llvm14.noopt.snap new file mode 100644 index 0000000..e69363d --- /dev/null +++ b/tests/snapshots/guppy__planqc3@llvm14.noopt.snap @@ -0,0 +1,605 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "--no-opt" + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define i32 @_hl.rus.35(i32 %0, i64 %1) { +alloca_block: + %"0" = alloca i32, align 4 + %"5_0" = alloca i32, align 4 + %"5_1" = alloca i64, align 8 + %"37_0" = alloca i32, align 4 + %"6_0" = alloca i32, align 4 + %"6_1" = alloca i64, align 8 + %"03" = alloca i32, align 4 + %"7_0" = alloca i64, align 8 + %"7_1" = alloca i64, align 8 + %"7_2" = alloca i32, align 4 + %"10_0" = alloca i64, align 8 + %"10_1" = alloca i64, align 8 + %"10_2" = alloca i32, align 4 + %"11_0" = alloca i32, align 4 + %"12_0" = alloca i64, align 8 + %"12_1" = alloca i64, align 8 + %"12_2" = alloca i32, align 4 + %"12_3" = alloca i32, align 4 + %"15_0" = alloca i64, align 8 + %"15_1" = alloca i64, align 8 + %"15_2" = alloca i32, align 4 + %"15_3" = alloca i32, align 4 + %"16_0" = alloca i32, align 4 + %"17_0" = alloca i64, align 8 + %"17_1" = alloca i64, align 8 + %"17_2" = alloca i32, align 4 + %"40_0" = alloca { {} }, align 8 + %"39_0" = alloca i64, align 8 + %"43_0" = alloca { i32, {}, { i64, i64 } }, align 8 + %"42_0" = alloca { i32, {}, {} }, align 8 + %"021" = alloca { i32, {}, { i64, i64 } }, align 8 + %"45_0" = alloca { i32, {}, { i64, i64 } }, align 8 + %"47_0" = alloca { i32, {}, { i64, i64 } }, align 8 + %"60_1" = alloca { i32, {}, {} }, align 8 + %"58_0" = alloca i32, align 4 + %"51_0" = alloca i32, align 4 + %"52_0" = alloca i32, align 4 + %"49_0" = alloca i32, align 4 + %"50_0" = alloca i32, align 4 + %"53_0" = alloca { { i32, i32 } }, align 8 + %"54_0" = alloca i32, align 4 + %"54_1" = alloca i32, align 4 + %"55_0" = alloca i32, align 4 + %"56_0" = alloca i32, align 4 + %"56_1" = alloca i32, align 4 + %"57_0" = alloca { { i32, i32 } }, align 8 + %"58_1" = alloca i32, align 4 + %"59_0" = alloca i32, align 4 + %"60_0" = alloca i32, align 4 + %"63_0" = alloca { {} }, align 8 + %"73_0" = alloca { i32, { i64, i64 }, {} }, align 8 + %"69_0" = alloca i32, align 4 + %"65_0" = alloca i32, align 4 + %"66_0" = alloca i32, align 4 + %"67_0" = alloca i32, align 4 + %"67_1" = alloca i32, align 4 + %"68_0" = alloca { { i32, i32 } }, align 8 + %"69_1" = alloca i32, align 4 + %"70_0" = alloca i32, align 4 + %"71_0" = alloca i32, align 4 + %"71_1" = alloca { i32, {}, {} }, align 8 + %"083" = alloca { i32, { i64, i64 }, {} }, align 8 + %"75_0" = alloca { i32, { i64, i64 }, {} }, align 8 + %"77_0" = alloca { i32, { i64, i64 }, {} }, align 8 + %"81_0" = alloca { {} }, align 8 + %"80_0" = alloca { {} }, align 8 + %"83_0" = alloca { {} }, align 8 + %"89_0" = alloca { {} }, align 8 + %"88_0" = alloca i64, align 8 + %"85_0" = alloca i32, align 4 + %"87_0" = alloca i64, align 8 + br label %entry_block + +entry_block: ; preds = %alloca_block + store i32 %0, i32* %"5_0", align 4 + store i64 %1, i64* %"5_1", align 4 + %"5_01" = load i32, i32* %"5_0", align 4 + %"5_12" = load i64, i64* %"5_1", align 4 + store i32 %"5_01", i32* %"6_0", align 4 + store i64 %"5_12", i64* %"6_1", align 4 + br label %4 + +2: ; preds = %4 + %3 = extractvalue { {} } %"40_010", 0 + store i64 %"39_011", i64* %"7_0", align 4 + store i64 %"6_112", i64* %"7_1", align 4 + store i32 %"6_013", i32* %"7_2", align 4 + br label %11 + +4: ; preds = %entry_block + %"6_04" = load i32, i32* %"6_0", align 4 + %"6_15" = load i64, i64* %"6_1", align 4 + store { {} } undef, { {} }* %"40_0", align 1 + store i64 0, i64* %"39_0", align 4 + store i32 %"6_04", i32* %"6_0", align 4 + store i64 %"6_15", i64* %"6_1", align 4 + %"40_06" = load { {} }, { {} }* %"40_0", align 1 + %"39_07" = load i64, i64* %"39_0", align 4 + %"6_18" = load i64, i64* %"6_1", align 4 + %"6_09" = load i32, i32* %"6_0", align 4 + store { {} } %"40_06", { {} }* %"40_0", align 1 + store i64 %"39_07", i64* %"39_0", align 4 + store i64 %"6_18", i64* %"6_1", align 4 + store i32 %"6_09", i32* %"6_0", align 4 + %"40_010" = load { {} }, { {} }* %"40_0", align 1 + %"39_011" = load i64, i64* %"39_0", align 4 + %"6_112" = load i64, i64* %"6_1", align 4 + %"6_013" = load i32, i32* %"6_0", align 4 + switch i32 0, label %2 [ + ] + +5: ; preds = %cond_exit_43 + %6 = extractvalue { i32, {}, { i64, i64 } } %"43_029", 1 + store i32 %"7_230", i32* %"11_0", align 4 + br label %41 + +7: ; preds = %cond_exit_43 + %8 = extractvalue { i32, {}, { i64, i64 } } %"43_029", 2 + %9 = extractvalue { i64, i64 } %8, 0 + %10 = extractvalue { i64, i64 } %8, 1 + store i64 %9, i64* %"10_0", align 4 + store i64 %10, i64* %"10_1", align 4 + store i32 %"7_230", i32* %"10_2", align 4 + br label %21 + +11: ; preds = %68, %62, %2 + %"7_015" = load i64, i64* %"7_0", align 4 + %"7_116" = load i64, i64* %"7_1", align 4 + %"7_217" = load i32, i32* %"7_2", align 4 + store i64 %"7_015", i64* %"7_0", align 4 + store i64 %"7_116", i64* %"7_1", align 4 + store i32 %"7_217", i32* %"7_2", align 4 + %"7_018" = load i64, i64* %"7_0", align 4 + %"7_119" = load i64, i64* %"7_1", align 4 + %12 = icmp slt i64 %"7_018", %"7_119" + %13 = select i1 %12, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + store { i32, {}, {} } %13, { i32, {}, {} }* %"42_0", align 4 + %"42_020" = load { i32, {}, {} }, { i32, {}, {} }* %"42_0", align 4 + %14 = extractvalue { i32, {}, {} } %"42_020", 0 + %15 = extractvalue { i32, {}, {} } %"42_020", 1 + %16 = extractvalue { i32, {}, {} } %"42_020", 2 + switch i32 %14, label %cond_43_case_0 [ + i32 1, label %cond_43_case_1 + ] + +17: ; preds = %21 + %18 = extractvalue { i32, {}, {} } %"60_155", 1 + store i64 %"10_056", i64* %"15_0", align 4 + store i64 %"10_157", i64* %"15_1", align 4 + store i32 %"58_058", i32* %"15_2", align 4 + store i32 %"10_259", i32* %"15_3", align 4 + br label %64 + +19: ; preds = %21 + %20 = extractvalue { i32, {}, {} } %"60_155", 2 + store i64 %"10_056", i64* %"12_0", align 4 + store i64 %"10_157", i64* %"12_1", align 4 + store i32 %"58_058", i32* %"12_2", align 4 + store i32 %"10_259", i32* %"12_3", align 4 + br label %48 + +21: ; preds = %7 + %"10_031" = load i64, i64* %"10_0", align 4 + %"10_132" = load i64, i64* %"10_1", align 4 + %"10_233" = load i32, i32* %"10_2", align 4 + %qalloc_call = call i32 @___qalloc() + store i32 %qalloc_call, i32* %"51_0", align 4 + %"51_034" = load i32, i32* %"51_0", align 4 + %h_call = call i32 @___h(i32 %"51_034") + store i32 %h_call, i32* %"52_0", align 4 + %qalloc_call35 = call i32 @___qalloc.1() + store i32 %qalloc_call35, i32* %"49_0", align 4 + %"49_036" = load i32, i32* %"49_0", align 4 + %h_call37 = call i32 @___h.2(i32 %"49_036") + store i32 %h_call37, i32* %"50_0", align 4 + %"50_038" = load i32, i32* %"50_0", align 4 + %"52_039" = load i32, i32* %"52_0", align 4 + %22 = insertvalue { i32, i32 } undef, i32 %"50_038", 0 + %23 = insertvalue { i32, i32 } %22, i32 %"52_039", 1 + %24 = insertvalue { { i32, i32 } } poison, { i32, i32 } %23, 0 + store { { i32, i32 } } %24, { { i32, i32 } }* %"53_0", align 4 + %"53_040" = load { { i32, i32 } }, { { i32, i32 } }* %"53_0", align 4 + %25 = extractvalue { { i32, i32 } } %"53_040", 0 + %26 = extractvalue { i32, i32 } %25, 0 + %27 = extractvalue { i32, i32 } %25, 1 + store i32 %26, i32* %"54_0", align 4 + store i32 %27, i32* %"54_1", align 4 + %"54_041" = load i32, i32* %"54_0", align 4 + %tdg_call = call i32 @___tdg(i32 %"54_041") + store i32 %tdg_call, i32* %"55_0", align 4 + %"54_142" = load i32, i32* %"54_1", align 4 + %"55_043" = load i32, i32* %"55_0", align 4 + %rz_call = call { i32, i32 } @___cx(i32 %"54_142", i32 %"55_043") + %28 = extractvalue { i32, i32 } %rz_call, 0 + %29 = extractvalue { i32, i32 } %rz_call, 1 + store i32 %28, i32* %"56_0", align 4 + store i32 %29, i32* %"56_1", align 4 + %"56_044" = load i32, i32* %"56_0", align 4 + %"56_145" = load i32, i32* %"56_1", align 4 + %30 = insertvalue { i32, i32 } undef, i32 %"56_044", 0 + %31 = insertvalue { i32, i32 } %30, i32 %"56_145", 1 + %32 = insertvalue { { i32, i32 } } poison, { i32, i32 } %31, 0 + store { { i32, i32 } } %32, { { i32, i32 } }* %"57_0", align 4 + %"57_046" = load { { i32, i32 } }, { { i32, i32 } }* %"57_0", align 4 + %33 = extractvalue { { i32, i32 } } %"57_046", 0 + %34 = extractvalue { i32, i32 } %33, 0 + %35 = extractvalue { i32, i32 } %33, 1 + store i32 %34, i32* %"58_0", align 4 + store i32 %35, i32* %"58_1", align 4 + %"58_147" = load i32, i32* %"58_1", align 4 + %t_call = call i32 @___t(i32 %"58_147") + store i32 %t_call, i32* %"59_0", align 4 + %"59_048" = load i32, i32* %"59_0", align 4 + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %"59_048") + %36 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %37 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + store i32 %36, i32* %"60_0", align 4 + store { i32, {}, {} } %37, { i32, {}, {} }* %"60_1", align 4 + %"60_049" = load i32, i32* %"60_0", align 4 + call void @___qfree(i32 %"60_049") + store i64 %"10_031", i64* %"10_0", align 4 + store i64 %"10_132", i64* %"10_1", align 4 + store i32 %"10_233", i32* %"10_2", align 4 + %"60_150" = load { i32, {}, {} }, { i32, {}, {} }* %"60_1", align 4 + %"10_051" = load i64, i64* %"10_0", align 4 + %"10_152" = load i64, i64* %"10_1", align 4 + %"58_053" = load i32, i32* %"58_0", align 4 + %"10_254" = load i32, i32* %"10_2", align 4 + store { i32, {}, {} } %"60_150", { i32, {}, {} }* %"60_1", align 4 + store i64 %"10_051", i64* %"10_0", align 4 + store i64 %"10_152", i64* %"10_1", align 4 + store i32 %"58_053", i32* %"58_0", align 4 + store i32 %"10_254", i32* %"10_2", align 4 + %"60_155" = load { i32, {}, {} }, { i32, {}, {} }* %"60_1", align 4 + %"10_056" = load i64, i64* %"10_0", align 4 + %"10_157" = load i64, i64* %"10_1", align 4 + %"58_058" = load i32, i32* %"58_0", align 4 + %"10_259" = load i32, i32* %"10_2", align 4 + %38 = extractvalue { i32, {}, {} } %"60_155", 0 + switch i32 %38, label %17 [ + i32 1, label %19 + ] + +39: ; preds = %41 + %40 = extractvalue { {} } %"63_063", 0 + store i32 %"11_064", i32* %"03", align 4 + br label %72 + +41: ; preds = %65, %5 + %"11_060" = load i32, i32* %"11_0", align 4 + store { {} } undef, { {} }* %"63_0", align 1 + store i32 %"11_060", i32* %"11_0", align 4 + %"63_061" = load { {} }, { {} }* %"63_0", align 1 + %"11_062" = load i32, i32* %"11_0", align 4 + store { {} } %"63_061", { {} }* %"63_0", align 1 + store i32 %"11_062", i32* %"11_0", align 4 + %"63_063" = load { {} }, { {} }* %"63_0", align 1 + %"11_064" = load i32, i32* %"11_0", align 4 + switch i32 0, label %39 [ + ] + +42: ; preds = %cond_exit_73 + %43 = extractvalue { i32, { i64, i64 }, {} } %"73_092", 1 + %44 = extractvalue { i64, i64 } %43, 0 + %45 = extractvalue { i64, i64 } %43, 1 + store i64 %44, i64* %"17_0", align 4 + store i64 %45, i64* %"17_1", align 4 + store i32 %"69_093", i32* %"17_2", align 4 + br label %70 + +46: ; preds = %cond_exit_73 + %47 = extractvalue { i32, { i64, i64 }, {} } %"73_092", 2 + store i32 %"69_093", i32* %"16_0", align 4 + br label %67 + +48: ; preds = %19 + %"12_065" = load i64, i64* %"12_0", align 4 + %"12_166" = load i64, i64* %"12_1", align 4 + %"12_267" = load i32, i32* %"12_2", align 4 + %"12_368" = load i32, i32* %"12_3", align 4 + store i64 %"12_065", i64* %"12_0", align 4 + store i64 %"12_166", i64* %"12_1", align 4 + store i32 %"12_267", i32* %"12_2", align 4 + store i32 %"12_368", i32* %"12_3", align 4 + %"12_369" = load i32, i32* %"12_3", align 4 + %t_call70 = call i32 @___t.3(i32 %"12_369") + store i32 %t_call70, i32* %"65_0", align 4 + %"65_071" = load i32, i32* %"65_0", align 4 + %z_call = call i32 @___z(i32 %"65_071") + store i32 %z_call, i32* %"66_0", align 4 + %"66_072" = load i32, i32* %"66_0", align 4 + %"12_273" = load i32, i32* %"12_2", align 4 + %rz_call74 = call { i32, i32 } @___cx.4(i32 %"66_072", i32 %"12_273") + %49 = extractvalue { i32, i32 } %rz_call74, 0 + %50 = extractvalue { i32, i32 } %rz_call74, 1 + store i32 %49, i32* %"67_0", align 4 + store i32 %50, i32* %"67_1", align 4 + %"67_075" = load i32, i32* %"67_0", align 4 + %"67_176" = load i32, i32* %"67_1", align 4 + %51 = insertvalue { i32, i32 } undef, i32 %"67_075", 0 + %52 = insertvalue { i32, i32 } %51, i32 %"67_176", 1 + %53 = insertvalue { { i32, i32 } } poison, { i32, i32 } %52, 0 + store { { i32, i32 } } %53, { { i32, i32 } }* %"68_0", align 4 + %"68_077" = load { { i32, i32 } }, { { i32, i32 } }* %"68_0", align 4 + %54 = extractvalue { { i32, i32 } } %"68_077", 0 + %55 = extractvalue { i32, i32 } %54, 0 + %56 = extractvalue { i32, i32 } %54, 1 + store i32 %55, i32* %"69_0", align 4 + store i32 %56, i32* %"69_1", align 4 + %"69_178" = load i32, i32* %"69_1", align 4 + %t_call79 = call i32 @___t.5(i32 %"69_178") + store i32 %t_call79, i32* %"70_0", align 4 + %"70_080" = load i32, i32* %"70_0", align 4 + %measure_call81 = call { i32, { i32, {}, {} } } @___measure.6(i32 %"70_080") + %57 = extractvalue { i32, { i32, {}, {} } } %measure_call81, 0 + %58 = extractvalue { i32, { i32, {}, {} } } %measure_call81, 1 + store i32 %57, i32* %"71_0", align 4 + store { i32, {}, {} } %58, { i32, {}, {} }* %"71_1", align 4 + %"71_182" = load { i32, {}, {} }, { i32, {}, {} }* %"71_1", align 4 + %59 = extractvalue { i32, {}, {} } %"71_182", 0 + %60 = extractvalue { i32, {}, {} } %"71_182", 1 + %61 = extractvalue { i32, {}, {} } %"71_182", 2 + switch i32 %59, label %cond_73_case_0 [ + i32 1, label %cond_73_case_1 + ] + +62: ; preds = %64 + %63 = extractvalue { {} } %"81_0103", 0 + store i64 %"15_0104", i64* %"7_0", align 4 + store i64 %"15_1105", i64* %"7_1", align 4 + store i32 %"15_3106", i32* %"7_2", align 4 + br label %11 + +64: ; preds = %17 + %"15_094" = load i64, i64* %"15_0", align 4 + %"15_195" = load i64, i64* %"15_1", align 4 + %"15_296" = load i32, i32* %"15_2", align 4 + %"15_397" = load i32, i32* %"15_3", align 4 + store { {} } undef, { {} }* %"81_0", align 1 + store { {} } undef, { {} }* %"80_0", align 1 + store i64 %"15_094", i64* %"15_0", align 4 + store i64 %"15_195", i64* %"15_1", align 4 + store i32 %"15_296", i32* %"15_2", align 4 + store i32 %"15_397", i32* %"15_3", align 4 + %"81_098" = load { {} }, { {} }* %"81_0", align 1 + %"15_099" = load i64, i64* %"15_0", align 4 + %"15_1100" = load i64, i64* %"15_1", align 4 + %"15_3101" = load i32, i32* %"15_3", align 4 + store { {} } %"81_098", { {} }* %"81_0", align 1 + store i64 %"15_099", i64* %"15_0", align 4 + store i64 %"15_1100", i64* %"15_1", align 4 + store i32 %"15_3101", i32* %"15_3", align 4 + %"15_2102" = load i32, i32* %"15_2", align 4 + call void @___qfree.8(i32 %"15_2102") + %"81_0103" = load { {} }, { {} }* %"81_0", align 1 + %"15_0104" = load i64, i64* %"15_0", align 4 + %"15_1105" = load i64, i64* %"15_1", align 4 + %"15_3106" = load i32, i32* %"15_3", align 4 + switch i32 0, label %62 [ + ] + +65: ; preds = %67 + %66 = extractvalue { {} } %"83_0110", 0 + store i32 %"16_0111", i32* %"11_0", align 4 + br label %41 + +67: ; preds = %46 + %"16_0107" = load i32, i32* %"16_0", align 4 + store { {} } undef, { {} }* %"83_0", align 1 + store i32 %"16_0107", i32* %"16_0", align 4 + %"83_0108" = load { {} }, { {} }* %"83_0", align 1 + %"16_0109" = load i32, i32* %"16_0", align 4 + store { {} } %"83_0108", { {} }* %"83_0", align 1 + store i32 %"16_0109", i32* %"16_0", align 4 + %"83_0110" = load { {} }, { {} }* %"83_0", align 1 + %"16_0111" = load i32, i32* %"16_0", align 4 + switch i32 0, label %65 [ + ] + +68: ; preds = %70 + %69 = extractvalue { {} } %"89_0122", 0 + store i64 %"88_0123", i64* %"7_0", align 4 + store i64 %"17_1124", i64* %"7_1", align 4 + store i32 %"85_0125", i32* %"7_2", align 4 + br label %11 + +70: ; preds = %42 + %"17_0112" = load i64, i64* %"17_0", align 4 + %"17_1113" = load i64, i64* %"17_1", align 4 + %"17_2114" = load i32, i32* %"17_2", align 4 + store { {} } undef, { {} }* %"89_0", align 1 + store i64 1, i64* %"87_0", align 4 + store i64 %"17_0112", i64* %"17_0", align 4 + store i64 %"17_1113", i64* %"17_1", align 4 + store i32 %"17_2114", i32* %"17_2", align 4 + %"17_2115" = load i32, i32* %"17_2", align 4 + %x_call = call i32 @___x(i32 %"17_2115") + store i32 %x_call, i32* %"85_0", align 4 + %"17_0116" = load i64, i64* %"17_0", align 4 + %"87_0117" = load i64, i64* %"87_0", align 4 + %71 = add i64 %"17_0116", %"87_0117" + store i64 %71, i64* %"88_0", align 4 + %"89_0118" = load { {} }, { {} }* %"89_0", align 1 + %"88_0119" = load i64, i64* %"88_0", align 4 + %"17_1120" = load i64, i64* %"17_1", align 4 + %"85_0121" = load i32, i32* %"85_0", align 4 + store { {} } %"89_0118", { {} }* %"89_0", align 1 + store i64 %"88_0119", i64* %"88_0", align 4 + store i64 %"17_1120", i64* %"17_1", align 4 + store i32 %"85_0121", i32* %"85_0", align 4 + %"89_0122" = load { {} }, { {} }* %"89_0", align 1 + %"88_0123" = load i64, i64* %"88_0", align 4 + %"17_1124" = load i64, i64* %"17_1", align 4 + %"85_0125" = load i32, i32* %"85_0", align 4 + switch i32 0, label %68 [ + ] + +72: ; preds = %39 + %"014" = load i32, i32* %"03", align 4 + store i32 %"014", i32* %"37_0", align 4 + %"37_0126" = load i32, i32* %"37_0", align 4 + store i32 %"37_0126", i32* %"0", align 4 + %"0127" = load i32, i32* %"0", align 4 + ret i32 %"0127" + +cond_43_case_0: ; preds = %11 + store { i32, {}, { i64, i64 } } { i32 0, {} undef, { i64, i64 } poison }, { i32, {}, { i64, i64 } }* %"45_0", align 4 + %"45_023" = load { i32, {}, { i64, i64 } }, { i32, {}, { i64, i64 } }* %"45_0", align 4 + store { i32, {}, { i64, i64 } } %"45_023", { i32, {}, { i64, i64 } }* %"021", align 4 + br label %cond_exit_43 + +cond_43_case_1: ; preds = %11 + %"7_024" = load i64, i64* %"7_0", align 4 + %"7_125" = load i64, i64* %"7_1", align 4 + %73 = insertvalue { i64, i64 } undef, i64 %"7_024", 0 + %74 = insertvalue { i64, i64 } %73, i64 %"7_125", 1 + %75 = insertvalue { i32, {}, { i64, i64 } } { i32 1, {} poison, { i64, i64 } poison }, { i64, i64 } %74, 2 + store { i32, {}, { i64, i64 } } %75, { i32, {}, { i64, i64 } }* %"47_0", align 4 + %"47_026" = load { i32, {}, { i64, i64 } }, { i32, {}, { i64, i64 } }* %"47_0", align 4 + store { i32, {}, { i64, i64 } } %"47_026", { i32, {}, { i64, i64 } }* %"021", align 4 + br label %cond_exit_43 + +cond_exit_43: ; preds = %cond_43_case_1, %cond_43_case_0 + %"022" = load { i32, {}, { i64, i64 } }, { i32, {}, { i64, i64 } }* %"021", align 4 + store { i32, {}, { i64, i64 } } %"022", { i32, {}, { i64, i64 } }* %"43_0", align 4 + %"43_027" = load { i32, {}, { i64, i64 } }, { i32, {}, { i64, i64 } }* %"43_0", align 4 + %"7_228" = load i32, i32* %"7_2", align 4 + store { i32, {}, { i64, i64 } } %"43_027", { i32, {}, { i64, i64 } }* %"43_0", align 4 + store i32 %"7_228", i32* %"7_2", align 4 + %"43_029" = load { i32, {}, { i64, i64 } }, { i32, {}, { i64, i64 } }* %"43_0", align 4 + %"7_230" = load i32, i32* %"7_2", align 4 + %76 = extractvalue { i32, {}, { i64, i64 } } %"43_029", 0 + switch i32 %76, label %5 [ + i32 1, label %7 + ] + +cond_73_case_0: ; preds = %48 + %"12_085" = load i64, i64* %"12_0", align 4 + %"12_186" = load i64, i64* %"12_1", align 4 + %77 = insertvalue { i64, i64 } undef, i64 %"12_085", 0 + %78 = insertvalue { i64, i64 } %77, i64 %"12_186", 1 + %79 = insertvalue { i32, { i64, i64 }, {} } { i32 0, { i64, i64 } poison, {} poison }, { i64, i64 } %78, 1 + store { i32, { i64, i64 }, {} } %79, { i32, { i64, i64 }, {} }* %"75_0", align 4 + %"75_087" = load { i32, { i64, i64 }, {} }, { i32, { i64, i64 }, {} }* %"75_0", align 4 + store { i32, { i64, i64 }, {} } %"75_087", { i32, { i64, i64 }, {} }* %"083", align 4 + br label %cond_exit_73 + +cond_73_case_1: ; preds = %48 + store { i32, { i64, i64 }, {} } { i32 1, { i64, i64 } poison, {} undef }, { i32, { i64, i64 }, {} }* %"77_0", align 4 + %"77_088" = load { i32, { i64, i64 }, {} }, { i32, { i64, i64 }, {} }* %"77_0", align 4 + store { i32, { i64, i64 }, {} } %"77_088", { i32, { i64, i64 }, {} }* %"083", align 4 + br label %cond_exit_73 + +cond_exit_73: ; preds = %cond_73_case_1, %cond_73_case_0 + %"084" = load { i32, { i64, i64 }, {} }, { i32, { i64, i64 }, {} }* %"083", align 4 + store { i32, { i64, i64 }, {} } %"084", { i32, { i64, i64 }, {} }* %"73_0", align 4 + %"73_089" = load { i32, { i64, i64 }, {} }, { i32, { i64, i64 }, {} }* %"73_0", align 4 + %"69_090" = load i32, i32* %"69_0", align 4 + store { i32, { i64, i64 }, {} } %"73_089", { i32, { i64, i64 }, {} }* %"73_0", align 4 + store i32 %"69_090", i32* %"69_0", align 4 + %"71_091" = load i32, i32* %"71_0", align 4 + call void @___qfree.7(i32 %"71_091") + %"73_092" = load { i32, { i64, i64 }, {} }, { i32, { i64, i64 }, {} }* %"73_0", align 4 + %"69_093" = load i32, i32* %"69_0", align 4 + %80 = extractvalue { i32, { i64, i64 }, {} } %"73_092", 0 + switch i32 %80, label %42 [ + i32 1, label %46 + ] +} + +declare i32 @___qalloc() + +declare i32 @___h(i32) + +declare i32 @___qalloc.1() + +declare i32 @___h.2(i32) + +declare i32 @___tdg(i32) + +declare { i32, i32 } @___cx(i32, i32) + +declare i32 @___t(i32) + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + +declare i32 @___t.3(i32) + +declare i32 @___z(i32) + +declare { i32, i32 } @___cx.4(i32, i32) + +declare i32 @___t.5(i32) + +declare { i32, { i32, {}, {} } } @___measure.6(i32) + +declare void @___qfree.7(i32) + +declare void @___qfree.8(i32) + +declare i32 @___x(i32) + +define { i32, {}, {} } @_hl.main.36() { +alloca_block: + %"0" = alloca { i32, {}, {} }, align 8 + %"90_0" = alloca { i32, {}, {} }, align 8 + %"01" = alloca { i32, {}, {} }, align 8 + %"97_0" = alloca { {} }, align 8 + %"95_1" = alloca { i32, {}, {} }, align 8 + %"93_0" = alloca i64, align 8 + %"91_0" = alloca i32, align 4 + %"94_0" = alloca i32, align 4 + %"95_0" = alloca i32, align 4 + br label %entry_block + +entry_block: ; preds = %alloca_block + br label %2 + +0: ; preds = %2 + %1 = extractvalue { {} } %"97_08", 0 + store { i32, {}, {} } %"95_19", { i32, {}, {} }* %"01", align 4 + br label %6 + +2: ; preds = %entry_block + store { {} } undef, { {} }* %"97_0", align 1 + store i64 100, i64* %"93_0", align 4 + %qalloc_call = call i32 @___qalloc.9() + store i32 %qalloc_call, i32* %"91_0", align 4 + %"91_02" = load i32, i32* %"91_0", align 4 + %"93_03" = load i64, i64* %"93_0", align 4 + %3 = call i32 @_hl.rus.35(i32 %"91_02", i64 %"93_03") + store i32 %3, i32* %"94_0", align 4 + %"94_04" = load i32, i32* %"94_0", align 4 + %measure_call = call { i32, { i32, {}, {} } } @___measure.10(i32 %"94_04") + %4 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %5 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + store i32 %4, i32* %"95_0", align 4 + store { i32, {}, {} } %5, { i32, {}, {} }* %"95_1", align 4 + %"97_05" = load { {} }, { {} }* %"97_0", align 1 + %"95_16" = load { i32, {}, {} }, { i32, {}, {} }* %"95_1", align 4 + store { {} } %"97_05", { {} }* %"97_0", align 1 + store { i32, {}, {} } %"95_16", { i32, {}, {} }* %"95_1", align 4 + %"95_07" = load i32, i32* %"95_0", align 4 + call void @___qfree.11(i32 %"95_07") + %"97_08" = load { {} }, { {} }* %"97_0", align 1 + %"95_19" = load { i32, {}, {} }, { i32, {}, {} }* %"95_1", align 4 + switch i32 0, label %0 [ + ] + +6: ; preds = %0 + %"010" = load { i32, {}, {} }, { i32, {}, {} }* %"01", align 4 + store { i32, {}, {} } %"010", { i32, {}, {} }* %"90_0", align 4 + %"90_011" = load { i32, {}, {} }, { i32, {}, {} }* %"90_0", align 4 + store { i32, {}, {} } %"90_011", { i32, {}, {} }* %"0", align 4 + %"012" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 + ret { i32, {}, {} } %"012" +} + +declare i32 @___qalloc.9() + +declare { i32, { i32, {}, {} } } @___measure.10(i32) + +declare void @___qfree.11(i32) + + +----- stderr ----- +HUGR valid! diff --git a/tests/snapshots/guppy__planqc3@llvm14.opt.snap b/tests/snapshots/guppy__planqc3@llvm14.opt.snap new file mode 100644 index 0000000..631eb42 --- /dev/null +++ b/tests/snapshots/guppy__planqc3@llvm14.opt.snap @@ -0,0 +1,184 @@ +--- +source: tests/guppy.rs +info: + program: hugr-llvm + args: + - "-" +--- +success: true +exit_code: 0 +----- stdout ----- +; ModuleID = 'module' +source_filename = "module" + +define i32 @_hl.rus.35(i32 %0, i64 %1) { +alloca_block: + %2 = extractvalue { {} } undef, 0 + br label %cond_exit_43 + +3: ; preds = %cond_exit_43 + %4 = extractvalue { i32, {}, { i64, i64 } } %"021.0", 1 + br label %56 + +5: ; preds = %cond_exit_43 + %6 = extractvalue { i32, {}, { i64, i64 } } %"021.0", 2 + %7 = extractvalue { i64, i64 } %6, 0 + %8 = extractvalue { i64, i64 } %6, 1 + %qalloc_call = call i32 @___qalloc() + %h_call = call i32 @___h(i32 %qalloc_call) + %qalloc_call35 = call i32 @___qalloc.1() + %h_call37 = call i32 @___h.2(i32 %qalloc_call35) + %9 = insertvalue { i32, i32 } undef, i32 %h_call37, 0 + %10 = insertvalue { i32, i32 } %9, i32 %h_call, 1 + %11 = insertvalue { { i32, i32 } } poison, { i32, i32 } %10, 0 + %12 = extractvalue { { i32, i32 } } %11, 0 + %13 = extractvalue { i32, i32 } %12, 0 + %14 = extractvalue { i32, i32 } %12, 1 + %tdg_call = call i32 @___tdg(i32 %13) + %rz_call = call { i32, i32 } @___cx(i32 %14, i32 %tdg_call) + %15 = extractvalue { i32, i32 } %rz_call, 0 + %16 = extractvalue { i32, i32 } %rz_call, 1 + %17 = insertvalue { i32, i32 } undef, i32 %15, 0 + %18 = insertvalue { i32, i32 } %17, i32 %16, 1 + %19 = insertvalue { { i32, i32 } } poison, { i32, i32 } %18, 0 + %20 = extractvalue { { i32, i32 } } %19, 0 + %21 = extractvalue { i32, i32 } %20, 0 + %22 = extractvalue { i32, i32 } %20, 1 + %t_call = call i32 @___t(i32 %22) + %measure_call = call { i32, { i32, {}, {} } } @___measure(i32 %t_call) + %23 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %24 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + call void @___qfree(i32 %23) + %25 = extractvalue { i32, {}, {} } %24, 0 + %cond129 = icmp eq i32 %25, 1 + br i1 %cond129, label %cond_exit_73, label %35 + +cond_exit_43: ; preds = %58, %35, %alloca_block + %"7_2.0" = phi i32 [ %0, %alloca_block ], [ %"7_2.0", %35 ], [ %x_call, %58 ] + %"7_1.0" = phi i64 [ %1, %alloca_block ], [ %8, %35 ], [ %61, %58 ] + %"7_0.0" = phi i64 [ 0, %alloca_block ], [ %7, %35 ], [ %62, %58 ] + %26 = icmp slt i64 %"7_0.0", %"7_1.0" + %27 = select i1 %26, { i32, {}, {} } { i32 1, {} poison, {} undef }, { i32, {}, {} } { i32 0, {} undef, {} poison } + %28 = extractvalue { i32, {}, {} } %27, 0 + %29 = extractvalue { i32, {}, {} } %27, 1 + %30 = extractvalue { i32, {}, {} } %27, 2 + %cond = icmp eq i32 %28, 1 + %31 = insertvalue { i64, i64 } undef, i64 %"7_0.0", 0 + %32 = insertvalue { i64, i64 } %31, i64 %"7_1.0", 1 + %33 = insertvalue { i32, {}, { i64, i64 } } { i32 1, {} poison, { i64, i64 } poison }, { i64, i64 } %32, 2 + %"021.0" = select i1 %cond, { i32, {}, { i64, i64 } } %33, { i32, {}, { i64, i64 } } { i32 0, {} undef, { i64, i64 } poison } + %34 = extractvalue { i32, {}, { i64, i64 } } %"021.0", 0 + %cond128 = icmp eq i32 %34, 1 + br i1 %cond128, label %5, label %3 + +35: ; preds = %5 + %36 = extractvalue { i32, {}, {} } %24, 1 + call void @___qfree.8(i32 %21) + %37 = extractvalue { {} } undef, 0 + br label %cond_exit_43 + +cond_exit_73: ; preds = %5 + %38 = extractvalue { i32, {}, {} } %24, 2 + %t_call70 = call i32 @___t.3(i32 %"7_2.0") + %z_call = call i32 @___z(i32 %t_call70) + %rz_call74 = call { i32, i32 } @___cx.4(i32 %z_call, i32 %21) + %39 = extractvalue { i32, i32 } %rz_call74, 0 + %40 = extractvalue { i32, i32 } %rz_call74, 1 + %41 = insertvalue { i32, i32 } undef, i32 %39, 0 + %42 = insertvalue { i32, i32 } %41, i32 %40, 1 + %43 = insertvalue { { i32, i32 } } poison, { i32, i32 } %42, 0 + %44 = extractvalue { { i32, i32 } } %43, 0 + %45 = extractvalue { i32, i32 } %44, 0 + %46 = extractvalue { i32, i32 } %44, 1 + %t_call79 = call i32 @___t.5(i32 %46) + %measure_call81 = call { i32, { i32, {}, {} } } @___measure.6(i32 %t_call79) + %47 = extractvalue { i32, { i32, {}, {} } } %measure_call81, 0 + %48 = extractvalue { i32, { i32, {}, {} } } %measure_call81, 1 + %49 = extractvalue { i32, {}, {} } %48, 0 + %50 = extractvalue { i32, {}, {} } %48, 1 + %51 = extractvalue { i32, {}, {} } %48, 2 + %cond130 = icmp eq i32 %49, 1 + %52 = insertvalue { i64, i64 } undef, i64 %7, 0 + %53 = insertvalue { i64, i64 } %52, i64 %8, 1 + %54 = insertvalue { i32, { i64, i64 }, {} } { i32 0, { i64, i64 } poison, {} poison }, { i64, i64 } %53, 1 + %"083.0" = select i1 %cond130, { i32, { i64, i64 }, {} } { i32 1, { i64, i64 } poison, {} undef }, { i32, { i64, i64 }, {} } %54 + call void @___qfree.7(i32 %47) + %55 = extractvalue { i32, { i64, i64 }, {} } %"083.0", 0 + %cond131 = icmp eq i32 %55, 1 + br i1 %cond131, label %64, label %58 + +56: ; preds = %64, %3 + %"11_0.0" = phi i32 [ %"7_2.0", %3 ], [ %45, %64 ] + %57 = extractvalue { {} } undef, 0 + ret i32 %"11_0.0" + +58: ; preds = %cond_exit_73 + %59 = extractvalue { i32, { i64, i64 }, {} } %"083.0", 1 + %60 = extractvalue { i64, i64 } %59, 0 + %61 = extractvalue { i64, i64 } %59, 1 + %x_call = call i32 @___x(i32 %45) + %62 = add i64 %60, 1 + %63 = extractvalue { {} } undef, 0 + br label %cond_exit_43 + +64: ; preds = %cond_exit_73 + %65 = extractvalue { i32, { i64, i64 }, {} } %"083.0", 2 + %66 = extractvalue { {} } undef, 0 + br label %56 +} + +declare i32 @___qalloc() + +declare i32 @___h(i32) + +declare i32 @___qalloc.1() + +declare i32 @___h.2(i32) + +declare i32 @___tdg(i32) + +declare { i32, i32 } @___cx(i32, i32) + +declare i32 @___t(i32) + +declare { i32, { i32, {}, {} } } @___measure(i32) + +declare void @___qfree(i32) + +declare i32 @___t.3(i32) + +declare i32 @___z(i32) + +declare { i32, i32 } @___cx.4(i32, i32) + +declare i32 @___t.5(i32) + +declare { i32, { i32, {}, {} } } @___measure.6(i32) + +declare void @___qfree.7(i32) + +declare void @___qfree.8(i32) + +declare i32 @___x(i32) + +define { i32, {}, {} } @_hl.main.36() { +alloca_block: + %qalloc_call = call i32 @___qalloc.9() + %0 = call i32 @_hl.rus.35(i32 %qalloc_call, i64 100) + %measure_call = call { i32, { i32, {}, {} } } @___measure.10(i32 %0) + %1 = extractvalue { i32, { i32, {}, {} } } %measure_call, 0 + %2 = extractvalue { i32, { i32, {}, {} } } %measure_call, 1 + call void @___qfree.11(i32 %1) + %3 = extractvalue { {} } undef, 0 + ret { i32, {}, {} } %2 +} + +declare i32 @___qalloc.9() + +declare { i32, { i32, {}, {} } } @___measure.10(i32) + +declare void @___qfree.11(i32) + + +----- stderr ----- +HUGR valid!