13179dcf6SAlex Crichton# Testing Cranelift 23179dcf6SAlex Crichton 33179dcf6SAlex CrichtonCranelift is tested at multiple levels of abstraction and integration. When 43179dcf6SAlex Crichtonpossible, Rust unit tests are used to verify single functions and types. When 53179dcf6SAlex Crichtontesting the interaction between compiler passes, file-level tests are 63179dcf6SAlex Crichtonappropriate. 73179dcf6SAlex Crichton 83179dcf6SAlex Crichton## Rust tests 93179dcf6SAlex Crichton 103179dcf6SAlex CrichtonRust and Cargo have good support for testing. Cranelift uses unit tests, doc 113179dcf6SAlex Crichtontests, and integration tests where appropriate. The 123179dcf6SAlex Crichton[Rust By Example page on Testing] is a great illustration on how to write 133179dcf6SAlex Crichtoneach of these forms of test. 143179dcf6SAlex Crichton 153179dcf6SAlex Crichton[Rust By Example page on Testing]: https://doc.rust-lang.org/rust-by-example/testing.html 163179dcf6SAlex Crichton 173179dcf6SAlex Crichton## File tests 183179dcf6SAlex Crichton 193179dcf6SAlex CrichtonCompilers work with large data structures representing programs, and it quickly 203179dcf6SAlex Crichtongets unwieldy to generate test data programmatically. File-level tests make it 213179dcf6SAlex Crichtoneasier to provide substantial input functions for the compiler tests. 223179dcf6SAlex Crichton 233179dcf6SAlex CrichtonFile tests are `*.clif` files in the `filetests/` directory 243179dcf6SAlex Crichtonhierarchy. Each file has a header describing what to test followed by a number 253179dcf6SAlex Crichtonof input functions in the :doc:`Cranelift textual intermediate representation 263179dcf6SAlex Crichton<ir>`: 273179dcf6SAlex Crichton 283179dcf6SAlex Crichton.. productionlist:: 293179dcf6SAlex Crichton test_file : test_header `function_list` 303179dcf6SAlex Crichton test_header : test_commands (`isa_specs` | `settings`) 313179dcf6SAlex Crichton test_commands : test_command { test_command } 323179dcf6SAlex Crichton test_command : "test" test_name { option } "\n" 333179dcf6SAlex Crichton 343179dcf6SAlex CrichtonThe available test commands are described below. 353179dcf6SAlex Crichton 363179dcf6SAlex CrichtonMany test commands only make sense in the context of a target instruction set 373179dcf6SAlex Crichtonarchitecture. These tests require one or more ISA specifications in the test 383179dcf6SAlex Crichtonheader: 393179dcf6SAlex Crichton 403179dcf6SAlex Crichton.. productionlist:: 413179dcf6SAlex Crichton isa_specs : { [`settings`] isa_spec } 423179dcf6SAlex Crichton isa_spec : "isa" isa_name { `option` } "\n" 433179dcf6SAlex Crichton 443179dcf6SAlex CrichtonThe options given on the `isa` line modify the ISA-specific settings defined in 453179dcf6SAlex Crichton`cranelift-codegen/meta-python/isa/*/settings.py`. 463179dcf6SAlex Crichton 473179dcf6SAlex CrichtonAll types of tests allow shared Cranelift settings to be modified: 483179dcf6SAlex Crichton 493179dcf6SAlex Crichton.. productionlist:: 503179dcf6SAlex Crichton settings : { setting } 513179dcf6SAlex Crichton setting : "set" { option } "\n" 523179dcf6SAlex Crichton option : flag | setting "=" value 533179dcf6SAlex Crichton 543179dcf6SAlex CrichtonThe shared settings available for all target ISAs are defined in 553179dcf6SAlex Crichton`cranelift-codegen/meta-python/base/settings.py`. 563179dcf6SAlex Crichton 573179dcf6SAlex CrichtonThe `set` lines apply settings cumulatively: 583179dcf6SAlex Crichton 593179dcf6SAlex Crichton``` 603179dcf6SAlex Crichton test legalizer 613179dcf6SAlex Crichton set opt_level=best 623179dcf6SAlex Crichton set is_pic=1 63437f448aSAfonso Bordado target riscv64 643179dcf6SAlex Crichton set is_pic=0 65437f448aSAfonso Bordado target riscv32 supports_m=false 663179dcf6SAlex Crichton 673179dcf6SAlex Crichton function %foo() {} 683179dcf6SAlex Crichton``` 693179dcf6SAlex Crichton 703179dcf6SAlex CrichtonThis example will run the legalizer test twice. Both runs will have 713179dcf6SAlex Crichton`opt_level=best`, but they will have different `is_pic` settings. The 32-bit 723179dcf6SAlex Crichtonrun will also have the RISC-V specific flag `supports_m` disabled. 733179dcf6SAlex Crichton 743179dcf6SAlex CrichtonThe filetests are run automatically as part of `cargo test`, and they can 753179dcf6SAlex Crichtonalso be run manually with the `clif-util test` command. 763179dcf6SAlex Crichton 77c0503455SNick FitzgeraldBy default, the test runner will spawn a thread pool with as many threads as 78c0503455SNick Fitzgeraldthere are logical CPUs. You can explicitly control how many threads are spawned 79c0503455SNick Fitzgeraldvia the `CRANELIFT_FILETESTS_THREADS` environment variable. For example, to 80c0503455SNick Fitzgeraldlimit the test runner to a single thread, use: 81c0503455SNick Fitzgerald 82c0503455SNick Fitzgerald``` 83c0503455SNick Fitzgerald$ CRANELIFT_FILETESTS_THREADS=1 clif-util test path/to/file.clif 84c0503455SNick Fitzgerald``` 85c0503455SNick Fitzgerald 863179dcf6SAlex Crichton### Filecheck 873179dcf6SAlex Crichton 883179dcf6SAlex CrichtonMany of the test commands described below use *filecheck* to verify their 893179dcf6SAlex Crichtonoutput. Filecheck is a Rust implementation of the LLVM tool of the same name. 903179dcf6SAlex CrichtonSee the `documentation <https://docs.rs/filecheck/>`_ for details of its syntax. 913179dcf6SAlex Crichton 923179dcf6SAlex CrichtonComments in `.clif` files are associated with the entity they follow. 933179dcf6SAlex CrichtonThis typically means an instruction or the whole function. Those tests that 943179dcf6SAlex Crichtonuse filecheck will extract comments associated with each function (or its 953179dcf6SAlex Crichtonentities) and scan them for filecheck directives. The test output for each 963179dcf6SAlex Crichtonfunction is then matched against the filecheck directives for that function. 973179dcf6SAlex Crichton 983179dcf6SAlex CrichtonComments appearing before the first function in a file apply to every function. 993179dcf6SAlex CrichtonThis is useful for defining common regular expression variables with the 1003179dcf6SAlex Crichton`regex:` directive, for example. 1013179dcf6SAlex Crichton 1023179dcf6SAlex CrichtonNote that LLVM's file tests don't separate filecheck directives by their 1033179dcf6SAlex Crichtonassociated function. It verifies the concatenated output against all filecheck 1043179dcf6SAlex Crichtondirectives in the test file. LLVM's :command:`FileCheck` command has a 1053179dcf6SAlex Crichton`CHECK-LABEL:` directive to help separate the output from different functions. 1063179dcf6SAlex CrichtonCranelift's tests don't need this. 1073179dcf6SAlex Crichton 1083179dcf6SAlex Crichton### `test cat` 1093179dcf6SAlex Crichton 1103179dcf6SAlex CrichtonThis is one of the simplest file tests, used for testing the conversion to and 1113179dcf6SAlex Crichtonfrom textual IR. The `test cat` command simply parses each function and 1123179dcf6SAlex Crichtonconverts it back to text again. The text of each function is then matched 1133179dcf6SAlex Crichtonagainst the associated filecheck directives. 1143179dcf6SAlex Crichton 1153179dcf6SAlex CrichtonExample: 1163179dcf6SAlex Crichton 1173179dcf6SAlex Crichton``` 1183179dcf6SAlex Crichton function %r1() -> i32, f32 { 119437f448aSAfonso Bordado block1: 1203179dcf6SAlex Crichton v10 = iconst.i32 3 1213179dcf6SAlex Crichton v20 = f32const 0.0 1223179dcf6SAlex Crichton return v10, v20 1233179dcf6SAlex Crichton } 1243179dcf6SAlex Crichton ; sameln: function %r1() -> i32, f32 { 125437f448aSAfonso Bordado ; nextln: block0: 1263179dcf6SAlex Crichton ; nextln: v10 = iconst.i32 3 1273179dcf6SAlex Crichton ; nextln: v20 = f32const 0.0 1283179dcf6SAlex Crichton ; nextln: return v10, v20 1293179dcf6SAlex Crichton ; nextln: } 1303179dcf6SAlex Crichton``` 1313179dcf6SAlex Crichton 1323179dcf6SAlex Crichton### `test verifier` 1333179dcf6SAlex Crichton 1343179dcf6SAlex CrichtonRun each function through the IR verifier and check that it produces the 1353179dcf6SAlex Crichtonexpected error messages. 1363179dcf6SAlex Crichton 1373179dcf6SAlex CrichtonExpected error messages are indicated with an `error:` directive *on the 1383179dcf6SAlex Crichtoninstruction that produces the verifier error*. Both the error message and 1393179dcf6SAlex Crichtonreported location of the error is verified: 1403179dcf6SAlex Crichton 1413179dcf6SAlex Crichton``` 1423179dcf6SAlex Crichton test verifier 1433179dcf6SAlex Crichton 1443179dcf6SAlex Crichton function %test(i32) { 145437f448aSAfonso Bordado block0(v0: i32): 146437f448aSAfonso Bordado jump block1 ; error: terminator 1473179dcf6SAlex Crichton return 1483179dcf6SAlex Crichton } 1493179dcf6SAlex Crichton``` 1503179dcf6SAlex Crichton 1513179dcf6SAlex CrichtonThis example test passes if the verifier fails with an error message containing 1523179dcf6SAlex Crichtonthe sub-string `"terminator"` *and* the error is reported for the `jump` 1533179dcf6SAlex Crichtoninstruction. 1543179dcf6SAlex Crichton 1553179dcf6SAlex CrichtonIf a function contains no `error:` annotations, the test passes if the 1563179dcf6SAlex Crichtonfunction verifies correctly. 1573179dcf6SAlex Crichton 1583179dcf6SAlex Crichton### `test print-cfg` 1593179dcf6SAlex Crichton 1603179dcf6SAlex CrichtonPrint the control flow graph of each function as a Graphviz graph, and run 1613179dcf6SAlex Crichtonfilecheck over the result. See also the :command:`clif-util print-cfg` 1623179dcf6SAlex Crichtoncommand: 1633179dcf6SAlex Crichton 1643179dcf6SAlex Crichton``` 1653179dcf6SAlex Crichton ; For testing cfg generation. This code is nonsense. 1663179dcf6SAlex Crichton test print-cfg 1673179dcf6SAlex Crichton test verifier 1683179dcf6SAlex Crichton 1693179dcf6SAlex Crichton function %nonsense(i32, i32) -> f32 { 1703179dcf6SAlex Crichton ; check: digraph %nonsense { 1713179dcf6SAlex Crichton ; regex: I=\binst\d+\b 172a5698cedSTrevor Elliott ; check: label="{block0 | <$(BRIF=$I)>brif v1, block1(v2), block2 }"] 1733179dcf6SAlex Crichton 174437f448aSAfonso Bordado block0(v0: i32, v1: i32): 1753179dcf6SAlex Crichton v2 = iconst.i32 0 176a5698cedSTrevor Elliott brif v1, block1(v2), block2 ; unordered: block0:$BRIF -> block1 177a5698cedSTrevor Elliott ; unordered: block0:$BRIF -> block2 1783179dcf6SAlex Crichton 179437f448aSAfonso Bordado block1(v5: i32): 1803179dcf6SAlex Crichton return v0 1813179dcf6SAlex Crichton 182437f448aSAfonso Bordado block2: 1833179dcf6SAlex Crichton v100 = f32const 0.0 1843179dcf6SAlex Crichton return v100 1853179dcf6SAlex Crichton } 1863179dcf6SAlex Crichton``` 1873179dcf6SAlex Crichton 1883179dcf6SAlex Crichton### `test domtree` 1893179dcf6SAlex Crichton 1903179dcf6SAlex CrichtonCompute the dominator tree of each function and validate it against the 1913179dcf6SAlex Crichton`dominates:` annotations:: 1923179dcf6SAlex Crichton 1933179dcf6SAlex Crichton``` 1943179dcf6SAlex Crichton test domtree 1953179dcf6SAlex Crichton 1963179dcf6SAlex Crichton function %test(i32) { 197437f448aSAfonso Bordado block0(v0: i32): 198437f448aSAfonso Bordado jump block1 ; dominates: block1 199437f448aSAfonso Bordado block1: 200a5698cedSTrevor Elliott brif v0, block2, block3 ; dominates: block2, block3 201437f448aSAfonso Bordado block2: 202437f448aSAfonso Bordado jump block3 203437f448aSAfonso Bordado block3: 2043179dcf6SAlex Crichton return 2053179dcf6SAlex Crichton } 2063179dcf6SAlex Crichton``` 2073179dcf6SAlex Crichton 208*c17a3d89STrevor ElliottEvery reachable basic block except for the entry block has an 2093179dcf6SAlex Crichton*immediate dominator* which is a jump or branch instruction. This test passes 2103179dcf6SAlex Crichtonif the `dominates:` annotations on the immediate dominator instructions are 2113179dcf6SAlex Crichtonboth correct and complete. 2123179dcf6SAlex Crichton 2133179dcf6SAlex CrichtonThis test also sends the computed CFG post-order through filecheck. 2143179dcf6SAlex Crichton 2153179dcf6SAlex Crichton### `test legalizer` 2163179dcf6SAlex Crichton 2173179dcf6SAlex CrichtonLegalize each function for the specified target ISA and run the resulting 2183179dcf6SAlex Crichtonfunction through filecheck. This test command can be used to validate the 2193179dcf6SAlex Crichtonencodings selected for legal instructions as well as the instruction 2203179dcf6SAlex Crichtontransformations performed by the legalizer. 2213179dcf6SAlex Crichton 2223179dcf6SAlex Crichton### `test regalloc` 2233179dcf6SAlex Crichton 2243179dcf6SAlex CrichtonTest the register allocator. 2253179dcf6SAlex Crichton 2263179dcf6SAlex CrichtonFirst, each function is legalized for the specified target ISA. This is 2273179dcf6SAlex Crichtonrequired for register allocation since the instruction encodings provide 2283179dcf6SAlex Crichtonregister class constraints to the register allocator. 2293179dcf6SAlex Crichton 2303179dcf6SAlex CrichtonSecond, the register allocator is run on the function, inserting spill code and 2313179dcf6SAlex Crichtonassigning registers and stack slots to all values. 2323179dcf6SAlex Crichton 2333179dcf6SAlex CrichtonThe resulting function is then run through filecheck. 2343179dcf6SAlex Crichton 2353179dcf6SAlex Crichton 2363179dcf6SAlex Crichton### `test simple-gvn` 2373179dcf6SAlex Crichton 2383179dcf6SAlex CrichtonTest the simple GVN pass. 2393179dcf6SAlex Crichton 2403179dcf6SAlex CrichtonThe simple GVN pass is run on each function, and then results are run 2413179dcf6SAlex Crichtonthrough filecheck. 2423179dcf6SAlex Crichton 2433179dcf6SAlex Crichton### `test licm` 2443179dcf6SAlex Crichton 2453179dcf6SAlex CrichtonTest the LICM pass. 2463179dcf6SAlex Crichton 2473179dcf6SAlex CrichtonThe LICM pass is run on each function, and then results are run 2483179dcf6SAlex Crichtonthrough filecheck. 2493179dcf6SAlex Crichton 2503179dcf6SAlex Crichton### `test dce` 2513179dcf6SAlex Crichton 2523179dcf6SAlex CrichtonTest the DCE pass. 2533179dcf6SAlex Crichton 2543179dcf6SAlex CrichtonThe DCE pass is run on each function, and then results are run 2553179dcf6SAlex Crichtonthrough filecheck. 2563179dcf6SAlex Crichton 2573179dcf6SAlex Crichton### `test shrink` 2583179dcf6SAlex Crichton 2593179dcf6SAlex CrichtonTest the instruction shrinking pass. 2603179dcf6SAlex Crichton 2613179dcf6SAlex CrichtonThe shrink pass is run on each function, and then results are run 2623179dcf6SAlex Crichtonthrough filecheck. 2633179dcf6SAlex Crichton 26491580155SJamey Sharp### `test simple_preopt` 2653179dcf6SAlex Crichton 2663179dcf6SAlex CrichtonTest the preopt pass. 2673179dcf6SAlex Crichton 2683179dcf6SAlex CrichtonThe preopt pass is run on each function, and then results are run 2693179dcf6SAlex Crichtonthrough filecheck. 2703179dcf6SAlex Crichton 2713179dcf6SAlex Crichton### `test compile` 2723179dcf6SAlex Crichton 2733179dcf6SAlex CrichtonTest the whole code generation pipeline. 2743179dcf6SAlex Crichton 2753179dcf6SAlex CrichtonEach function is passed through the full `Context::compile()` function 2763179dcf6SAlex Crichtonwhich is normally used to compile code. This type of test often depends 2773179dcf6SAlex Crichtonon assertions or verifier errors, but it is also possible to use 2783179dcf6SAlex Crichtonfilecheck directives which will be matched against the final form of the 2793179dcf6SAlex CrichtonCranelift IR right before binary machine code emission. 2803179dcf6SAlex Crichton 2813179dcf6SAlex Crichton### `test run` 2823179dcf6SAlex Crichton 2833179dcf6SAlex CrichtonCompile and execute a function. 2843179dcf6SAlex Crichton 285d6796d0dSAndrew BrownThis test command allows several directives: 286d6796d0dSAndrew Brown - to print the result of running a function to stdout, add a `print` 287d6796d0dSAndrew Brown directive and call the preceding function with arguments (see `%foo` in 288d6796d0dSAndrew Brown the example below); remember to enable `--nocapture` if running these 289d6796d0dSAndrew Brown tests through Cargo 290d6796d0dSAndrew Brown - to check the result of a function, add a `run` directive and call the 291d6796d0dSAndrew Brown preceding function with a comparison (`==` or `!=`) (see `%bar` below) 292d6796d0dSAndrew Brown - for backwards compatibility, to check the result of a function with a 293437f448aSAfonso Bordado `() -> i*` signature, only the `run` directive is required, with no 294437f448aSAfonso Bordado invocation or comparison (see `%baz` below); a non zero value is 295437f448aSAfonso Bordado interpreted as a successful test execution, whereas a zero value is 296d6796d0dSAndrew Brown interpreted as a failed test. 2973179dcf6SAlex Crichton 298d1aa86f9SAlex CrichtonCurrently a `target` is required but is only used to indicate whether the host 299d6796d0dSAndrew Brownplatform can run the test and currently only the architecture is filtered. The 300d1aa86f9SAlex Crichtonhost platform's native target will be used to actually compile the test. 301d1aa86f9SAlex Crichton 3023179dcf6SAlex CrichtonExample: 3033179dcf6SAlex Crichton 3043179dcf6SAlex Crichton``` 3053179dcf6SAlex Crichton test run 306d1aa86f9SAlex Crichton target x86_64 3073179dcf6SAlex Crichton 308d6796d0dSAndrew Brown ; how to print the results of a function 309d6796d0dSAndrew Brown function %foo() -> i32 { 310d6796d0dSAndrew Brown block0: 311d6796d0dSAndrew Brown v0 = iconst.i32 42 312d6796d0dSAndrew Brown return v0 313d6796d0dSAndrew Brown } 314d6796d0dSAndrew Brown ; print: %foo() 315d6796d0dSAndrew Brown 316d6796d0dSAndrew Brown ; how to check the results of a function 317d6796d0dSAndrew Brown function %bar(i32) -> i32 { 318d6796d0dSAndrew Brown block0(v0:i32): 319d6796d0dSAndrew Brown v1 = iadd_imm v0, 1 320d6796d0dSAndrew Brown return v1 321d6796d0dSAndrew Brown } 322d6796d0dSAndrew Brown ; run: %bar(1) == 2 323d6796d0dSAndrew Brown 324d6796d0dSAndrew Brown ; legacy method of checking the results of a function 325437f448aSAfonso Bordado function %baz() -> i8 { 326d6796d0dSAndrew Brown block0: 327437f448aSAfonso Bordado v0 = iconst.i8 1 3283179dcf6SAlex Crichton return v0 3293179dcf6SAlex Crichton } 3303179dcf6SAlex Crichton ; run 3313179dcf6SAlex Crichton``` 332