diff --git a/Cargo.lock b/Cargo.lock index 620864b458..d7170e7c42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,6 +167,24 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "arc-swap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" +dependencies = [ + "rustversion", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -253,12 +271,30 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + [[package]] name = "block" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block2" version = "0.5.1" @@ -297,7 +333,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -429,6 +465,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chrono" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +dependencies = [ + "num-traits", +] + [[package]] name = "clap" version = "4.5.53" @@ -457,10 +502,10 @@ version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -670,6 +715,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -679,6 +733,28 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -698,6 +774,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -710,12 +795,68 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + [[package]] name = "cursor-icon" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -726,7 +867,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 2.0.111", ] [[package]] @@ -775,6 +916,16 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -810,7 +961,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -831,6 +982,21 @@ dependencies = [ "litrs", ] +[[package]] +name = "dot-generator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aaac7ada45f71873ebce336491d1c1bc4a7c8042c7cea978168ad59e805b871" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "dot-structures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cfcded997a93eb31edd639361fa33fd229a8784e953b37d71035fe3890b7b" + [[package]] name = "downcast-rs" version = "1.2.1" @@ -843,6 +1009,171 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "egglog" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "chrono", + "clap", + "csv", + "dyn-clone", + "egglog-add-primitive", + "egglog-ast", + "egglog-bridge", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egraph-serialize", + "env_logger", + "hashbrown 0.16.1", + "im-rc", + "indexmap 2.12.1", + "log", + "mimalloc", + "num", + "ordered-float 5.1.0", + "rayon", + "rustc-hash 2.1.1", + "serde_json", + "thiserror 2.0.17", + "web-time", +] + +[[package]] +name = "egglog-add-primitive" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "quote", + "syn 2.0.111", +] + +[[package]] +name = "egglog-ast" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "ordered-float 5.1.0", +] + +[[package]] +name = "egglog-bridge" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "anyhow", + "dyn-clone", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "hashbrown 0.16.1", + "indexmap 2.12.1", + "log", + "num-rational", + "once_cell", + "ordered-float 5.1.0", + "petgraph", + "rayon", + "smallvec", + "thiserror 2.0.17", + "web-time", +] + +[[package]] +name = "egglog-concurrency" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "arc-swap", + "egglog-numeric-id", + "rayon", + "smallvec", +] + +[[package]] +name = "egglog-core-relations" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "anyhow", + "bumpalo", + "crossbeam", + "crossbeam-queue", + "dashmap", + "dyn-clone", + "egglog-concurrency", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "fixedbitset", + "hashbrown 0.16.1", + "indexmap 2.12.1", + "log", + "num", + "once_cell", + "petgraph", + "rand 0.9.2", + "rayon", + "rustc-hash 2.1.1", + "smallvec", + "thiserror 2.0.17", + "web-time", +] + +[[package]] +name = "egglog-numeric-id" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "rayon", +] + +[[package]] +name = "egglog-reports" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "clap", + "hashbrown 0.16.1", + "indexmap 2.12.1", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "web-time", +] + +[[package]] +name = "egglog-union-find" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git#57fdb7dfa7bef87d057a98ed691df87e0b8fdeb2" +dependencies = [ + "crossbeam", + "egglog-concurrency", + "egglog-numeric-id", +] + +[[package]] +name = "egraph-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0977732fb537ace6f8c15ce160ebdda78b6502b4866d3b904e4fe752e2be4702" +dependencies = [ + "graphviz-rust", + "indexmap 2.12.1", + "once_cell", + "ordered-float 5.1.0", + "serde", + "serde_json", +] + [[package]] name = "either" version = "1.15.0" @@ -906,7 +1237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1052,7 +1383,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1135,7 +1466,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1168,6 +1499,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gethostname" version = "1.1.0" @@ -1325,6 +1666,22 @@ dependencies = [ "bitflags 2.10.0", ] +[[package]] +name = "graphviz-rust" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db134cb611668917cabf340af9a39518426f9a10827b4cedcb4cdcf84443f6d0" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "into-attr-derive", + "pest", + "pest_derive", + "rand 0.9.2", + "tempfile", +] + [[package]] name = "half" version = "2.7.1" @@ -1343,6 +1700,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.15.5" @@ -1361,9 +1724,19 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "allocator-api2", + "equivalent", "foldhash 0.2.0", + "serde", + "serde_core", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -1493,6 +1866,20 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "im-rc" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1553,6 +1940,28 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" +[[package]] +name = "into-attr" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b48c537e49a709e678caec3753a7dba6854661a1eaa27675024283b3f8b376" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "into-attr-derive" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecac7c1ae6cd2c6a3a64d1061a8bdc7f52ff62c26a831a2301e54c1b5d70d5b1" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "quote", + "syn 1.0.109", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1604,7 +2013,7 @@ checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1726,6 +2135,16 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libmimalloc-sys" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libredox" version = "0.1.11" @@ -1839,6 +2258,15 @@ dependencies = [ "paste", ] +[[package]] +name = "mimalloc" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8" +dependencies = [ + "libmimalloc-sys", +] + [[package]] name = "minifb" version = "0.28.0" @@ -1935,7 +2363,7 @@ dependencies = [ "num-traits", "once_cell", "petgraph", - "rustc-hash", + "rustc-hash 1.1.0", "spirv", "thiserror 2.0.17", "unicode-ident", @@ -2014,7 +2442,71 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", ] [[package]] @@ -2056,7 +2548,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2338,6 +2830,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" dependencies = [ "num-traits", + "rand 0.8.5", + "serde", ] [[package]] @@ -2395,6 +2889,49 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "pest_meta" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" +dependencies = [ + "pest", + "sha2", +] + [[package]] name = "petgraph" version = "0.8.3" @@ -2404,6 +2941,7 @@ dependencies = [ "fixedbitset", "hashbrown 0.15.5", "indexmap 2.12.1", + "serde", ] [[package]] @@ -2429,7 +2967,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2488,6 +3026,15 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "presser" version = "0.3.1" @@ -2552,6 +3099,63 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "serde", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "range-alloc" version = "0.1.4" @@ -2690,11 +3294,10 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "rspirv" -version = "0.12.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d" +version = "0.12.0+sdk-1.4.335.0" +source = "git+https://github.com/gfx-rs/rspirv?branch=sdk-update#6a8d3db93205311ffb156793727df8f348bd3099" dependencies = [ - "rustc-hash", + "rustc-hash 1.1.0", "spirv", ] @@ -2717,6 +3320,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_codegen_spirv" version = "0.9.0" @@ -2804,7 +3413,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -2953,7 +3562,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2962,6 +3571,7 @@ version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ + "indexmap 2.12.1", "itoa", "memchr", "ryu", @@ -2987,6 +3597,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -3024,6 +3645,16 @@ dependencies = [ "spirv-std", ] +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + [[package]] name = "sky-shader" version = "0.0.0" @@ -3105,7 +3736,7 @@ dependencies = [ "itertools 0.10.5", "lazy_static", "longest-increasing-subsequence", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "serde_json", "smallvec", @@ -3113,9 +3744,8 @@ dependencies = [ [[package]] name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +version = "0.3.0+sdk-1.4.335.0" +source = "git+https://github.com/gfx-rs/rspirv?branch=sdk-update#6a8d3db93205311ffb156793727df8f348bd3099" dependencies = [ "bitflags 2.10.0", "serde", @@ -3159,7 +3789,7 @@ dependencies = [ "proc-macro2", "quote", "spirv-std-types", - "syn", + "syn 2.0.111", ] [[package]] @@ -3168,22 +3798,41 @@ version = "0.9.0" [[package]] name = "spirv-tools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "863f14733a4ecb68c0bde9ea9b93bc58085a4172e76c8cefe7c810c940f02131" +version = "0.1.0" +source = "git+https://github.com/Rust-GPU/SPIRV-Tools#e0e30b37ecd011ad25142444eba9925f312aecd7" dependencies = [ - "memchr", - "spirv-tools-sys", - "tempfile", + "rspirv", + "spirv-tools-core", + "spirv-tools-opt", ] [[package]] -name = "spirv-tools-sys" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219df977b2dd5a34a3529a7f7d2be12727abd87e4545abd0d54edd4fa2cfe5a8" +name = "spirv-tools-core" +version = "0.1.0" +source = "git+https://github.com/Rust-GPU/SPIRV-Tools#e0e30b37ecd011ad25142444eba9925f312aecd7" dependencies = [ - "cc", + "bitflags 2.10.0", + "heck 0.4.1", + "libc", + "once_cell", + "rspirv", + "serde", + "serde_json", + "spirv", + "thiserror 1.0.69", +] + +[[package]] +name = "spirv-tools-opt" +version = "0.1.0" +source = "git+https://github.com/Rust-GPU/SPIRV-Tools#e0e30b37ecd011ad25142444eba9925f312aecd7" +dependencies = [ + "arbitrary", + "clap", + "egglog", + "rspirv", + "spirv-tools-core", + "thiserror 1.0.69", ] [[package]] @@ -3225,10 +3874,21 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn", + "syn 2.0.111", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] @@ -3250,7 +3910,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3273,7 +3933,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix 1.1.2", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3344,7 +4004,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3355,7 +4015,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3517,7 +4177,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3606,6 +4266,18 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "unicode-ident" version = "1.0.22" @@ -3705,10 +4377,10 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ef06db404cbaed87cb25fd2ca3a62502af485f43383c9641ffcf1479d02fffd" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3791,7 +4463,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.111", "wasm-bindgen-shared", ] @@ -4089,7 +4761,7 @@ dependencies = [ "portable-atomic", "profiling", "raw-window-handle 0.6.2", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", "thiserror 2.0.17", "wgpu-core-deps-apple", @@ -4211,7 +4883,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4251,7 +4923,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -4262,7 +4934,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -4683,7 +5355,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", "synstructure", ] @@ -4704,7 +5376,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -4724,7 +5396,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", "synstructure", ] @@ -4758,5 +5430,5 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] diff --git a/Cargo.toml b/Cargo.toml index 1eb4422bb0..be9f4df1ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ spirv-builder = { path = "./crates/spirv-builder", version = "=0.9.0", default-f spirv-std = { path = "./crates/spirv-std", version = "=0.9.0" } spirv-std-types = { path = "./crates/spirv-std/shared", version = "=0.9.0" } spirv-std-macros = { path = "./crates/spirv-std/macros", version = "=0.9.0" } -spirv-tools = { version = "0.13.0", default-features = false } +spirv-tools = { git = "https://github.com/Rust-GPU/SPIRV-Tools", default-features = false } rustc_codegen_spirv = { path = "./crates/rustc_codegen_spirv", version = "=0.9.0", default-features = false } rustc_codegen_spirv-types = { path = "./crates/rustc_codegen_spirv-types", version = "=0.9.0" } @@ -61,6 +61,12 @@ glam = { version = ">=0.30.8", default-features = false } libm = { version = "0.2.5", default-features = false } bytemuck = { version = "1.23", features = ["derive"] } +# Patch rspirv/spirv to use newer versions with additional SPIR-V opcodes needed by spirv-tools. +# TODO: Once a newer rspirv is published that includes these opcodes, switch to a crates.io version. +[patch.crates-io] +rspirv = { git = "https://github.com/gfx-rs/rspirv", branch = "sdk-update" } +spirv = { git = "https://github.com/gfx-rs/rspirv", branch = "sdk-update", package = "spirv" } + # Enable incremental by default in release mode. [profile.release] incremental = true diff --git a/crates/rustc_codegen_spirv/Cargo.toml b/crates/rustc_codegen_spirv/Cargo.toml index 2357ae1f7f..b0e6907c39 100644 --- a/crates/rustc_codegen_spirv/Cargo.toml +++ b/crates/rustc_codegen_spirv/Cargo.toml @@ -12,20 +12,11 @@ repository.workspace = true crate-type = ["dylib"] [features] -# By default, the use-compiled-tools is enabled, as doesn't require additional -# setup steps for the user. This does however mean that you will need to disable -# default features and explicitly enable `use-installed-tools` if you are using -# this in an environment with spirv-tools in PATH, and you don't want to take -# the compile time cost -default = ["use-compiled-tools"] -# If enabled, uses spirv-tools binaries installed in PATH, instead of -# compiling and linking the spirv-tools C++ code -use-installed-tools = ["spirv-tools/use-installed-tools"] -# If enabled will compile and link the C++ code for the spirv tools, the compiled -# version is preferred if both this and `use-installed-tools` are enabled -use-compiled-tools = ["spirv-tools/use-compiled-tools"] +# These features are no-ops kept for compatibility with existing build configurations. +use-installed-tools = [] +use-compiled-tools = [] # If enabled, this will not check whether the current rustc version is set to the -# appropriate channel. rustc_cogeden_spirv requires a specific nightly version, +# appropriate channel. rustc_codegen_spirv requires a specific nightly version, # and will likely produce compile errors when built against a different toolchain. # Enable this feature to be able to experiment with other versions. skip-toolchain-check = [] diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 840a206174..82c79b0bcf 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -341,7 +341,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn ordering_to_semantics_def(&mut self, ordering: AtomicOrdering) -> SpirvValue { let mut invalid_seq_cst = false; let semantics = match ordering { - AtomicOrdering::Relaxed => MemorySemantics::NONE, + AtomicOrdering::Relaxed => MemorySemantics::RELAXED, AtomicOrdering::Acquire => MemorySemantics::MAKE_VISIBLE | MemorySemantics::ACQUIRE, AtomicOrdering::Release => MemorySemantics::MAKE_AVAILABLE | MemorySemantics::RELEASE, AtomicOrdering::AcqRel => { diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index 894c5a8d02..b06a52186e 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -32,9 +32,23 @@ pub struct InstructionTable { impl InstructionTable { pub fn new() -> Self { - let table = rspirv::grammar::CoreInstructionTable::iter() + let mut table: FxHashMap<_, _> = rspirv::grammar::CoreInstructionTable::iter() .map(|inst| (inst.opname, inst)) .collect(); + + // Add aliases for EXT/KHR instructions whose suffixes were removed + for inst in rspirv::grammar::CoreInstructionTable::iter() { + match inst.opname { + "DemoteToHelperInvocation" => { + table.insert("DemoteToHelperInvocationEXT", inst); + } + "IsHelperInvocation" => { + table.insert("IsHelperInvocationEXT", inst); + } + _ => {} + } + } + Self { table } } } @@ -1529,6 +1543,38 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { Ok(x) => inst.operands.push(dr::Operand::StoreCacheControl(x)), Err(()) => self.err(format!("unknown StoreCacheControl {word}")), }, + // New operand kinds added in newer SPIR-V versions - not yet supported in inline asm + (OperandKind::RawAccessChainOperands, Some(word)) => { + self.err(format!("RawAccessChainOperands not yet supported: {word}")); + } + (OperandKind::CooperativeMatrixReduce, Some(word)) => { + self.err(format!("CooperativeMatrixReduce not yet supported: {word}")); + } + (OperandKind::TensorClampMode, Some(word)) => { + self.err(format!("TensorClampMode not yet supported: {word}")); + } + (OperandKind::TensorAddressingOperands, Some(word)) => { + self.err(format!( + "TensorAddressingOperands not yet supported: {word}" + )); + } + (OperandKind::FPEncoding, Some(word)) => { + self.err(format!("FPEncoding not yet supported: {word}")); + } + (OperandKind::NamedMaximumNumberOfRegisters, Some(word)) => { + self.err(format!( + "NamedMaximumNumberOfRegisters not yet supported: {word}" + )); + } + (OperandKind::MatrixMultiplyAccumulateOperands, Some(word)) => { + self.err(format!( + "MatrixMultiplyAccumulateOperands not yet supported: {word}" + )); + } + // Catch-all for any other new operand kinds + (kind, Some(word)) => { + self.err(format!("unsupported operand kind {kind:?}: {word}")); + } (kind, None) => match token { Token::Word(_) => bug!(), Token::String(_) => { @@ -1563,16 +1609,13 @@ pub const IMAGE_OPERANDS: &[(&str, ImageOperands)] = &[ ("Sample", ImageOperands::SAMPLE), ("MinLod", ImageOperands::MIN_LOD), ("MakeTexelAvailable", ImageOperands::MAKE_TEXEL_AVAILABLE), - ( - "MakeTexelAvailableKHR", - ImageOperands::MAKE_TEXEL_AVAILABLE_KHR, - ), + ("MakeTexelAvailableKHR", ImageOperands::MAKE_TEXEL_AVAILABLE), ("MakeTexelVisible", ImageOperands::MAKE_TEXEL_VISIBLE), - ("MakeTexelVisibleKHR", ImageOperands::MAKE_TEXEL_VISIBLE_KHR), + ("MakeTexelVisibleKHR", ImageOperands::MAKE_TEXEL_VISIBLE), ("NonPrivateTexel", ImageOperands::NON_PRIVATE_TEXEL), - ("NonPrivateTexelKHR", ImageOperands::NON_PRIVATE_TEXEL_KHR), + ("NonPrivateTexelKHR", ImageOperands::NON_PRIVATE_TEXEL), ("VolatileTexel", ImageOperands::VOLATILE_TEXEL), - ("VolatileTexelKHR", ImageOperands::VOLATILE_TEXEL_KHR), + ("VolatileTexelKHR", ImageOperands::VOLATILE_TEXEL), ("SignExtend", ImageOperands::SIGN_EXTEND), ("ZeroExtend", ImageOperands::ZERO_EXTEND), ]; @@ -1610,7 +1653,7 @@ pub const FUNCTION_CONTROL: &[(&str, FunctionControl)] = &[ ]; pub const MEMORY_SEMANTICS: &[(&str, MemorySemantics)] = &[ ("Relaxed", MemorySemantics::RELAXED), - ("None", MemorySemantics::NONE), + ("None", MemorySemantics::RELAXED), ("Acquire", MemorySemantics::ACQUIRE), ("Release", MemorySemantics::RELEASE), ("AcquireRelease", MemorySemantics::ACQUIRE_RELEASE), @@ -1631,11 +1674,11 @@ pub const MEMORY_SEMANTICS: &[(&str, MemorySemantics)] = &[ ), ("ImageMemory", MemorySemantics::IMAGE_MEMORY), ("OutputMemory", MemorySemantics::OUTPUT_MEMORY), - ("OutputMemoryKHR", MemorySemantics::OUTPUT_MEMORY_KHR), + ("OutputMemoryKHR", MemorySemantics::OUTPUT_MEMORY), ("MakeAvailable", MemorySemantics::MAKE_AVAILABLE), - ("MakeAvailableKHR", MemorySemantics::MAKE_AVAILABLE_KHR), + ("MakeAvailableKHR", MemorySemantics::MAKE_AVAILABLE), ("MakeVisible", MemorySemantics::MAKE_VISIBLE), - ("MakeVisibleKHR", MemorySemantics::MAKE_VISIBLE_KHR), + ("MakeVisibleKHR", MemorySemantics::MAKE_VISIBLE), ("Volatile", MemorySemantics::VOLATILE), ]; pub const MEMORY_ACCESS: &[(&str, MemoryAccess)] = &[ @@ -1646,18 +1689,12 @@ pub const MEMORY_ACCESS: &[(&str, MemoryAccess)] = &[ ("MakePointerAvailable", MemoryAccess::MAKE_POINTER_AVAILABLE), ( "MakePointerAvailableKHR", - MemoryAccess::MAKE_POINTER_AVAILABLE_KHR, + MemoryAccess::MAKE_POINTER_AVAILABLE, ), ("MakePointerVisible", MemoryAccess::MAKE_POINTER_VISIBLE), - ( - "MakePointerVisibleKHR", - MemoryAccess::MAKE_POINTER_VISIBLE_KHR, - ), + ("MakePointerVisibleKHR", MemoryAccess::MAKE_POINTER_VISIBLE), ("NonPrivatePointer", MemoryAccess::NON_PRIVATE_POINTER), - ( - "NonPrivatePointerKHR", - MemoryAccess::NON_PRIVATE_POINTER_KHR, - ), + ("NonPrivatePointerKHR", MemoryAccess::NON_PRIVATE_POINTER), ]; pub const KERNEL_PROFILING_INFO: &[(&str, KernelProfilingInfo)] = &[ ("None", KernelProfilingInfo::NONE), diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs index e78175785e..720bf0ba81 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -6,6 +6,7 @@ use crate::abi::ConvSpirvType; use crate::attr::{AggregatedSpirvAttributes, Entry, Spanned, SpecConstant}; use crate::builder::Builder; use crate::builder_spirv::{SpirvFunctionCursor, SpirvValue, SpirvValueExt}; +use crate::custom_decorations::{CustomDecoration, SrcLocDecoration}; use crate::spirv_type::SpirvType; use rspirv::dr::Operand; use rspirv::spirv::{ @@ -988,6 +989,14 @@ impl<'tcx> CodegenCx<'tcx> { self.emit_global() .variable(var_ptr_spirv_type, Some(var), storage_class, None); + // Add SrcLocDecoration to the variable for rich error messages. + let src_loc_inst = SrcLocDecoration::from_rustc_span(hir_param.span, &self.builder) + .map(|src_loc| src_loc.encode_to_inst(var)); + self.emit_global() + .module_mut() + .annotations + .extend(src_loc_inst); + // Record this `OpVariable` as needing to be added (if applicable), // to the *Interface* operands of the `OpEntryPoint` instruction. if self.emit_global().version().unwrap() > (1, 3) { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index d36e789b1c..3fefc0ed12 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -313,6 +313,10 @@ pub struct CodegenArgs { pub run_spirv_opt: bool, + /// Preserve internal debug decorations (SrcLocDecoration, ZombieDecoration) in the output. + /// These are normally stripped after validation. Enable for debugging or testing. + pub preserve_debug_decorations: bool, + /// All options pertinent to `rustc_codegen_spirv::linker` specifically. // // FIXME(eddyb) should these be handled as `-C linker-args="..."` instead? @@ -384,6 +388,12 @@ impl CodegenArgs { "disables running spirv-opt on the final output", ); + opts.optflag( + "", + "preserve-debug-decorations", + "preserve internal debug decorations (SrcLocDecoration, ZombieDecoration) in the output", + ); + opts.optflag( "", "preserve-bindings", @@ -652,6 +662,8 @@ impl CodegenArgs { run_spirv_opt, + preserve_debug_decorations: matches.opt_present("preserve-debug-decorations"), + linker_opts, // NOTE(eddyb) these are debugging options that used to be env vars diff --git a/crates/rustc_codegen_spirv/src/custom_decorations.rs b/crates/rustc_codegen_spirv/src/custom_decorations.rs index 1027df9aed..c8efd57c95 100644 --- a/crates/rustc_codegen_spirv/src/custom_decorations.rs +++ b/crates/rustc_codegen_spirv/src/custom_decorations.rs @@ -18,7 +18,7 @@ use std::{fmt, iter, slice, str}; /// Decorations not native to SPIR-V require some form of encoding into existing /// SPIR-V constructs, for which we use `OpDecorateString` with decoration type -/// `UserTypeGOOGLE` and some encoded Rust value as the decoration string. +/// `UserSemantic` and some encoded Rust value as the decoration string. /// /// Each decoration type has to implement this trait, and use a different /// `ENCODING_PREFIX` from any other decoration type, to disambiguate them. @@ -27,7 +27,10 @@ use std::{fmt, iter, slice, str}; /// ideally as soon as they're no longer needed, because no other tools /// processing the SPIR-V would understand them correctly. /// -/// TODO: uses `non_semantic` instead of piggybacking off of `UserTypeGOOGLE` +/// Custom decorations are encoded using `OpDecorateString` with `UserSemantic`, +/// which is a standard SPIR-V decoration that doesn't require any extension. +/// +/// TODO: consider using `non_semantic` instead for even cleaner separation /// pub trait CustomDecoration<'a>: Sized { const ENCODING_PREFIX: &'static str; @@ -45,7 +48,7 @@ pub trait CustomDecoration<'a>: Sized { None, vec![ Operand::IdRef(id), - Operand::Decoration(Decoration::UserTypeGOOGLE), + Operand::Decoration(Decoration::UserSemantic), Operand::LiteralString(encoded), ], ) @@ -53,7 +56,7 @@ pub trait CustomDecoration<'a>: Sized { fn try_decode_from_inst(inst: &Instruction) -> Option<(Word, LazilyDecoded<'_, Self>)> { if inst.class.opcode == Op::DecorateString - && inst.operands[1].unwrap_decoration() == Decoration::UserTypeGOOGLE + && inst.operands[1].unwrap_decoration() == Decoration::UserSemantic { let id = inst.operands[0].unwrap_id_ref(); let prefixed_encoded = inst.operands[2].unwrap_literal_string(); diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index 3e57d8648d..c844c818e3 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -138,6 +138,7 @@ mod spirv_type_constraints; mod symbols; mod target; mod target_feature; +mod validation_err; use builder::Builder; use codegen_cx::CodegenCx; diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index 038d307930..635764008f 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -253,8 +253,26 @@ fn post_link_single_module( out_filename: &Path, dump_prefix: Option<&OsStr>, ) { - cg_args.do_disassemble(&module); - let spv_binary = module.assemble(); + use crate::custom_decorations::{CustomDecoration, SrcLocDecoration, ZombieDecoration}; + + // Strip internal debug decorations (SrcLocDecoration, ZombieDecoration) BEFORE + // disassembly/validation/optimization unless preserve_debug_decorations is set. + // These decorations are only valid on certain targets (variables), but rust-gpu + // also places them on functions for span tracking which is invalid SPIR-V. + // Keep the original module for span lookup in error messages. + let (module_for_output, original_module_for_spans) = if cg_args.preserve_debug_decorations { + // When preserving decorations, use the same module for both + (module.clone(), module) + } else { + let mut stripped = module.clone(); + SrcLocDecoration::remove_all(&mut stripped); + ZombieDecoration::remove_all(&mut stripped); + (stripped, module) + }; + + // Disassemble the stripped module (unless preserving decorations) + cg_args.do_disassemble(&module_for_output); + let spv_binary = module_for_output.assemble(); if let Some(dir) = &cg_args.dump_post_link { // FIXME(eddyb) rename `filename` with `file_path` to make this less confusing. @@ -305,7 +323,13 @@ fn post_link_single_module( }; if cg_args.run_spirv_val { - do_spirv_val(sess, &spv_binary, out_filename, val_options); + do_spirv_val( + sess, + &spv_binary, + &original_module_for_spans, + out_filename, + val_options, + ); } { @@ -393,18 +417,20 @@ fn do_spirv_opt( fn do_spirv_val( sess: &Session, spv_binary: &[u32], + original_module_for_spans: &Module, filename: &Path, options: spirv_tools::val::ValidatorOptions, ) { + use crate::validation_err::ValidationErrorContext; use spirv_tools::val::{self, Validator}; let validator = val::create(sess.target.options.env.parse().ok()); if let Err(e) = validator.validate(spv_binary, Some(options)) { - let mut err = sess.dcx().struct_err(e.to_string()); - err.note("spirv-val failed"); - err.note(format!("module `{}`", filename.display())); - err.emit(); + // Use the ORIGINAL module (with SrcLocDecoration) to look up source spans + // Note: We validate the stripped binary, but look up spans in the original + let mut ctx = ValidationErrorContext::new(sess, Some(original_module_for_spans), filename); + ctx.emit_error(&e); } } diff --git a/crates/rustc_codegen_spirv/src/linker/inline.rs b/crates/rustc_codegen_spirv/src/linker/inline.rs index 0ab19bd40f..edb31c485d 100644 --- a/crates/rustc_codegen_spirv/src/linker/inline.rs +++ b/crates/rustc_codegen_spirv/src/linker/inline.rs @@ -298,8 +298,8 @@ impl LegalGlobal { let global = match inst.class.opcode { Op::TypePointer => Self::TypePointer(inst.operands[0].unwrap_storage_class()), Op::Variable => Self::Variable, - op if rspirv::grammar::reflect::is_type(op) => Self::TypeNonPointer, - op if rspirv::grammar::reflect::is_constant(op) => Self::Const, + op if op.is_type() => Self::TypeNonPointer, + op if op.is_constant() => Self::Const, // FIXME(eddyb) should this be `unreachable!()`? _ => continue, diff --git a/crates/rustc_codegen_spirv/src/linker/mod.rs b/crates/rustc_codegen_spirv/src/linker/mod.rs index b6e3b9a05f..eaed8e2143 100644 --- a/crates/rustc_codegen_spirv/src/linker/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/mod.rs @@ -19,7 +19,6 @@ mod zombies; use std::borrow::Cow; use crate::codegen_cx::{ModuleOutputType, SpirvMetadata}; -use crate::custom_decorations::{CustomDecoration, SrcLocDecoration, ZombieDecoration}; use crate::custom_insts; use either::Either; use rspirv::binary::Assemble; @@ -768,13 +767,10 @@ pub fn link( output.header.as_mut().unwrap().bound = simple_passes::compact_ids(output); }; - // FIXME(eddyb) convert these into actual `OpLine`s with a SPIR-T pass, - // but that'd require keeping the modules in SPIR-T form (once lowered), - // and never loading them back into `rspirv` once lifted back to SPIR-V. - SrcLocDecoration::remove_all(output); - - // FIXME(eddyb) might make more sense to rewrite these away on SPIR-T. - ZombieDecoration::remove_all(output); + // NOTE: We keep SrcLocDecoration and ZombieDecoration in the module + // so that they can be used for rich error messages during validation. + // These are encoded as OpDecorateString with UserSemantic, which is + // valid SPIR-V and should not cause validation failures. } Ok(output) diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs index 3951a7f8c0..11cdb6ccb8 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs @@ -128,7 +128,7 @@ fn try_decode_custom_decoration<'a, D: CustomDecoration<'a>>( }; let str_imms = spv_inst .imms - .strip_prefix(&[spv::Imm::Short(wk.Decoration, wk.UserTypeGOOGLE)])?; + .strip_prefix(&[spv::Imm::Short(wk.Decoration, wk.UserSemantic)])?; decode_spv_lit_str_with(str_imms, |prefixed_encoded| { let encoded = prefixed_encoded.strip_prefix(D::ENCODING_PREFIX)?; diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs index f41dc5aa4d..2f78875be4 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs @@ -113,7 +113,7 @@ def_spv_spec_with_extra_well_known! { MemoryAccess, ], decoration: u32 = [ - UserTypeGOOGLE, + UserSemantic, MatrixStride, ], storage_class: u32 = [ diff --git a/crates/rustc_codegen_spirv/src/spirv_type.rs b/crates/rustc_codegen_spirv/src/spirv_type.rs index 3213b13129..6bc31b27e7 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type.rs @@ -104,7 +104,7 @@ impl SpirvType<'_> { Self::Void => cx.emit_global().type_void_id(id), Self::Bool => cx.emit_global().type_bool_id(id), Self::Integer(width, signed) => cx.emit_global().type_int_id(id, width, signed as u32), - Self::Float(width) => cx.emit_global().type_float_id(id, width), + Self::Float(width) => cx.emit_global().type_float_id(id, width, None), Self::Adt { def_id: _, align: _, diff --git a/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs b/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs index c838fc4b54..9a60d50435 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs @@ -1096,9 +1096,9 @@ pub fn instruction_signatures(op: Op) -> Option<&'static [InstSig<'static>]> { | Op::ImageBlockMatchSSDQCOM | Op::ImageBlockMatchSADQCOM => reserved!(SPV_QCOM_image_processing), // SPV_AMDX_shader_enqueue - Op::FinalizeNodePayloadsAMDX + Op::EnqueueNodePayloadsAMDX | Op::FinishWritingNodePayloadAMDX - | Op::InitializeNodePayloadsAMDX => reserved!(SPV_AMDX_shader_enqueue), + | Op::AllocateNodePayloadsAMDX => reserved!(SPV_AMDX_shader_enqueue), // SPV_NV_displacement_micromap Op::FetchMicroTriangleVertexPositionNV | Op::FetchMicroTriangleVertexBarycentricNV => { reserved!(SPV_NV_displacement_micromap) @@ -1124,6 +1124,8 @@ pub fn instruction_signatures(op: Op) -> Option<&'static [InstSig<'static>]> { | Op::SpecConstantCompositeContinuedINTEL | Op::ControlBarrierArriveINTEL | Op::ControlBarrierWaitINTEL => reserved!(unknown_extension_INTEL), + // Catch-all for any new ops added in newer SPIR-V versions + _ => return None, } None diff --git a/crates/rustc_codegen_spirv/src/symbols.rs b/crates/rustc_codegen_spirv/src/symbols.rs index 7660f37b5a..3160e54bcc 100644 --- a/crates/rustc_codegen_spirv/src/symbols.rs +++ b/crates/rustc_codegen_spirv/src/symbols.rs @@ -271,10 +271,10 @@ const EXECUTION_MODES: &[(&str, ExecutionMode, ExecutionModeExtraDim)] = { ("rounding_mode_rte", RoundingModeRTE, Value), ("rounding_mode_rtz", RoundingModeRTZ, Value), ("stencil_ref_replacing_ext", StencilRefReplacingEXT, None), - ("output_lines_nv", OutputLinesNV, None), - ("output_primitives_nv", OutputPrimitivesNV, Value), - ("derivative_group_quads_nv", DerivativeGroupQuadsNV, None), - ("output_triangles_nv", OutputTrianglesNV, None), + ("output_lines_nv", OutputLinesEXT, None), + ("output_primitives_nv", OutputPrimitivesEXT, Value), + ("derivative_group_quads_nv", DerivativeGroupQuadsKHR, None), + ("output_triangles_nv", OutputTrianglesEXT, None), ("output_lines_ext", ExecutionMode::OutputLinesEXT, None), ( "output_triangles_ext", diff --git a/crates/rustc_codegen_spirv/src/validation_err.rs b/crates/rustc_codegen_spirv/src/validation_err.rs new file mode 100644 index 0000000000..6bf569d116 --- /dev/null +++ b/crates/rustc_codegen_spirv/src/validation_err.rs @@ -0,0 +1,590 @@ +//! Rich error reporting for SPIR-V validation errors. +//! +//! This module provides utilities for converting SPIR-V validation errors into +//! user-friendly rustc diagnostics with source spans and helpful hints. + +use std::path::Path; + +use rspirv::dr::Module; +use rspirv::spirv::{BuiltIn, Capability, Decoration, Op}; +use rustc_session::Session; +use spirv_tools::ValidationError; + +use crate::custom_decorations::SpanRegenerator; + +/// Context for generating rich validation error messages. +pub struct ValidationErrorContext<'a> { + sess: &'a Session, + module: Option<&'a Module>, + span_regen: Option>, + filename: &'a Path, +} + +impl<'a> ValidationErrorContext<'a> { + /// Creates a new validation error context. + pub fn new(sess: &'a Session, module: Option<&'a Module>, filename: &'a Path) -> Self { + let span_regen = module.map(|m| SpanRegenerator::new(sess.source_map(), m)); + Self { + sess, + module, + span_regen, + filename, + } + } + + /// Emits a rich diagnostic for the given validation error. + pub fn emit_error(&mut self, error: &spirv_tools::val::ValidatorError) { + match &error.validation_error { + ValidationError::EntryPointInterfaceLocationConflict { + first_var, + second_var, + location, + component, + storage_class, + .. + } => { + self.emit_location_conflict( + u32::from(*first_var), + u32::from(*second_var), + *location, + *component, + *storage_class, + ); + } + ValidationError::NotALogicalPointer { + instruction, + pointer, + source_opcode, + } => { + self.emit_not_a_logical_pointer(*instruction, u32::from(*pointer), *source_opcode); + } + ValidationError::MissingInstructionCapability { + opcode, + required_capability, + } => { + self.emit_missing_capability(*opcode, *required_capability, None); + } + ValidationError::MissingOperandCapability { + opcode, + operand_index, + required_capability, + } => { + self.emit_missing_capability(*opcode, *required_capability, Some(*operand_index)); + } + ValidationError::MissingDescriptorSetDecoration { variable } => { + self.emit_missing_decoration( + u32::from(*variable), + "DescriptorSet", + "#[spirv(descriptor_set = N)]", + ); + } + ValidationError::MissingBindingDecoration { variable } => { + self.emit_missing_decoration( + u32::from(*variable), + "Binding", + "#[spirv(binding = N)]", + ); + } + ValidationError::InvalidBlockLayout { + struct_type, + reason, + } => { + self.emit_invalid_block_layout(u32::from(*struct_type), reason); + } + ValidationError::InvalidBuiltInType { builtin, expected } => { + self.emit_invalid_builtin_type(*builtin, expected); + } + _ => { + // Fall back to generic error message + self.emit_generic_error(error); + } + } + } + + /// Emits a generic validation error without rich formatting. + fn emit_generic_error(&self, error: &spirv_tools::val::ValidatorError) { + let mut err = self.sess.dcx().struct_err(error.to_string()); + err.note(format!("module `{}`", self.filename.display())); + err.emit(); + } + + fn emit_location_conflict( + &mut self, + first_var_id: u32, + second_var_id: u32, + location: u32, + component: u32, + storage_class: rspirv::spirv::StorageClass, + ) { + let first_span = self.id_to_span(first_var_id); + let second_span = self.id_to_span(second_var_id); + + let first_name = self.get_name(first_var_id); + let second_name = self.get_name(second_var_id); + + let first_var_start_location = self.get_location_decoration(first_var_id); + let first_var_type_info = self.get_variable_type_info(first_var_id); + + let first_name_fallback = format!("%{}", first_var_id); + let second_name_fallback = format!("%{}", second_var_id); + let first_name_display = first_name.as_deref().unwrap_or(&first_name_fallback); + let second_name_display = second_name.as_deref().unwrap_or(&second_name_fallback); + + if let (Some(span1), Some(span2)) = (first_span, second_span) { + // Rich error with source spans + let mut err = self.sess.dcx().struct_span_err( + span2, + format!( + "{:?} variable `{}` at location {} conflicts with another variable", + storage_class, second_name_display, location + ), + ); + + err.span_note( + span1, + format!( + "variable `{}` already uses location {} component {}", + first_name_display, location, component + ), + ); + + // Add hint if the first variable spans multiple locations + if let Some(start_loc) = first_var_start_location { + if start_loc != location { + err.help(self.format_multi_location_hint( + first_name_display, + start_loc, + first_var_type_info.as_ref(), + )); + } + } + + err.note(format!("module `{}`", self.filename.display())); + err.emit(); + } else { + // Fall back to non-span error + let mut err = self.sess.dcx().struct_err(format!( + "{:?} variable `{}` at location {} conflicts with `{}`", + storage_class, second_name_display, location, first_name_display + )); + err.note(format!("module `{}`", self.filename.display())); + err.note(format!( + "variables `{}` and `{}` both use location {} component {}", + first_name_display, second_name_display, location, component + )); + err.emit(); + } + } + + fn emit_invalid_block_layout(&mut self, struct_type_id: u32, reason: &str) { + let span = self.id_to_span(struct_type_id); + let type_name = self.get_name(struct_type_id); + let type_name_fallback = format!("%{}", struct_type_id); + let type_name_display = type_name.as_deref().unwrap_or(&type_name_fallback); + + let message = format!( + "struct `{}` has invalid block layout: {}", + type_name_display, reason + ); + + let mut err = if let Some(span) = span { + self.sess.dcx().struct_span_err(span, message) + } else { + self.sess.dcx().struct_err(message) + }; + + err.help( + "ensure struct members are properly aligned according to std140/std430 layout rules", + ); + err.note(format!("module `{}`", self.filename.display())); + err.emit(); + } + + fn emit_invalid_builtin_type(&self, builtin: BuiltIn, expected: &str) { + let mut err = self.sess.dcx().struct_err(format!( + "BuiltIn {:?} has incorrect type, expected {}", + builtin, expected + )); + + err.help(format!( + "variables with `#[spirv(builtin = \"{:?}\")]` must have the correct type", + builtin + )); + err.note(format!("module `{}`", self.filename.display())); + err.emit(); + } + + fn emit_missing_decoration(&mut self, var_id: u32, decoration_name: &str, hint: &str) { + let span = self.id_to_span(var_id); + let var_name = self.get_name(var_id); + let var_name_fallback = format!("%{}", var_id); + let var_name_display = var_name.as_deref().unwrap_or(&var_name_fallback); + + let message = format!( + "resource variable `{}` is missing {} decoration", + var_name_display, decoration_name + ); + + let mut err = if let Some(span) = span { + self.sess.dcx().struct_span_err(span, message) + } else { + self.sess.dcx().struct_err(message) + }; + + err.help(format!("add `{}` to the variable", hint)); + err.note(format!("module `{}`", self.filename.display())); + err.emit(); + } + + fn emit_missing_capability( + &mut self, + opcode: Op, + capability: Capability, + operand_index: Option, + ) { + // Try to find an instruction with this opcode to get a span + let span = self.find_instruction_span_by_opcode(opcode); + + let message = if let Some(idx) = operand_index { + format!( + "operand {} of Op{:?} requires capability {:?}", + idx, opcode, capability + ) + } else { + format!("Op{:?} requires capability {:?}", opcode, capability) + }; + + let mut err = if let Some(span) = span { + self.sess.dcx().struct_span_err(span, message) + } else { + self.sess.dcx().struct_err(message) + }; + + err.help(format!( + "add `#[spirv(capability({:?}))]` to your entry point function", + capability + )); + err.note(format!("module `{}`", self.filename.display())); + err.emit(); + } + + fn emit_not_a_logical_pointer(&mut self, instruction: Op, pointer_id: u32, source_opcode: Op) { + // Try to find a useful span - first the pointer, then the instruction using it, + // then trace back through the def chain + let span = self.id_to_span(pointer_id).or_else(|| { + // Try to find the load/store instruction that uses this pointer + self.find_instruction_using_pointer(pointer_id, instruction) + .and_then(|inst_id| self.id_to_span(inst_id)) + }); + + let pointer_name = self.get_name(pointer_id); + let pointer_name_fallback = format!("%{}", pointer_id); + let pointer_name_display = pointer_name.as_deref().unwrap_or(&pointer_name_fallback); + + // Get SPIR-V context showing the relevant instructions + let spirv_context = self.get_spirv_context_for_pointer(pointer_id, source_opcode); + + let message = format!( + "Op{:?} cannot use pointer `{}` because it was produced by Op{:?}", + instruction, pointer_name_display, source_opcode + ); + + let mut err = if let Some(span) = span { + self.sess.dcx().struct_span_err(span, message) + } else { + self.sess.dcx().struct_err(message) + }; + + err.note(format!( + "in SPIR-V's logical addressing mode, pointers for Op{:?} must come from \ + specific instructions like OpVariable, OpAccessChain, or OpFunctionParameter", + instruction + )); + err.help(format!( + "Op{:?} cannot produce pointers valid for memory operations in logical addressing", + source_opcode + )); + + // Show SPIR-V context if available + if let Some(context) = spirv_context { + err.note(format!("generated SPIR-V:\n{}", context)); + } + + err.note(format!("module `{}`", self.filename.display())); + err.emit(); + } + + /// Finds the first instruction with the given opcode and returns its span. + fn find_instruction_span_by_opcode(&mut self, opcode: Op) -> Option { + let m = self.module?; + + // Search in functions first (most common case) + for func in &m.functions { + for block in &func.blocks { + for inst in &block.instructions { + if inst.class.opcode == opcode { + if let Some(id) = inst.result_id { + if let Some(span) = self.id_to_span(id) { + return Some(span); + } + } + } + } + } + } + + // Search in types/globals + for inst in &m.types_global_values { + if inst.class.opcode == opcode { + if let Some(id) = inst.result_id { + if let Some(span) = self.id_to_span(id) { + return Some(span); + } + } + } + } + + None + } + + /// Finds an instruction that uses the given pointer ID with the specified opcode. + fn find_instruction_using_pointer(&self, pointer_id: u32, opcode: Op) -> Option { + let m = self.module?; + for func in &m.functions { + for block in &func.blocks { + for inst in &block.instructions { + if inst.class.opcode == opcode { + // Check if any operand references our pointer + for operand in &inst.operands { + if let rspirv::dr::Operand::IdRef(id) = operand { + if *id == pointer_id { + return inst.result_id; + } + } + } + } + } + } + } + None + } + + /// Gets SPIR-V context showing the pointer-producing instruction and its use. + fn get_spirv_context_for_pointer(&self, pointer_id: u32, source_opcode: Op) -> Option { + let m = self.module?; + + // Find the instruction that produced the pointer + let mut context_lines = Vec::new(); + + for func in &m.functions { + for block in &func.blocks { + for inst in &block.instructions { + // Found the instruction that produced the pointer + if inst.result_id == Some(pointer_id) && inst.class.opcode == source_opcode { + context_lines.push(format!( + " %{} = Op{:?} ...", + pointer_id, source_opcode + )); + } + // Found instructions using the pointer + if matches!(inst.class.opcode, Op::Load | Op::Store) { + for operand in &inst.operands { + if let rspirv::dr::Operand::IdRef(id) = operand { + if *id == pointer_id { + let result = inst + .result_id + .map(|r| format!("%{} = ", r)) + .unwrap_or_default(); + context_lines.push(format!( + " -> {}Op{:?} %{} ...", + result, inst.class.opcode, pointer_id + )); + } + } + } + } + } + } + } + + if context_lines.is_empty() { + None + } else { + Some(context_lines.join("\n")) + } + } + + /// Looks up the rustc Span for a SPIR-V ID. + fn id_to_span(&mut self, id: u32) -> Option { + self.span_regen.as_mut().and_then(|sr| { + sr.src_loc_for_id(id) + .and_then(|src_loc| sr.src_loc_to_rustc(src_loc)) + }) + } + + /// Gets the name of a SPIR-V ID from OpName. + fn get_name(&self, id: u32) -> Option { + self.module.and_then(|m| { + m.debug_names.iter().find_map(|inst| { + if inst.class.opcode == Op::Name && inst.operands.first()?.unwrap_id_ref() == id { + Some(inst.operands.get(1)?.unwrap_literal_string().to_string()) + } else { + None + } + }) + }) + } + + /// Gets the Location decoration value for a variable. + fn get_location_decoration(&self, var_id: u32) -> Option { + self.module.and_then(|m| { + m.annotations.iter().find_map(|inst| { + if inst.class.opcode == Op::Decorate + && inst.operands.first()?.unwrap_id_ref() == var_id + && inst.operands.get(1)?.unwrap_decoration() == Decoration::Location + { + Some(inst.operands.get(2)?.unwrap_literal_bit32()) + } else { + None + } + }) + }) + } + + /// Gets type information for a variable (type name and location count). + fn get_variable_type_info(&self, var_id: u32) -> Option { + let m = self.module?; + + // Find the OpVariable + let var_inst = m + .types_global_values + .iter() + .find(|inst| inst.class.opcode == Op::Variable && inst.result_id == Some(var_id))?; + + // Get the pointer type, then the pointee type + let ptr_type_id = var_inst.result_type?; + let ptr_type = m + .types_global_values + .iter() + .find(|inst| inst.result_id == Some(ptr_type_id))?; + let pointee_type_id = ptr_type.operands.get(1)?.unwrap_id_ref(); + + // Look up the type name + let type_name = m.debug_names.iter().find_map(|inst| { + if inst.class.opcode == Op::Name + && inst.operands.first()?.unwrap_id_ref() == pointee_type_id + { + Some(inst.operands.get(1)?.unwrap_literal_string().to_string()) + } else { + None + } + }); + + // Compute location count + let location_count = Self::count_type_locations(m, pointee_type_id); + + Some(TypeInfo { + name: type_name, + location_count, + }) + } + + /// Counts the number of interface locations consumed by a type. + fn count_type_locations(m: &Module, type_id: u32) -> Option { + let type_inst = m + .types_global_values + .iter() + .find(|inst| inst.result_id == Some(type_id))?; + + match type_inst.class.opcode { + // Scalars and vectors use 1 location + Op::TypeBool | Op::TypeInt | Op::TypeFloat | Op::TypeVector => Some(1), + + // Matrices use 1 location per column + Op::TypeMatrix => { + let column_count = type_inst.operands.get(1)?.unwrap_literal_bit32(); + Some(column_count) + } + + // Arrays: element_locations * array_length + Op::TypeArray => { + let element_type_id = type_inst.operands.first()?.unwrap_id_ref(); + let length_id = type_inst.operands.get(1)?.unwrap_id_ref(); + let length_inst = m + .types_global_values + .iter() + .find(|inst| inst.result_id == Some(length_id))?; + let length = length_inst.operands.first()?.unwrap_literal_bit32(); + let element_locs = Self::count_type_locations(m, element_type_id)?; + Some(element_locs * length) + } + + // Structs: sum of member locations + Op::TypeStruct => { + let mut total = 0u32; + for operand in &type_inst.operands { + let member_type_id = operand.unwrap_id_ref(); + total += Self::count_type_locations(m, member_type_id)?; + } + Some(total) + } + + _ => None, + } + } + + fn format_multi_location_hint( + &self, + var_name: &str, + start_loc: u32, + type_info: Option<&TypeInfo>, + ) -> String { + let (type_name, location_count) = type_info + .map(|ti| (ti.name.as_deref(), ti.location_count)) + .unwrap_or((None, None)); + + match (type_name, location_count) { + (Some(name), Some(count)) => { + format!( + "`{}` is at location {} but type `{}` consumes {} locations ({}–{})", + var_name, + start_loc, + name, + count, + start_loc, + start_loc + count - 1 + ) + } + (Some(name), None) => { + format!( + "`{}` is at location {} but type `{}` consumes multiple locations", + var_name, start_loc, name + ) + } + (None, Some(count)) => { + format!( + "`{}` is at location {} but its type consumes {} locations ({}–{})", + var_name, + start_loc, + count, + start_loc, + start_loc + count - 1 + ) + } + (None, None) => { + format!( + "`{}` is at location {} but its type consumes multiple locations", + var_name, start_loc + ) + } + } + } +} + +/// Information about a SPIR-V type for error reporting. +struct TypeInfo { + /// The type name from OpName, if available. + name: Option, + /// The number of interface locations consumed by this type. + location_count: Option, +} diff --git a/deny.toml b/deny.toml index e4feda2e21..c7f40964c6 100644 --- a/deny.toml +++ b/deny.toml @@ -52,6 +52,10 @@ exceptions = [ # https://tldrlegal.com/license/creative-commons-cc0-1.0-universal { allow = ["CC0-1.0"], name = "notify" }, { allow = ["CC0-1.0"], name = "hexf-parse" }, + # MPL-2.0+ crates pulled in by egglog via im-rc + { allow = ["MPL-2.0"], name = "bitmaps" }, + { allow = ["MPL-2.0"], name = "im-rc" }, + { allow = ["MPL-2.0"], name = "sized-chunks" }, ] # See note in encoding_rs's readme! This clarification is copied directly from there. diff --git a/tests/compiletests/Cargo.toml b/tests/compiletests/Cargo.toml index 8b88c9211b..6e30fca0a2 100644 --- a/tests/compiletests/Cargo.toml +++ b/tests/compiletests/Cargo.toml @@ -7,11 +7,10 @@ edition.workspace = true license.workspace = true repository.workspace = true -# See rustc_codegen_spirv/Cargo.toml for details on these features [features] -default = ["use-compiled-tools"] -use-installed-tools = ["rustc_codegen_spirv/use-installed-tools"] -use-compiled-tools = ["rustc_codegen_spirv/use-compiled-tools"] +# These features are no-ops kept for compatibility with existing build configurations. +use-installed-tools = [] +use-compiled-tools = [] [dependencies] compiletest = { version = "0.11.2", package = "compiletest_rs" } diff --git a/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.rs b/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.rs index e0f13873ba..d29e92a080 100644 --- a/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.rs +++ b/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.rs @@ -4,7 +4,6 @@ // build-fail // normalize-stderr-test "ref/member_ref_arg-broken\.[^`]*" -> "ref/member_ref_arg-broken" -// normalize-stderr-test "38\[%38\]" -> "$$ID[%$$ID]" use spirv_std::spirv; diff --git a/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr b/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr index 4a41bfb462..049001ea7d 100644 --- a/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr +++ b/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr @@ -1,5 +1,5 @@ warning: `#[inline(never)]` function `member_ref_arg_broken::f` has been inlined - --> $DIR/member_ref_arg-broken.rs:20:4 + --> $DIR/member_ref_arg-broken.rs:21:4 | LL | fn f(x: &u32) -> u32 { | ^ @@ -8,7 +8,7 @@ LL | fn f(x: &u32) -> u32 { = note: called from `member_ref_arg_broken::main` warning: `#[inline(never)]` function `member_ref_arg_broken::g` has been inlined - --> $DIR/member_ref_arg-broken.rs:25:4 + --> $DIR/member_ref_arg-broken.rs:26:4 | LL | fn g(xy: (&u32, &u32)) -> (u32, u32) { | ^ @@ -17,7 +17,7 @@ LL | fn g(xy: (&u32, &u32)) -> (u32, u32) { = note: called from `member_ref_arg_broken::main` warning: `#[inline(never)]` function `member_ref_arg_broken::h` has been inlined - --> $DIR/member_ref_arg-broken.rs:30:4 + --> $DIR/member_ref_arg-broken.rs:31:4 | LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) { | ^ @@ -26,7 +26,7 @@ LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) { = note: called from `member_ref_arg_broken::main` warning: `#[inline(never)]` function `member_ref_arg_broken::h_newtyped` has been inlined - --> $DIR/member_ref_arg-broken.rs:41:4 + --> $DIR/member_ref_arg-broken.rs:42:4 | LL | fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) { | ^^^^^^^^^^ @@ -34,10 +34,13 @@ LL | fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) { = note: inlining was required due to illegal parameter type = note: called from `member_ref_arg_broken::main` -error: error:0:0 - OpLoad Pointer '$ID[%$ID]' is not a logical pointer. - %39 = OpLoad %uint %38 +error: OpLoad cannot use pointer `%38` because it was produced by OpCompositeExtract | - = note: spirv-val failed + = note: in SPIR-V's logical addressing mode, pointers for OpLoad must come from specific instructions like OpVariable, OpAccessChain, or OpFunctionParameter + = help: OpCompositeExtract cannot produce pointers valid for memory operations in logical addressing + = note: generated SPIR-V: + %38 = OpCompositeExtract ... + -> %39 = OpLoad %38 ... = note: module `$TEST_BUILD_DIR/lang/core/ref/member_ref_arg-broken` error: aborting due to 1 previous error; 4 warnings emitted diff --git a/tests/compiletests/ui/spirv-attr/location_assignment/explicit_overlap.stderr b/tests/compiletests/ui/spirv-attr/location_assignment/explicit_overlap.stderr index dbde616b1c..9fe59bf734 100644 --- a/tests/compiletests/ui/spirv-attr/location_assignment/explicit_overlap.stderr +++ b/tests/compiletests/ui/spirv-attr/location_assignment/explicit_overlap.stderr @@ -41,10 +41,18 @@ OpStore %26 %14 OpNoLine OpReturn OpFunctionEnd -error: error:0:0 - [VUID-StandaloneSpirv-OpEntryPoint-08722] Entry-point has conflicting output location assignment at location 1, component 0 - OpEntryPoint Vertex %1 "main" %out1 %out2 +error: Output variable `out2` at location 1 conflicts with another variable + --> $DIR/explicit_overlap.rs:24:53 | - = note: spirv-val failed +LL | pub fn main(#[spirv(location = 0)] out1: &mut Mat4, #[spirv(location = 1)] out2: &mut Vec2) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: variable `out1` already uses location 1 component 0 + --> $DIR/explicit_overlap.rs:24:13 + | +LL | pub fn main(#[spirv(location = 0)] out1: &mut Mat4, #[spirv(location = 1)] out2: &mut Vec2) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: `out1` is at location 0 but type `spirv_std::glam::Mat4` consumes 4 locations (0–3) = note: module `` error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/spirv-attr/location_assignment/mesh_shader.stderr b/tests/compiletests/ui/spirv-attr/location_assignment/mesh_shader.stderr index c6073a1bcb..d10e813f20 100644 --- a/tests/compiletests/ui/spirv-attr/location_assignment/mesh_shader.stderr +++ b/tests/compiletests/ui/spirv-attr/location_assignment/mesh_shader.stderr @@ -5,8 +5,8 @@ OpMemoryModel Logical Simple OpEntryPoint MeshEXT %1 "main" %2 %3 %4 %5 %6 %7 OpExecutionMode %1 LocalSize 1 1 1 OpExecutionMode %1 OutputVertices 9 -OpExecutionMode %1 OutputPrimitivesNV 3 -OpExecutionMode %1 OutputTrianglesNV +OpExecutionMode %1 OutputPrimitivesEXT 3 +OpExecutionMode %1 OutputTrianglesEXT OpName %16 "core::ops::Range" OpMemberName %16 0 "start" OpMemberName %16 1 "end" @@ -23,9 +23,9 @@ OpDecorate %3 Location 0 OpDecorate %4 Location 1 OpDecorate %5 BuiltIn PrimitiveTriangleIndicesEXT OpDecorate %6 Location 2 -OpDecorate %6 PerPrimitiveNV +OpDecorate %6 PerPrimitiveEXT OpDecorate %7 Location 3 -OpDecorate %7 PerPrimitiveNV +OpDecorate %7 PerPrimitiveEXT %17 = OpTypeFloat 32 %18 = OpTypeVector %17 4 %19 = OpTypeInt 32 0