about summary refs log tree commit diff
path: root/tests/run-make
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/run-make
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/run-make')
-rw-r--r--tests/run-make/const_fn_mir/Makefile10
-rw-r--r--tests/run-make/const_fn_mir/dump.mir42
-rw-r--r--tests/run-make/const_fn_mir/main.rs10
-rw-r--r--tests/run-make/coverage-llvmir/Makefile64
-rw-r--r--tests/run-make/coverage-llvmir/filecheck.testprog.txt50
-rw-r--r--tests/run-make/coverage-llvmir/testprog.rs38
-rw-r--r--tests/run-make/coverage-reports/Makefile185
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.abort.txt69
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.assert.txt34
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.async.txt139
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.async2.txt116
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.closure.txt222
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt42
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt83
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.conditions.txt94
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.continue.txt70
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt39
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.doctest.txt115
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt34
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.generator.txt32
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.generics.txt71
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.if.txt30
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.if_else.txt41
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt28
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.inline.txt54
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt60
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt16
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt189
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt36
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt29
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt64
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt14
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt68
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt50
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt26
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt87
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.overflow.txt64
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt32
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt48
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt37
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt45
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt6
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt125
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.unused.txt62
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt4
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt148
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt139
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.while.txt6
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt43
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.yield.txt38
-rwxr-xr-xtests/run-make/coverage-reports/normalize_paths.py12
-rw-r--r--tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt10
-rw-r--r--tests/run-make/coverage/abort.rs66
-rw-r--r--tests/run-make/coverage/assert.rs32
-rw-r--r--tests/run-make/coverage/async.rs128
-rw-r--r--tests/run-make/coverage/async2.rs69
-rw-r--r--tests/run-make/coverage/closure.rs215
-rw-r--r--tests/run-make/coverage/closure_macro.rs40
-rw-r--r--tests/run-make/coverage/closure_macro_async.rs81
-rw-r--r--tests/run-make/coverage/compiletest-ignore-dir3
-rw-r--r--tests/run-make/coverage/conditions.rs87
-rw-r--r--tests/run-make/coverage/continue.rs69
-rw-r--r--tests/run-make/coverage/coverage_tools.mk6
-rw-r--r--tests/run-make/coverage/dead_code.rs37
-rw-r--r--tests/run-make/coverage/doctest.rs99
-rw-r--r--tests/run-make/coverage/drop_trait.rs33
-rw-r--r--tests/run-make/coverage/generator.rs30
-rw-r--r--tests/run-make/coverage/generics.rs48
-rw-r--r--tests/run-make/coverage/if.rs28
-rw-r--r--tests/run-make/coverage/if_else.rs40
-rw-r--r--tests/run-make/coverage/inline-dead.rs27
-rw-r--r--tests/run-make/coverage/inline.rs51
-rw-r--r--tests/run-make/coverage/inner_items.rs57
-rw-r--r--tests/run-make/coverage/issue-83601.rs14
-rw-r--r--tests/run-make/coverage/issue-84561.rs182
-rw-r--r--tests/run-make/coverage/issue-85461.rs10
-rw-r--r--tests/run-make/coverage/issue-93054.rs28
-rw-r--r--tests/run-make/coverage/lazy_boolean.rs61
-rw-r--r--tests/run-make/coverage/lib/doctest_crate.rs9
-rw-r--r--tests/run-make/coverage/lib/inline_always_with_dead_code.rs22
-rw-r--r--tests/run-make/coverage/lib/unused_mod_helper.rs3
-rw-r--r--tests/run-make/coverage/lib/used_crate.rs100
-rw-r--r--tests/run-make/coverage/lib/used_inline_crate.rs90
-rw-r--r--tests/run-make/coverage/loop_break_value.rs13
-rw-r--r--tests/run-make/coverage/loops_branches.rs61
-rw-r--r--tests/run-make/coverage/match_or_pattern.rs45
-rw-r--r--tests/run-make/coverage/nested_loops.rs25
-rw-r--r--tests/run-make/coverage/no_cov_crate.rs86
-rw-r--r--tests/run-make/coverage/overflow.rs63
-rw-r--r--tests/run-make/coverage/panic_unwind.rs31
-rw-r--r--tests/run-make/coverage/partial_eq.rs46
-rw-r--r--tests/run-make/coverage/simple_loop.rs35
-rw-r--r--tests/run-make/coverage/simple_match.rs43
-rw-r--r--tests/run-make/coverage/tight_inf_loop.rs5
-rw-r--r--tests/run-make/coverage/try_error_result.rs118
-rw-r--r--tests/run-make/coverage/unused.rs39
-rw-r--r--tests/run-make/coverage/unused_mod.rs6
-rw-r--r--tests/run-make/coverage/uses_crate.rs12
-rw-r--r--tests/run-make/coverage/uses_inline_crate.rs17
-rw-r--r--tests/run-make/coverage/while.rs5
-rw-r--r--tests/run-make/coverage/while_early_ret.rs42
-rw-r--r--tests/run-make/coverage/yield.rs37
-rw-r--r--tests/run-make/dep-graph/Makefile12
-rw-r--r--tests/run-make/dep-graph/foo.rs1
-rw-r--r--tests/run-make/dump-mono-stats/Makefile5
-rw-r--r--tests/run-make/dump-mono-stats/foo.rs1
-rw-r--r--tests/run-make/emit-named-files/Makefile33
-rw-r--r--tests/run-make/emit-named-files/foo.rs1
-rw-r--r--tests/run-make/emit-path-unhashed/Makefile37
-rw-r--r--tests/run-make/emit-path-unhashed/foo.rs1
-rw-r--r--tests/run-make/emit-shared-files/Makefile46
-rw-r--r--tests/run-make/emit-shared-files/x.rs1
-rw-r--r--tests/run-make/emit-shared-files/y.css0
-rw-r--r--tests/run-make/emit-shared-files/z.css0
-rw-r--r--tests/run-make/env-dep-info/Makefile19
-rw-r--r--tests/run-make/env-dep-info/macro_def.rs12
-rw-r--r--tests/run-make/env-dep-info/macro_use.rs6
-rw-r--r--tests/run-make/env-dep-info/main.rs6
-rw-r--r--tests/run-make/export-executable-symbols/Makefile11
-rw-r--r--tests/run-make/export-executable-symbols/main.rs8
-rw-r--r--tests/run-make/fmt-write-bloat/Makefile25
-rw-r--r--tests/run-make/fmt-write-bloat/main.rs32
-rw-r--r--tests/run-make/git_clone_sha1.sh23
-rw-r--r--tests/run-make/incr-foreign-head-span/Makefile21
-rw-r--r--tests/run-make/incr-foreign-head-span/first_crate.rs1
-rw-r--r--tests/run-make/incr-foreign-head-span/second_crate.rs8
-rw-r--r--tests/run-make/incr-prev-body-beyond-eof/Makefile19
-rw-r--r--tests/run-make/incr-prev-body-beyond-eof/a.rs16
-rw-r--r--tests/run-make/incr-prev-body-beyond-eof/b.rs12
-rw-r--r--tests/run-make/incremental-session-fail/Makefile14
-rw-r--r--tests/run-make/incremental-session-fail/foo.rs1
-rw-r--r--tests/run-make/invalid-so/Makefile7
-rw-r--r--tests/run-make/invalid-so/bar.rs1
-rw-r--r--tests/run-make/issue-10971-temps-dir/Makefile10
-rw-r--r--tests/run-make/issue-36710/Makefile17
-rw-r--r--tests/run-make/issue-36710/foo.cpp15
-rw-r--r--tests/run-make/issue-36710/foo.rs10
-rw-r--r--tests/run-make/issue-47384/Makefile12
-rw-r--r--tests/run-make/issue-47384/lib.rs12
-rw-r--r--tests/run-make/issue-47384/linker.ld7
-rw-r--r--tests/run-make/issue-47384/main.rs1
-rw-r--r--tests/run-make/issue-71519/Makefile8
-rw-r--r--tests/run-make/issue-71519/main.rs4
-rw-r--r--tests/run-make/issue-83112-incr-test-moved-file/Makefile25
-rw-r--r--tests/run-make/issue-83112-incr-test-moved-file/main.rs1
-rw-r--r--tests/run-make/issue-85019-moved-src-dir/Makefile28
-rw-r--r--tests/run-make/issue-85019-moved-src-dir/main.rs5
-rw-r--r--tests/run-make/issue-85019-moved-src-dir/my_lib.rs1
-rw-r--r--tests/run-make/issue-85401-static-mir/Makefile16
-rw-r--r--tests/run-make/issue-85401-static-mir/bar.rs4
-rw-r--r--tests/run-make/issue-85401-static-mir/baz.rs3
-rw-r--r--tests/run-make/issue-85401-static-mir/foo.rs5
-rw-r--r--tests/run-make/issue-85441/Makefile9
-rw-r--r--tests/run-make/issue-85441/empty.rs1
-rw-r--r--tests/run-make/issue-88756-default-output/Makefile4
-rw-r--r--tests/run-make/issue-88756-default-output/README.md1
-rw-r--r--tests/run-make/issue-88756-default-output/output-default.stdout197
-rw-r--r--tests/run-make/issue-88756-default-output/x.rs1
-rw-r--r--tests/run-make/issue-96498/Makefile8
-rw-r--r--tests/run-make/issue-96498/foo.rs4
-rw-r--r--tests/run-make/libtest-thread-limit/Makefile7
-rw-r--r--tests/run-make/libtest-thread-limit/test.rs20
-rw-r--r--tests/run-make/llvm-outputs/Makefile5
-rw-r--r--tests/run-make/macos-deployment-target/Makefile21
-rw-r--r--tests/run-make/macos-deployment-target/with_deployment_target.rs4
-rw-r--r--tests/run-make/macos-fat-archive/Makefile10
-rw-r--r--tests/run-make/macos-fat-archive/lib.rs3
-rw-r--r--tests/run-make/macos-fat-archive/native-library.c1
-rw-r--r--tests/run-make/native-link-modifier-bundle/Makefile33
-rw-r--r--tests/run-make/native-link-modifier-bundle/bundled.rs11
-rw-r--r--tests/run-make/native-link-modifier-bundle/cdylib-bundled.rs1
-rw-r--r--tests/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs1
-rw-r--r--tests/run-make/native-link-modifier-bundle/native-staticlib.c1
-rw-r--r--tests/run-make/native-link-modifier-bundle/non-bundled.rs11
-rw-r--r--tests/run-make/native-link-modifier-verbatim-linker/Makefile15
-rw-r--r--tests/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs4
-rw-r--r--tests/run-make/native-link-modifier-verbatim-linker/main.rs9
-rw-r--r--tests/run-make/native-link-modifier-verbatim-rustc/Makefile12
-rw-r--r--tests/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs9
-rw-r--r--tests/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs4
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/Makefile52
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp11
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/directly_linked.rs6
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs7
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs7
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/indirectly_linked.rs5
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs5
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs11
-rw-r--r--tests/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs6
-rw-r--r--tests/run-make/pass-linker-flags-from-dep/Makefile10
-rw-r--r--tests/run-make/pass-linker-flags-from-dep/main.rs3
-rw-r--r--tests/run-make/pass-linker-flags-from-dep/native_dep_1.rs1
-rw-r--r--tests/run-make/pass-linker-flags-from-dep/native_dep_2.rs1
-rw-r--r--tests/run-make/pass-linker-flags-from-dep/rust_dep.rs9
-rw-r--r--tests/run-make/pass-linker-flags/Makefile4
-rw-r--r--tests/run-make/pass-linker-flags/rs.rs1
-rw-r--r--tests/run-make/raw-dylib-alt-calling-convention/Makefile32
-rw-r--r--tests/run-make/raw-dylib-alt-calling-convention/driver.rs8
-rw-r--r--tests/run-make/raw-dylib-alt-calling-convention/extern.c193
-rw-r--r--tests/run-make/raw-dylib-alt-calling-convention/lib.rs115
-rw-r--r--tests/run-make/raw-dylib-alt-calling-convention/output.msvc.txt12
-rw-r--r--tests/run-make/raw-dylib-alt-calling-convention/output.txt18
-rw-r--r--tests/run-make/raw-dylib-c/Makefile28
-rw-r--r--tests/run-make/raw-dylib-c/driver.rs5
-rw-r--r--tests/run-make/raw-dylib-c/extern_1.c28
-rw-r--r--tests/run-make/raw-dylib-c/extern_2.c6
-rw-r--r--tests/run-make/raw-dylib-c/lib.rs37
-rw-r--r--tests/run-make/raw-dylib-c/output.txt6
-rw-r--r--tests/run-make/raw-dylib-import-name-type/Makefile22
-rw-r--r--tests/run-make/raw-dylib-import-name-type/driver.rs133
-rw-r--r--tests/run-make/raw-dylib-import-name-type/extern.c108
-rw-r--r--tests/run-make/raw-dylib-import-name-type/extern.gnu.def22
-rw-r--r--tests/run-make/raw-dylib-import-name-type/extern.msvc.def26
-rw-r--r--tests/run-make/raw-dylib-import-name-type/output.txt20
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/Makefile31
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/driver.rs21
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/extern_1.c11
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/extern_2.c6
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/lib.rs21
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/lib_wrapper.rs6
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/output.txt6
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/Makefile22
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/driver.rs5
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/exporter.c12
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/exporter.def5
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/lib.rs21
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/output.txt3
-rw-r--r--tests/run-make/raw-dylib-stdcall-ordinal/Makefile23
-rw-r--r--tests/run-make/raw-dylib-stdcall-ordinal/driver.rs5
-rw-r--r--tests/run-make/raw-dylib-stdcall-ordinal/expected_output.txt2
-rw-r--r--tests/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def4
-rw-r--r--tests/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def4
-rw-r--r--tests/run-make/raw-dylib-stdcall-ordinal/exporter.c11
-rw-r--r--tests/run-make/raw-dylib-stdcall-ordinal/lib.rs20
-rw-r--r--tests/run-make/remap-path-prefix-dwarf/Makefile77
-rw-r--r--tests/run-make/remap-path-prefix-dwarf/src/quux.rs5
-rw-r--r--tests/run-make/repr128-dwarf/Makefile16
-rw-r--r--tests/run-make/repr128-dwarf/lib.rs23
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-2/Makefile22
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-2/main.rs5
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs4
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs10
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/Makefile34
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/main.rs4
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/native_dep_1.c1
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/native_dep_2.c1
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/native_dep_3.c1
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs13
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs13
-rw-r--r--tests/run-make/rustc-macro-dep-files/Makefile11
-rw-r--r--tests/run-make/rustc-macro-dep-files/bar.rs8
-rw-r--r--tests/run-make/rustc-macro-dep-files/foo.rs12
-rw-r--r--tests/run-make/rustdoc-scrape-examples-invalid-expr/Makefile5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs2
-rw-r--r--tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs1
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/Makefile5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs4
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs3
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk21
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/src/lib.rs6
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/Makefile5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs11
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs8
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/src/lib.rs6
-rw-r--r--tests/run-make/rustdoc-scrape-examples-remap/Makefile5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-remap/examples/ex.rs4
-rw-r--r--tests/run-make/rustdoc-scrape-examples-remap/src/a.rs1
-rw-r--r--tests/run-make/rustdoc-scrape-examples-remap/src/lib.rs8
-rw-r--r--tests/run-make/rustdoc-scrape-examples-test/Makefile6
-rw-r--r--tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs6
-rw-r--r--tests/run-make/rustdoc-scrape-examples-test/src/lib.rs3
-rw-r--r--tests/run-make/rustdoc-scrape-examples-whitespace/Makefile5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs8
-rw-r--r--tests/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs3
-rw-r--r--tests/run-make/rustdoc-verify-output-files/Makefile36
-rw-r--r--tests/run-make/rustdoc-verify-output-files/src/lib.rs1
-rw-r--r--tests/run-make/rustdoc-with-out-dir-option/Makefile8
-rw-r--r--tests/run-make/rustdoc-with-out-dir-option/src/lib.rs2
-rw-r--r--tests/run-make/rustdoc-with-output-option/Makefile8
-rw-r--r--tests/run-make/rustdoc-with-output-option/src/lib.rs2
-rw-r--r--tests/run-make/rustdoc-with-short-out-dir-option/Makefile8
-rw-r--r--tests/run-make/rustdoc-with-short-out-dir-option/src/lib.rs2
-rw-r--r--tests/run-make/static-pie/Makefile18
-rwxr-xr-xtests/run-make/static-pie/check_clang_version.sh20
-rwxr-xr-xtests/run-make/static-pie/check_gcc_version.sh20
-rw-r--r--tests/run-make/static-pie/test-aslr.rs43
-rw-r--r--tests/run-make/test-benches/Makefile11
-rw-r--r--tests/run-make/test-benches/smokebench.rs14
-rw-r--r--tests/run-make/thumb-none-cortex-m/Makefile38
-rw-r--r--tests/run-make/thumb-none-qemu/Makefile27
-rw-r--r--tests/run-make/thumb-none-qemu/example/.cargo/config45
-rw-r--r--tests/run-make/thumb-none-qemu/example/Cargo.lock199
-rw-r--r--tests/run-make/thumb-none-qemu/example/Cargo.toml10
-rw-r--r--tests/run-make/thumb-none-qemu/example/memory.x23
-rw-r--r--tests/run-make/thumb-none-qemu/example/src/main.rs24
-rw-r--r--tests/run-make/thumb-none-qemu/script.sh20
-rw-r--r--tests/run-make/track-path-dep-info/Makefile13
-rw-r--r--tests/run-make/track-path-dep-info/emojis.txt1
-rw-r--r--tests/run-make/track-path-dep-info/macro_def.rs11
-rw-r--r--tests/run-make/track-path-dep-info/macro_use.rs6
-rw-r--r--tests/run-make/track-pgo-dep-info/Makefile26
-rw-r--r--tests/run-make/track-pgo-dep-info/main.rs1
-rw-r--r--tests/run-make/translation/Makefile72
-rw-r--r--tests/run-make/translation/broken.ftl3
-rw-r--r--tests/run-make/translation/missing.ftl3
-rw-r--r--tests/run-make/translation/test.rs18
-rw-r--r--tests/run-make/translation/working.ftl2
-rw-r--r--tests/run-make/unstable-flag-required/Makefile4
-rw-r--r--tests/run-make/unstable-flag-required/README.md3
-rw-r--r--tests/run-make/unstable-flag-required/output-format-json.stderr2
-rw-r--r--tests/run-make/unstable-flag-required/x.rs1
-rw-r--r--tests/run-make/valid-print-requests/Makefile4
-rw-r--r--tests/run-make/valid-print-requests/valid-print-requests.stderr2
-rw-r--r--tests/run-make/wasm-abi/Makefile7
-rw-r--r--tests/run-make/wasm-abi/foo.js22
-rw-r--r--tests/run-make/wasm-abi/foo.rs87
-rw-r--r--tests/run-make/wasm-custom-section/Makefile8
-rw-r--r--tests/run-make/wasm-custom-section/bar.rs13
-rw-r--r--tests/run-make/wasm-custom-section/foo.js36
-rw-r--r--tests/run-make/wasm-custom-section/foo.rs8
-rw-r--r--tests/run-make/wasm-custom-sections-opt/Makefile7
-rw-r--r--tests/run-make/wasm-custom-sections-opt/foo.js15
-rw-r--r--tests/run-make/wasm-custom-sections-opt/foo.rs21
-rw-r--r--tests/run-make/wasm-export-all-symbols/Makefile19
-rw-r--r--tests/run-make/wasm-export-all-symbols/bar.rs7
-rw-r--r--tests/run-make/wasm-export-all-symbols/foo.rs3
-rw-r--r--tests/run-make/wasm-export-all-symbols/main.rs3
-rw-r--r--tests/run-make/wasm-export-all-symbols/verify.js32
-rw-r--r--tests/run-make/wasm-import-module/Makefile8
-rw-r--r--tests/run-make/wasm-import-module/bar.rs18
-rw-r--r--tests/run-make/wasm-import-module/foo.js18
-rw-r--r--tests/run-make/wasm-import-module/foo.rs7
-rw-r--r--tests/run-make/wasm-panic-small/Makefile17
-rw-r--r--tests/run-make/wasm-panic-small/foo.rs27
-rw-r--r--tests/run-make/wasm-spurious-import/Makefile7
-rw-r--r--tests/run-make/wasm-spurious-import/main.rs14
-rw-r--r--tests/run-make/wasm-spurious-import/verify.js9
-rw-r--r--tests/run-make/wasm-stringify-ints-small/Makefile10
-rw-r--r--tests/run-make/wasm-stringify-ints-small/foo.rs33
-rw-r--r--tests/run-make/wasm-symbols-different-module/Makefile28
-rw-r--r--tests/run-make/wasm-symbols-different-module/bar.rs33
-rw-r--r--tests/run-make/wasm-symbols-different-module/baz.rs22
-rw-r--r--tests/run-make/wasm-symbols-different-module/foo.rs23
-rw-r--r--tests/run-make/wasm-symbols-different-module/log.rs16
-rw-r--r--tests/run-make/wasm-symbols-different-module/verify-imports.js32
-rw-r--r--tests/run-make/wasm-symbols-not-exported/Makefile13
-rw-r--r--tests/run-make/wasm-symbols-not-exported/bar.rs35
-rw-r--r--tests/run-make/wasm-symbols-not-exported/foo.rs7
-rw-r--r--tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js21
-rw-r--r--tests/run-make/wasm-symbols-not-imported/Makefile13
-rw-r--r--tests/run-make/wasm-symbols-not-imported/foo.rs14
-rw-r--r--tests/run-make/wasm-symbols-not-imported/verify-no-imports.js10
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile23
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks8
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks6
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks15
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks6
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks16
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks7
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks6
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks16
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks2
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks6
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks16
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks2
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml12
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs30
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c18
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s7
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp21
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt33
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c26
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s7
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp29
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs49
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks8
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks7
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks2
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh58
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks6
380 files changed, 10134 insertions, 0 deletions
diff --git a/tests/run-make/const_fn_mir/Makefile b/tests/run-make/const_fn_mir/Makefile
new file mode 100644
index 00000000000..ad5695093a1
--- /dev/null
+++ b/tests/run-make/const_fn_mir/Makefile
@@ -0,0 +1,10 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/dump.mir dump.mir
+else
+	$(DIFF) dump.mir "$(TMPDIR)"/dump.mir
+endif
diff --git a/tests/run-make/const_fn_mir/dump.mir b/tests/run-make/const_fn_mir/dump.mir
new file mode 100644
index 00000000000..ab4084c952a
--- /dev/null
+++ b/tests/run-make/const_fn_mir/dump.mir
@@ -0,0 +1,42 @@
+// WARNING: This output format is intended for human consumers only
+// and is subject to change without notice. Knock yourself out.
+fn foo() -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at main.rs:4:19: 4:22
+
+    bb0: {
+        _0 = const 11_i32;               // scope 0 at main.rs:5:5: 5:10
+        return;                          // scope 0 at main.rs:6:2: 6:2
+    }
+}
+
+// MIR FOR CTFE
+fn foo() -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at main.rs:4:19: 4:22
+    let mut _1: (i32, bool);             // in scope 0 at main.rs:5:5: 5:10
+
+    bb0: {
+        _1 = CheckedAdd(const 5_i32, const 6_i32); // scope 0 at main.rs:5:5: 5:10
+        assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> bb1; // scope 0 at main.rs:5:5: 5:10
+    }
+
+    bb1: {
+        _0 = move (_1.0: i32);           // scope 0 at main.rs:5:5: 5:10
+        return;                          // scope 0 at main.rs:6:2: 6:2
+    }
+}
+
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at main.rs:8:11: 8:11
+    let _1: i32;                         // in scope 0 at main.rs:9:5: 9:10
+
+    bb0: {
+        _1 = foo() -> bb1;               // scope 0 at main.rs:9:5: 9:10
+                                         // mir::Constant
+                                         // + span: main.rs:9:5: 9:8
+                                         // + literal: Const { ty: fn() -> i32 {foo}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        return;                          // scope 0 at main.rs:10:2: 10:2
+    }
+}
diff --git a/tests/run-make/const_fn_mir/main.rs b/tests/run-make/const_fn_mir/main.rs
new file mode 100644
index 00000000000..e8552bd285a
--- /dev/null
+++ b/tests/run-make/const_fn_mir/main.rs
@@ -0,0 +1,10 @@
+// emit-mir
+// check-pass
+
+const fn foo() -> i32 {
+    5 + 6
+}
+
+fn main() {
+    foo();
+}
diff --git a/tests/run-make/coverage-llvmir/Makefile b/tests/run-make/coverage-llvmir/Makefile
new file mode 100644
index 00000000000..7be65505332
--- /dev/null
+++ b/tests/run-make/coverage-llvmir/Makefile
@@ -0,0 +1,64 @@
+# needs-profiler-support
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-llvmir
+
+ifeq ($(UNAME),Darwin)
+	INSTR_PROF_DATA_SUFFIX=,regular,live_support
+	DATA_SECTION_PREFIX=__DATA,
+	LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+	COMDAT_IF_SUPPORTED=
+else
+	INSTR_PROF_DATA_SUFFIX=
+	DATA_SECTION_PREFIX=
+	LLVM_COV_SECTION_PREFIX=
+	COMDAT_IF_SUPPORTED=, comdat
+endif
+
+DEFINE_INTERNAL=define internal
+
+ifdef IS_WINDOWS
+	LLVM_FILECHECK_OPTIONS=\
+		-check-prefixes=CHECK,WINDOWS \
+		-DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+		-DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+		-DINSTR_PROF_DATA='.lprfd$$M' \
+		-DINSTR_PROF_NAME='.lprfn$$M' \
+		-DINSTR_PROF_CNTS='.lprfc$$M' \
+		-DINSTR_PROF_VALS='.lprfv$$M' \
+		-DINSTR_PROF_VNODES='.lprfnd$$M' \
+		-DINSTR_PROF_COVMAP='.lcovmap$$M' \
+		-DINSTR_PROF_COVFUN='.lcovfun$$M' \
+		-DINSTR_PROF_ORDERFILE='.lorderfile$$M'
+else
+	LLVM_FILECHECK_OPTIONS=\
+		-check-prefixes=CHECK \
+		-DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+		-DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+		-DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \
+		-DINSTR_PROF_NAME='$(DATA_SECTION_PREFIX)__llvm_prf_names' \
+		-DINSTR_PROF_CNTS='$(DATA_SECTION_PREFIX)__llvm_prf_cnts' \
+		-DINSTR_PROF_VALS='$(DATA_SECTION_PREFIX)__llvm_prf_vals' \
+		-DINSTR_PROF_VNODES='$(DATA_SECTION_PREFIX)__llvm_prf_vnds' \
+		-DINSTR_PROF_COVMAP='$(LLVM_COV_SECTION_PREFIX)__llvm_covmap' \
+		-DINSTR_PROF_COVFUN='$(LLVM_COV_SECTION_PREFIX)__llvm_covfun' \
+		-DINSTR_PROF_ORDERFILE='$(DATA_SECTION_PREFIX)__llvm_orderfile'
+endif
+
+all: test_llvm_ir
+
+test_llvm_ir:
+	# Compile the test program with non-experimental coverage instrumentation, and generate LLVM IR
+	$(RUSTC) $(BASEDIR)/testprog.rs \
+			-Cinstrument-coverage \
+			--emit=llvm-ir
+
+	cat "$(TMPDIR)"/testprog.ll | \
+			"$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
diff --git a/tests/run-make/coverage-llvmir/filecheck.testprog.txt b/tests/run-make/coverage-llvmir/filecheck.testprog.txt
new file mode 100644
index 00000000000..c943261d799
--- /dev/null
+++ b/tests/run-make/coverage-llvmir/filecheck.testprog.txt
@@ -0,0 +1,50 @@
+# Check for metadata, variables, declarations, and function definitions injected
+# into LLVM IR when compiling with -Cinstrument-coverage.
+
+WINDOWS:      $__llvm_profile_runtime_user = comdat any
+
+CHECK:        @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
+CHECK-SAME:   section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
+
+CHECK:        @__llvm_coverage_mapping = private constant
+CHECK-SAME:   section "[[INSTR_PROF_COVMAP]]", align 8
+
+WINDOWS:      @__llvm_profile_runtime = external{{.*}}global i32
+
+CHECK:        @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME:   section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK:        @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME:   @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called
+CHECK-SAME:   section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK:        @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME:   section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK:        @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME:   @__profc__R{{[a-zA-Z0-9_]+}}testprog4main
+CHECK-SAME:   section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK:        @__llvm_prf_nm = private constant
+CHECK-SAME:   section "[[INSTR_PROF_NAME]]", align 1
+
+CHECK:        @llvm.used = appending global
+CHECK-SAME:   @__llvm_coverage_mapping
+CHECK-SAME:   @__llvm_prf_nm
+CHECK-SAME:   section "llvm.metadata"
+
+CHECK:        [[DEFINE_INTERNAL]] { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+CHECK-NEXT:   start:
+CHECK-NOT:    [[DEFINE_INTERNAL]]
+CHECK:        %pgocount = load i64, {{i64\*|ptr}}
+CHECK-SAME:   @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK:        declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
+
+WINDOWS:      define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+WINDOWS-NEXT: %1 = load i32, {{i32\*|ptr}} @__llvm_profile_runtime
+WINDOWS-NEXT: ret i32 %1
+WINDOWS-NEXT: }
+
+CHECK:        attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
+WINDOWS:      attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
diff --git a/tests/run-make/coverage-llvmir/testprog.rs b/tests/run-make/coverage-llvmir/testprog.rs
new file mode 100644
index 00000000000..358c25677ae
--- /dev/null
+++ b/tests/run-make/coverage-llvmir/testprog.rs
@@ -0,0 +1,38 @@
+pub fn will_be_called() -> &'static str {
+    let val = "called";
+    println!("{}", val);
+    val
+}
+
+pub fn will_not_be_called() -> bool {
+    println!("should not have been called");
+    false
+}
+
+pub fn print<T>(left: &str, value: T, right: &str)
+where
+    T: std::fmt::Display,
+{
+    println!("{}{}{}", left, value, right);
+}
+
+pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
+where
+    F: FnOnce(&T)
+{
+    if should_wrap {
+        wrapper(&inner)
+    }
+}
+
+fn main() {
+    let less = 1;
+    let more = 100;
+
+    if less < more {
+        wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
+        wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
+    } else {
+        wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
+    }
+}
diff --git a/tests/run-make/coverage-reports/Makefile b/tests/run-make/coverage-reports/Makefile
new file mode 100644
index 00000000000..d06cd9c6a54
--- /dev/null
+++ b/tests/run-make/coverage-reports/Makefile
@@ -0,0 +1,185 @@
+# needs-profiler-support
+# ignore-windows-gnu
+
+# FIXME(pietroalbini): this test currently does not work on cross-compiled
+# targets because remote-test is not capable of sending back the *.profraw
+# files generated by the LLVM instrumentation.
+# ignore-cross-compile
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
+# properly. Since we only have GCC on the CI ignore the test for now.
+
+include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-reports
+SOURCEDIR=../coverage
+
+# The `llvm-cov show` flag `--debug`, used to generate the `counters` output files, is only
+# enabled if LLVM assertions are enabled. This requires Rust config `llvm/optimize` and not
+# `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting
+# `NO_LLVM_ASSERTIONS=1`), so the tests must still pass even if the `--debug` flag is
+# not supported. (Note that `counters` files are only produced in the `$(TMPDIR)`
+# directory, for inspection and debugging support. They are *not* copied to `expected_*`
+# files when `--bless`ed.)
+LLVM_COV_DEBUG := $(shell \
+		"$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \
+		grep -q "Unknown command line argument '--debug'"; \
+		echo $$?)
+ifeq ($(LLVM_COV_DEBUG), 1)
+DEBUG_FLAG=--debug
+endif
+
+# FIXME(richkadel): I'm adding `--ignore-filename-regex=` line(s) for specific test(s) that produce
+# `llvm-cov` results for multiple files (for example `uses_crate.rs` and `used_crate/mod.rs`) as a
+# workaround for two problems causing tests to fail on Windows:
+#
+# 1. When multiple files appear in the `llvm-cov show` results, each file's coverage results can
+#    appear in different a different order. Whether this is random or, somehow, platform-specific,
+#    the Windows output flips the order of the files, compared to Linux. In the `uses_crate.rs`
+#    test, the only test-unique (interesting) results we care about are the results for only one
+#    of the two files, `mod/uses_crate.rs`, so the workaround is to ignore all but this one file.
+#    In the future, we may want a more sophisticated solution that splits apart `llvm-cov show`
+#    results into separate results files for each result (taking care not to create new file
+#    paths that might be too long for Windows MAX_PATH limits when creating these new sub-results,
+#    as well).
+# 2. When multiple files appear in the `llvm-cov show` results, the results for each file are
+#    prefixed with their filename, including platform-specific path separators (`\` for Windows,
+#    and `/` everywhere else). This could be filtered or normalized of course, but by ignoring
+#    coverage results for all but one of the file, the filenames are no longer included anyway.
+#    If this changes (if/when we decide to support `llvm-cov show` results for multiple files),
+#    the file path separator differences may need to be addressed.
+#
+# Since this is only a workaround, I decided to implement the override by adding an option for
+# each file to be ignored, using a `--ignore-filename-regex=` entry for each one, rather than
+# implement some more sophisticated solution with a new custom test directive in the test file
+# itself (similar to `expect-exit-status`) because that would add a lot of complexity and still
+# be a workaround, with the same result, with no benefit.
+#
+# Yes these `--ignore-filename-regex=` options are included in all invocations of `llvm-cov show`
+# for now, but it is effectively ignored for all tests that don't include this file anyway.
+#
+# (Note that it's also possible the `_counters.<test>.txt` and `<test>.json` files (if generated)
+# may order results from multiple files inconsistently, which might also have to be accommodated
+# if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators
+# appear to be normalized to `/` in those files, thankfully.)
+LLVM_COV_IGNORE_FILES=\
+	--ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)'
+
+all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
+
+# Ensure there are no `expected` results for tests that may have been removed or renamed
+.PHONY: clear_expected_if_blessed
+clear_expected_if_blessed:
+ifdef RUSTC_BLESS_TEST
+	rm -f expected_*
+endif
+
+-include clear_expected_if_blessed
+
+%: $(SOURCEDIR)/lib/%.rs
+	# Compile the test library with coverage instrumentation
+	$(RUSTC) $(SOURCEDIR)/lib/$@.rs \
+			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \
+			--crate-type rlib -Cinstrument-coverage --target $(TARGET)
+
+%: $(SOURCEDIR)/%.rs
+	# Compile the test program with coverage instrumentation
+	$(RUSTC) $(SOURCEDIR)/$@.rs \
+			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+			-L "$(TMPDIR)" -Cinstrument-coverage --target $(TARGET)
+
+	# Run it in order to generate some profiling data,
+	# with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
+	# output the coverage stats for this run.
+	LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
+			$(call RUN,$@) || \
+			( \
+				status=$$?; \
+				grep -q "^\/\/ expect-exit-status-$$status" $(SOURCEDIR)/$@.rs || \
+				( >&2 echo "program exited with an unexpected exit status: $$status"; \
+					false \
+				) \
+			)
+
+	# Run it through rustdoc as well to cover doctests.
+	# `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone
+	# might result in overwritten files and failed tests, as rustdoc spawns each
+	# doctest as its own process, so make sure the filename is as unique as possible.
+	LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \
+			$(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
+			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+			-L "$(TMPDIR)" -Cinstrument-coverage \
+			-Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
+
+	# Postprocess the profiling data so it can be used by the llvm-cov tool
+	"$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
+			"$(TMPDIR)"/$@*.profraw \
+			-o "$(TMPDIR)"/$@.profdata
+
+	# Generate a coverage report using `llvm-cov show`.
+	"$(LLVM_BIN_DIR)"/llvm-cov show \
+			$(DEBUG_FLAG) \
+			$(LLVM_COV_IGNORE_FILES) \
+			--compilation-dir=. \
+			--Xdemangler="$(RUST_DEMANGLER)" \
+			--show-line-counts-or-regions \
+			--instr-profile="$(TMPDIR)"/$@.profdata \
+			$(call BIN,"$(TMPDIR)"/$@) \
+			$$( \
+				for file in $(TMPDIR)/rustdoc-$@/*/rust_out*; do \
+				[ -x "$$file" ] && printf "%s %s " -object $$file; \
+				done \
+			) \
+		2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+		| "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
+		> "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+	( status=$$? ; \
+		>&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
+		exit $$status \
+	)
+
+ifdef DEBUG_FLAG
+	# The first line (beginning with "Args:" contains hard-coded, build-specific
+	# file paths. Strip that line and keep the remaining lines with counter debug
+	# data.
+	tail -n +2 "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+		> "$(TMPDIR)"/actual_show_coverage_counters.$@.txt
+endif
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/actual_show_coverage.$@.txt \
+			expected_show_coverage.$@.txt
+else
+	# Compare the show coverage output (`--bless` refreshes `typical` files).
+	#
+	# FIXME(richkadel): None of the Rust test source samples have the
+	# `// ignore-llvm-cov-show-diffs` anymore. This directive exists to work around a limitation
+	# with `llvm-cov show`. When reporting coverage for multiple instantiations of a generic function,
+	# with different type substitutions, `llvm-cov show` prints these in a non-deterministic order,
+	# breaking the `diff` comparison.
+	#
+	# A partial workaround is implemented below, with `diff --ignore-matching-lines=RE`
+	# to ignore each line prefixing each generic instantiation coverage code region.
+	#
+	# This workaround only works if the coverage counts are identical across all reported
+	# instantiations. If there is no way to ensure this, you may need to apply the
+	# `// ignore-llvm-cov-show-diffs` directive, and check for differences using the
+	# `.json` files to validate that results have not changed. (Until then, the JSON
+	# files are redundant, so there is no need to generate `expected_*.json` files or
+	# compare actual JSON results.)
+
+	$(DIFF) --ignore-matching-lines='^  | .*::<.*>.*:$$' --ignore-matching-lines='^  | <.*>::.*:$$' \
+		expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+		( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
+			>&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
+		) || \
+		( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \
+			false \
+		)
+endif
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
new file mode 100644
index 00000000000..00f46f42a07
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
@@ -0,0 +1,69 @@
+    1|       |#![feature(c_unwind)]
+    2|       |#![allow(unused_assignments)]
+    3|       |
+    4|     12|extern "C" fn might_abort(should_abort: bool) {
+    5|     12|    if should_abort {
+    6|      0|        println!("aborting...");
+    7|      0|        panic!("panics and aborts");
+    8|     12|    } else {
+    9|     12|        println!("Don't Panic");
+   10|     12|    }
+   11|     12|}
+   12|       |
+   13|      1|fn main() -> Result<(), u8> {
+   14|      1|    let mut countdown = 10;
+   15|     11|    while countdown > 0 {
+   16|     10|        if countdown < 5 {
+   17|      4|            might_abort(false);
+   18|      6|        }
+   19|       |        // See discussion (below the `Notes` section) on coverage results for the closing brace.
+   20|     10|        if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+                                       ^4                     ^6
+   21|       |        // For the following example, the closing brace is the last character on the line.
+   22|       |        // This shows the character after the closing brace is highlighted, even if that next
+   23|       |        // character is a newline.
+   24|     10|        if countdown < 5 { might_abort(false); }
+                                       ^4                     ^6
+   25|     10|        countdown -= 1;
+   26|       |    }
+   27|      1|    Ok(())
+   28|      1|}
+   29|       |
+   30|       |// Notes:
+   31|       |//   1. Compare this program and its coverage results to those of the similar tests
+   32|       |//      `panic_unwind.rs` and `try_error_result.rs`.
+   33|       |//   2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+   34|       |//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
+   35|       |//      results show where the program did and did not execute.
+   36|       |//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
+   37|       |//      intended"). Coverage results would show no executed coverage regions.
+   38|       |//   6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+   39|       |//      (on Linux at least).
+   40|       |
+   41|       |/*
+   42|       |
+   43|       |Expect the following coverage results:
+   44|       |
+   45|       |```text
+   46|       |    16|     11|    while countdown > 0 {
+   47|       |    17|     10|        if countdown < 5 {
+   48|       |    18|      4|            might_abort(false);
+   49|       |    19|      6|        }
+   50|       |```
+   51|       |
+   52|       |This is actually correct.
+   53|       |
+   54|       |The condition `countdown < 5` executed 10 times (10 loop iterations).
+   55|       |
+   56|       |It evaluated to `true` 4 times, and executed the `might_abort()` call.
+   57|       |
+   58|       |It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+   59|       |`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+   60|       |closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+   61|       |non-true condition.
+   62|       |
+   63|       |As another example of why this is important, say the condition was `countdown < 50`, which is always
+   64|       |`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+   65|       |The closing brace would have a count of `0`, highlighting the missed coverage.
+   66|       |*/
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.assert.txt b/tests/run-make/coverage-reports/expected_show_coverage.assert.txt
new file mode 100644
index 00000000000..405688806ea
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.assert.txt
@@ -0,0 +1,34 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-status-101
+    3|       |
+    4|      4|fn might_fail_assert(one_plus_one: u32) {
+    5|      4|    println!("does 1 + 1 = {}?", one_plus_one);
+    6|      4|    assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+                                                  ^1
+    7|      3|}
+    8|       |
+    9|      1|fn main() -> Result<(),u8> {
+   10|      1|    let mut countdown = 10;
+   11|     11|    while countdown > 0 {
+   12|     11|        if countdown == 1 {
+   13|      1|            might_fail_assert(3);
+   14|     10|        } else if countdown < 5 {
+   15|      3|            might_fail_assert(2);
+   16|      6|        }
+   17|     10|        countdown -= 1;
+   18|       |    }
+   19|      0|    Ok(())
+   20|      0|}
+   21|       |
+   22|       |// Notes:
+   23|       |//   1. Compare this program and its coverage results to those of the very similar test
+   24|       |//      `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+   25|       |//   2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+   26|       |//      related `assert_*!()` macro.
+   27|       |//   3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+   28|       |//      conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+   29|       |//      `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+   30|       |//   4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+   31|       |//      (and in many other coverage tests). The `Assert` terminator is typically generated by the
+   32|       |//      Rust compiler to check for runtime failures, such as numeric overflows.
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async.txt b/tests/run-make/coverage-reports/expected_show_coverage.async.txt
new file mode 100644
index 00000000000..87ccb6c43ea
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.async.txt
@@ -0,0 +1,139 @@
+    1|       |#![allow(unused_assignments, dead_code)]
+    2|       |
+    3|       |// compile-flags: --edition=2018 -C opt-level=1
+    4|       |
+    5|      1|async fn c(x: u8) -> u8 {
+    6|      1|    if x == 8 {
+    7|      1|        1
+    8|       |    } else {
+    9|      0|        0
+   10|       |    }
+   11|      1|}
+   12|       |
+   13|      0|async fn d() -> u8 { 1 }
+   14|       |
+   15|      0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+   16|       |
+   17|      1|async fn f() -> u8 { 1 }
+   18|       |
+   19|      0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+   20|       |
+   21|      1|pub async fn g(x: u8) {
+   22|      0|    match x {
+   23|      0|        y if e().await == y => (),
+   24|      0|        y if f().await == y => (),
+   25|      0|        _ => (),
+   26|       |    }
+   27|      0|}
+   28|       |
+   29|      1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
+   30|      0|                       // executed (not awaited) so the open brace has a `0` count (at least when
+   31|      0|                       // displayed with `llvm-cov show` in color-mode).
+   32|      0|    match x {
+   33|      0|        y if foo().await[y] => (),
+   34|      0|        _ => (),
+   35|       |    }
+   36|      0|}
+   37|       |
+   38|      1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+   39|      1|                    // (a) the function signature, counted when the function is called; and
+   40|      1|                    // (b) the open brace for the function body, counted once when the body is
+   41|      1|                    // executed asynchronously.
+   42|      1|    match x {
+   43|      1|        y if c(x).await == y + 1 => { d().await; }
+                      ^0       ^0                   ^0 ^0
+   44|      1|        y if f().await == y + 1 => (),
+                      ^0      ^0                 ^0
+   45|      1|        _ => (),
+   46|       |    }
+   47|      1|}
+   48|       |
+   49|      1|fn j(x: u8) {
+   50|      1|    // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+   51|      1|    fn c(x: u8) -> u8 {
+   52|      1|        if x == 8 {
+   53|      1|            1 // This line appears covered, but the 1-character expression span covering the `1`
+                          ^0
+   54|      1|              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+   55|      1|              // `fn j()` executes the open brace for the function body, followed by the function's
+   56|      1|              // first executable statement, `match x`. Inner function declarations are not
+   57|      1|              // "visible" to the MIR for `j()`, so the code region counts all lines between the
+   58|      1|              // open brace and the first statement as executed, which is, in a sense, true.
+   59|      1|              // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+   60|      1|              // of the enclosed coverages, (that is, the `1` expression was not executed, and
+   61|      1|              // accurately displays a `0`).
+   62|      1|        } else {
+   63|      1|            0
+   64|      1|        }
+   65|      1|    }
+   66|      1|    fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+                  ^0
+   67|      1|    fn f() -> u8 { 1 }
+   68|      1|    match x {
+   69|      1|        y if c(x) == y + 1 => { d(); }
+                      ^0                    ^0
+   70|      1|        y if f() == y + 1 => (),
+                      ^0                   ^0
+   71|      1|        _ => (),
+   72|       |    }
+   73|      1|}
+   74|       |
+   75|      0|fn k(x: u8) { // unused function
+   76|      0|    match x {
+   77|      0|        1 => (),
+   78|      0|        2 => (),
+   79|      0|        _ => (),
+   80|       |    }
+   81|      0|}
+   82|       |
+   83|      1|fn l(x: u8) {
+   84|      1|    match x {
+   85|      0|        1 => (),
+   86|      0|        2 => (),
+   87|      1|        _ => (),
+   88|       |    }
+   89|      1|}
+   90|       |
+   91|      1|async fn m(x: u8) -> u8 { x - 1 }
+                                      ^0
+   92|       |
+   93|      1|fn main() {
+   94|      1|    let _ = g(10);
+   95|      1|    let _ = h(9);
+   96|      1|    let mut future = Box::pin(i(8));
+   97|      1|    j(7);
+   98|      1|    l(6);
+   99|      1|    let _ = m(5);
+  100|      1|    executor::block_on(future.as_mut());
+  101|      1|}
+  102|       |
+  103|       |mod executor {
+  104|       |    use core::{
+  105|       |        future::Future,
+  106|       |        pin::Pin,
+  107|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+  108|       |    };
+  109|       |
+  110|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  111|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  112|      1|        use std::hint::unreachable_unchecked;
+  113|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  114|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+                              ^0
+  115|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+                              ^0
+  116|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+                              ^0
+  117|      1|            |_| (),
+  118|      1|        );
+  119|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  120|      1|        let mut context = Context::from_waker(&waker);
+  121|       |
+  122|       |        loop {
+  123|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  124|      1|                break val;
+  125|      0|            }
+  126|       |        }
+  127|      1|    }
+  128|       |}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async2.txt b/tests/run-make/coverage-reports/expected_show_coverage.async2.txt
new file mode 100644
index 00000000000..500dde1f269
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.async2.txt
@@ -0,0 +1,116 @@
+    1|       |// compile-flags: --edition=2018
+    2|       |
+    3|       |use core::{
+    4|       |    future::Future,
+    5|       |    marker::Send,
+    6|       |    pin::Pin,
+    7|       |};
+    8|       |
+    9|      1|fn non_async_func() {
+   10|      1|    println!("non_async_func was covered");
+   11|      1|    let b = true;
+   12|      1|    if b {
+   13|      1|        println!("non_async_func println in block");
+   14|      1|    }
+                   ^0
+   15|      1|}
+   16|       |
+   17|       |
+   18|       |
+   19|       |
+   20|      1|async fn async_func() {
+   21|      1|    println!("async_func was covered");
+   22|      1|    let b = true;
+   23|      1|    if b {
+   24|      1|        println!("async_func println in block");
+   25|      1|    }
+                   ^0
+   26|      1|}
+   27|       |
+   28|       |
+   29|       |
+   30|       |
+   31|      1|async fn async_func_just_println() {
+   32|      1|    println!("async_func_just_println was covered");
+   33|      1|}
+   34|       |
+   35|      1|fn main() {
+   36|      1|    println!("codecovsample::main");
+   37|      1|
+   38|      1|    non_async_func();
+   39|      1|
+   40|      1|    executor::block_on(async_func());
+   41|      1|    executor::block_on(async_func_just_println());
+   42|      1|}
+   43|       |
+   44|       |mod executor {
+   45|       |    use core::{
+   46|       |        future::Future,
+   47|       |        pin::Pin,
+   48|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+   49|       |    };
+   50|       |
+   51|      2|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   52|      2|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+   53|      2|        use std::hint::unreachable_unchecked;
+   54|      2|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+   55|      2|            |_| unsafe { unreachable_unchecked() }, // clone
+                              ^0
+   56|      2|            |_| unsafe { unreachable_unchecked() }, // wake
+                              ^0
+   57|      2|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+                              ^0
+   58|      2|            |_| (),
+   59|      2|        );
+   60|      2|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+   61|      2|        let mut context = Context::from_waker(&waker);
+   62|       |
+   63|       |        loop {
+   64|      2|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   65|      2|                break val;
+   66|      0|            }
+   67|       |        }
+   68|      2|    }
+  ------------------
+  | async2::executor::block_on::<async2::async_func::{closure#0}>:
+  |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  |   53|      1|        use std::hint::unreachable_unchecked;
+  |   54|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  |   55|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+  |   56|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+  |   57|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+  |   58|      1|            |_| (),
+  |   59|      1|        );
+  |   60|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  |   61|      1|        let mut context = Context::from_waker(&waker);
+  |   62|       |
+  |   63|       |        loop {
+  |   64|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  |   65|      1|                break val;
+  |   66|      0|            }
+  |   67|       |        }
+  |   68|      1|    }
+  ------------------
+  | async2::executor::block_on::<async2::async_func_just_println::{closure#0}>:
+  |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  |   53|      1|        use std::hint::unreachable_unchecked;
+  |   54|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  |   55|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+  |   56|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+  |   57|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+  |   58|      1|            |_| (),
+  |   59|      1|        );
+  |   60|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  |   61|      1|        let mut context = Context::from_waker(&waker);
+  |   62|       |
+  |   63|       |        loop {
+  |   64|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  |   65|      1|                break val;
+  |   66|      0|            }
+  |   67|       |        }
+  |   68|      1|    }
+  ------------------
+   69|       |}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt b/tests/run-make/coverage-reports/expected_show_coverage.closure.txt
new file mode 100644
index 00000000000..e463099a5ee
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.closure.txt
@@ -0,0 +1,222 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|    let is_false = ! is_true;
+    9|      1|
+   10|      1|    let mut some_string = Some(String::from("the string content"));
+   11|      1|    println!(
+   12|      1|        "The string or alt: {}"
+   13|      1|        ,
+   14|      1|        some_string
+   15|      1|            .
+   16|      1|            unwrap_or_else
+   17|      1|        (
+   18|      1|            ||
+   19|      0|            {
+   20|      0|                let mut countdown = 0;
+   21|      0|                if is_false {
+   22|      0|                    countdown = 10;
+   23|      0|                }
+   24|      0|                "alt string 1".to_owned()
+   25|      1|            }
+   26|      1|        )
+   27|      1|    );
+   28|      1|
+   29|      1|    some_string = Some(String::from("the string content"));
+   30|      1|    let
+   31|      1|        a
+   32|      1|    =
+   33|      1|        ||
+   34|      0|    {
+   35|      0|        let mut countdown = 0;
+   36|      0|        if is_false {
+   37|      0|            countdown = 10;
+   38|      0|        }
+   39|      0|        "alt string 2".to_owned()
+   40|      0|    };
+   41|      1|    println!(
+   42|      1|        "The string or alt: {}"
+   43|      1|        ,
+   44|      1|        some_string
+   45|      1|            .
+   46|      1|            unwrap_or_else
+   47|      1|        (
+   48|      1|            a
+   49|      1|        )
+   50|      1|    );
+   51|      1|
+   52|      1|    some_string = None;
+   53|      1|    println!(
+   54|      1|        "The string or alt: {}"
+   55|      1|        ,
+   56|      1|        some_string
+   57|      1|            .
+   58|      1|            unwrap_or_else
+   59|      1|        (
+   60|      1|            ||
+   61|      1|            {
+   62|      1|                let mut countdown = 0;
+   63|      1|                if is_false {
+   64|      0|                    countdown = 10;
+   65|      1|                }
+   66|      1|                "alt string 3".to_owned()
+   67|      1|            }
+   68|      1|        )
+   69|      1|    );
+   70|      1|
+   71|      1|    some_string = None;
+   72|      1|    let
+   73|      1|        a
+   74|      1|    =
+   75|      1|        ||
+   76|      1|    {
+   77|      1|        let mut countdown = 0;
+   78|      1|        if is_false {
+   79|      0|            countdown = 10;
+   80|      1|        }
+   81|      1|        "alt string 4".to_owned()
+   82|      1|    };
+   83|      1|    println!(
+   84|      1|        "The string or alt: {}"
+   85|      1|        ,
+   86|      1|        some_string
+   87|      1|            .
+   88|      1|            unwrap_or_else
+   89|      1|        (
+   90|      1|            a
+   91|      1|        )
+   92|      1|    );
+   93|      1|
+   94|      1|    let
+   95|      1|        quote_closure
+   96|      1|    =
+   97|      1|        |val|
+   98|      5|    {
+   99|      5|        let mut countdown = 0;
+  100|      5|        if is_false {
+  101|      0|            countdown = 10;
+  102|      5|        }
+  103|      5|        format!("'{}'", val)
+  104|      5|    };
+  105|      1|    println!(
+  106|      1|        "Repeated, quoted string: {:?}"
+  107|      1|        ,
+  108|      1|        std::iter::repeat("repeat me")
+  109|      1|            .take(5)
+  110|      1|            .map
+  111|      1|        (
+  112|      1|            quote_closure
+  113|      1|        )
+  114|      1|            .collect::<Vec<_>>()
+  115|      1|    );
+  116|      1|
+  117|      1|    let
+  118|      1|        _unused_closure
+  119|       |    =
+  120|       |        |
+  121|       |            mut countdown
+  122|       |        |
+  123|      0|    {
+  124|      0|        if is_false {
+  125|      0|            countdown = 10;
+  126|      0|        }
+  127|      0|        "closure should be unused".to_owned()
+  128|      0|    };
+  129|       |
+  130|      1|    let mut countdown = 10;
+  131|      1|    let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+                                                                  ^0
+  132|       |
+  133|       |
+  134|      1|    let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+  135|      1|    let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+                                                                              ^0
+  136|      1|    let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+                                                                        ^0
+  137|       |
+  138|       |
+  139|       |
+  140|       |
+  141|      1|    let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+                                                                        ^0
+  142|       |
+  143|      1|    let _shortish_unused_closure = | _unused_arg: u8 | {
+  144|      0|        println!("not called")
+  145|      0|    };
+  146|       |
+  147|      1|    let _as_short_unused_closure = |
+  148|       |        _unused_arg: u8
+  149|      0|    | { println!("not called") };
+  150|       |
+  151|      1|    let _almost_as_short_unused_closure = |
+  152|       |        _unused_arg: u8
+  153|      0|    | { println!("not called") }
+  154|       |    ;
+  155|       |
+  156|       |
+  157|       |
+  158|       |
+  159|       |
+  160|      1|    let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+  161|      0|println!("not called")
+  162|       |    ;
+  163|       |
+  164|      1|    let _short_unused_closure_line_break_no_block2 =
+  165|       |        | _unused_arg: u8 |
+  166|      0|            println!(
+  167|      0|                "not called"
+  168|      0|            )
+  169|       |    ;
+  170|       |
+  171|      1|    let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+  172|       |        | _unused_arg: u8 |
+  173|      0|            println!(
+  174|      0|                "not called: {}",
+  175|      0|                if is_true { "check" } else { "me" }
+  176|      0|            )
+  177|       |    ;
+  178|       |
+  179|      1|    let short_used_not_covered_closure_line_break_block_embedded_branch =
+  180|      1|        | _unused_arg: u8 |
+  181|      0|        {
+  182|      0|            println!(
+  183|      0|                "not called: {}",
+  184|      0|                if is_true { "check" } else { "me" }
+  185|       |            )
+  186|      0|        }
+  187|       |    ;
+  188|       |
+  189|      1|    let short_used_covered_closure_line_break_no_block_embedded_branch =
+  190|      1|        | _unused_arg: u8 |
+  191|      1|            println!(
+  192|      1|                "not called: {}",
+  193|      1|                if is_true { "check" } else { "me" }
+                                                            ^0
+  194|      1|            )
+  195|       |    ;
+  196|       |
+  197|      1|    let short_used_covered_closure_line_break_block_embedded_branch =
+  198|      1|        | _unused_arg: u8 |
+  199|      1|        {
+  200|      1|            println!(
+  201|      1|                "not called: {}",
+  202|      1|                if is_true { "check" } else { "me" }
+                                                            ^0
+  203|       |            )
+  204|      1|        }
+  205|       |    ;
+  206|       |
+  207|      1|    if is_false {
+  208|      0|        short_used_not_covered_closure_macro(0);
+  209|      0|        short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+  210|      0|        short_used_not_covered_closure_line_break_block_embedded_branch(0);
+  211|      1|    }
+  212|      1|    short_used_covered_closure_macro(0);
+  213|      1|    short_used_covered_closure_line_break_no_block_embedded_branch(0);
+  214|      1|    short_used_covered_closure_line_break_block_embedded_branch(0);
+  215|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt b/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
new file mode 100644
index 00000000000..87f7014760e
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
@@ -0,0 +1,42 @@
+    1|       |// compile-flags: --edition=2018
+    2|       |#![feature(no_coverage)]
+    3|       |
+    4|       |macro_rules! bail {
+    5|       |    ($msg:literal $(,)?) => {
+    6|       |        if $msg.len() > 0 {
+    7|       |            println!("no msg");
+    8|       |        } else {
+    9|       |            println!($msg);
+   10|       |        }
+   11|       |        return Err(String::from($msg));
+   12|       |    };
+   13|       |}
+   14|       |
+   15|       |macro_rules! on_error {
+   16|       |    ($value:expr, $error_message:expr) => {
+   17|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+   18|       |            let message = format!($error_message, e);
+   19|       |            if message.len() > 0 {
+   20|       |                println!("{}", message);
+   21|       |                Ok(String::from("ok"))
+   22|       |            } else {
+   23|       |                bail!("error");
+   24|       |            }
+   25|       |        })
+   26|       |    };
+   27|       |}
+   28|       |
+   29|      1|fn load_configuration_files() -> Result<String, String> {
+   30|      1|    Ok(String::from("config"))
+   31|      1|}
+   32|       |
+   33|      1|pub fn main() -> Result<(), String> {
+   34|      1|    println!("Starting service");
+   35|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+                                                                                                 ^0
+   36|       |
+   37|      1|    let startup_delay_duration = String::from("arg");
+   38|      1|    let _ = (config, startup_delay_duration);
+   39|      1|    Ok(())
+   40|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt b/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
new file mode 100644
index 00000000000..2b5418132c3
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
@@ -0,0 +1,83 @@
+    1|       |// compile-flags: --edition=2018
+    2|       |#![feature(no_coverage)]
+    3|       |
+    4|       |macro_rules! bail {
+    5|       |    ($msg:literal $(,)?) => {
+    6|       |        if $msg.len() > 0 {
+    7|       |            println!("no msg");
+    8|       |        } else {
+    9|       |            println!($msg);
+   10|       |        }
+   11|       |        return Err(String::from($msg));
+   12|       |    };
+   13|       |}
+   14|       |
+   15|       |macro_rules! on_error {
+   16|       |    ($value:expr, $error_message:expr) => {
+   17|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+   18|       |            let message = format!($error_message, e);
+   19|       |            if message.len() > 0 {
+   20|       |                println!("{}", message);
+   21|       |                Ok(String::from("ok"))
+   22|       |            } else {
+   23|       |                bail!("error");
+   24|       |            }
+   25|       |        })
+   26|       |    };
+   27|       |}
+   28|       |
+   29|      1|fn load_configuration_files() -> Result<String, String> {
+   30|      1|    Ok(String::from("config"))
+   31|      1|}
+   32|       |
+   33|      1|pub async fn test() -> Result<(), String> {
+   34|      1|    println!("Starting service");
+   35|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+                                                                                                 ^0
+   36|       |
+   37|      1|    let startup_delay_duration = String::from("arg");
+   38|      1|    let _ = (config, startup_delay_duration);
+   39|      1|    Ok(())
+   40|      1|}
+   41|       |
+   42|       |#[no_coverage]
+   43|       |fn main() {
+   44|       |    executor::block_on(test());
+   45|       |}
+   46|       |
+   47|       |mod executor {
+   48|       |    use core::{
+   49|       |        future::Future,
+   50|       |        pin::Pin,
+   51|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+   52|       |    };
+   53|       |
+   54|       |    #[no_coverage]
+   55|       |    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   56|       |        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+   57|       |        use std::hint::unreachable_unchecked;
+   58|       |        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+   59|       |
+   60|       |            #[no_coverage]
+   61|       |            |_| unsafe { unreachable_unchecked() }, // clone
+   62|       |
+   63|       |            #[no_coverage]
+   64|       |            |_| unsafe { unreachable_unchecked() }, // wake
+   65|       |
+   66|       |            #[no_coverage]
+   67|       |            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+   68|       |
+   69|       |            #[no_coverage]
+   70|       |            |_| (),
+   71|       |        );
+   72|       |        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+   73|       |        let mut context = Context::from_waker(&waker);
+   74|       |
+   75|       |        loop {
+   76|       |            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   77|       |                break val;
+   78|       |            }
+   79|       |        }
+   80|       |    }
+   81|       |}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt b/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt
new file mode 100644
index 00000000000..2d8a98a5d0c
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt
@@ -0,0 +1,94 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    let mut countdown = 0;
+    5|      1|    if true {
+    6|      1|        countdown = 10;
+    7|      1|    }
+                   ^0
+    8|       |
+    9|       |    const B: u32 = 100;
+   10|      1|    let x = if countdown > 7 {
+   11|      1|        countdown -= 4;
+   12|      1|        B
+   13|      0|    } else if countdown > 2 {
+   14|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   15|      0|            countdown = 0;
+   16|      0|        }
+   17|      0|        countdown -= 5;
+   18|      0|        countdown
+   19|       |    } else {
+   20|      0|        return;
+   21|       |    };
+   22|       |
+   23|      1|    let mut countdown = 0;
+   24|      1|    if true {
+   25|      1|        countdown = 10;
+   26|      1|    }
+                   ^0
+   27|       |
+   28|      1|    if countdown > 7 {
+   29|      1|        countdown -= 4;
+   30|      1|    } else if countdown > 2 {
+                            ^0
+   31|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   32|      0|            countdown = 0;
+   33|      0|        }
+   34|      0|        countdown -= 5;
+   35|       |    } else {
+   36|      0|        return;
+   37|       |    }
+   38|       |
+   39|      1|    if true {
+   40|      1|        let mut countdown = 0;
+   41|      1|        if true {
+   42|      1|            countdown = 10;
+   43|      1|        }
+                       ^0
+   44|       |
+   45|      1|        if countdown > 7 {
+   46|      1|            countdown -= 4;
+   47|      1|        }
+   48|      0|        else if countdown > 2 {
+   49|      0|            if countdown < 1 || countdown > 5 || countdown != 9 {
+   50|      0|                countdown = 0;
+   51|      0|            }
+   52|      0|            countdown -= 5;
+   53|       |        } else {
+   54|      0|            return;
+   55|       |        }
+   56|      0|    }
+   57|       |
+   58|       |
+   59|      1|    let mut countdown = 0;
+   60|      1|    if true {
+   61|      1|        countdown = 1;
+   62|      1|    }
+                   ^0
+   63|       |
+   64|      1|    let z = if countdown > 7 {
+                      ^0
+   65|      0|        countdown -= 4;
+   66|      1|    } else if countdown > 2 {
+   67|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   68|      0|            countdown = 0;
+   69|      0|        }
+   70|      0|        countdown -= 5;
+   71|       |    } else {
+   72|      1|        let should_be_reachable = countdown;
+   73|      1|        println!("reached");
+   74|      1|        return;
+   75|       |    };
+   76|       |
+   77|      0|    let w = if countdown > 7 {
+   78|      0|        countdown -= 4;
+   79|      0|    } else if countdown > 2 {
+   80|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   81|      0|            countdown = 0;
+   82|      0|        }
+   83|      0|        countdown -= 5;
+   84|       |    } else {
+   85|      0|        return;
+   86|       |    };
+   87|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt b/tests/run-make/coverage-reports/expected_show_coverage.continue.txt
new file mode 100644
index 00000000000..1c64ead9f26
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.continue.txt
@@ -0,0 +1,70 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    let is_true = std::env::args().len() == 1;
+    5|      1|
+    6|      1|    let mut x = 0;
+    7|     11|    for _ in 0..10 {
+    8|     10|        match is_true {
+    9|       |            true => {
+   10|     10|                continue;
+   11|       |            }
+   12|      0|            _ => {
+   13|      0|                x = 1;
+   14|      0|            }
+   15|      0|        }
+   16|      0|        x = 3;
+   17|       |    }
+   18|     11|    for _ in 0..10 {
+   19|     10|        match is_true {
+   20|      0|            false => {
+   21|      0|                x = 1;
+   22|      0|            }
+   23|       |            _ => {
+   24|     10|                continue;
+   25|       |            }
+   26|       |        }
+   27|      0|        x = 3;
+   28|       |    }
+   29|     11|    for _ in 0..10 {
+   30|     10|        match is_true {
+   31|     10|            true => {
+   32|     10|                x = 1;
+   33|     10|            }
+   34|       |            _ => {
+   35|      0|                continue;
+   36|       |            }
+   37|       |        }
+   38|     10|        x = 3;
+   39|       |    }
+   40|     11|    for _ in 0..10 {
+   41|     10|        if is_true {
+   42|     10|            continue;
+   43|      0|        }
+   44|      0|        x = 3;
+   45|       |    }
+   46|     11|    for _ in 0..10 {
+   47|     10|        match is_true {
+   48|      0|            false => {
+   49|      0|                x = 1;
+   50|      0|            }
+   51|     10|            _ => {
+   52|     10|                let _ = x;
+   53|     10|            }
+   54|       |        }
+   55|     10|        x = 3;
+   56|       |    }
+   57|      1|    for _ in 0..10 {
+   58|      1|        match is_true {
+   59|      0|            false => {
+   60|      0|                x = 1;
+   61|      0|            }
+   62|       |            _ => {
+   63|      1|                break;
+   64|       |            }
+   65|       |        }
+   66|      0|        x = 3;
+   67|       |    }
+   68|       |    let _ = x;
+   69|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt b/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt
new file mode 100644
index 00000000000..09ff14c6f27
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt
@@ -0,0 +1,39 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      0|pub fn unused_pub_fn_not_in_library() {
+    4|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      0|    // dependent conditions.
+    7|      0|    let is_true = std::env::args().len() == 1;
+    8|      0|
+    9|      0|    let mut countdown = 0;
+   10|      0|    if is_true {
+   11|      0|        countdown = 10;
+   12|      0|    }
+   13|      0|}
+   14|       |
+   15|      0|fn unused_fn() {
+   16|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   17|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   18|      0|    // dependent conditions.
+   19|      0|    let is_true = std::env::args().len() == 1;
+   20|      0|
+   21|      0|    let mut countdown = 0;
+   22|      0|    if is_true {
+   23|      0|        countdown = 10;
+   24|      0|    }
+   25|      0|}
+   26|       |
+   27|      1|fn main() {
+   28|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   29|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   30|      1|    // dependent conditions.
+   31|      1|    let is_true = std::env::args().len() == 1;
+   32|      1|
+   33|      1|    let mut countdown = 0;
+   34|      1|    if is_true {
+   35|      1|        countdown = 10;
+   36|      1|    }
+                   ^0
+   37|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt b/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt
new file mode 100644
index 00000000000..732de652627
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt
@@ -0,0 +1,115 @@
+../coverage/doctest.rs:
+    1|       |//! This test ensures that code from doctests is properly re-mapped.
+    2|       |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+    3|       |//!
+    4|       |//! Just some random code:
+    5|      1|//! ```
+    6|      1|//! if true {
+    7|       |//!     // this is executed!
+    8|      1|//!     assert_eq!(1, 1);
+    9|       |//! } else {
+   10|       |//!     // this is not!
+   11|      0|//!     assert_eq!(1, 2);
+   12|       |//! }
+   13|      1|//! ```
+   14|       |//!
+   15|       |//! doctest testing external code:
+   16|       |//! ```
+   17|      1|//! extern crate doctest_crate;
+   18|      1|//! doctest_crate::fn_run_in_doctests(1);
+   19|      1|//! ```
+   20|       |//!
+   21|       |//! doctest returning a result:
+   22|      1|//! ```
+   23|      2|//! #[derive(Debug, PartialEq)]
+                       ^1
+   24|      1|//! struct SomeError {
+   25|      1|//!     msg: String,
+   26|      1|//! }
+   27|      1|//! let mut res = Err(SomeError { msg: String::from("a message") });
+   28|      1|//! if res.is_ok() {
+   29|      0|//!     res?;
+   30|       |//! } else {
+   31|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   32|      1|//!         println!("{:?}", res);
+   33|      1|//!     }
+                   ^0
+   34|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   35|      1|//!         res = Ok(1);
+   36|      1|//!     }
+                   ^0
+   37|      1|//!     res = Ok(0);
+   38|       |//! }
+   39|       |//! // need to be explicit because rustdoc cant infer the return type
+   40|      1|//! Ok::<(), SomeError>(())
+   41|      1|//! ```
+   42|       |//!
+   43|       |//! doctest with custom main:
+   44|       |//! ```
+   45|      1|//! fn some_func() {
+   46|      1|//!     println!("called some_func()");
+   47|      1|//! }
+   48|       |//!
+   49|      0|//! #[derive(Debug)]
+   50|       |//! struct SomeError;
+   51|       |//!
+   52|       |//! extern crate doctest_crate;
+   53|       |//!
+   54|      1|//! fn doctest_main() -> Result<(), SomeError> {
+   55|      1|//!     some_func();
+   56|      1|//!     doctest_crate::fn_run_in_doctests(2);
+   57|      1|//!     Ok(())
+   58|      1|//! }
+   59|       |//!
+   60|       |//! // this `main` is not shown as covered, as it clashes with all the other
+   61|       |//! // `main` functions that were automatically generated for doctests
+   62|       |//! fn main() -> Result<(), SomeError> {
+   63|       |//!     doctest_main()
+   64|       |//! }
+   65|       |//! ```
+   66|       |
+   67|       |/// doctest attached to fn testing external code:
+   68|       |/// ```
+   69|      1|/// extern crate doctest_crate;
+   70|      1|/// doctest_crate::fn_run_in_doctests(3);
+   71|      1|/// ```
+   72|       |///
+   73|      1|fn main() {
+   74|      1|    if true {
+   75|      1|        assert_eq!(1, 1);
+   76|       |    } else {
+   77|      0|        assert_eq!(1, 2);
+   78|       |    }
+   79|      1|}
+   80|       |
+   81|       |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+   82|       |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+   83|       |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+   84|       |//
+   85|       |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+   86|       |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+   87|       |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+   88|       |// one character past, the `if` block's closing brace. In both cases, these are most likely off
+   89|       |// by the number of characters stripped from the beginning of each doc comment line: indent
+   90|       |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+   91|       |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+   92|       |// more pronounced, and show up in more places, with background color used to show some distinct
+   93|       |// code regions with different coverage counts.
+   94|       |//
+   95|       |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+   96|       |// character stripped from the beginning of doc comment lines with a space. This will give coverage
+   97|       |// results the correct column offsets, and I think it should compile correctly, but I don't know
+   98|       |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+   99|       |// if the indentation changed. I don't know if there is a more viable solution.
+
+../coverage/lib/doctest_crate.rs:
+    1|       |/// A function run only from within doctests
+    2|      3|pub fn fn_run_in_doctests(conditional: usize) {
+    3|      3|    match conditional {
+    4|      1|        1 => assert_eq!(1, 1), // this is run,
+    5|      1|        2 => assert_eq!(1, 1), // this,
+    6|      1|        3 => assert_eq!(1, 1), // and this too
+    7|      0|        _ => assert_eq!(1, 2), // however this is not
+    8|       |    }
+    9|      3|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt b/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
new file mode 100644
index 00000000000..fe6a9e93cbf
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
@@ -0,0 +1,34 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-status-1
+    3|       |
+    4|       |struct Firework {
+    5|       |    strength: i32,
+    6|       |}
+    7|       |
+    8|       |impl Drop for Firework {
+    9|      2|    fn drop(&mut self) {
+   10|      2|        println!("BOOM times {}!!!", self.strength);
+   11|      2|    }
+   12|       |}
+   13|       |
+   14|      1|fn main() -> Result<(),u8> {
+   15|      1|    let _firecracker = Firework { strength: 1 };
+   16|      1|
+   17|      1|    let _tnt = Firework { strength: 100 };
+   18|      1|
+   19|      1|    if true {
+   20|      1|        println!("Exiting with error...");
+   21|      1|        return Err(1);
+   22|      0|    }
+   23|      0|
+   24|      0|    let _ = Firework { strength: 1000 };
+   25|      0|
+   26|      0|    Ok(())
+   27|      1|}
+   28|       |
+   29|       |// Expected program output:
+   30|       |//   Exiting with error...
+   31|       |//   BOOM times 100!!!
+   32|       |//   BOOM times 1!!!
+   33|       |//   Error: 1
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generator.txt b/tests/run-make/coverage-reports/expected_show_coverage.generator.txt
new file mode 100644
index 00000000000..0fb3808ff2e
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.generator.txt
@@ -0,0 +1,32 @@
+    1|       |#![feature(generators, generator_trait)]
+    2|       |
+    3|       |use std::ops::{Generator, GeneratorState};
+    4|       |use std::pin::Pin;
+    5|       |
+    6|       |// The following implementation of a function called from a `yield` statement
+    7|       |// (apparently requiring the Result and the `String` type or constructor)
+    8|       |// creates conditions where the `generator::StateTransform` MIR transform will
+    9|       |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+   10|       |// to handle this condition, and still report dead block coverage.
+   11|      1|fn get_u32(val: bool) -> Result<u32, String> {
+   12|      1|    if val { Ok(1) } else { Err(String::from("some error")) }
+                                          ^0
+   13|      1|}
+   14|       |
+   15|      1|fn main() {
+   16|      1|    let is_true = std::env::args().len() == 1;
+   17|      1|    let mut generator = || {
+   18|      1|        yield get_u32(is_true);
+   19|      1|        return "foo";
+   20|      1|    };
+   21|       |
+   22|      1|    match Pin::new(&mut generator).resume(()) {
+   23|      1|        GeneratorState::Yielded(Ok(1)) => {}
+   24|      0|        _ => panic!("unexpected return from resume"),
+   25|       |    }
+   26|      1|    match Pin::new(&mut generator).resume(()) {
+   27|      1|        GeneratorState::Complete("foo") => {}
+   28|      0|        _ => panic!("unexpected return from resume"),
+   29|       |    }
+   30|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generics.txt b/tests/run-make/coverage-reports/expected_show_coverage.generics.txt
new file mode 100644
index 00000000000..48983ba4358
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.generics.txt
@@ -0,0 +1,71 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-status-1
+    3|       |
+    4|       |struct Firework<T> where T: Copy + std::fmt::Display {
+    5|       |    strength: T,
+    6|       |}
+    7|       |
+    8|       |impl<T> Firework<T> where T: Copy + std::fmt::Display {
+    9|       |    #[inline(always)]
+   10|      3|    fn set_strength(&mut self, new_strength: T) {
+   11|      3|        self.strength = new_strength;
+   12|      3|    }
+  ------------------
+  | <generics::Firework<i32>>::set_strength:
+  |   10|      1|    fn set_strength(&mut self, new_strength: T) {
+  |   11|      1|        self.strength = new_strength;
+  |   12|      1|    }
+  ------------------
+  | <generics::Firework<f64>>::set_strength:
+  |   10|      2|    fn set_strength(&mut self, new_strength: T) {
+  |   11|      2|        self.strength = new_strength;
+  |   12|      2|    }
+  ------------------
+   13|       |}
+   14|       |
+   15|       |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+   16|       |    #[inline(always)]
+   17|      2|    fn drop(&mut self) {
+   18|      2|        println!("BOOM times {}!!!", self.strength);
+   19|      2|    }
+  ------------------
+  | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
+  |   17|      1|    fn drop(&mut self) {
+  |   18|      1|        println!("BOOM times {}!!!", self.strength);
+  |   19|      1|    }
+  ------------------
+  | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
+  |   17|      1|    fn drop(&mut self) {
+  |   18|      1|        println!("BOOM times {}!!!", self.strength);
+  |   19|      1|    }
+  ------------------
+   20|       |}
+   21|       |
+   22|      1|fn main() -> Result<(),u8> {
+   23|      1|    let mut firecracker = Firework { strength: 1 };
+   24|      1|    firecracker.set_strength(2);
+   25|      1|
+   26|      1|    let mut tnt = Firework { strength: 100.1 };
+   27|      1|    tnt.set_strength(200.1);
+   28|      1|    tnt.set_strength(300.3);
+   29|      1|
+   30|      1|    if true {
+   31|      1|        println!("Exiting with error...");
+   32|      1|        return Err(1);
+   33|      0|    }
+   34|      0|
+   35|      0|
+   36|      0|
+   37|      0|
+   38|      0|
+   39|      0|    let _ = Firework { strength: 1000 };
+   40|      0|
+   41|      0|    Ok(())
+   42|      1|}
+   43|       |
+   44|       |// Expected program output:
+   45|       |//   Exiting with error...
+   46|       |//   BOOM times 100!!!
+   47|       |//   BOOM times 1!!!
+   48|       |//   Error: 1
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if.txt b/tests/run-make/coverage-reports/expected_show_coverage.if.txt
new file mode 100644
index 00000000000..0c9eff227ed
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.if.txt
@@ -0,0 +1,30 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let
+    8|      1|    is_true
+    9|      1|    =
+   10|      1|        std::env::args().len()
+   11|      1|    ==
+   12|      1|        1
+   13|      1|    ;
+   14|      1|    let
+   15|      1|        mut
+   16|      1|    countdown
+   17|      1|    =
+   18|      1|        0
+   19|      1|    ;
+   20|      1|    if
+   21|      1|        is_true
+   22|      1|    {
+   23|      1|        countdown
+   24|      1|        =
+   25|      1|            10
+   26|      1|        ;
+   27|      1|    }
+                   ^0
+   28|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt b/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt
new file mode 100644
index 00000000000..4285d318686
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt
@@ -0,0 +1,41 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 0;
+   10|      1|    if
+   11|      1|        is_true
+   12|      1|    {
+   13|      1|        countdown
+   14|      1|        =
+   15|      1|            10
+   16|      1|        ;
+   17|      1|    }
+   18|       |    else // Note coverage region difference without semicolon
+   19|       |    {
+   20|      0|        countdown
+   21|      0|        =
+   22|      0|            100
+   23|       |    }
+   24|       |
+   25|       |    if
+   26|      1|        is_true
+   27|      1|    {
+   28|      1|        countdown
+   29|      1|        =
+   30|      1|            10
+   31|      1|        ;
+   32|      1|    }
+   33|       |    else
+   34|      0|    {
+   35|      0|        countdown
+   36|      0|        =
+   37|      0|            100
+   38|      0|        ;
+   39|      0|    }
+   40|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt b/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
new file mode 100644
index 00000000000..a59fe1146f4
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
@@ -0,0 +1,28 @@
+    1|       |// Regression test for issue #98833.
+    2|       |// compile-flags: -Zinline-mir -Cdebug-assertions=off
+    3|       |
+    4|      1|fn main() {
+    5|      1|    println!("{}", live::<false>());
+    6|      1|
+    7|      1|    let f = |x: bool| {
+    8|       |        debug_assert!(
+    9|      0|            x
+   10|       |        );
+   11|      1|    };
+   12|      1|    f(false);
+   13|      1|}
+   14|       |
+   15|       |#[inline]
+   16|      1|fn live<const B: bool>() -> u32 {
+   17|      1|    if B {
+   18|      0|        dead()
+   19|       |    } else {
+   20|      1|        0
+   21|       |    }
+   22|      1|}
+   23|       |
+   24|       |#[inline]
+   25|      0|fn dead() -> u32 {
+   26|      0|    42
+   27|      0|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline.txt b/tests/run-make/coverage-reports/expected_show_coverage.inline.txt
new file mode 100644
index 00000000000..6f5d1544fa0
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.inline.txt
@@ -0,0 +1,54 @@
+    1|       |// compile-flags: -Zinline-mir
+    2|       |
+    3|       |use std::fmt::Display;
+    4|       |
+    5|      1|fn main() {
+    6|      1|    permutations(&['a', 'b', 'c']);
+    7|      1|}
+    8|       |
+    9|       |#[inline(always)]
+   10|      1|fn permutations<T: Copy + Display>(xs: &[T]) {
+   11|      1|    let mut ys = xs.to_owned();
+   12|      1|    permutate(&mut ys, 0);
+   13|      1|}
+   14|       |
+   15|     16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+   16|     16|    let n = length(xs);
+   17|     16|    if k == n {
+   18|      6|        display(xs);
+   19|     10|    } else if k < n {
+   20|     15|        for i in k..n {
+                               ^10
+   21|     15|            swap(xs, i, k);
+   22|     15|            permutate(xs, k + 1);
+   23|     15|            swap(xs, i, k);
+   24|     15|        }
+   25|      0|    } else {
+   26|      0|        error();
+   27|      0|    }
+   28|     16|}
+   29|       |
+   30|     16|fn length<T>(xs: &[T]) -> usize {
+   31|     16|    xs.len()
+   32|     16|}
+   33|       |
+   34|       |#[inline]
+   35|     30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+   36|     30|    let t = xs[i];
+   37|     30|    xs[i] = xs[j];
+   38|     30|    xs[j] = t;
+   39|     30|}
+   40|       |
+   41|      6|fn display<T: Display>(xs: &[T]) {
+   42|     24|    for x in xs {
+                      ^18
+   43|     18|        print!("{}", x);
+   44|     18|    }
+   45|      6|    println!();
+   46|      6|}
+   47|       |
+   48|       |#[inline(always)]
+   49|      0|fn error() {
+   50|      0|    panic!("error");
+   51|      0|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt b/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt
new file mode 100644
index 00000000000..883254a09ba
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt
@@ -0,0 +1,60 @@
+    1|       |#![allow(unused_assignments, unused_variables, dead_code)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 0;
+   10|      1|    if is_true {
+   11|      1|        countdown = 10;
+   12|      1|    }
+                   ^0
+   13|       |
+   14|       |    mod in_mod {
+   15|       |        const IN_MOD_CONST: u32 = 1000;
+   16|       |    }
+   17|       |
+   18|      3|    fn in_func(a: u32) {
+   19|      3|        let b = 1;
+   20|      3|        let c = a + b;
+   21|      3|        println!("c = {}", c)
+   22|      3|    }
+   23|       |
+   24|       |    struct InStruct {
+   25|       |        in_struct_field: u32,
+   26|       |    }
+   27|       |
+   28|       |    const IN_CONST: u32 = 1234;
+   29|       |
+   30|       |    trait InTrait {
+   31|       |        fn trait_func(&mut self, incr: u32);
+   32|       |
+   33|      1|        fn default_trait_func(&mut self) {
+   34|      1|            in_func(IN_CONST);
+   35|      1|            self.trait_func(IN_CONST);
+   36|      1|        }
+   37|       |    }
+   38|       |
+   39|       |    impl InTrait for InStruct {
+   40|      1|        fn trait_func(&mut self, incr: u32) {
+   41|      1|            self.in_struct_field += incr;
+   42|      1|            in_func(self.in_struct_field);
+   43|      1|        }
+   44|       |    }
+   45|       |
+   46|       |    type InType = String;
+   47|       |
+   48|      1|    if is_true {
+   49|      1|        in_func(countdown);
+   50|      1|    }
+                   ^0
+   51|       |
+   52|      1|    let mut val = InStruct {
+   53|      1|        in_struct_field: 101,
+   54|      1|    };
+   55|      1|
+   56|      1|    val.default_trait_func();
+   57|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt b/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
new file mode 100644
index 00000000000..25c74ab2e70
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
@@ -0,0 +1,16 @@
+    1|       |// Shows that rust-lang/rust/83601 is resolved
+    2|       |
+    3|      3|#[derive(Debug, PartialEq, Eq)]
+                              ^2
+    4|       |struct Foo(u32);
+    5|       |
+    6|      1|fn main() {
+    7|      1|    let bar = Foo(1);
+    8|      1|    assert_eq!(bar, Foo(1));
+    9|      1|    let baz = Foo(0);
+   10|      1|    assert_ne!(baz, Foo(1));
+   11|      1|    println!("{:?}", Foo(1));
+   12|      1|    println!("{:?}", bar);
+   13|      1|    println!("{:?}", baz);
+   14|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
new file mode 100644
index 00000000000..4a60432c14c
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
@@ -0,0 +1,189 @@
+    1|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+    2|       |
+    3|       |// expect-exit-status-101
+    4|     21|#[derive(PartialEq, Eq)]
+    5|       |struct Foo(u32);
+    6|      1|fn test3() {
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|    let bar = Foo(1);
+    9|      1|    assert_eq!(bar, Foo(1));
+   10|      1|    let baz = Foo(0);
+   11|      1|    assert_ne!(baz, Foo(1));
+   12|      1|    println!("{:?}", Foo(1));
+   13|      1|    println!("{:?}", bar);
+   14|      1|    println!("{:?}", baz);
+   15|      1|
+   16|      1|    assert_eq!(Foo(1), Foo(1));
+   17|      1|    assert_ne!(Foo(0), Foo(1));
+   18|      1|    assert_eq!(Foo(2), Foo(2));
+   19|      1|    let bar = Foo(0);
+   20|      1|    assert_ne!(bar, Foo(3));
+   21|      1|    assert_ne!(Foo(0), Foo(4));
+   22|      1|    assert_eq!(Foo(3), Foo(3), "with a message");
+                                             ^0
+   23|      1|    println!("{:?}", bar);
+   24|      1|    println!("{:?}", Foo(1));
+   25|      1|
+   26|      1|    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+                                             ^0                 ^0                      ^0
+   27|      1|    assert_ne!(
+   28|       |        Foo(0)
+   29|       |        ,
+   30|       |        Foo(5)
+   31|       |        ,
+   32|      0|        "{}"
+   33|      0|        ,
+   34|      0|        if
+   35|      0|        is_true
+   36|       |        {
+   37|      0|            "true message"
+   38|       |        } else {
+   39|      0|            "false message"
+   40|       |        }
+   41|       |    );
+   42|       |
+   43|      1|    let is_true = std::env::args().len() == 1;
+   44|      1|
+   45|      1|    assert_eq!(
+   46|      1|        Foo(1),
+   47|      1|        Foo(1)
+   48|      1|    );
+   49|      1|    assert_ne!(
+   50|      1|        Foo(0),
+   51|      1|        Foo(1)
+   52|      1|    );
+   53|      1|    assert_eq!(
+   54|      1|        Foo(2),
+   55|      1|        Foo(2)
+   56|      1|    );
+   57|      1|    let bar = Foo(1);
+   58|      1|    assert_ne!(
+   59|      1|        bar,
+   60|      1|        Foo(3)
+   61|      1|    );
+   62|      1|    if is_true {
+   63|      1|        assert_ne!(
+   64|      1|            Foo(0),
+   65|      1|            Foo(4)
+   66|      1|        );
+   67|       |    } else {
+   68|      0|        assert_eq!(
+   69|      0|            Foo(3),
+   70|      0|            Foo(3)
+   71|      0|        );
+   72|       |    }
+   73|      1|    if is_true {
+   74|      1|        assert_ne!(
+   75|       |            Foo(0),
+   76|       |            Foo(4),
+   77|      0|            "with a message"
+   78|       |        );
+   79|       |    } else {
+   80|      0|        assert_eq!(
+   81|       |            Foo(3),
+   82|       |            Foo(3),
+   83|      0|            "with a message"
+   84|       |        );
+   85|       |    }
+   86|      1|    assert_ne!(
+   87|      1|        if is_true {
+   88|      1|            Foo(0)
+   89|       |        } else {
+   90|      0|            Foo(1)
+   91|       |        },
+   92|       |        Foo(5)
+   93|       |    );
+   94|      1|    assert_ne!(
+   95|      1|        Foo(5),
+   96|      1|        if is_true {
+   97|      1|            Foo(0)
+   98|       |        } else {
+   99|      0|            Foo(1)
+  100|       |        }
+  101|       |    );
+  102|      1|    assert_ne!(
+  103|      1|        if is_true {
+  104|      1|            assert_eq!(
+  105|      1|                Foo(3),
+  106|      1|                Foo(3)
+  107|      1|            );
+  108|      1|            Foo(0)
+  109|       |        } else {
+  110|      0|            assert_ne!(
+  111|      0|                if is_true {
+  112|      0|                    Foo(0)
+  113|       |                } else {
+  114|      0|                    Foo(1)
+  115|       |                },
+  116|       |                Foo(5)
+  117|       |            );
+  118|      0|            Foo(1)
+  119|       |        },
+  120|       |        Foo(5),
+  121|      0|        "with a message"
+  122|       |    );
+  123|      1|    assert_eq!(
+  124|       |        Foo(1),
+  125|       |        Foo(3),
+  126|      1|        "this assert should fail"
+  127|       |    );
+  128|      0|    assert_eq!(
+  129|       |        Foo(3),
+  130|       |        Foo(3),
+  131|      0|        "this assert should not be reached"
+  132|       |    );
+  133|      0|}
+  134|       |
+  135|       |impl std::fmt::Debug for Foo {
+  136|       |    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+  137|      7|        write!(f, "try and succeed")?;
+                                                  ^0
+  138|      7|        Ok(())
+  139|      7|    }
+  140|       |}
+  141|       |
+  142|       |static mut DEBUG_LEVEL_ENABLED: bool = false;
+  143|       |
+  144|       |macro_rules! debug {
+  145|       |    ($($arg:tt)+) => (
+  146|       |        if unsafe { DEBUG_LEVEL_ENABLED } {
+  147|       |            println!($($arg)+);
+  148|       |        }
+  149|       |    );
+  150|       |}
+  151|       |
+  152|      1|fn test1() {
+  153|      1|    debug!("debug is enabled");
+                         ^0
+  154|      1|    debug!("debug is enabled");
+                         ^0
+  155|      1|    let _ = 0;
+  156|      1|    debug!("debug is enabled");
+                         ^0
+  157|      1|    unsafe {
+  158|      1|        DEBUG_LEVEL_ENABLED = true;
+  159|      1|    }
+  160|      1|    debug!("debug is enabled");
+  161|      1|}
+  162|       |
+  163|       |macro_rules! call_debug {
+  164|       |    ($($arg:tt)+) => (
+  165|      1|        fn call_print(s: &str) {
+  166|      1|            print!("{}", s);
+  167|      1|        }
+  168|       |
+  169|       |        call_print("called from call_debug: ");
+  170|       |        debug!($($arg)+);
+  171|       |    );
+  172|       |}
+  173|       |
+  174|      1|fn test2() {
+  175|      1|    call_debug!("debug is enabled");
+  176|      1|}
+  177|       |
+  178|      1|fn main() {
+  179|      1|    test1();
+  180|      1|    test2();
+  181|      1|    test3();
+  182|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt b/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
new file mode 100644
index 00000000000..1aa4a22c33e
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
@@ -0,0 +1,36 @@
+../coverage/issue-85461.rs:
+    1|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+    2|       |
+    3|       |extern crate inline_always_with_dead_code;
+    4|       |
+    5|       |use inline_always_with_dead_code::{bar, baz};
+    6|       |
+    7|      1|fn main() {
+    8|      1|    bar::call_me();
+    9|      1|    baz::call_me();
+   10|      1|}
+
+../coverage/lib/inline_always_with_dead_code.rs:
+    1|       |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+    2|       |
+    3|       |#![allow(dead_code)]
+    4|       |
+    5|       |mod foo {
+    6|       |    #[inline(always)]
+    7|      2|    pub fn called() { }
+    8|       |
+    9|      0|    fn uncalled() { }
+   10|       |}
+   11|       |
+   12|       |pub mod bar {
+   13|      1|    pub fn call_me() {
+   14|      1|        super::foo::called();
+   15|      1|    }
+   16|       |}
+   17|       |
+   18|       |pub mod baz {
+   19|      1|    pub fn call_me() {
+   20|      1|        super::foo::called();
+   21|      1|    }
+   22|       |}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt b/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
new file mode 100644
index 00000000000..a1655adedd4
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
@@ -0,0 +1,29 @@
+    1|       |// Regression test for #93054: Functions using uninhabited types often only have a single,
+    2|       |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+    3|       |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+    4|       |
+    5|       |// compile-flags: --edition=2021
+    6|       |
+    7|       |enum Never { }
+    8|       |
+    9|       |impl Never {
+   10|       |    fn foo(self) {
+   11|       |        match self { }
+   12|       |        make().map(|never| match never { });
+   13|       |    }
+   14|       |
+   15|       |    fn bar(&self) {
+   16|       |        match *self { }
+   17|       |    }
+   18|       |}
+   19|       |
+   20|      0|async fn foo2(never: Never) {
+   21|       |    match never { }
+   22|       |}
+   23|       |
+   24|      0|fn make() -> Option<Never> {
+   25|      0|    None
+   26|      0|}
+   27|       |
+   28|      1|fn main() { }
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt b/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
new file mode 100644
index 00000000000..bd349df2fbc
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
@@ -0,0 +1,64 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let (mut a, mut b, mut c) = (0, 0, 0);
+   10|      1|    if is_true {
+   11|      1|        a = 1;
+   12|      1|        b = 10;
+   13|      1|        c = 100;
+   14|      1|    }
+                   ^0
+   15|       |    let
+   16|      1|        somebool
+   17|       |        =
+   18|      1|            a < b
+   19|       |        ||
+   20|      0|            b < c
+   21|       |    ;
+   22|       |    let
+   23|      1|        somebool
+   24|       |        =
+   25|      1|            b < a
+   26|       |        ||
+   27|      1|            b < c
+   28|       |    ;
+   29|      1|    let somebool = a < b && b < c;
+   30|      1|    let somebool = b < a && b < c;
+                                          ^0
+   31|       |
+   32|       |    if
+   33|      1|        !
+   34|      1|        is_true
+   35|      0|    {
+   36|      0|        a = 2
+   37|      0|        ;
+   38|      1|    }
+   39|       |
+   40|       |    if
+   41|      1|        is_true
+   42|      1|    {
+   43|      1|        b = 30
+   44|      1|        ;
+   45|      1|    }
+   46|       |    else
+   47|      0|    {
+   48|      0|        c = 400
+   49|      0|        ;
+   50|      0|    }
+   51|       |
+   52|      1|    if !is_true {
+   53|      0|        a = 2;
+   54|      1|    }
+   55|       |
+   56|      1|    if is_true {
+   57|      1|        b = 30;
+   58|      1|    } else {
+   59|      0|        c = 400;
+   60|      0|    }
+   61|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt b/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
new file mode 100644
index 00000000000..022fe4c5962
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
@@ -0,0 +1,14 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    let result
+    5|      1|        =
+    6|      1|            loop
+    7|      1|        {
+    8|      1|            break
+    9|      1|            10
+   10|      1|            ;
+   11|      1|        }
+   12|      1|    ;
+   13|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt b/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
new file mode 100644
index 00000000000..b7ad79a2484
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
@@ -0,0 +1,68 @@
+    1|       |#![allow(unused_assignments, unused_variables, while_true)]
+    2|       |
+    3|       |// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+    4|       |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+    5|       |
+    6|       |struct DebugTest;
+    7|       |
+    8|       |impl std::fmt::Debug for DebugTest {
+    9|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   10|      1|        if true {
+   11|      1|            if false {
+   12|      0|                while true {
+   13|      0|                }
+   14|      1|            }
+   15|      1|            write!(f, "cool")?;
+                                           ^0
+   16|      0|        } else {
+   17|      0|        }
+   18|       |
+   19|     11|        for i in 0..10 {
+                          ^10
+   20|     10|            if true {
+   21|     10|                if false {
+   22|      0|                    while true {}
+   23|     10|                }
+   24|     10|                write!(f, "cool")?;
+                                               ^0
+   25|      0|            } else {
+   26|      0|            }
+   27|       |        }
+   28|      1|        Ok(())
+   29|      1|    }
+   30|       |}
+   31|       |
+   32|       |struct DisplayTest;
+   33|       |
+   34|       |impl std::fmt::Display for DisplayTest {
+   35|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   36|      1|        if false {
+   37|      0|        } else {
+   38|      1|            if false {
+   39|      0|                while true {}
+   40|      1|            }
+   41|      1|            write!(f, "cool")?;
+                                           ^0
+   42|       |        }
+   43|     11|        for i in 0..10 {
+                          ^10
+   44|     10|            if false {
+   45|      0|            } else {
+   46|     10|                if false {
+   47|      0|                    while true {}
+   48|     10|                }
+   49|     10|                write!(f, "cool")?;
+                                               ^0
+   50|       |            }
+   51|       |        }
+   52|      1|        Ok(())
+   53|      1|    }
+   54|       |}
+   55|       |
+   56|      1|fn main() {
+   57|      1|    let debug_test = DebugTest;
+   58|      1|    println!("{:?}", debug_test);
+   59|      1|    let display_test = DisplayTest;
+   60|      1|    println!("{}", display_test);
+   61|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt b/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
new file mode 100644
index 00000000000..a0fccb24f99
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
@@ -0,0 +1,50 @@
+    1|       |#![feature(or_patterns)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut a: u8 = 0;
+   10|      1|    let mut b: u8 = 0;
+   11|      1|    if is_true {
+   12|      1|        a = 2;
+   13|      1|        b = 0;
+   14|      1|    }
+                   ^0
+   15|      1|    match (a, b) {
+   16|       |        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+   17|       |        // This test confirms a fix for Issue #79569.
+   18|      0|        (0 | 1, 2 | 3) => {}
+   19|      1|        _ => {}
+   20|       |    }
+   21|      1|    if is_true {
+   22|      1|        a = 0;
+   23|      1|        b = 0;
+   24|      1|    }
+                   ^0
+   25|      1|    match (a, b) {
+   26|      0|        (0 | 1, 2 | 3) => {}
+   27|      1|        _ => {}
+   28|       |    }
+   29|      1|    if is_true {
+   30|      1|        a = 2;
+   31|      1|        b = 2;
+   32|      1|    }
+                   ^0
+   33|      1|    match (a, b) {
+   34|      0|        (0 | 1, 2 | 3) => {}
+   35|      1|        _ => {}
+   36|       |    }
+   37|      1|    if is_true {
+   38|      1|        a = 0;
+   39|      1|        b = 2;
+   40|      1|    }
+                   ^0
+   41|      1|    match (a, b) {
+   42|      1|        (0 | 1, 2 | 3) => {}
+   43|      0|        _ => {}
+   44|       |    }
+   45|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt b/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
new file mode 100644
index 00000000000..0dbd6bcf313
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
@@ -0,0 +1,26 @@
+    1|      1|fn main() {
+    2|      1|    let is_true = std::env::args().len() == 1;
+    3|      1|    let mut countdown = 10;
+    4|       |
+    5|      1|    'outer: while countdown > 0 {
+    6|      1|        let mut a = 100;
+    7|      1|        let mut b = 100;
+    8|      3|        for _ in 0..50 {
+    9|      3|            if a < 30 {
+   10|      0|                break;
+   11|      3|            }
+   12|      3|            a -= 5;
+   13|      3|            b -= 5;
+   14|      3|            if b < 90 {
+   15|      1|                a -= 10;
+   16|      1|                if is_true {
+   17|      1|                    break 'outer;
+   18|      0|                } else {
+   19|      0|                    a -= 2;
+   20|      0|                }
+   21|      2|            }
+   22|       |        }
+   23|      0|        countdown -= 1;
+   24|       |    }
+   25|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt b/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
new file mode 100644
index 00000000000..83a9204136f
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
@@ -0,0 +1,87 @@
+    1|       |// Enables `no_coverage` on the entire crate
+    2|       |#![feature(no_coverage)]
+    3|       |
+    4|       |#[no_coverage]
+    5|       |fn do_not_add_coverage_1() {
+    6|       |    println!("called but not covered");
+    7|       |}
+    8|       |
+    9|       |fn do_not_add_coverage_2() {
+   10|       |    #![no_coverage]
+   11|       |    println!("called but not covered");
+   12|       |}
+   13|       |
+   14|       |#[no_coverage]
+   15|       |fn do_not_add_coverage_not_called() {
+   16|       |    println!("not called and not covered");
+   17|       |}
+   18|       |
+   19|      1|fn add_coverage_1() {
+   20|      1|    println!("called and covered");
+   21|      1|}
+   22|       |
+   23|      1|fn add_coverage_2() {
+   24|      1|    println!("called and covered");
+   25|      1|}
+   26|       |
+   27|      0|fn add_coverage_not_called() {
+   28|      0|    println!("not called but covered");
+   29|      0|}
+   30|       |
+   31|       |// FIXME: These test-cases illustrate confusing results of nested functions.
+   32|       |// See https://github.com/rust-lang/rust/issues/93319
+   33|       |mod nested_fns {
+   34|       |    #[no_coverage]
+   35|       |    pub fn outer_not_covered(is_true: bool) {
+   36|      1|        fn inner(is_true: bool) {
+   37|      1|            if is_true {
+   38|      1|                println!("called and covered");
+   39|      1|            } else {
+   40|      0|                println!("absolutely not covered");
+   41|      0|            }
+   42|      1|        }
+   43|       |        println!("called but not covered");
+   44|       |        inner(is_true);
+   45|       |    }
+   46|       |
+   47|      1|    pub fn outer(is_true: bool) {
+   48|      1|        println!("called and covered");
+   49|      1|        inner_not_covered(is_true);
+   50|      1|
+   51|      1|        #[no_coverage]
+   52|      1|        fn inner_not_covered(is_true: bool) {
+   53|      1|            if is_true {
+   54|      1|                println!("called but not covered");
+   55|      1|            } else {
+   56|      1|                println!("absolutely not covered");
+   57|      1|            }
+   58|      1|        }
+   59|      1|    }
+   60|       |
+   61|      1|    pub fn outer_both_covered(is_true: bool) {
+   62|      1|        println!("called and covered");
+   63|      1|        inner(is_true);
+   64|      1|
+   65|      1|        fn inner(is_true: bool) {
+   66|      1|            if is_true {
+   67|      1|                println!("called and covered");
+   68|      1|            } else {
+   69|      0|                println!("absolutely not covered");
+   70|      0|            }
+   71|      1|        }
+   72|      1|    }
+   73|       |}
+   74|       |
+   75|      1|fn main() {
+   76|      1|    let is_true = std::env::args().len() == 1;
+   77|      1|
+   78|      1|    do_not_add_coverage_1();
+   79|      1|    do_not_add_coverage_2();
+   80|      1|    add_coverage_1();
+   81|      1|    add_coverage_2();
+   82|      1|
+   83|      1|    nested_fns::outer_not_covered(is_true);
+   84|      1|    nested_fns::outer(is_true);
+   85|      1|    nested_fns::outer_both_covered(is_true);
+   86|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt b/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt
new file mode 100644
index 00000000000..25e822bffd1
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt
@@ -0,0 +1,64 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-status-101
+    3|       |
+    4|      4|fn might_overflow(to_add: u32) -> u32 {
+    5|      4|    if to_add > 5 {
+    6|      1|        println!("this will probably overflow");
+    7|      3|    }
+    8|      4|    let add_to = u32::MAX - 5;
+    9|      4|    println!("does {} + {} overflow?", add_to, to_add);
+   10|      4|    let result = to_add + add_to;
+   11|      4|    println!("continuing after overflow check");
+   12|      4|    result
+   13|      4|}
+   14|       |
+   15|      1|fn main() -> Result<(),u8> {
+   16|      1|    let mut countdown = 10;
+   17|     11|    while countdown > 0 {
+   18|     11|        if countdown == 1 {
+   19|      1|            let result = might_overflow(10);
+   20|      1|            println!("Result: {}", result);
+   21|     10|        } else if countdown < 5 {
+   22|      3|            let result = might_overflow(1);
+   23|      3|            println!("Result: {}", result);
+   24|      6|        }
+   25|     10|        countdown -= 1;
+   26|       |    }
+   27|      0|    Ok(())
+   28|      0|}
+   29|       |
+   30|       |// Notes:
+   31|       |//   1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+   32|       |//      and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+   33|       |//   2. This test confirms the coverage generated when a program passes or fails a
+   34|       |//      compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+   35|       |//   3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+   36|       |//      compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+   37|       |//      expected behavior. To simplify the coverage graphs and keep instrumented programs as
+   38|       |//      small and fast as possible, `Assert` terminators are assumed to always succeed, and
+   39|       |//      therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+   40|       |//      get its own coverage counter.
+   41|       |//   4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+   42|       |//      In this test, the final count for the statements after the `if` block in `might_overflow()`
+   43|       |//      is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+   44|       |//      on the MIR graph and the structure of the code, this count could have been 3 (which might
+   45|       |//      have been valid for the overflowed add `+`, but should have been 4 for the lines before
+   46|       |//      the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+   47|       |//      via StatementKind::Counter at the end of the block, but (as in the case in this test),
+   48|       |//      a CounterKind::Expression is always evaluated. In this case, the expression was based on
+   49|       |//      a `Counter` incremented as part of the evaluation of the `if` expression, which was
+   50|       |//      executed, and counted, 4 times, before reaching the overflow add.
+   51|       |
+   52|       |// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+   53|       |//
+   54|       |//     4|       |fn might_overflow(to_add: u32) -> u32 {
+   55|       |//     5|      4|    if to_add > 5 {
+   56|       |//     6|      0|        println!("this will probably overflow");
+   57|       |//     7|      4|    }
+   58|       |//     8|      4|    let add_to = u32::MAX - 5;
+   59|       |//     9|      4|    println!("does {} + {} overflow?", add_to, to_add);
+   60|       |//    10|      4|    let result = to_add + add_to;
+   61|       |//    11|      4|    println!("continuing after overflow check");
+   62|       |//    12|      4|    result
+   63|       |//    13|      4|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt b/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
new file mode 100644
index 00000000000..114507dc9fd
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
@@ -0,0 +1,32 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-status-101
+    3|       |
+    4|      4|fn might_panic(should_panic: bool) {
+    5|      4|    if should_panic {
+    6|      1|        println!("panicking...");
+    7|      1|        panic!("panics");
+    8|      3|    } else {
+    9|      3|        println!("Don't Panic");
+   10|      3|    }
+   11|      3|}
+   12|       |
+   13|      1|fn main() -> Result<(), u8> {
+   14|      1|    let mut countdown = 10;
+   15|     11|    while countdown > 0 {
+   16|     11|        if countdown == 1 {
+   17|      1|            might_panic(true);
+   18|     10|        } else if countdown < 5 {
+   19|      3|            might_panic(false);
+   20|      6|        }
+   21|     10|        countdown -= 1;
+   22|       |    }
+   23|      0|    Ok(())
+   24|      0|}
+   25|       |
+   26|       |// Notes:
+   27|       |//   1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+   28|       |//      `try_error_result.rs`.
+   29|       |//   2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+   30|       |//      normal program exit cleanup, including writing out the current values of the coverage
+   31|       |//      counters.
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt b/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
new file mode 100644
index 00000000000..a77175af663
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
@@ -0,0 +1,48 @@
+    1|       |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+    2|       |// structure of this test.
+    3|       |
+    4|      2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+                       ^0            ^0      ^0     ^1       ^1 ^0^0
+    5|       |pub struct Version {
+    6|       |    major: usize,
+    7|       |    minor: usize,
+    8|       |    patch: usize,
+    9|       |}
+   10|       |
+   11|       |impl Version {
+   12|      2|    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+   13|      2|        Self {
+   14|      2|            major,
+   15|      2|            minor,
+   16|      2|            patch,
+   17|      2|        }
+   18|      2|    }
+   19|       |}
+   20|       |
+   21|      1|fn main() {
+   22|      1|    let version_3_2_1 = Version::new(3, 2, 1);
+   23|      1|    let version_3_3_0 = Version::new(3, 3, 0);
+   24|      1|
+   25|      1|    println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+   26|      1|}
+   27|       |
+   28|       |/*
+   29|       |
+   30|       |This test verifies a bug was fixed that otherwise generated this error:
+   31|       |
+   32|       |thread 'rustc' panicked at 'No counters provided the source_hash for function:
+   33|       |    Instance {
+   34|       |        def: Item(WithOptConstParam {
+   35|       |            did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+   36|       |            const_param_did: None
+   37|       |        }),
+   38|       |        substs: []
+   39|       |    }'
+   40|       |The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+   41|       |without a code region associated with any `Counter`. Code regions were associated with at least
+   42|       |one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+   43|       |(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+   44|       |`function_source_hash` without a code region, if necessary.
+   45|       |
+   46|       |*/
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt b/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
new file mode 100644
index 00000000000..feb83bad674
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
@@ -0,0 +1,37 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 0;
+   10|      1|
+   11|      1|    if
+   12|      1|        is_true
+   13|      1|    {
+   14|      1|        countdown
+   15|      1|        =
+   16|      1|            10
+   17|      1|        ;
+   18|      1|    }
+                   ^0
+   19|       |
+   20|       |    loop
+   21|       |    {
+   22|       |        if
+   23|     11|            countdown
+   24|     11|                ==
+   25|     11|            0
+   26|       |        {
+   27|      1|            break
+   28|       |            ;
+   29|     10|        }
+   30|     10|        countdown
+   31|     10|        -=
+   32|     10|        1
+   33|       |        ;
+   34|       |    }
+   35|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt b/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt
new file mode 100644
index 00000000000..b9298213111
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt
@@ -0,0 +1,45 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 1;
+   10|      1|    if is_true {
+   11|      1|        countdown = 0;
+   12|      1|    }
+                   ^0
+   13|       |
+   14|       |    for
+   15|       |        _
+   16|       |    in
+   17|      3|        0..2
+   18|       |    {
+   19|       |        let z
+   20|       |        ;
+   21|       |        match
+   22|      2|            countdown
+   23|       |        {
+   24|      1|            x
+   25|       |            if
+   26|      2|                x
+   27|      2|                    <
+   28|      2|                1
+   29|       |            =>
+   30|      1|            {
+   31|      1|                z = countdown
+   32|      1|                ;
+   33|      1|                let y = countdown
+   34|      1|                ;
+   35|      1|                countdown = 10
+   36|      1|                ;
+   37|      1|            }
+   38|       |            _
+   39|       |            =>
+   40|      1|            {}
+   41|       |        }
+   42|       |    }
+   43|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt b/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
new file mode 100644
index 00000000000..2d4c57f451a
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
@@ -0,0 +1,6 @@
+    1|      1|fn main() {
+    2|      1|    if false {
+    3|      0|        loop {}
+    4|      1|    }
+    5|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt b/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
new file mode 100644
index 00000000000..0ad0180b761
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
@@ -0,0 +1,125 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-status-1
+    3|       |
+    4|      6|fn call(return_error: bool) -> Result<(),()> {
+    5|      6|    if return_error {
+    6|      1|        Err(())
+    7|       |    } else {
+    8|      5|        Ok(())
+    9|       |    }
+   10|      6|}
+   11|       |
+   12|      1|fn test1() -> Result<(),()> {
+   13|      1|    let mut
+   14|      1|        countdown = 10
+   15|       |    ;
+   16|       |    for
+   17|       |        _
+   18|       |    in
+   19|      6|        0..10
+   20|       |    {
+   21|      6|        countdown
+   22|      6|            -= 1
+   23|      6|        ;
+   24|      6|        if
+   25|      6|            countdown < 5
+   26|       |        {
+   27|      1|            call(/*return_error=*/ true)?;
+   28|      0|            call(/*return_error=*/ false)?;
+   29|       |        }
+   30|       |        else
+   31|       |        {
+   32|      5|            call(/*return_error=*/ false)?;
+                                                       ^0
+   33|       |        }
+   34|       |    }
+   35|      0|    Ok(())
+   36|      1|}
+   37|       |
+   38|       |struct Thing1;
+   39|       |impl Thing1 {
+   40|     18|    fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+   41|     18|        if return_error {
+   42|      1|            Err(())
+   43|       |        } else {
+   44|     17|            Ok(Thing2{})
+   45|       |        }
+   46|     18|    }
+   47|       |}
+   48|       |
+   49|       |struct Thing2;
+   50|       |impl Thing2 {
+   51|     17|    fn call(&self, return_error: bool) -> Result<u32,()> {
+   52|     17|        if return_error {
+   53|      2|            Err(())
+   54|       |        } else {
+   55|     15|            Ok(57)
+   56|       |        }
+   57|     17|    }
+   58|       |}
+   59|       |
+   60|      1|fn test2() -> Result<(),()> {
+   61|      1|    let thing1 = Thing1{};
+   62|      1|    let mut
+   63|      1|        countdown = 10
+   64|       |    ;
+   65|       |    for
+   66|       |        _
+   67|       |    in
+   68|      6|        0..10
+   69|       |    {
+   70|      6|        countdown
+   71|      6|            -= 1
+   72|      6|        ;
+   73|      6|        if
+   74|      6|            countdown < 5
+   75|       |        {
+   76|      1|            thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+                                                            ^0
+   77|      1|            thing1
+   78|      1|                .
+   79|      1|                get_thing_2(/*return_error=*/ false)
+   80|      0|                ?
+   81|       |                .
+   82|      1|                call(/*return_error=*/ true)
+   83|      1|                .
+   84|      1|                expect_err(
+   85|      1|                    "call should fail"
+   86|      1|                );
+   87|      1|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+                              ^0                                                ^0                          ^0
+   88|      0|            assert_eq!(val, 57);
+   89|      0|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+   90|      0|            assert_eq!(val, 57);
+   91|       |        }
+   92|       |        else
+   93|       |        {
+   94|      5|            let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+                                                                               ^0                             ^0
+   95|      5|            assert_eq!(val, 57);
+   96|      5|            let val = thing1
+   97|      5|                .get_thing_2(/*return_error=*/ false)?
+                                                                   ^0
+   98|      5|                .call(/*return_error=*/ false)?;
+                                                            ^0
+   99|      5|            assert_eq!(val, 57);
+  100|      5|            let val = thing1
+  101|      5|                .get_thing_2(/*return_error=*/ false)
+  102|      0|                ?
+  103|      5|                .call(/*return_error=*/ false)
+  104|      0|                ?
+  105|       |                ;
+  106|      5|            assert_eq!(val, 57);
+  107|       |        }
+  108|       |    }
+  109|      0|    Ok(())
+  110|      1|}
+  111|       |
+  112|      1|fn main() -> Result<(),()> {
+  113|      1|    test1().expect_err("test1 should fail");
+  114|      1|    test2()
+  115|      1|    ?
+  116|       |    ;
+  117|      0|    Ok(())
+  118|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused.txt b/tests/run-make/coverage-reports/expected_show_coverage.unused.txt
new file mode 100644
index 00000000000..15fcf21c0ef
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.unused.txt
@@ -0,0 +1,62 @@
+    1|      2|fn foo<T>(x: T) {
+    2|      2|    let mut i = 0;
+    3|     22|    while i < 10 {
+    4|     20|        i != 0 || i != 0;
+                                ^2
+    5|     20|        i += 1;
+    6|       |    }
+    7|      2|}
+  ------------------
+  | unused::foo::<f32>:
+  |    1|      1|fn foo<T>(x: T) {
+  |    2|      1|    let mut i = 0;
+  |    3|     11|    while i < 10 {
+  |    4|     10|        i != 0 || i != 0;
+  |                                ^1
+  |    5|     10|        i += 1;
+  |    6|       |    }
+  |    7|      1|}
+  ------------------
+  | unused::foo::<u32>:
+  |    1|      1|fn foo<T>(x: T) {
+  |    2|      1|    let mut i = 0;
+  |    3|     11|    while i < 10 {
+  |    4|     10|        i != 0 || i != 0;
+  |                                ^1
+  |    5|     10|        i += 1;
+  |    6|       |    }
+  |    7|      1|}
+  ------------------
+    8|       |
+    9|      0|fn unused_template_func<T>(x: T) {
+   10|      0|    let mut i = 0;
+   11|      0|    while i < 10 {
+   12|      0|        i != 0 || i != 0;
+   13|      0|        i += 1;
+   14|       |    }
+   15|      0|}
+   16|       |
+   17|      0|fn unused_func(mut a: u32) {
+   18|      0|    if a != 0 {
+   19|      0|        a += 1;
+   20|      0|    }
+   21|      0|}
+   22|       |
+   23|      0|fn unused_func2(mut a: u32) {
+   24|      0|    if a != 0 {
+   25|      0|        a += 1;
+   26|      0|    }
+   27|      0|}
+   28|       |
+   29|      0|fn unused_func3(mut a: u32) {
+   30|      0|    if a != 0 {
+   31|      0|        a += 1;
+   32|      0|    }
+   33|      0|}
+   34|       |
+   35|      1|fn main() -> Result<(), u8> {
+   36|      1|    foo::<u32>(0);
+   37|      1|    foo::<f32>(0.0);
+   38|      1|    Ok(())
+   39|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt b/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
new file mode 100644
index 00000000000..82d6fccc271
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
@@ -0,0 +1,4 @@
+    1|      0|pub fn never_called_function() {
+    2|      0|    println!("I am never called");
+    3|      0|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt b/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
new file mode 100644
index 00000000000..65eb1008dd8
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
@@ -0,0 +1,148 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+    3|       |use std::fmt::Debug;
+    4|       |
+    5|      1|pub fn used_function() {
+    6|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    7|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    8|      1|    // dependent conditions.
+    9|      1|    let is_true = std::env::args().len() == 1;
+   10|      1|    let mut countdown = 0;
+   11|      1|    if is_true {
+   12|      1|        countdown = 10;
+   13|      1|    }
+                   ^0
+   14|      1|    use_this_lib_crate();
+   15|      1|}
+   16|       |
+   17|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+   18|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+   19|      2|}
+  ------------------
+  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
+  |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   19|      1|}
+  ------------------
+  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   19|      1|}
+  ------------------
+  | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+   20|       |// Expect for above function: `Unexecuted instantiation` (see below)
+   21|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+   22|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+   23|      2|}
+  ------------------
+  | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   23|      1|}
+  ------------------
+  | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+  |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   23|      1|}
+  ------------------
+   24|       |
+   25|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   26|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   27|      2|}
+  ------------------
+  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   27|      1|}
+  ------------------
+  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   27|      1|}
+  ------------------
+   28|       |
+   29|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   30|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   31|      2|}
+  ------------------
+  | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   29|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   30|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   31|      1|}
+  ------------------
+  | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   29|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   30|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   31|      1|}
+  ------------------
+   32|       |
+   33|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
+   34|      0|    println!("unused_generic_function with {:?}", arg);
+   35|      0|}
+   36|       |
+   37|      0|pub fn unused_function() {
+   38|      0|    let is_true = std::env::args().len() == 1;
+   39|      0|    let mut countdown = 2;
+   40|      0|    if !is_true {
+   41|      0|        countdown = 20;
+   42|      0|    }
+   43|      0|}
+   44|       |
+   45|      0|fn unused_private_function() {
+   46|      0|    let is_true = std::env::args().len() == 1;
+   47|      0|    let mut countdown = 2;
+   48|      0|    if !is_true {
+   49|      0|        countdown = 20;
+   50|      0|    }
+   51|      0|}
+   52|       |
+   53|      1|fn use_this_lib_crate() {
+   54|      1|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+   55|      1|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   56|      1|        "used from library used_crate.rs",
+   57|      1|    );
+   58|      1|    let some_vec = vec![5, 6, 7, 8];
+   59|      1|    used_only_from_this_lib_crate_generic_function(some_vec);
+   60|      1|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+   61|      1|}
+   62|       |
+   63|       |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+   64|       |// for example:
+   65|       |//
+   66|       |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+   67|       |//
+   68|       |// These notices appear when `llvm-cov` shows instantiations. This may be a
+   69|       |// default option, but it can be suppressed with:
+   70|       |//
+   71|       |// ```shell
+   72|       |// $ `llvm-cov show --show-instantiations=0 ...`
+   73|       |// ```
+   74|       |//
+   75|       |// The notice is triggered because the function is unused by the library itself,
+   76|       |// and when the library is compiled, a synthetic function is generated, so
+   77|       |// unused function coverage can be reported. Coverage can be skipped for unused
+   78|       |// generic functions with:
+   79|       |//
+   80|       |// ```shell
+   81|       |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+   82|       |// ```
+   83|       |//
+   84|       |// Even though this function is used by `uses_crate.rs` (and
+   85|       |// counted), with substitutions for `T`, those instantiations are only generated
+   86|       |// when the generic function is actually used (from the binary, not from this
+   87|       |// library crate). So the test result shows coverage for all instantiated
+   88|       |// versions and their generic type substitutions, plus the `Unexecuted
+   89|       |// instantiation` message for the non-substituted version. This is valid, but
+   90|       |// unfortunately a little confusing.
+   91|       |//
+   92|       |// The library crate has its own coverage map, and the only way to show unused
+   93|       |// coverage of a generic function is to include the generic function in the
+   94|       |// coverage map, marked as an "unused function". If the library were used by
+   95|       |// another binary that never used this generic function, then it would be valid
+   96|       |// to show the unused generic, with unknown substitution (`_`).
+   97|       |//
+   98|       |// The alternative is to exclude all generics from being included in the "unused
+   99|       |// functions" list, which would then omit coverage results for
+  100|       |// `unused_generic_function<T>()`, below.
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
new file mode 100644
index 00000000000..748343885de
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
@@ -0,0 +1,139 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+    4|       |
+    5|       |use std::fmt::Debug;
+    6|       |
+    7|      1|pub fn used_function() {
+    8|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    9|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   10|      1|    // dependent conditions.
+   11|      1|    let is_true = std::env::args().len() == 1;
+   12|      1|    let mut countdown = 0;
+   13|      1|    if is_true {
+   14|      1|        countdown = 10;
+   15|      1|    }
+                   ^0
+   16|      1|    use_this_lib_crate();
+   17|      1|}
+   18|       |
+   19|       |#[inline(always)]
+   20|      1|pub fn used_inline_function() {
+   21|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   22|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   23|      1|    // dependent conditions.
+   24|      1|    let is_true = std::env::args().len() == 1;
+   25|      1|    let mut countdown = 0;
+   26|      1|    if is_true {
+   27|      1|        countdown = 10;
+   28|      1|    }
+                   ^0
+   29|      1|    use_this_lib_crate();
+   30|      1|}
+   31|       |
+   32|       |
+   33|       |
+   34|       |
+   35|       |
+   36|       |
+   37|       |
+   38|       |#[inline(always)]
+   39|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+   40|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+   41|      2|}
+  ------------------
+  | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   41|      1|}
+  ------------------
+  | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
+  |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   41|      1|}
+  ------------------
+  | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+   42|       |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+   43|       |
+   44|       |#[inline(always)]
+   45|      4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+   46|      4|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+   47|      4|}
+  ------------------
+  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+  |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   47|      2|}
+  ------------------
+  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   47|      2|}
+  ------------------
+   48|       |
+   49|       |#[inline(always)]
+   50|      3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   51|      3|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   52|      3|}
+  ------------------
+  | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   50|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   51|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   52|      1|}
+  ------------------
+  | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   50|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   51|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   52|      2|}
+  ------------------
+   53|       |
+   54|       |#[inline(always)]
+   55|      3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   56|      3|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   57|      3|}
+  ------------------
+  | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   55|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   56|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   57|      1|}
+  ------------------
+  | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   55|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   56|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   57|      2|}
+  ------------------
+   58|       |
+   59|       |#[inline(always)]
+   60|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
+   61|      0|    println!("unused_generic_function with {:?}", arg);
+   62|      0|}
+   63|       |
+   64|       |#[inline(always)]
+   65|      0|pub fn unused_function() {
+   66|      0|    let is_true = std::env::args().len() == 1;
+   67|      0|    let mut countdown = 2;
+   68|      0|    if !is_true {
+   69|      0|        countdown = 20;
+   70|      0|    }
+   71|      0|}
+   72|       |
+   73|       |#[inline(always)]
+   74|      0|fn unused_private_function() {
+   75|      0|    let is_true = std::env::args().len() == 1;
+   76|      0|    let mut countdown = 2;
+   77|      0|    if !is_true {
+   78|      0|        countdown = 20;
+   79|      0|    }
+   80|      0|}
+   81|       |
+   82|      2|fn use_this_lib_crate() {
+   83|      2|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+   84|      2|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   85|      2|        "used from library used_crate.rs",
+   86|      2|    );
+   87|      2|    let some_vec = vec![5, 6, 7, 8];
+   88|      2|    used_only_from_this_lib_crate_generic_function(some_vec);
+   89|      2|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+   90|      2|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while.txt b/tests/run-make/coverage-reports/expected_show_coverage.while.txt
new file mode 100644
index 00000000000..efa7d083f0c
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.while.txt
@@ -0,0 +1,6 @@
+    1|      1|fn main() {
+    2|      1|    let num = 9;
+    3|      1|    while num >= 10 {
+    4|      0|    }
+    5|      1|}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt b/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
new file mode 100644
index 00000000000..d19afc0de61
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
@@ -0,0 +1,43 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-status-1
+    3|       |
+    4|      1|fn main() -> Result<(),u8> {
+    5|      1|    let mut countdown = 10;
+    6|       |    while
+    7|      7|        countdown
+    8|      7|            >
+    9|      7|        0
+   10|       |    {
+   11|       |        if
+   12|      7|            countdown
+   13|      7|                <
+   14|      7|            5
+   15|       |        {
+   16|       |            return
+   17|       |                if
+   18|      1|                    countdown
+   19|      1|                        >
+   20|      1|                    8
+   21|       |                {
+   22|      0|                    Ok(())
+   23|       |                }
+   24|       |                else
+   25|       |                {
+   26|      1|                    Err(1)
+   27|       |                }
+   28|       |                ;
+   29|      6|        }
+   30|      6|        countdown
+   31|      6|            -=
+   32|      6|        1
+   33|       |        ;
+   34|       |    }
+   35|      0|    Ok(())
+   36|      1|}
+   37|       |
+   38|       |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+   39|       |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+   40|       |// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+   41|       |// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+   42|       |// to the coverage test for early returns, but this is a limitation that should be fixed.
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.yield.txt b/tests/run-make/coverage-reports/expected_show_coverage.yield.txt
new file mode 100644
index 00000000000..6e2f23ee77b
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.yield.txt
@@ -0,0 +1,38 @@
+    1|       |#![feature(generators, generator_trait)]
+    2|       |#![allow(unused_assignments)]
+    3|       |
+    4|       |use std::ops::{Generator, GeneratorState};
+    5|       |use std::pin::Pin;
+    6|       |
+    7|      1|fn main() {
+    8|      1|    let mut generator = || {
+    9|      1|        yield 1;
+   10|      1|        return "foo"
+   11|      1|    };
+   12|       |
+   13|      1|    match Pin::new(&mut generator).resume(()) {
+   14|      1|        GeneratorState::Yielded(1) => {}
+   15|      0|        _ => panic!("unexpected value from resume"),
+   16|       |    }
+   17|      1|    match Pin::new(&mut generator).resume(()) {
+   18|      1|        GeneratorState::Complete("foo") => {}
+   19|      0|        _ => panic!("unexpected value from resume"),
+   20|       |    }
+   21|       |
+   22|      1|    let mut generator = || {
+   23|      1|        yield 1;
+   24|      1|        yield 2;
+   25|      0|        yield 3;
+   26|      0|        return "foo"
+   27|      0|    };
+   28|       |
+   29|      1|    match Pin::new(&mut generator).resume(()) {
+   30|      1|        GeneratorState::Yielded(1) => {}
+   31|      0|        _ => panic!("unexpected value from resume"),
+   32|       |    }
+   33|      1|    match Pin::new(&mut generator).resume(()) {
+   34|      1|        GeneratorState::Yielded(2) => {}
+   35|      0|        _ => panic!("unexpected value from resume"),
+   36|       |    }
+   37|      1|}
+
diff --git a/tests/run-make/coverage-reports/normalize_paths.py b/tests/run-make/coverage-reports/normalize_paths.py
new file mode 100755
index 00000000000..e5777ad2512
--- /dev/null
+++ b/tests/run-make/coverage-reports/normalize_paths.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import sys
+
+# Normalize file paths in output
+for line in sys.stdin:
+    if line.startswith("..") and line.rstrip().endswith(".rs:"):
+        print(line.replace("\\", "/"), end='')
+    else:
+        print(line, end='')
diff --git a/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt b/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
new file mode 100644
index 00000000000..6a1403b8a00
--- /dev/null
+++ b/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
@@ -0,0 +1,10 @@
+IMPORTANT: The Rust test programs in this directory generate various output
+files in the `../coverage*` directories (`expected` and `actual` files).
+
+Microsoft Windows has a relatively short limit on file paths (not individual
+path components, but the entire path). The files generated by these
+`../coverage*` tests typically have file paths that include the program
+source file name plus function and type names (depending on the program).
+
+Keep the test file names short, and keep function names and other symbols
+short as well, to avoid hitting the Windows limits.
diff --git a/tests/run-make/coverage/abort.rs b/tests/run-make/coverage/abort.rs
new file mode 100644
index 00000000000..3dac43df8f3
--- /dev/null
+++ b/tests/run-make/coverage/abort.rs
@@ -0,0 +1,66 @@
+#![feature(c_unwind)]
+#![allow(unused_assignments)]
+
+extern "C" fn might_abort(should_abort: bool) {
+    if should_abort {
+        println!("aborting...");
+        panic!("panics and aborts");
+    } else {
+        println!("Don't Panic");
+    }
+}
+
+fn main() -> Result<(), u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown < 5 {
+            might_abort(false);
+        }
+        // See discussion (below the `Notes` section) on coverage results for the closing brace.
+        if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+        // For the following example, the closing brace is the last character on the line.
+        // This shows the character after the closing brace is highlighted, even if that next
+        // character is a newline.
+        if countdown < 5 { might_abort(false); }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the similar tests
+//      `panic_unwind.rs` and `try_error_result.rs`.
+//   2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
+//      results show where the program did and did not execute.
+//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
+//      intended"). Coverage results would show no executed coverage regions.
+//   6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+//      (on Linux at least).
+
+/*
+
+Expect the following coverage results:
+
+```text
+    16|     11|    while countdown > 0 {
+    17|     10|        if countdown < 5 {
+    18|      4|            might_abort(false);
+    19|      6|        }
+```
+
+This is actually correct.
+
+The condition `countdown < 5` executed 10 times (10 loop iterations).
+
+It evaluated to `true` 4 times, and executed the `might_abort()` call.
+
+It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+non-true condition.
+
+As another example of why this is important, say the condition was `countdown < 50`, which is always
+`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+The closing brace would have a count of `0`, highlighting the missed coverage.
+*/
diff --git a/tests/run-make/coverage/assert.rs b/tests/run-make/coverage/assert.rs
new file mode 100644
index 00000000000..c85f2748eb9
--- /dev/null
+++ b/tests/run-make/coverage/assert.rs
@@ -0,0 +1,32 @@
+#![allow(unused_assignments)]
+// expect-exit-status-101
+
+fn might_fail_assert(one_plus_one: u32) {
+    println!("does 1 + 1 = {}?", one_plus_one);
+    assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+}
+
+fn main() -> Result<(),u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown == 1 {
+            might_fail_assert(3);
+        } else if countdown < 5 {
+            might_fail_assert(2);
+        }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the very similar test
+//      `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+//   2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+//      related `assert_*!()` macro.
+//   3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+//      conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+//      `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+//   4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+//      (and in many other coverage tests). The `Assert` terminator is typically generated by the
+//      Rust compiler to check for runtime failures, such as numeric overflows.
diff --git a/tests/run-make/coverage/async.rs b/tests/run-make/coverage/async.rs
new file mode 100644
index 00000000000..efd9e62d64e
--- /dev/null
+++ b/tests/run-make/coverage/async.rs
@@ -0,0 +1,128 @@
+#![allow(unused_assignments, dead_code)]
+
+// compile-flags: --edition=2018 -C opt-level=1
+
+async fn c(x: u8) -> u8 {
+    if x == 8 {
+        1
+    } else {
+        0
+    }
+}
+
+async fn d() -> u8 { 1 }
+
+async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+
+async fn f() -> u8 { 1 }
+
+async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+
+pub async fn g(x: u8) {
+    match x {
+        y if e().await == y => (),
+        y if f().await == y => (),
+        _ => (),
+    }
+}
+
+async fn h(x: usize) { // The function signature is counted when called, but the body is not
+                       // executed (not awaited) so the open brace has a `0` count (at least when
+                       // displayed with `llvm-cov show` in color-mode).
+    match x {
+        y if foo().await[y] => (),
+        _ => (),
+    }
+}
+
+async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+                    // (a) the function signature, counted when the function is called; and
+                    // (b) the open brace for the function body, counted once when the body is
+                    // executed asynchronously.
+    match x {
+        y if c(x).await == y + 1 => { d().await; }
+        y if f().await == y + 1 => (),
+        _ => (),
+    }
+}
+
+fn j(x: u8) {
+    // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+    fn c(x: u8) -> u8 {
+        if x == 8 {
+            1 // This line appears covered, but the 1-character expression span covering the `1`
+              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+              // `fn j()` executes the open brace for the function body, followed by the function's
+              // first executable statement, `match x`. Inner function declarations are not
+              // "visible" to the MIR for `j()`, so the code region counts all lines between the
+              // open brace and the first statement as executed, which is, in a sense, true.
+              // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+              // of the enclosed coverages, (that is, the `1` expression was not executed, and
+              // accurately displays a `0`).
+        } else {
+            0
+        }
+    }
+    fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+    fn f() -> u8 { 1 }
+    match x {
+        y if c(x) == y + 1 => { d(); }
+        y if f() == y + 1 => (),
+        _ => (),
+    }
+}
+
+fn k(x: u8) { // unused function
+    match x {
+        1 => (),
+        2 => (),
+        _ => (),
+    }
+}
+
+fn l(x: u8) {
+    match x {
+        1 => (),
+        2 => (),
+        _ => (),
+    }
+}
+
+async fn m(x: u8) -> u8 { x - 1 }
+
+fn main() {
+    let _ = g(10);
+    let _ = h(9);
+    let mut future = Box::pin(i(8));
+    j(7);
+    l(6);
+    let _ = m(5);
+    executor::block_on(future.as_mut());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+        use std::hint::unreachable_unchecked;
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+            |_| unsafe { unreachable_unchecked() }, // clone
+            |_| unsafe { unreachable_unchecked() }, // wake
+            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/tests/run-make/coverage/async2.rs b/tests/run-make/coverage/async2.rs
new file mode 100644
index 00000000000..959d48ce9db
--- /dev/null
+++ b/tests/run-make/coverage/async2.rs
@@ -0,0 +1,69 @@
+// compile-flags: --edition=2018
+
+use core::{
+    future::Future,
+    marker::Send,
+    pin::Pin,
+};
+
+fn non_async_func() {
+    println!("non_async_func was covered");
+    let b = true;
+    if b {
+        println!("non_async_func println in block");
+    }
+}
+
+
+
+
+async fn async_func() {
+    println!("async_func was covered");
+    let b = true;
+    if b {
+        println!("async_func println in block");
+    }
+}
+
+
+
+
+async fn async_func_just_println() {
+    println!("async_func_just_println was covered");
+}
+
+fn main() {
+    println!("codecovsample::main");
+
+    non_async_func();
+
+    executor::block_on(async_func());
+    executor::block_on(async_func_just_println());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+        use std::hint::unreachable_unchecked;
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+            |_| unsafe { unreachable_unchecked() }, // clone
+            |_| unsafe { unreachable_unchecked() }, // wake
+            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/tests/run-make/coverage/closure.rs b/tests/run-make/coverage/closure.rs
new file mode 100644
index 00000000000..32ec0bcdf8c
--- /dev/null
+++ b/tests/run-make/coverage/closure.rs
@@ -0,0 +1,215 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let is_false = ! is_true;
+
+    let mut some_string = Some(String::from("the string content"));
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            ||
+            {
+                let mut countdown = 0;
+                if is_false {
+                    countdown = 10;
+                }
+                "alt string 1".to_owned()
+            }
+        )
+    );
+
+    some_string = Some(String::from("the string content"));
+    let
+        a
+    =
+        ||
+    {
+        let mut countdown = 0;
+        if is_false {
+            countdown = 10;
+        }
+        "alt string 2".to_owned()
+    };
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            a
+        )
+    );
+
+    some_string = None;
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            ||
+            {
+                let mut countdown = 0;
+                if is_false {
+                    countdown = 10;
+                }
+                "alt string 3".to_owned()
+            }
+        )
+    );
+
+    some_string = None;
+    let
+        a
+    =
+        ||
+    {
+        let mut countdown = 0;
+        if is_false {
+            countdown = 10;
+        }
+        "alt string 4".to_owned()
+    };
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            a
+        )
+    );
+
+    let
+        quote_closure
+    =
+        |val|
+    {
+        let mut countdown = 0;
+        if is_false {
+            countdown = 10;
+        }
+        format!("'{}'", val)
+    };
+    println!(
+        "Repeated, quoted string: {:?}"
+        ,
+        std::iter::repeat("repeat me")
+            .take(5)
+            .map
+        (
+            quote_closure
+        )
+            .collect::<Vec<_>>()
+    );
+
+    let
+        _unused_closure
+    =
+        |
+            mut countdown
+        |
+    {
+        if is_false {
+            countdown = 10;
+        }
+        "closure should be unused".to_owned()
+    };
+
+    let mut countdown = 10;
+    let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+
+
+    let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+    let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+    let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+
+
+
+
+    let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+
+    let _shortish_unused_closure = | _unused_arg: u8 | {
+        println!("not called")
+    };
+
+    let _as_short_unused_closure = |
+        _unused_arg: u8
+    | { println!("not called") };
+
+    let _almost_as_short_unused_closure = |
+        _unused_arg: u8
+    | { println!("not called") }
+    ;
+
+
+
+
+
+    let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+println!("not called")
+    ;
+
+    let _short_unused_closure_line_break_no_block2 =
+        | _unused_arg: u8 |
+            println!(
+                "not called"
+            )
+    ;
+
+    let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+        | _unused_arg: u8 |
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+    ;
+
+    let short_used_not_covered_closure_line_break_block_embedded_branch =
+        | _unused_arg: u8 |
+        {
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+        }
+    ;
+
+    let short_used_covered_closure_line_break_no_block_embedded_branch =
+        | _unused_arg: u8 |
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+    ;
+
+    let short_used_covered_closure_line_break_block_embedded_branch =
+        | _unused_arg: u8 |
+        {
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+        }
+    ;
+
+    if is_false {
+        short_used_not_covered_closure_macro(0);
+        short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+        short_used_not_covered_closure_line_break_block_embedded_branch(0);
+    }
+    short_used_covered_closure_macro(0);
+    short_used_covered_closure_line_break_no_block_embedded_branch(0);
+    short_used_covered_closure_line_break_block_embedded_branch(0);
+}
diff --git a/tests/run-make/coverage/closure_macro.rs b/tests/run-make/coverage/closure_macro.rs
new file mode 100644
index 00000000000..5e3b00d1ef5
--- /dev/null
+++ b/tests/run-make/coverage/closure_macro.rs
@@ -0,0 +1,40 @@
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+macro_rules! bail {
+    ($msg:literal $(,)?) => {
+        if $msg.len() > 0 {
+            println!("no msg");
+        } else {
+            println!($msg);
+        }
+        return Err(String::from($msg));
+    };
+}
+
+macro_rules! on_error {
+    ($value:expr, $error_message:expr) => {
+        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+            let message = format!($error_message, e);
+            if message.len() > 0 {
+                println!("{}", message);
+                Ok(String::from("ok"))
+            } else {
+                bail!("error");
+            }
+        })
+    };
+}
+
+fn load_configuration_files() -> Result<String, String> {
+    Ok(String::from("config"))
+}
+
+pub fn main() -> Result<(), String> {
+    println!("Starting service");
+    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+
+    let startup_delay_duration = String::from("arg");
+    let _ = (config, startup_delay_duration);
+    Ok(())
+}
diff --git a/tests/run-make/coverage/closure_macro_async.rs b/tests/run-make/coverage/closure_macro_async.rs
new file mode 100644
index 00000000000..e3e89e9c8b3
--- /dev/null
+++ b/tests/run-make/coverage/closure_macro_async.rs
@@ -0,0 +1,81 @@
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+macro_rules! bail {
+    ($msg:literal $(,)?) => {
+        if $msg.len() > 0 {
+            println!("no msg");
+        } else {
+            println!($msg);
+        }
+        return Err(String::from($msg));
+    };
+}
+
+macro_rules! on_error {
+    ($value:expr, $error_message:expr) => {
+        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+            let message = format!($error_message, e);
+            if message.len() > 0 {
+                println!("{}", message);
+                Ok(String::from("ok"))
+            } else {
+                bail!("error");
+            }
+        })
+    };
+}
+
+fn load_configuration_files() -> Result<String, String> {
+    Ok(String::from("config"))
+}
+
+pub async fn test() -> Result<(), String> {
+    println!("Starting service");
+    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+
+    let startup_delay_duration = String::from("arg");
+    let _ = (config, startup_delay_duration);
+    Ok(())
+}
+
+#[no_coverage]
+fn main() {
+    executor::block_on(test());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    #[no_coverage]
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+        use std::hint::unreachable_unchecked;
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+
+            #[no_coverage]
+            |_| unsafe { unreachable_unchecked() }, // clone
+
+            #[no_coverage]
+            |_| unsafe { unreachable_unchecked() }, // wake
+
+            #[no_coverage]
+            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+
+            #[no_coverage]
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/tests/run-make/coverage/compiletest-ignore-dir b/tests/run-make/coverage/compiletest-ignore-dir
new file mode 100644
index 00000000000..b533b272d38
--- /dev/null
+++ b/tests/run-make/coverage/compiletest-ignore-dir
@@ -0,0 +1,3 @@
+# Directory "coverage" supports the tests at prefix ../coverage-*
+
+# Use ./x.py [options] test src/test/run-make/coverage to run all related tests.
diff --git a/tests/run-make/coverage/conditions.rs b/tests/run-make/coverage/conditions.rs
new file mode 100644
index 00000000000..057599d1b47
--- /dev/null
+++ b/tests/run-make/coverage/conditions.rs
@@ -0,0 +1,87 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    let mut countdown = 0;
+    if true {
+        countdown = 10;
+    }
+
+    const B: u32 = 100;
+    let x = if countdown > 7 {
+        countdown -= 4;
+        B
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+        countdown
+    } else {
+        return;
+    };
+
+    let mut countdown = 0;
+    if true {
+        countdown = 10;
+    }
+
+    if countdown > 7 {
+        countdown -= 4;
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+    } else {
+        return;
+    }
+
+    if true {
+        let mut countdown = 0;
+        if true {
+            countdown = 10;
+        }
+
+        if countdown > 7 {
+            countdown -= 4;
+        }
+        else if countdown > 2 {
+            if countdown < 1 || countdown > 5 || countdown != 9 {
+                countdown = 0;
+            }
+            countdown -= 5;
+        } else {
+            return;
+        }
+    }
+
+
+    let mut countdown = 0;
+    if true {
+        countdown = 1;
+    }
+
+    let z = if countdown > 7 {
+        countdown -= 4;
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+    } else {
+        let should_be_reachable = countdown;
+        println!("reached");
+        return;
+    };
+
+    let w = if countdown > 7 {
+        countdown -= 4;
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+    } else {
+        return;
+    };
+}
diff --git a/tests/run-make/coverage/continue.rs b/tests/run-make/coverage/continue.rs
new file mode 100644
index 00000000000..624aa98341b
--- /dev/null
+++ b/tests/run-make/coverage/continue.rs
@@ -0,0 +1,69 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+
+    let mut x = 0;
+    for _ in 0..10 {
+        match is_true {
+            true => {
+                continue;
+            }
+            _ => {
+                x = 1;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            false => {
+                x = 1;
+            }
+            _ => {
+                continue;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            true => {
+                x = 1;
+            }
+            _ => {
+                continue;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        if is_true {
+            continue;
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            false => {
+                x = 1;
+            }
+            _ => {
+                let _ = x;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            false => {
+                x = 1;
+            }
+            _ => {
+                break;
+            }
+        }
+        x = 3;
+    }
+    let _ = x;
+}
diff --git a/tests/run-make/coverage/coverage_tools.mk b/tests/run-make/coverage/coverage_tools.mk
new file mode 100644
index 00000000000..0b6bbc33167
--- /dev/null
+++ b/tests/run-make/coverage/coverage_tools.mk
@@ -0,0 +1,6 @@
+# Common Makefile include for Rust `run-make/coverage-* tests. Include this
+# file with the line:
+#
+# include ../coverage/coverage_tools.mk
+
+include ../../run-make-fulldeps/tools.mk
diff --git a/tests/run-make/coverage/dead_code.rs b/tests/run-make/coverage/dead_code.rs
new file mode 100644
index 00000000000..a1285df0ec6
--- /dev/null
+++ b/tests/run-make/coverage/dead_code.rs
@@ -0,0 +1,37 @@
+#![allow(unused_assignments, unused_variables)]
+
+pub fn unused_pub_fn_not_in_library() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+}
+
+fn unused_fn() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+}
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+}
diff --git a/tests/run-make/coverage/doctest.rs b/tests/run-make/coverage/doctest.rs
new file mode 100644
index 00000000000..ec04ea57063
--- /dev/null
+++ b/tests/run-make/coverage/doctest.rs
@@ -0,0 +1,99 @@
+//! This test ensures that code from doctests is properly re-mapped.
+//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+//!
+//! Just some random code:
+//! ```
+//! if true {
+//!     // this is executed!
+//!     assert_eq!(1, 1);
+//! } else {
+//!     // this is not!
+//!     assert_eq!(1, 2);
+//! }
+//! ```
+//!
+//! doctest testing external code:
+//! ```
+//! extern crate doctest_crate;
+//! doctest_crate::fn_run_in_doctests(1);
+//! ```
+//!
+//! doctest returning a result:
+//! ```
+//! #[derive(Debug, PartialEq)]
+//! struct SomeError {
+//!     msg: String,
+//! }
+//! let mut res = Err(SomeError { msg: String::from("a message") });
+//! if res.is_ok() {
+//!     res?;
+//! } else {
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         println!("{:?}", res);
+//!     }
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         res = Ok(1);
+//!     }
+//!     res = Ok(0);
+//! }
+//! // need to be explicit because rustdoc cant infer the return type
+//! Ok::<(), SomeError>(())
+//! ```
+//!
+//! doctest with custom main:
+//! ```
+//! fn some_func() {
+//!     println!("called some_func()");
+//! }
+//!
+//! #[derive(Debug)]
+//! struct SomeError;
+//!
+//! extern crate doctest_crate;
+//!
+//! fn doctest_main() -> Result<(), SomeError> {
+//!     some_func();
+//!     doctest_crate::fn_run_in_doctests(2);
+//!     Ok(())
+//! }
+//!
+//! // this `main` is not shown as covered, as it clashes with all the other
+//! // `main` functions that were automatically generated for doctests
+//! fn main() -> Result<(), SomeError> {
+//!     doctest_main()
+//! }
+//! ```
+
+/// doctest attached to fn testing external code:
+/// ```
+/// extern crate doctest_crate;
+/// doctest_crate::fn_run_in_doctests(3);
+/// ```
+///
+fn main() {
+    if true {
+        assert_eq!(1, 1);
+    } else {
+        assert_eq!(1, 2);
+    }
+}
+
+// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+//
+// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+// one character past, the `if` block's closing brace. In both cases, these are most likely off
+// by the number of characters stripped from the beginning of each doc comment line: indent
+// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+// more pronounced, and show up in more places, with background color used to show some distinct
+// code regions with different coverage counts.
+//
+// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+// character stripped from the beginning of doc comment lines with a space. This will give coverage
+// results the correct column offsets, and I think it should compile correctly, but I don't know
+// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+// if the indentation changed. I don't know if there is a more viable solution.
diff --git a/tests/run-make/coverage/drop_trait.rs b/tests/run-make/coverage/drop_trait.rs
new file mode 100644
index 00000000000..d15bfc0f877
--- /dev/null
+++ b/tests/run-make/coverage/drop_trait.rs
@@ -0,0 +1,33 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+struct Firework {
+    strength: i32,
+}
+
+impl Drop for Firework {
+    fn drop(&mut self) {
+        println!("BOOM times {}!!!", self.strength);
+    }
+}
+
+fn main() -> Result<(),u8> {
+    let _firecracker = Firework { strength: 1 };
+
+    let _tnt = Firework { strength: 100 };
+
+    if true {
+        println!("Exiting with error...");
+        return Err(1);
+    }
+
+    let _ = Firework { strength: 1000 };
+
+    Ok(())
+}
+
+// Expected program output:
+//   Exiting with error...
+//   BOOM times 100!!!
+//   BOOM times 1!!!
+//   Error: 1
diff --git a/tests/run-make/coverage/generator.rs b/tests/run-make/coverage/generator.rs
new file mode 100644
index 00000000000..4319991021e
--- /dev/null
+++ b/tests/run-make/coverage/generator.rs
@@ -0,0 +1,30 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+// The following implementation of a function called from a `yield` statement
+// (apparently requiring the Result and the `String` type or constructor)
+// creates conditions where the `generator::StateTransform` MIR transform will
+// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+// to handle this condition, and still report dead block coverage.
+fn get_u32(val: bool) -> Result<u32, String> {
+    if val { Ok(1) } else { Err(String::from("some error")) }
+}
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+    let mut generator = || {
+        yield get_u32(is_true);
+        return "foo";
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(Ok(1)) => {}
+        _ => panic!("unexpected return from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Complete("foo") => {}
+        _ => panic!("unexpected return from resume"),
+    }
+}
diff --git a/tests/run-make/coverage/generics.rs b/tests/run-make/coverage/generics.rs
new file mode 100644
index 00000000000..18b38868496
--- /dev/null
+++ b/tests/run-make/coverage/generics.rs
@@ -0,0 +1,48 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+struct Firework<T> where T: Copy + std::fmt::Display {
+    strength: T,
+}
+
+impl<T> Firework<T> where T: Copy + std::fmt::Display {
+    #[inline(always)]
+    fn set_strength(&mut self, new_strength: T) {
+        self.strength = new_strength;
+    }
+}
+
+impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+    #[inline(always)]
+    fn drop(&mut self) {
+        println!("BOOM times {}!!!", self.strength);
+    }
+}
+
+fn main() -> Result<(),u8> {
+    let mut firecracker = Firework { strength: 1 };
+    firecracker.set_strength(2);
+
+    let mut tnt = Firework { strength: 100.1 };
+    tnt.set_strength(200.1);
+    tnt.set_strength(300.3);
+
+    if true {
+        println!("Exiting with error...");
+        return Err(1);
+    }
+
+
+
+
+
+    let _ = Firework { strength: 1000 };
+
+    Ok(())
+}
+
+// Expected program output:
+//   Exiting with error...
+//   BOOM times 100!!!
+//   BOOM times 1!!!
+//   Error: 1
diff --git a/tests/run-make/coverage/if.rs b/tests/run-make/coverage/if.rs
new file mode 100644
index 00000000000..8ad5042ff7b
--- /dev/null
+++ b/tests/run-make/coverage/if.rs
@@ -0,0 +1,28 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let
+    is_true
+    =
+        std::env::args().len()
+    ==
+        1
+    ;
+    let
+        mut
+    countdown
+    =
+        0
+    ;
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+}
diff --git a/tests/run-make/coverage/if_else.rs b/tests/run-make/coverage/if_else.rs
new file mode 100644
index 00000000000..3244e1e3afd
--- /dev/null
+++ b/tests/run-make/coverage/if_else.rs
@@ -0,0 +1,40 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+    else // Note coverage region difference without semicolon
+    {
+        countdown
+        =
+            100
+    }
+
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+    else
+    {
+        countdown
+        =
+            100
+        ;
+    }
+}
diff --git a/tests/run-make/coverage/inline-dead.rs b/tests/run-make/coverage/inline-dead.rs
new file mode 100644
index 00000000000..854fa062967
--- /dev/null
+++ b/tests/run-make/coverage/inline-dead.rs
@@ -0,0 +1,27 @@
+// Regression test for issue #98833.
+// compile-flags: -Zinline-mir -Cdebug-assertions=off
+
+fn main() {
+    println!("{}", live::<false>());
+
+    let f = |x: bool| {
+        debug_assert!(
+            x
+        );
+    };
+    f(false);
+}
+
+#[inline]
+fn live<const B: bool>() -> u32 {
+    if B {
+        dead()
+    } else {
+        0
+    }
+}
+
+#[inline]
+fn dead() -> u32 {
+    42
+}
diff --git a/tests/run-make/coverage/inline.rs b/tests/run-make/coverage/inline.rs
new file mode 100644
index 00000000000..9cfab9ddbad
--- /dev/null
+++ b/tests/run-make/coverage/inline.rs
@@ -0,0 +1,51 @@
+// compile-flags: -Zinline-mir
+
+use std::fmt::Display;
+
+fn main() {
+    permutations(&['a', 'b', 'c']);
+}
+
+#[inline(always)]
+fn permutations<T: Copy + Display>(xs: &[T]) {
+    let mut ys = xs.to_owned();
+    permutate(&mut ys, 0);
+}
+
+fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+    let n = length(xs);
+    if k == n {
+        display(xs);
+    } else if k < n {
+        for i in k..n {
+            swap(xs, i, k);
+            permutate(xs, k + 1);
+            swap(xs, i, k);
+        }
+    } else {
+        error();
+    }
+}
+
+fn length<T>(xs: &[T]) -> usize {
+    xs.len()
+}
+
+#[inline]
+fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+    let t = xs[i];
+    xs[i] = xs[j];
+    xs[j] = t;
+}
+
+fn display<T: Display>(xs: &[T]) {
+    for x in xs {
+        print!("{}", x);
+    }
+    println!();
+}
+
+#[inline(always)]
+fn error() {
+    panic!("error");
+}
diff --git a/tests/run-make/coverage/inner_items.rs b/tests/run-make/coverage/inner_items.rs
new file mode 100644
index 00000000000..bcb62b3031c
--- /dev/null
+++ b/tests/run-make/coverage/inner_items.rs
@@ -0,0 +1,57 @@
+#![allow(unused_assignments, unused_variables, dead_code)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+
+    mod in_mod {
+        const IN_MOD_CONST: u32 = 1000;
+    }
+
+    fn in_func(a: u32) {
+        let b = 1;
+        let c = a + b;
+        println!("c = {}", c)
+    }
+
+    struct InStruct {
+        in_struct_field: u32,
+    }
+
+    const IN_CONST: u32 = 1234;
+
+    trait InTrait {
+        fn trait_func(&mut self, incr: u32);
+
+        fn default_trait_func(&mut self) {
+            in_func(IN_CONST);
+            self.trait_func(IN_CONST);
+        }
+    }
+
+    impl InTrait for InStruct {
+        fn trait_func(&mut self, incr: u32) {
+            self.in_struct_field += incr;
+            in_func(self.in_struct_field);
+        }
+    }
+
+    type InType = String;
+
+    if is_true {
+        in_func(countdown);
+    }
+
+    let mut val = InStruct {
+        in_struct_field: 101,
+    };
+
+    val.default_trait_func();
+}
diff --git a/tests/run-make/coverage/issue-83601.rs b/tests/run-make/coverage/issue-83601.rs
new file mode 100644
index 00000000000..0b72a81947c
--- /dev/null
+++ b/tests/run-make/coverage/issue-83601.rs
@@ -0,0 +1,14 @@
+// Shows that rust-lang/rust/83601 is resolved
+
+#[derive(Debug, PartialEq, Eq)]
+struct Foo(u32);
+
+fn main() {
+    let bar = Foo(1);
+    assert_eq!(bar, Foo(1));
+    let baz = Foo(0);
+    assert_ne!(baz, Foo(1));
+    println!("{:?}", Foo(1));
+    println!("{:?}", bar);
+    println!("{:?}", baz);
+}
diff --git a/tests/run-make/coverage/issue-84561.rs b/tests/run-make/coverage/issue-84561.rs
new file mode 100644
index 00000000000..b39a289c45e
--- /dev/null
+++ b/tests/run-make/coverage/issue-84561.rs
@@ -0,0 +1,182 @@
+// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+
+// expect-exit-status-101
+#[derive(PartialEq, Eq)]
+struct Foo(u32);
+fn test3() {
+    let is_true = std::env::args().len() == 1;
+    let bar = Foo(1);
+    assert_eq!(bar, Foo(1));
+    let baz = Foo(0);
+    assert_ne!(baz, Foo(1));
+    println!("{:?}", Foo(1));
+    println!("{:?}", bar);
+    println!("{:?}", baz);
+
+    assert_eq!(Foo(1), Foo(1));
+    assert_ne!(Foo(0), Foo(1));
+    assert_eq!(Foo(2), Foo(2));
+    let bar = Foo(0);
+    assert_ne!(bar, Foo(3));
+    assert_ne!(Foo(0), Foo(4));
+    assert_eq!(Foo(3), Foo(3), "with a message");
+    println!("{:?}", bar);
+    println!("{:?}", Foo(1));
+
+    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+    assert_ne!(
+        Foo(0)
+        ,
+        Foo(5)
+        ,
+        "{}"
+        ,
+        if
+        is_true
+        {
+            "true message"
+        } else {
+            "false message"
+        }
+    );
+
+    let is_true = std::env::args().len() == 1;
+
+    assert_eq!(
+        Foo(1),
+        Foo(1)
+    );
+    assert_ne!(
+        Foo(0),
+        Foo(1)
+    );
+    assert_eq!(
+        Foo(2),
+        Foo(2)
+    );
+    let bar = Foo(1);
+    assert_ne!(
+        bar,
+        Foo(3)
+    );
+    if is_true {
+        assert_ne!(
+            Foo(0),
+            Foo(4)
+        );
+    } else {
+        assert_eq!(
+            Foo(3),
+            Foo(3)
+        );
+    }
+    if is_true {
+        assert_ne!(
+            Foo(0),
+            Foo(4),
+            "with a message"
+        );
+    } else {
+        assert_eq!(
+            Foo(3),
+            Foo(3),
+            "with a message"
+        );
+    }
+    assert_ne!(
+        if is_true {
+            Foo(0)
+        } else {
+            Foo(1)
+        },
+        Foo(5)
+    );
+    assert_ne!(
+        Foo(5),
+        if is_true {
+            Foo(0)
+        } else {
+            Foo(1)
+        }
+    );
+    assert_ne!(
+        if is_true {
+            assert_eq!(
+                Foo(3),
+                Foo(3)
+            );
+            Foo(0)
+        } else {
+            assert_ne!(
+                if is_true {
+                    Foo(0)
+                } else {
+                    Foo(1)
+                },
+                Foo(5)
+            );
+            Foo(1)
+        },
+        Foo(5),
+        "with a message"
+    );
+    assert_eq!(
+        Foo(1),
+        Foo(3),
+        "this assert should fail"
+    );
+    assert_eq!(
+        Foo(3),
+        Foo(3),
+        "this assert should not be reached"
+    );
+}
+
+impl std::fmt::Debug for Foo {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        write!(f, "try and succeed")?;
+        Ok(())
+    }
+}
+
+static mut DEBUG_LEVEL_ENABLED: bool = false;
+
+macro_rules! debug {
+    ($($arg:tt)+) => (
+        if unsafe { DEBUG_LEVEL_ENABLED } {
+            println!($($arg)+);
+        }
+    );
+}
+
+fn test1() {
+    debug!("debug is enabled");
+    debug!("debug is enabled");
+    let _ = 0;
+    debug!("debug is enabled");
+    unsafe {
+        DEBUG_LEVEL_ENABLED = true;
+    }
+    debug!("debug is enabled");
+}
+
+macro_rules! call_debug {
+    ($($arg:tt)+) => (
+        fn call_print(s: &str) {
+            print!("{}", s);
+        }
+
+        call_print("called from call_debug: ");
+        debug!($($arg)+);
+    );
+}
+
+fn test2() {
+    call_debug!("debug is enabled");
+}
+
+fn main() {
+    test1();
+    test2();
+    test3();
+}
diff --git a/tests/run-make/coverage/issue-85461.rs b/tests/run-make/coverage/issue-85461.rs
new file mode 100644
index 00000000000..a1b9ebb1ed3
--- /dev/null
+++ b/tests/run-make/coverage/issue-85461.rs
@@ -0,0 +1,10 @@
+// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+
+extern crate inline_always_with_dead_code;
+
+use inline_always_with_dead_code::{bar, baz};
+
+fn main() {
+    bar::call_me();
+    baz::call_me();
+}
diff --git a/tests/run-make/coverage/issue-93054.rs b/tests/run-make/coverage/issue-93054.rs
new file mode 100644
index 00000000000..c160b3db03f
--- /dev/null
+++ b/tests/run-make/coverage/issue-93054.rs
@@ -0,0 +1,28 @@
+// Regression test for #93054: Functions using uninhabited types often only have a single,
+// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+
+// compile-flags: --edition=2021
+
+enum Never { }
+
+impl Never {
+    fn foo(self) {
+        match self { }
+        make().map(|never| match never { });
+    }
+
+    fn bar(&self) {
+        match *self { }
+    }
+}
+
+async fn foo2(never: Never) {
+    match never { }
+}
+
+fn make() -> Option<Never> {
+    None
+}
+
+fn main() { }
diff --git a/tests/run-make/coverage/lazy_boolean.rs b/tests/run-make/coverage/lazy_boolean.rs
new file mode 100644
index 00000000000..bb6219e851c
--- /dev/null
+++ b/tests/run-make/coverage/lazy_boolean.rs
@@ -0,0 +1,61 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let (mut a, mut b, mut c) = (0, 0, 0);
+    if is_true {
+        a = 1;
+        b = 10;
+        c = 100;
+    }
+    let
+        somebool
+        =
+            a < b
+        ||
+            b < c
+    ;
+    let
+        somebool
+        =
+            b < a
+        ||
+            b < c
+    ;
+    let somebool = a < b && b < c;
+    let somebool = b < a && b < c;
+
+    if
+        !
+        is_true
+    {
+        a = 2
+        ;
+    }
+
+    if
+        is_true
+    {
+        b = 30
+        ;
+    }
+    else
+    {
+        c = 400
+        ;
+    }
+
+    if !is_true {
+        a = 2;
+    }
+
+    if is_true {
+        b = 30;
+    } else {
+        c = 400;
+    }
+}
diff --git a/tests/run-make/coverage/lib/doctest_crate.rs b/tests/run-make/coverage/lib/doctest_crate.rs
new file mode 100644
index 00000000000..c3210146d69
--- /dev/null
+++ b/tests/run-make/coverage/lib/doctest_crate.rs
@@ -0,0 +1,9 @@
+/// A function run only from within doctests
+pub fn fn_run_in_doctests(conditional: usize) {
+    match conditional {
+        1 => assert_eq!(1, 1), // this is run,
+        2 => assert_eq!(1, 1), // this,
+        3 => assert_eq!(1, 1), // and this too
+        _ => assert_eq!(1, 2), // however this is not
+    }
+}
diff --git a/tests/run-make/coverage/lib/inline_always_with_dead_code.rs b/tests/run-make/coverage/lib/inline_always_with_dead_code.rs
new file mode 100644
index 00000000000..2b21dee6ccf
--- /dev/null
+++ b/tests/run-make/coverage/lib/inline_always_with_dead_code.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+
+#![allow(dead_code)]
+
+mod foo {
+    #[inline(always)]
+    pub fn called() { }
+
+    fn uncalled() { }
+}
+
+pub mod bar {
+    pub fn call_me() {
+        super::foo::called();
+    }
+}
+
+pub mod baz {
+    pub fn call_me() {
+        super::foo::called();
+    }
+}
diff --git a/tests/run-make/coverage/lib/unused_mod_helper.rs b/tests/run-make/coverage/lib/unused_mod_helper.rs
new file mode 100644
index 00000000000..ae1cc1531ed
--- /dev/null
+++ b/tests/run-make/coverage/lib/unused_mod_helper.rs
@@ -0,0 +1,3 @@
+pub fn never_called_function() {
+    println!("I am never called");
+}
diff --git a/tests/run-make/coverage/lib/used_crate.rs b/tests/run-make/coverage/lib/used_crate.rs
new file mode 100644
index 00000000000..8b8b1f7f351
--- /dev/null
+++ b/tests/run-make/coverage/lib/used_crate.rs
@@ -0,0 +1,100 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+use std::fmt::Debug;
+
+pub fn used_function() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+    use_this_lib_crate();
+}
+
+pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+}
+// Expect for above function: `Unexecuted instantiation` (see below)
+pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn unused_generic_function<T: Debug>(arg: T) {
+    println!("unused_generic_function with {:?}", arg);
+}
+
+pub fn unused_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+fn unused_private_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+fn use_this_lib_crate() {
+    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+        "used from library used_crate.rs",
+    );
+    let some_vec = vec![5, 6, 7, 8];
+    used_only_from_this_lib_crate_generic_function(some_vec);
+    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+}
+
+// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+// for example:
+//
+// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+//
+// These notices appear when `llvm-cov` shows instantiations. This may be a
+// default option, but it can be suppressed with:
+//
+// ```shell
+// $ `llvm-cov show --show-instantiations=0 ...`
+// ```
+//
+// The notice is triggered because the function is unused by the library itself,
+// and when the library is compiled, a synthetic function is generated, so
+// unused function coverage can be reported. Coverage can be skipped for unused
+// generic functions with:
+//
+// ```shell
+// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+// ```
+//
+// Even though this function is used by `uses_crate.rs` (and
+// counted), with substitutions for `T`, those instantiations are only generated
+// when the generic function is actually used (from the binary, not from this
+// library crate). So the test result shows coverage for all instantiated
+// versions and their generic type substitutions, plus the `Unexecuted
+// instantiation` message for the non-substituted version. This is valid, but
+// unfortunately a little confusing.
+//
+// The library crate has its own coverage map, and the only way to show unused
+// coverage of a generic function is to include the generic function in the
+// coverage map, marked as an "unused function". If the library were used by
+// another binary that never used this generic function, then it would be valid
+// to show the unused generic, with unknown substitution (`_`).
+//
+// The alternative is to exclude all generics from being included in the "unused
+// functions" list, which would then omit coverage results for
+// `unused_generic_function<T>()`, below.
diff --git a/tests/run-make/coverage/lib/used_inline_crate.rs b/tests/run-make/coverage/lib/used_inline_crate.rs
new file mode 100644
index 00000000000..4a052756d4e
--- /dev/null
+++ b/tests/run-make/coverage/lib/used_inline_crate.rs
@@ -0,0 +1,90 @@
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+use std::fmt::Debug;
+
+pub fn used_function() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+    use_this_lib_crate();
+}
+
+#[inline(always)]
+pub fn used_inline_function() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+    use_this_lib_crate();
+}
+
+
+
+
+
+
+
+#[inline(always)]
+pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+}
+// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+
+#[inline(always)]
+pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn unused_generic_function<T: Debug>(arg: T) {
+    println!("unused_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn unused_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+#[inline(always)]
+fn unused_private_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+fn use_this_lib_crate() {
+    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+        "used from library used_crate.rs",
+    );
+    let some_vec = vec![5, 6, 7, 8];
+    used_only_from_this_lib_crate_generic_function(some_vec);
+    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+}
diff --git a/tests/run-make/coverage/loop_break_value.rs b/tests/run-make/coverage/loop_break_value.rs
new file mode 100644
index 00000000000..dbc4fad7a23
--- /dev/null
+++ b/tests/run-make/coverage/loop_break_value.rs
@@ -0,0 +1,13 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    let result
+        =
+            loop
+        {
+            break
+            10
+            ;
+        }
+    ;
+}
diff --git a/tests/run-make/coverage/loops_branches.rs b/tests/run-make/coverage/loops_branches.rs
new file mode 100644
index 00000000000..7116ce47f4b
--- /dev/null
+++ b/tests/run-make/coverage/loops_branches.rs
@@ -0,0 +1,61 @@
+#![allow(unused_assignments, unused_variables, while_true)]
+
+// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+
+struct DebugTest;
+
+impl std::fmt::Debug for DebugTest {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        if true {
+            if false {
+                while true {
+                }
+            }
+            write!(f, "cool")?;
+        } else {
+        }
+
+        for i in 0..10 {
+            if true {
+                if false {
+                    while true {}
+                }
+                write!(f, "cool")?;
+            } else {
+            }
+        }
+        Ok(())
+    }
+}
+
+struct DisplayTest;
+
+impl std::fmt::Display for DisplayTest {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        if false {
+        } else {
+            if false {
+                while true {}
+            }
+            write!(f, "cool")?;
+        }
+        for i in 0..10 {
+            if false {
+            } else {
+                if false {
+                    while true {}
+                }
+                write!(f, "cool")?;
+            }
+        }
+        Ok(())
+    }
+}
+
+fn main() {
+    let debug_test = DebugTest;
+    println!("{:?}", debug_test);
+    let display_test = DisplayTest;
+    println!("{}", display_test);
+}
diff --git a/tests/run-make/coverage/match_or_pattern.rs b/tests/run-make/coverage/match_or_pattern.rs
new file mode 100644
index 00000000000..4c6a8a9b703
--- /dev/null
+++ b/tests/run-make/coverage/match_or_pattern.rs
@@ -0,0 +1,45 @@
+#![feature(or_patterns)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut a: u8 = 0;
+    let mut b: u8 = 0;
+    if is_true {
+        a = 2;
+        b = 0;
+    }
+    match (a, b) {
+        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+        // This test confirms a fix for Issue #79569.
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+    if is_true {
+        a = 0;
+        b = 0;
+    }
+    match (a, b) {
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+    if is_true {
+        a = 2;
+        b = 2;
+    }
+    match (a, b) {
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+    if is_true {
+        a = 0;
+        b = 2;
+    }
+    match (a, b) {
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+}
diff --git a/tests/run-make/coverage/nested_loops.rs b/tests/run-make/coverage/nested_loops.rs
new file mode 100644
index 00000000000..4c7c7842796
--- /dev/null
+++ b/tests/run-make/coverage/nested_loops.rs
@@ -0,0 +1,25 @@
+fn main() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 10;
+
+    'outer: while countdown > 0 {
+        let mut a = 100;
+        let mut b = 100;
+        for _ in 0..50 {
+            if a < 30 {
+                break;
+            }
+            a -= 5;
+            b -= 5;
+            if b < 90 {
+                a -= 10;
+                if is_true {
+                    break 'outer;
+                } else {
+                    a -= 2;
+                }
+            }
+        }
+        countdown -= 1;
+    }
+}
diff --git a/tests/run-make/coverage/no_cov_crate.rs b/tests/run-make/coverage/no_cov_crate.rs
new file mode 100644
index 00000000000..0bfbdda2cab
--- /dev/null
+++ b/tests/run-make/coverage/no_cov_crate.rs
@@ -0,0 +1,86 @@
+// Enables `no_coverage` on the entire crate
+#![feature(no_coverage)]
+
+#[no_coverage]
+fn do_not_add_coverage_1() {
+    println!("called but not covered");
+}
+
+fn do_not_add_coverage_2() {
+    #![no_coverage]
+    println!("called but not covered");
+}
+
+#[no_coverage]
+fn do_not_add_coverage_not_called() {
+    println!("not called and not covered");
+}
+
+fn add_coverage_1() {
+    println!("called and covered");
+}
+
+fn add_coverage_2() {
+    println!("called and covered");
+}
+
+fn add_coverage_not_called() {
+    println!("not called but covered");
+}
+
+// FIXME: These test-cases illustrate confusing results of nested functions.
+// See https://github.com/rust-lang/rust/issues/93319
+mod nested_fns {
+    #[no_coverage]
+    pub fn outer_not_covered(is_true: bool) {
+        fn inner(is_true: bool) {
+            if is_true {
+                println!("called and covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+        println!("called but not covered");
+        inner(is_true);
+    }
+
+    pub fn outer(is_true: bool) {
+        println!("called and covered");
+        inner_not_covered(is_true);
+
+        #[no_coverage]
+        fn inner_not_covered(is_true: bool) {
+            if is_true {
+                println!("called but not covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+    }
+
+    pub fn outer_both_covered(is_true: bool) {
+        println!("called and covered");
+        inner(is_true);
+
+        fn inner(is_true: bool) {
+            if is_true {
+                println!("called and covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+    }
+}
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+
+    do_not_add_coverage_1();
+    do_not_add_coverage_2();
+    add_coverage_1();
+    add_coverage_2();
+
+    nested_fns::outer_not_covered(is_true);
+    nested_fns::outer(is_true);
+    nested_fns::outer_both_covered(is_true);
+}
diff --git a/tests/run-make/coverage/overflow.rs b/tests/run-make/coverage/overflow.rs
new file mode 100644
index 00000000000..e537b0e95c3
--- /dev/null
+++ b/tests/run-make/coverage/overflow.rs
@@ -0,0 +1,63 @@
+#![allow(unused_assignments)]
+// expect-exit-status-101
+
+fn might_overflow(to_add: u32) -> u32 {
+    if to_add > 5 {
+        println!("this will probably overflow");
+    }
+    let add_to = u32::MAX - 5;
+    println!("does {} + {} overflow?", add_to, to_add);
+    let result = to_add + add_to;
+    println!("continuing after overflow check");
+    result
+}
+
+fn main() -> Result<(),u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown == 1 {
+            let result = might_overflow(10);
+            println!("Result: {}", result);
+        } else if countdown < 5 {
+            let result = might_overflow(1);
+            println!("Result: {}", result);
+        }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+//      and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+//   2. This test confirms the coverage generated when a program passes or fails a
+//      compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+//   3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+//      compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+//      expected behavior. To simplify the coverage graphs and keep instrumented programs as
+//      small and fast as possible, `Assert` terminators are assumed to always succeed, and
+//      therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+//      get its own coverage counter.
+//   4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+//      In this test, the final count for the statements after the `if` block in `might_overflow()`
+//      is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+//      on the MIR graph and the structure of the code, this count could have been 3 (which might
+//      have been valid for the overflowed add `+`, but should have been 4 for the lines before
+//      the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+//      via StatementKind::Counter at the end of the block, but (as in the case in this test),
+//      a CounterKind::Expression is always evaluated. In this case, the expression was based on
+//      a `Counter` incremented as part of the evaluation of the `if` expression, which was
+//      executed, and counted, 4 times, before reaching the overflow add.
+
+// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+//
+//     4|       |fn might_overflow(to_add: u32) -> u32 {
+//     5|      4|    if to_add > 5 {
+//     6|      0|        println!("this will probably overflow");
+//     7|      4|    }
+//     8|      4|    let add_to = u32::MAX - 5;
+//     9|      4|    println!("does {} + {} overflow?", add_to, to_add);
+//    10|      4|    let result = to_add + add_to;
+//    11|      4|    println!("continuing after overflow check");
+//    12|      4|    result
+//    13|      4|}
diff --git a/tests/run-make/coverage/panic_unwind.rs b/tests/run-make/coverage/panic_unwind.rs
new file mode 100644
index 00000000000..03128c2cce6
--- /dev/null
+++ b/tests/run-make/coverage/panic_unwind.rs
@@ -0,0 +1,31 @@
+#![allow(unused_assignments)]
+// expect-exit-status-101
+
+fn might_panic(should_panic: bool) {
+    if should_panic {
+        println!("panicking...");
+        panic!("panics");
+    } else {
+        println!("Don't Panic");
+    }
+}
+
+fn main() -> Result<(), u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown == 1 {
+            might_panic(true);
+        } else if countdown < 5 {
+            might_panic(false);
+        }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+//      `try_error_result.rs`.
+//   2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+//      normal program exit cleanup, including writing out the current values of the coverage
+//      counters.
diff --git a/tests/run-make/coverage/partial_eq.rs b/tests/run-make/coverage/partial_eq.rs
new file mode 100644
index 00000000000..4ceaba9b111
--- /dev/null
+++ b/tests/run-make/coverage/partial_eq.rs
@@ -0,0 +1,46 @@
+// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+// structure of this test.
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Version {
+    major: usize,
+    minor: usize,
+    patch: usize,
+}
+
+impl Version {
+    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+        Self {
+            major,
+            minor,
+            patch,
+        }
+    }
+}
+
+fn main() {
+    let version_3_2_1 = Version::new(3, 2, 1);
+    let version_3_3_0 = Version::new(3, 3, 0);
+
+    println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+}
+
+/*
+
+This test verifies a bug was fixed that otherwise generated this error:
+
+thread 'rustc' panicked at 'No counters provided the source_hash for function:
+    Instance {
+        def: Item(WithOptConstParam {
+            did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+            const_param_did: None
+        }),
+        substs: []
+    }'
+The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+without a code region associated with any `Counter`. Code regions were associated with at least
+one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+`function_source_hash` without a code region, if necessary.
+
+*/
diff --git a/tests/run-make/coverage/simple_loop.rs b/tests/run-make/coverage/simple_loop.rs
new file mode 100644
index 00000000000..6f7f23475b8
--- /dev/null
+++ b/tests/run-make/coverage/simple_loop.rs
@@ -0,0 +1,35 @@
+#![allow(unused_assignments)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+
+    loop
+    {
+        if
+            countdown
+                ==
+            0
+        {
+            break
+            ;
+        }
+        countdown
+        -=
+        1
+        ;
+    }
+}
diff --git a/tests/run-make/coverage/simple_match.rs b/tests/run-make/coverage/simple_match.rs
new file mode 100644
index 00000000000..be99e59a826
--- /dev/null
+++ b/tests/run-make/coverage/simple_match.rs
@@ -0,0 +1,43 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 1;
+    if is_true {
+        countdown = 0;
+    }
+
+    for
+        _
+    in
+        0..2
+    {
+        let z
+        ;
+        match
+            countdown
+        {
+            x
+            if
+                x
+                    <
+                1
+            =>
+            {
+                z = countdown
+                ;
+                let y = countdown
+                ;
+                countdown = 10
+                ;
+            }
+            _
+            =>
+            {}
+        }
+    }
+}
diff --git a/tests/run-make/coverage/tight_inf_loop.rs b/tests/run-make/coverage/tight_inf_loop.rs
new file mode 100644
index 00000000000..cef99027aaa
--- /dev/null
+++ b/tests/run-make/coverage/tight_inf_loop.rs
@@ -0,0 +1,5 @@
+fn main() {
+    if false {
+        loop {}
+    }
+}
diff --git a/tests/run-make/coverage/try_error_result.rs b/tests/run-make/coverage/try_error_result.rs
new file mode 100644
index 00000000000..cd0acf72302
--- /dev/null
+++ b/tests/run-make/coverage/try_error_result.rs
@@ -0,0 +1,118 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+fn call(return_error: bool) -> Result<(),()> {
+    if return_error {
+        Err(())
+    } else {
+        Ok(())
+    }
+}
+
+fn test1() -> Result<(),()> {
+    let mut
+        countdown = 10
+    ;
+    for
+        _
+    in
+        0..10
+    {
+        countdown
+            -= 1
+        ;
+        if
+            countdown < 5
+        {
+            call(/*return_error=*/ true)?;
+            call(/*return_error=*/ false)?;
+        }
+        else
+        {
+            call(/*return_error=*/ false)?;
+        }
+    }
+    Ok(())
+}
+
+struct Thing1;
+impl Thing1 {
+    fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+        if return_error {
+            Err(())
+        } else {
+            Ok(Thing2{})
+        }
+    }
+}
+
+struct Thing2;
+impl Thing2 {
+    fn call(&self, return_error: bool) -> Result<u32,()> {
+        if return_error {
+            Err(())
+        } else {
+            Ok(57)
+        }
+    }
+}
+
+fn test2() -> Result<(),()> {
+    let thing1 = Thing1{};
+    let mut
+        countdown = 10
+    ;
+    for
+        _
+    in
+        0..10
+    {
+        countdown
+            -= 1
+        ;
+        if
+            countdown < 5
+        {
+            thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+            thing1
+                .
+                get_thing_2(/*return_error=*/ false)
+                ?
+                .
+                call(/*return_error=*/ true)
+                .
+                expect_err(
+                    "call should fail"
+                );
+            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+            assert_eq!(val, 57);
+            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+            assert_eq!(val, 57);
+        }
+        else
+        {
+            let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+            assert_eq!(val, 57);
+            let val = thing1
+                .get_thing_2(/*return_error=*/ false)?
+                .call(/*return_error=*/ false)?;
+            assert_eq!(val, 57);
+            let val = thing1
+                .get_thing_2(/*return_error=*/ false)
+                ?
+                .call(/*return_error=*/ false)
+                ?
+                ;
+            assert_eq!(val, 57);
+        }
+    }
+    Ok(())
+}
+
+fn main() -> Result<(),()> {
+    test1().expect_err("test1 should fail");
+    test2()
+    ?
+    ;
+    Ok(())
+}
diff --git a/tests/run-make/coverage/unused.rs b/tests/run-make/coverage/unused.rs
new file mode 100644
index 00000000000..fb6113eb01c
--- /dev/null
+++ b/tests/run-make/coverage/unused.rs
@@ -0,0 +1,39 @@
+fn foo<T>(x: T) {
+    let mut i = 0;
+    while i < 10 {
+        i != 0 || i != 0;
+        i += 1;
+    }
+}
+
+fn unused_template_func<T>(x: T) {
+    let mut i = 0;
+    while i < 10 {
+        i != 0 || i != 0;
+        i += 1;
+    }
+}
+
+fn unused_func(mut a: u32) {
+    if a != 0 {
+        a += 1;
+    }
+}
+
+fn unused_func2(mut a: u32) {
+    if a != 0 {
+        a += 1;
+    }
+}
+
+fn unused_func3(mut a: u32) {
+    if a != 0 {
+        a += 1;
+    }
+}
+
+fn main() -> Result<(), u8> {
+    foo::<u32>(0);
+    foo::<f32>(0.0);
+    Ok(())
+}
diff --git a/tests/run-make/coverage/unused_mod.rs b/tests/run-make/coverage/unused_mod.rs
new file mode 100644
index 00000000000..679b4e53188
--- /dev/null
+++ b/tests/run-make/coverage/unused_mod.rs
@@ -0,0 +1,6 @@
+#[path = "lib/unused_mod_helper.rs"]
+mod unused_module;
+
+fn main() {
+    println!("hello world!");
+}
diff --git a/tests/run-make/coverage/uses_crate.rs b/tests/run-make/coverage/uses_crate.rs
new file mode 100644
index 00000000000..20cb05fe5b0
--- /dev/null
+++ b/tests/run-make/coverage/uses_crate.rs
@@ -0,0 +1,12 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+extern crate used_crate;
+
+fn main() {
+    used_crate::used_function();
+    let some_vec = vec![1, 2, 3, 4];
+    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+}
diff --git a/tests/run-make/coverage/uses_inline_crate.rs b/tests/run-make/coverage/uses_inline_crate.rs
new file mode 100644
index 00000000000..a7fe8532be3
--- /dev/null
+++ b/tests/run-make/coverage/uses_inline_crate.rs
@@ -0,0 +1,17 @@
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+extern crate used_inline_crate;
+
+fn main() {
+    used_inline_crate::used_function();
+    used_inline_crate::used_inline_function();
+    let some_vec = vec![1, 2, 3, 4];
+    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+        "interesting?",
+    );
+}
diff --git a/tests/run-make/coverage/while.rs b/tests/run-make/coverage/while.rs
new file mode 100644
index 00000000000..781b90b3566
--- /dev/null
+++ b/tests/run-make/coverage/while.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let num = 9;
+    while num >= 10 {
+    }
+}
diff --git a/tests/run-make/coverage/while_early_ret.rs b/tests/run-make/coverage/while_early_ret.rs
new file mode 100644
index 00000000000..1fcea9c85c4
--- /dev/null
+++ b/tests/run-make/coverage/while_early_ret.rs
@@ -0,0 +1,42 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+fn main() -> Result<(),u8> {
+    let mut countdown = 10;
+    while
+        countdown
+            >
+        0
+    {
+        if
+            countdown
+                <
+            5
+        {
+            return
+                if
+                    countdown
+                        >
+                    8
+                {
+                    Ok(())
+                }
+                else
+                {
+                    Err(1)
+                }
+                ;
+        }
+        countdown
+            -=
+        1
+        ;
+    }
+    Ok(())
+}
+
+// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+// to the coverage test for early returns, but this is a limitation that should be fixed.
diff --git a/tests/run-make/coverage/yield.rs b/tests/run-make/coverage/yield.rs
new file mode 100644
index 00000000000..ff7616656ff
--- /dev/null
+++ b/tests/run-make/coverage/yield.rs
@@ -0,0 +1,37 @@
+#![feature(generators, generator_trait)]
+#![allow(unused_assignments)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+fn main() {
+    let mut generator = || {
+        yield 1;
+        return "foo"
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(1) => {}
+        _ => panic!("unexpected value from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Complete("foo") => {}
+        _ => panic!("unexpected value from resume"),
+    }
+
+    let mut generator = || {
+        yield 1;
+        yield 2;
+        yield 3;
+        return "foo"
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(1) => {}
+        _ => panic!("unexpected value from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(2) => {}
+        _ => panic!("unexpected value from resume"),
+    }
+}
diff --git a/tests/run-make/dep-graph/Makefile b/tests/run-make/dep-graph/Makefile
new file mode 100644
index 00000000000..ae97b1672ae
--- /dev/null
+++ b/tests/run-make/dep-graph/Makefile
@@ -0,0 +1,12 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-cross-compile
+
+# Just verify that we successfully run and produce dep graphs when requested.
+
+all:
+	RUST_DEP_GRAPH=$(TMPDIR)/dep-graph $(RUSTC) \
+        -Cincremental=$(TMPDIR)/incr \
+        -Zquery-dep-graph -Zdump-dep-graph foo.rs
+	test -f $(TMPDIR)/dep-graph.txt
+	test -f $(TMPDIR)/dep-graph.dot
diff --git a/tests/run-make/dep-graph/foo.rs b/tests/run-make/dep-graph/foo.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/dep-graph/foo.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/dump-mono-stats/Makefile b/tests/run-make/dump-mono-stats/Makefile
new file mode 100644
index 00000000000..fe1112fb0a4
--- /dev/null
+++ b/tests/run-make/dump-mono-stats/Makefile
@@ -0,0 +1,5 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type lib foo.rs -Z dump-mono-stats=$(TMPDIR) -Zdump-mono-stats-format=json
+	cat $(TMPDIR)/foo.mono_items.json | $(CGREP) '"name":"bar"'
diff --git a/tests/run-make/dump-mono-stats/foo.rs b/tests/run-make/dump-mono-stats/foo.rs
new file mode 100644
index 00000000000..c5c0bc606cd
--- /dev/null
+++ b/tests/run-make/dump-mono-stats/foo.rs
@@ -0,0 +1 @@
+pub fn bar() {}
diff --git a/tests/run-make/emit-named-files/Makefile b/tests/run-make/emit-named-files/Makefile
new file mode 100644
index 00000000000..e081fa4793b
--- /dev/null
+++ b/tests/run-make/emit-named-files/Makefile
@@ -0,0 +1,33 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUT=$(TMPDIR)/emit
+
+all: asm llvm-bc llvm-ir obj metadata link dep-info mir
+
+asm: $(OUT)
+	$(RUSTC) --emit asm=$(OUT)/libfoo.s foo.rs
+	test -f $(OUT)/libfoo.s
+llvm-bc: $(OUT)
+	$(RUSTC) --emit llvm-bc=$(OUT)/libfoo.bc foo.rs
+	test -f $(OUT)/libfoo.bc
+llvm-ir: $(OUT)
+	$(RUSTC) --emit llvm-ir=$(OUT)/libfoo.ll foo.rs
+	test -f $(OUT)/libfoo.ll
+obj: $(OUT)
+	$(RUSTC) --emit obj=$(OUT)/libfoo.o foo.rs
+	test -f $(OUT)/libfoo.o
+metadata: $(OUT)
+	$(RUSTC) --emit metadata=$(OUT)/libfoo.rmeta foo.rs
+	test -f $(OUT)/libfoo.rmeta
+link: $(OUT)
+	$(RUSTC) --emit link=$(OUT)/libfoo.rlib foo.rs
+	test -f $(OUT)/libfoo.rlib
+dep-info: $(OUT)
+	$(RUSTC) --emit dep-info=$(OUT)/libfoo.d foo.rs
+	test -f $(OUT)/libfoo.d
+mir: $(OUT)
+	$(RUSTC) --emit mir=$(OUT)/libfoo.mir foo.rs
+	test -f $(OUT)/libfoo.mir
+
+$(OUT):
+	mkdir -p $(OUT)
diff --git a/tests/run-make/emit-named-files/foo.rs b/tests/run-make/emit-named-files/foo.rs
new file mode 100644
index 00000000000..c1bfaa6cab5
--- /dev/null
+++ b/tests/run-make/emit-named-files/foo.rs
@@ -0,0 +1 @@
+#![crate_type = "rlib"]
diff --git a/tests/run-make/emit-path-unhashed/Makefile b/tests/run-make/emit-path-unhashed/Makefile
new file mode 100644
index 00000000000..c144d4aa92f
--- /dev/null
+++ b/tests/run-make/emit-path-unhashed/Makefile
@@ -0,0 +1,37 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUT=$(TMPDIR)/emit
+
+# --emit KIND=PATH should not affect crate hash vs --emit KIND
+all: $(OUT)/a/libfoo.rlib $(OUT)/b/libfoo.rlib $(OUT)/c/libfoo.rlib \
+		$(TMPDIR)/libfoo.rlib
+	$(RUSTC) -Zls $(TMPDIR)/libfoo.rlib > $(TMPDIR)/base.txt
+	$(RUSTC) -Zls $(OUT)/a/libfoo.rlib > $(TMPDIR)/a.txt
+	$(RUSTC) -Zls $(OUT)/b/libfoo.rlib > $(TMPDIR)/b.txt
+	$(RUSTC) -Zls $(OUT)/c/libfoo.rlib > $(TMPDIR)/c.txt
+
+	diff $(TMPDIR)/base.txt $(TMPDIR)/a.txt
+	diff $(TMPDIR)/base.txt $(TMPDIR)/b.txt
+
+	# Different KIND parameters do affect hash.
+	# diff exits 1 on difference, 2 on trouble
+	diff $(TMPDIR)/base.txt $(TMPDIR)/c.txt ; test "$$?" -eq 1
+
+# Default output name
+$(TMPDIR)/libfoo.rlib: foo.rs
+	$(RUSTC) --emit link foo.rs
+
+# Output named with -o
+$(OUT)/a/libfoo.rlib: foo.rs
+	mkdir -p $(OUT)/a
+	$(RUSTC) --emit link -o $@ foo.rs
+
+# Output named with KIND=PATH
+$(OUT)/b/libfoo.rlib: foo.rs
+	mkdir -p $(OUT)/b
+	$(RUSTC) --emit link=$@ foo.rs
+
+# Output multiple kinds
+$(OUT)/c/libfoo.rlib: foo.rs
+	mkdir -p $(OUT)/c
+	$(RUSTC) --emit link=$@,metadata foo.rs
diff --git a/tests/run-make/emit-path-unhashed/foo.rs b/tests/run-make/emit-path-unhashed/foo.rs
new file mode 100644
index 00000000000..c1bfaa6cab5
--- /dev/null
+++ b/tests/run-make/emit-path-unhashed/foo.rs
@@ -0,0 +1 @@
+#![crate_type = "rlib"]
diff --git a/tests/run-make/emit-shared-files/Makefile b/tests/run-make/emit-shared-files/Makefile
new file mode 100644
index 00000000000..cad0c9e5b81
--- /dev/null
+++ b/tests/run-make/emit-shared-files/Makefile
@@ -0,0 +1,46 @@
+include ../../run-make-fulldeps/tools.mk
+
+INVOCATION_ONLY = $(TMPDIR)/invocation-only
+TOOLCHAIN_ONLY = $(TMPDIR)/toolchain-only
+ALL_SHARED = $(TMPDIR)/all-shared
+
+all: invocation-only toolchain-only all-shared
+
+invocation-only:
+	$(RUSTDOC) -Z unstable-options --emit=invocation-specific --output $(INVOCATION_ONLY) --resource-suffix=-xxx --theme y.css --extend-css z.css x.rs
+	[ -e $(INVOCATION_ONLY)/search-index-xxx.js ]
+	[ -e $(INVOCATION_ONLY)/settings.html ]
+	[ -e $(INVOCATION_ONLY)/x/all.html ]
+	[ -e $(INVOCATION_ONLY)/x/index.html ]
+	[ -e $(INVOCATION_ONLY)/theme-xxx.css ] # generated from z.css
+	! [ -e $(INVOCATION_ONLY)/storage-xxx.js ]
+	! [ -e $(INVOCATION_ONLY)/SourceSerif4-It.ttf.woff2 ]
+
+	# FIXME: this probably shouldn't have a suffix
+	[ -e $(INVOCATION_ONLY)/y-xxx.css ]
+	# FIXME: this is technically incorrect (see `write_shared`)
+	! [ -e $(INVOCATION_ONLY)/main-xxx.js ]
+
+toolchain-only:
+	$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs
+	[ -e $(TOOLCHAIN_ONLY)/static.files/storage-*.js ]
+	[ -e $(TOOLCHAIN_ONLY)/static.files/SourceSerif4-It-*.ttf.woff2 ]
+	! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ]
+	! [ -e $(TOOLCHAIN_ONLY)/x/index.html ]
+	! [ -e $(TOOLCHAIN_ONLY)/theme.css ]
+
+	[ -e $(TOOLCHAIN_ONLY)/static.files/main-*.js ]
+	! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ]
+
+all-shared:
+	$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs
+	[ -e $(ALL_SHARED)/static.files/storage-*.js ]
+	[ -e $(ALL_SHARED)/static.files/SourceSerif4-It-*.ttf.woff2 ]
+	! [ -e $(ALL_SHARED)/search-index-xxx.js ]
+	! [ -e $(ALL_SHARED)/settings.html ]
+	! [ -e $(ALL_SHARED)/x ]
+	! [ -e $(ALL_SHARED)/src ]
+	! [ -e $(ALL_SHARED)/theme.css ]
+
+	[ -e $(ALL_SHARED)/static.files/main-*.js ]
+	! [ -e $(ALL_SHARED)/y-xxx.css ]
diff --git a/tests/run-make/emit-shared-files/x.rs b/tests/run-make/emit-shared-files/x.rs
new file mode 100644
index 00000000000..5df7576133a
--- /dev/null
+++ b/tests/run-make/emit-shared-files/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/tests/run-make/emit-shared-files/y.css b/tests/run-make/emit-shared-files/y.css
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/run-make/emit-shared-files/y.css
diff --git a/tests/run-make/emit-shared-files/z.css b/tests/run-make/emit-shared-files/z.css
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/run-make/emit-shared-files/z.css
diff --git a/tests/run-make/env-dep-info/Makefile b/tests/run-make/env-dep-info/Makefile
new file mode 100644
index 00000000000..1675a61b167
--- /dev/null
+++ b/tests/run-make/env-dep-info/Makefile
@@ -0,0 +1,19 @@
+include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+
+all:
+	EXISTING_ENV=1 EXISTING_OPT_ENV=1 $(RUSTC) --emit dep-info main.rs
+	$(CGREP) "# env-dep:EXISTING_ENV=1" < $(TMPDIR)/main.d
+	$(CGREP) "# env-dep:EXISTING_OPT_ENV=1" < $(TMPDIR)/main.d
+	$(CGREP) "# env-dep:NONEXISTENT_OPT_ENV" < $(TMPDIR)/main.d
+	$(CGREP) "# env-dep:ESCAPE\nESCAPE\\" < $(TMPDIR)/main.d
+	# Proc macro
+	$(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs
+	EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs
+	$(CGREP) "# env-dep:EXISTING_PROC_MACRO_ENV=1" < $(TMPDIR)/macro_use.d
+	$(CGREP) "# env-dep:NONEXISTENT_PROC_MACEO_ENV" < $(TMPDIR)/macro_use.d
diff --git a/tests/run-make/env-dep-info/macro_def.rs b/tests/run-make/env-dep-info/macro_def.rs
new file mode 100644
index 00000000000..e328eae4832
--- /dev/null
+++ b/tests/run-make/env-dep-info/macro_def.rs
@@ -0,0 +1,12 @@
+#![feature(proc_macro_tracked_env)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn access_env_vars(_: TokenStream) -> TokenStream {
+    let _ = tracked_env::var("EXISTING_PROC_MACRO_ENV");
+    let _ = tracked_env::var("NONEXISTENT_PROC_MACEO_ENV");
+    TokenStream::new()
+}
diff --git a/tests/run-make/env-dep-info/macro_use.rs b/tests/run-make/env-dep-info/macro_use.rs
new file mode 100644
index 00000000000..2f5267471fc
--- /dev/null
+++ b/tests/run-make/env-dep-info/macro_use.rs
@@ -0,0 +1,6 @@
+#[macro_use]
+extern crate macro_def;
+
+access_env_vars!();
+
+fn main() {}
diff --git a/tests/run-make/env-dep-info/main.rs b/tests/run-make/env-dep-info/main.rs
new file mode 100644
index 00000000000..a25246bac79
--- /dev/null
+++ b/tests/run-make/env-dep-info/main.rs
@@ -0,0 +1,6 @@
+fn main() {
+    env!("EXISTING_ENV");
+    option_env!("EXISTING_OPT_ENV");
+    option_env!("NONEXISTENT_OPT_ENV");
+    option_env!("ESCAPE\nESCAPE\\");
+}
diff --git a/tests/run-make/export-executable-symbols/Makefile b/tests/run-make/export-executable-symbols/Makefile
new file mode 100644
index 00000000000..daa77c99dcd
--- /dev/null
+++ b/tests/run-make/export-executable-symbols/Makefile
@@ -0,0 +1,11 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-wasm32
+# ignore-wasm64
+# ignore-none no-std is not supported
+# only-linux
+
+all:
+	$(RUSTC) -Zexport-executable-symbols  main.rs --target $(TARGET) --crate-type=bin
+	nm $(TMPDIR)/main | $(CGREP) exported_symbol
+
diff --git a/tests/run-make/export-executable-symbols/main.rs b/tests/run-make/export-executable-symbols/main.rs
new file mode 100644
index 00000000000..c498381a33f
--- /dev/null
+++ b/tests/run-make/export-executable-symbols/main.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+fn main() {}
+
+#[no_mangle]
+pub fn exported_symbol() -> i8 {
+    42
+}
diff --git a/tests/run-make/fmt-write-bloat/Makefile b/tests/run-make/fmt-write-bloat/Makefile
new file mode 100644
index 00000000000..07e6e025e08
--- /dev/null
+++ b/tests/run-make/fmt-write-bloat/Makefile
@@ -0,0 +1,25 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-windows
+
+ifeq ($(shell $(RUSTC) -vV | grep 'host: $(TARGET)'),)
+
+# Don't run this test when cross compiling.
+all:
+
+else
+
+NM = nm
+
+PANIC_SYMS = panic_bounds_check pad_integral Display Debug
+
+# Allow for debug_assert!() in debug builds of std.
+ifdef NO_DEBUG_ASSERTIONS
+PANIC_SYMS += panicking panic_fmt
+endif
+
+all: main.rs
+	$(RUSTC) $< -O
+	$(NM) $(call RUN_BINFILE,main) | $(CGREP) -v $(PANIC_SYMS)
+
+endif
diff --git a/tests/run-make/fmt-write-bloat/main.rs b/tests/run-make/fmt-write-bloat/main.rs
new file mode 100644
index 00000000000..e86c48014c3
--- /dev/null
+++ b/tests/run-make/fmt-write-bloat/main.rs
@@ -0,0 +1,32 @@
+#![feature(lang_items)]
+#![feature(start)]
+#![no_std]
+
+use core::fmt;
+use core::fmt::Write;
+
+#[link(name = "c")]
+extern "C" {}
+
+struct Dummy;
+
+impl fmt::Write for Dummy {
+    #[inline(never)]
+    fn write_str(&mut self, _: &str) -> fmt::Result {
+        Ok(())
+    }
+}
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    let _ = writeln!(Dummy, "Hello World");
+    0
+}
+
+#[lang = "eh_personality"]
+fn eh_personality() {}
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/tests/run-make/git_clone_sha1.sh b/tests/run-make/git_clone_sha1.sh
new file mode 100644
index 00000000000..626e4e42761
--- /dev/null
+++ b/tests/run-make/git_clone_sha1.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -x
+
+# Usage: $0 project_name url sha1
+# Get the crate with the specified sha1.
+#
+# all arguments are required.
+#
+# See below link for git usage:
+# https://stackoverflow.com/questions/3489173#14091182
+
+# Mandatory arguments:
+PROJECT_NAME=$1
+URL=$2
+SHA1=$3
+
+function err_exit() {
+    echo "ERROR:" $*
+    exit 1
+}
+
+git clone $URL $PROJECT_NAME || err_exit
+cd $PROJECT_NAME || err_exit
+git reset --hard $SHA1 || err_exit
diff --git a/tests/run-make/incr-foreign-head-span/Makefile b/tests/run-make/incr-foreign-head-span/Makefile
new file mode 100644
index 00000000000..712965eaa88
--- /dev/null
+++ b/tests/run-make/incr-foreign-head-span/Makefile
@@ -0,0 +1,21 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
+
+# Ensure that modifying a crate on disk (without recompiling it)
+# does not cause ICEs in downstream crates.
+# Previously, we would call `SourceMap.guess_head_span` on a span
+# from an external crate, which would cause us to read an upstream
+# source file from disk during compilation of a downstream crate
+# See #86480 for more details
+
+INCR=$(TMPDIR)/incr
+
+all:
+	cp first_crate.rs second_crate.rs $(TMPDIR)
+	$(RUSTC) $(TMPDIR)/first_crate.rs  -C incremental=$(INCR) --target $(TARGET) --crate-type lib
+	$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET)  --extern first-crate=$(TMPDIR) --crate-type lib
+	rm $(TMPDIR)/first_crate.rs
+	$(RUSTC) $(TMPDIR)/second_crate.rs  -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib
+
diff --git a/tests/run-make/incr-foreign-head-span/first_crate.rs b/tests/run-make/incr-foreign-head-span/first_crate.rs
new file mode 100644
index 00000000000..69dd103bfc0
--- /dev/null
+++ b/tests/run-make/incr-foreign-head-span/first_crate.rs
@@ -0,0 +1 @@
+pub trait OtherTrait {}
diff --git a/tests/run-make/incr-foreign-head-span/second_crate.rs b/tests/run-make/incr-foreign-head-span/second_crate.rs
new file mode 100644
index 00000000000..102f6b26c8d
--- /dev/null
+++ b/tests/run-make/incr-foreign-head-span/second_crate.rs
@@ -0,0 +1,8 @@
+extern crate first_crate;
+use first_crate::OtherTrait;
+
+#[cfg(not(second_run))]
+trait Foo: OtherTrait {}
+
+#[cfg(second_run)]
+trait Bar: OtherTrait {}
diff --git a/tests/run-make/incr-prev-body-beyond-eof/Makefile b/tests/run-make/incr-prev-body-beyond-eof/Makefile
new file mode 100644
index 00000000000..24eea3acaea
--- /dev/null
+++ b/tests/run-make/incr-prev-body-beyond-eof/Makefile
@@ -0,0 +1,19 @@
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
+
+include ../../run-make-fulldeps/tools.mk
+
+# Tests that we don't ICE during incremental compilation after modifying a
+# function span such that its previous end line exceeds the number of lines
+# in the new file, but its start line/column and length remain the same.
+
+SRC=$(TMPDIR)/src
+INCR=$(TMPDIR)/incr
+
+all:
+	mkdir $(SRC)
+	mkdir $(INCR)
+	cp a.rs $(SRC)/main.rs
+	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
+	cp b.rs $(SRC)/main.rs
+	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
diff --git a/tests/run-make/incr-prev-body-beyond-eof/a.rs b/tests/run-make/incr-prev-body-beyond-eof/a.rs
new file mode 100644
index 00000000000..ca70fb56334
--- /dev/null
+++ b/tests/run-make/incr-prev-body-beyond-eof/a.rs
@@ -0,0 +1,16 @@
+fn main() {
+    // foo must be used.
+    foo();
+}
+
+// For this test to operate correctly, foo's body must start on exactly the same
+// line and column and have the exact same length in bytes in a.rs and b.rs. In
+// a.rs, the body must end on a line number which does not exist in b.rs.
+// Basically, avoid modifying this file, including adding or removing whitespace!
+fn foo() {
+    assert_eq!(1, 1);
+
+
+
+
+}
diff --git a/tests/run-make/incr-prev-body-beyond-eof/b.rs b/tests/run-make/incr-prev-body-beyond-eof/b.rs
new file mode 100644
index 00000000000..a272e44a632
--- /dev/null
+++ b/tests/run-make/incr-prev-body-beyond-eof/b.rs
@@ -0,0 +1,12 @@
+fn main() {
+    // foo must be used.
+    foo();
+}
+
+// For this test to operate correctly, foo's body must start on exactly the same
+// line and column and have the exact same length in bytes in a.rs and b.rs. In
+// a.rs, the body must end on a line number which does not exist in b.rs.
+// Basically, avoid modifying this file, including adding or removing whitespace!
+fn foo() {
+    assert_eq!(1, 1);////
+}
diff --git a/tests/run-make/incremental-session-fail/Makefile b/tests/run-make/incremental-session-fail/Makefile
new file mode 100644
index 00000000000..0461bb926e7
--- /dev/null
+++ b/tests/run-make/incremental-session-fail/Makefile
@@ -0,0 +1,14 @@
+include ../../run-make-fulldeps/tools.mk
+
+SESSION_DIR := $(TMPDIR)/session
+OUTPUT_FILE := $(TMPDIR)/build-output
+
+all:
+	echo $(TMPDIR)
+	# Make it so that rustc will fail to create a session directory.
+	touch $(SESSION_DIR)
+	# Check exit code is 1 for an error, and not 101 for ICE.
+	$(RUSTC) foo.rs --crate-type=rlib -C incremental=$(SESSION_DIR) > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ]
+	$(CGREP) "Could not create incremental compilation crate directory" < $(OUTPUT_FILE)
+	# -v tests are fragile, hopefully this text won't change
+	$(CGREP) -v "internal compiler error" < $(OUTPUT_FILE)
diff --git a/tests/run-make/incremental-session-fail/foo.rs b/tests/run-make/incremental-session-fail/foo.rs
new file mode 100644
index 00000000000..d11c69f812a
--- /dev/null
+++ b/tests/run-make/incremental-session-fail/foo.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/tests/run-make/invalid-so/Makefile b/tests/run-make/invalid-so/Makefile
new file mode 100644
index 00000000000..5b82ecd207d
--- /dev/null
+++ b/tests/run-make/invalid-so/Makefile
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -)
+
+all:
+	echo >> $(TMPDIR)/$(DYLIB_NAME)
+	$(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`'
diff --git a/tests/run-make/invalid-so/bar.rs b/tests/run-make/invalid-so/bar.rs
new file mode 100644
index 00000000000..49af74e1b74
--- /dev/null
+++ b/tests/run-make/invalid-so/bar.rs
@@ -0,0 +1 @@
+extern crate foo;
diff --git a/tests/run-make/issue-10971-temps-dir/Makefile b/tests/run-make/issue-10971-temps-dir/Makefile
new file mode 100644
index 00000000000..e589bbffe60
--- /dev/null
+++ b/tests/run-make/issue-10971-temps-dir/Makefile
@@ -0,0 +1,10 @@
+include ../../run-make-fulldeps/tools.mk
+
+# Regression test for issue #10971
+# Running two invocations in parallel would overwrite each other's temp files.
+
+all:
+	touch $(TMPDIR)/lib.rs
+
+	$(RUSTC) --crate-type=lib -Z temps-dir=$(TMPDIR)/temp1 $(TMPDIR)/lib.rs & \
+	$(RUSTC) --crate-type=staticlib -Z temps-dir=$(TMPDIR)/temp2 $(TMPDIR)/lib.rs
diff --git a/tests/run-make/issue-36710/Makefile b/tests/run-make/issue-36710/Makefile
new file mode 100644
index 00000000000..d6145c07126
--- /dev/null
+++ b/tests/run-make/issue-36710/Makefile
@@ -0,0 +1,17 @@
+# ignore-none no-std is not supported
+# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM
+# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
+# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain
+#                    (see dist-i586-gnu-i586-i686-musl Dockerfile)
+
+include ../../run-make-fulldeps/tools.mk
+
+all: foo
+	$(call RUN,foo)
+
+foo: foo.rs $(call NATIVE_STATICLIB,foo)
+	$(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET)
+
+$(TMPDIR)/libfoo.o: foo.cpp
+	$(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/tests/run-make/issue-36710/foo.cpp b/tests/run-make/issue-36710/foo.cpp
new file mode 100644
index 00000000000..8f878c2c272
--- /dev/null
+++ b/tests/run-make/issue-36710/foo.cpp
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+struct A {
+    A() { v = 1234; }
+    ~A() { v = 1; }
+    uint32_t v;
+};
+
+A a;
+
+extern "C" {
+    uint32_t get() {
+        return a.v;
+    }
+}
diff --git a/tests/run-make/issue-36710/foo.rs b/tests/run-make/issue-36710/foo.rs
new file mode 100644
index 00000000000..f30a35e27c0
--- /dev/null
+++ b/tests/run-make/issue-36710/foo.rs
@@ -0,0 +1,10 @@
+// Tests that linking to C++ code with global destructors works.
+
+extern "C" {
+    fn get() -> u32;
+}
+
+fn main() {
+    let i = unsafe { get() };
+    assert_eq!(i, 1234);
+}
diff --git a/tests/run-make/issue-47384/Makefile b/tests/run-make/issue-47384/Makefile
new file mode 100644
index 00000000000..0aadf6c88c9
--- /dev/null
+++ b/tests/run-make/issue-47384/Makefile
@@ -0,0 +1,12 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-linux
+# ignore-cross-compile
+
+all: main.rs
+	$(RUSTC) --crate-type lib lib.rs
+	$(RUSTC) --crate-type cdylib -Clink-args="-Tlinker.ld" main.rs
+	# Ensure `#[used]` and `KEEP`-ed section is there
+	objdump -s -j".static" $(TMPDIR)/libmain.so
+	# Ensure `#[no_mangle]` symbol is there
+	nm $(TMPDIR)/libmain.so | $(CGREP) bar
diff --git a/tests/run-make/issue-47384/lib.rs b/tests/run-make/issue-47384/lib.rs
new file mode 100644
index 00000000000..99508bcdaf3
--- /dev/null
+++ b/tests/run-make/issue-47384/lib.rs
@@ -0,0 +1,12 @@
+mod foo {
+    #[link_section = ".rodata.STATIC"]
+    #[used]
+    static STATIC: [u32; 10] = [1; 10];
+}
+
+mod bar {
+    #[no_mangle]
+    extern "C" fn bar() -> i32 {
+        0
+    }
+}
diff --git a/tests/run-make/issue-47384/linker.ld b/tests/run-make/issue-47384/linker.ld
new file mode 100644
index 00000000000..2e70acab3f4
--- /dev/null
+++ b/tests/run-make/issue-47384/linker.ld
@@ -0,0 +1,7 @@
+SECTIONS
+{
+    .static : ALIGN(4)
+    {
+        KEEP(*(.rodata.STATIC));
+    }
+}
diff --git a/tests/run-make/issue-47384/main.rs b/tests/run-make/issue-47384/main.rs
new file mode 100644
index 00000000000..02572632517
--- /dev/null
+++ b/tests/run-make/issue-47384/main.rs
@@ -0,0 +1 @@
+extern crate lib;
diff --git a/tests/run-make/issue-71519/Makefile b/tests/run-make/issue-71519/Makefile
new file mode 100644
index 00000000000..57497f52053
--- /dev/null
+++ b/tests/run-make/issue-71519/Makefile
@@ -0,0 +1,8 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-msvc
+# needs-rust-lld
+# ignore-s390x lld does not yet support s390x as target
+all:
+	RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
+	$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/tests/run-make/issue-71519/main.rs b/tests/run-make/issue-71519/main.rs
new file mode 100644
index 00000000000..f8d09e89753
--- /dev/null
+++ b/tests/run-make/issue-71519/main.rs
@@ -0,0 +1,4 @@
+// test linking using cc with rust-lld injected into search path as ld
+// see rust-lang/rust#71519 for more info
+
+fn main() {}
diff --git a/tests/run-make/issue-83112-incr-test-moved-file/Makefile b/tests/run-make/issue-83112-incr-test-moved-file/Makefile
new file mode 100644
index 00000000000..2f796e5b2fc
--- /dev/null
+++ b/tests/run-make/issue-83112-incr-test-moved-file/Makefile
@@ -0,0 +1,25 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
+
+# Regression test for issue #83112
+# The generated test harness code contains spans with a dummy location,
+# but a non-dummy SyntaxContext. Previously, the incremental cache was encoding
+# these spans as a full span (with a source file index), instead of skipping
+# the encoding of the location information. If the file gest moved, the hash
+# of the span will be unchanged (since it has a dummy location), so the incr
+# cache would end up try to load a non-existent file using the previously
+# enccoded source file id.
+
+SRC=$(TMPDIR)/src
+INCR=$(TMPDIR)/incr
+
+all:
+	mkdir $(SRC)
+	mkdir $(SRC)/mydir
+	mkdir $(INCR)
+	cp main.rs $(SRC)/main.rs
+	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
+	mv $(SRC)/main.rs $(SRC)/mydir/main.rs
+	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs --target $(TARGET)
diff --git a/tests/run-make/issue-83112-incr-test-moved-file/main.rs b/tests/run-make/issue-83112-incr-test-moved-file/main.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/issue-83112-incr-test-moved-file/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/issue-85019-moved-src-dir/Makefile b/tests/run-make/issue-85019-moved-src-dir/Makefile
new file mode 100644
index 00000000000..3606d4fdf57
--- /dev/null
+++ b/tests/run-make/issue-85019-moved-src-dir/Makefile
@@ -0,0 +1,28 @@
+include ../../run-make-fulldeps/tools.mk
+
+INCR=$(TMPDIR)/incr
+FIRST_SRC=$(TMPDIR)/first_src
+SECOND_SRC=$(TMPDIR)/second_src
+
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
+
+# Tests that we don't get an ICE when the working directory
+# (but not the build directory!) changes between compilation
+# sessions
+
+all:
+	mkdir $(INCR)
+	# Build from 'FIRST_SRC'
+	mkdir $(FIRST_SRC)
+	cp my_lib.rs $(FIRST_SRC)/my_lib.rs
+	cp main.rs $(FIRST_SRC)/main.rs
+	cd $(FIRST_SRC) && \
+		$(RUSTC) -C incremental=$(INCR) --crate-type lib my_lib.rs --target $(TARGET) && \
+		$(RUSTC) -C incremental=$(INCR) --extern my_lib=$(TMPDIR)/libmy_lib.rlib main.rs --target $(TARGET)
+	# Build from 'SECOND_SRC', keeping the output directory and incremental directory
+	# the same
+	mv $(FIRST_SRC) $(SECOND_SRC)
+	cd $(SECOND_SRC) && \
+		$(RUSTC) -C incremental=$(INCR) --crate-type lib my_lib.rs --target $(TARGET) && \
+		$(RUSTC) -C incremental=$(INCR) --extern my_lib=$(TMPDIR)/libmy_lib.rlib main.rs --target $(TARGET)
diff --git a/tests/run-make/issue-85019-moved-src-dir/main.rs b/tests/run-make/issue-85019-moved-src-dir/main.rs
new file mode 100644
index 00000000000..543559a5c53
--- /dev/null
+++ b/tests/run-make/issue-85019-moved-src-dir/main.rs
@@ -0,0 +1,5 @@
+extern crate my_lib;
+
+fn main() {
+    my_lib::my_fn("hi");
+}
diff --git a/tests/run-make/issue-85019-moved-src-dir/my_lib.rs b/tests/run-make/issue-85019-moved-src-dir/my_lib.rs
new file mode 100644
index 00000000000..432875739af
--- /dev/null
+++ b/tests/run-make/issue-85019-moved-src-dir/my_lib.rs
@@ -0,0 +1 @@
+pub fn my_fn<T: Copy>(_val: T) {}
diff --git a/tests/run-make/issue-85401-static-mir/Makefile b/tests/run-make/issue-85401-static-mir/Makefile
new file mode 100644
index 00000000000..99590166bca
--- /dev/null
+++ b/tests/run-make/issue-85401-static-mir/Makefile
@@ -0,0 +1,16 @@
+include ../../run-make-fulldeps/tools.mk
+
+# Regression test for issue #85401
+# Verify that we do not ICE when trying to access MIR for statics,
+# but emit an error when linking.
+
+OUTPUT_FILE := $(TMPDIR)/build-output
+
+all:
+	$(RUSTC) --crate-type rlib --crate-name foo -Crelocation-model=pic --edition=2018 foo.rs -Zalways-encode-mir=yes --emit metadata -o $(TMPDIR)/libfoo.rmeta
+	$(RUSTC) --crate-type rlib --crate-name bar -Crelocation-model=pic --edition=2018 bar.rs -o $(TMPDIR)/libbar.rlib --extern=foo=$(TMPDIR)/libfoo.rmeta
+	$(RUSTC) --crate-type bin --crate-name baz -Crelocation-model=pic --edition=2018 baz.rs -o $(TMPDIR)/baz -L $(TMPDIR) --extern=bar=$(TMPDIR)/libbar.rlib > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ]
+	cat  $(OUTPUT_FILE)
+	$(CGREP) 'crate `foo` required to be available in rlib format, but was not found in this form' < $(OUTPUT_FILE)
+	# -v tests are fragile, hopefully this text won't change
+	$(CGREP) -v "internal compiler error" < $(OUTPUT_FILE)
diff --git a/tests/run-make/issue-85401-static-mir/bar.rs b/tests/run-make/issue-85401-static-mir/bar.rs
new file mode 100644
index 00000000000..15b12ecf36f
--- /dev/null
+++ b/tests/run-make/issue-85401-static-mir/bar.rs
@@ -0,0 +1,4 @@
+pub fn bar() {
+    println!("bar {}", foo::FOO);
+    foo::foo();
+}
diff --git a/tests/run-make/issue-85401-static-mir/baz.rs b/tests/run-make/issue-85401-static-mir/baz.rs
new file mode 100644
index 00000000000..2ff4c51e5d2
--- /dev/null
+++ b/tests/run-make/issue-85401-static-mir/baz.rs
@@ -0,0 +1,3 @@
+fn main() {
+    bar::bar()
+}
diff --git a/tests/run-make/issue-85401-static-mir/foo.rs b/tests/run-make/issue-85401-static-mir/foo.rs
new file mode 100644
index 00000000000..d064c454600
--- /dev/null
+++ b/tests/run-make/issue-85401-static-mir/foo.rs
@@ -0,0 +1,5 @@
+pub static FOO: &str = "foo";
+
+pub fn foo() {
+    println!("foo");
+}
diff --git a/tests/run-make/issue-85441/Makefile b/tests/run-make/issue-85441/Makefile
new file mode 100644
index 00000000000..f04b07d51fa
--- /dev/null
+++ b/tests/run-make/issue-85441/Makefile
@@ -0,0 +1,9 @@
+# only-windows-msvc
+
+include ../../run-make-fulldeps/tools.mk
+
+# Tests that WS2_32.dll is not unnecessarily linked, see issue #85441
+
+all:
+	$(RUSTC) empty.rs
+	objdump -p $(TMPDIR)/empty.exe | $(CGREP) -v -i "WS2_32.dll"
diff --git a/tests/run-make/issue-85441/empty.rs b/tests/run-make/issue-85441/empty.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/issue-85441/empty.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/issue-88756-default-output/Makefile b/tests/run-make/issue-88756-default-output/Makefile
new file mode 100644
index 00000000000..275c35c2629
--- /dev/null
+++ b/tests/run-make/issue-88756-default-output/Makefile
@@ -0,0 +1,4 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout
diff --git a/tests/run-make/issue-88756-default-output/README.md b/tests/run-make/issue-88756-default-output/README.md
new file mode 100644
index 00000000000..8cbfac4f7d2
--- /dev/null
+++ b/tests/run-make/issue-88756-default-output/README.md
@@ -0,0 +1 @@
+This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756).
diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/issue-88756-default-output/output-default.stdout
new file mode 100644
index 00000000000..b280698230d
--- /dev/null
+++ b/tests/run-make/issue-88756-default-output/output-default.stdout
@@ -0,0 +1,197 @@
+rustdoc [options] <input>
+
+Options:
+    -h, --help          show this help message
+    -V, --version       print rustdoc's version
+    -v, --verbose       use verbose output
+    -w, --output-format [html]
+                        the output type to write
+        --output PATH   Which directory to place the output. This option is
+                        deprecated, use --out-dir instead.
+    -o, --out-dir PATH  which directory to place the output
+        --crate-name NAME
+                        specify the name of this crate
+        --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]
+                        Comma separated list of types of crates
+                        for the compiler to emit
+    -L, --library-path DIR
+                        directory to add to crate search path
+        --cfg           pass a --cfg to rustc
+        --check-cfg     pass a --check-cfg to rustc
+        --extern NAME[=PATH]
+                        pass an --extern to rustc
+        --extern-html-root-url NAME=URL
+                        base URL to use for dependencies; for example,
+                        "std=/doc" links std::vec::Vec to
+                        /doc/std/vec/struct.Vec.html
+        --extern-html-root-takes-precedence 
+                        give precedence to `--extern-html-root-url`, not
+                        `html_root_url`
+    -C, --codegen OPT[=VALUE]
+                        pass a codegen option to rustc
+        --document-private-items 
+                        document private items
+        --document-hidden-items 
+                        document items that have doc(hidden)
+        --test          run code examples as tests
+        --test-args ARGS
+                        arguments to pass to the test runner
+        --test-run-directory PATH
+                        The working directory in which to run tests
+        --target TRIPLE target triple to document
+        --markdown-css FILES
+                        CSS files to include via <link> in a rendered Markdown
+                        file
+        --html-in-header FILES
+                        files to include inline in the <head> section of a
+                        rendered Markdown file or generated documentation
+        --html-before-content FILES
+                        files to include inline between <body> and the content
+                        of a rendered Markdown file or generated documentation
+        --html-after-content FILES
+                        files to include inline between the content and
+                        </body> of a rendered Markdown file or generated
+                        documentation
+        --markdown-before-content FILES
+                        files to include inline between <body> and the content
+                        of a rendered Markdown file or generated documentation
+        --markdown-after-content FILES
+                        files to include inline between the content and
+                        </body> of a rendered Markdown file or generated
+                        documentation
+        --markdown-playground-url URL
+                        URL to send code snippets to
+        --markdown-no-toc 
+                        don't include table of contents
+    -e, --extend-css PATH
+                        To add some CSS rules with a given file to generate
+                        doc with your own theme. However, your theme might
+                        break if the rustdoc's generated HTML changes, so be
+                        careful!
+    -Z FLAG             unstable / perma-unstable options (only on nightly
+                        build)
+        --sysroot PATH  Override the system root
+        --playground-url URL
+                        URL to send code snippets to, may be reset by
+                        --markdown-playground-url or
+                        `#![doc(html_playground_url=...)]`
+        --display-doctest-warnings 
+                        show warnings that originate in doctests
+        --crate-version VERSION
+                        crate version to print into documentation
+        --sort-modules-by-appearance 
+                        sort modules by where they appear in the program,
+                        rather than alphabetically
+        --default-theme THEME
+                        Set the default theme. THEME should be the theme name,
+                        generally lowercase. If an unknown default theme is
+                        specified, the builtin default is used. The set of
+                        themes, and the rustdoc built-in default, are not
+                        stable.
+        --default-setting SETTING[=VALUE]
+                        Default value for a rustdoc setting (used when
+                        "rustdoc-SETTING" is absent from web browser Local
+                        Storage). If VALUE is not supplied, "true" is used.
+                        Supported SETTINGs and VALUEs are not documented and
+                        not stable.
+        --theme FILES   additional themes which will be added to the generated
+                        docs
+        --check-theme FILES
+                        check if given theme is valid
+        --resource-suffix PATH
+                        suffix to add to CSS and JavaScript files, e.g.,
+                        "light.css" will become "light-suffix.css"
+        --edition EDITION
+                        edition to use when compiling rust code (default:
+                        2015)
+        --color auto|always|never
+                        Configure coloring of output:
+                        auto = colorize, if output goes to a tty (default);
+                        always = always colorize output;
+                        never = never colorize output
+        --error-format human|json|short
+                        How errors and other messages are produced
+        --diagnostic-width WIDTH
+                        Provide width of the output for truncated error
+                        messages
+        --json CONFIG   Configure the structure of JSON diagnostics
+    -A, --allow LINT    Set lint allowed
+    -W, --warn LINT     Set lint warnings
+        --force-warn LINT
+                        Set lint force-warn
+    -D, --deny LINT     Set lint denied
+    -F, --forbid LINT   Set lint forbidden
+        --cap-lints LEVEL
+                        Set the most restrictive lint level. More restrictive
+                        lints are capped at this level. By default, it is at
+                        `forbid` level.
+        --index-page PATH
+                        Markdown file to be used as index page
+        --enable-index-page 
+                        To enable generation of the index page
+        --static-root-path PATH
+                        Path string to force loading static files from in
+                        output pages. If not set, uses combinations of '../'
+                        to reach the documentation root.
+        --disable-per-crate-search 
+                        disables generating the crate selector on the search
+                        box
+        --persist-doctests PATH
+                        Directory to persist doctest executables into
+        --show-coverage 
+                        calculate percentage of public items with
+                        documentation
+        --enable-per-target-ignores 
+                        parse ignore-foo for ignoring doctests on a per-target
+                        basis
+        --runtool The tool to run tests with when building for a different target than host
+                        
+        --runtool-arg One (of possibly many) arguments to pass to the runtool
+                        
+        --test-builder PATH
+                        The rustc-like binary to use as the test builder
+        --check         Run rustdoc checks
+        --generate-redirect-map 
+                        Generate JSON file at the top level instead of
+                        generating HTML redirection files
+        --emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific]
+                        Comma separated list of types of output for rustdoc to
+                        emit
+        --no-run        Compile doctests without running them
+        --show-type-layout 
+                        Include the memory layout of types in the docs
+        --nocapture     Don't capture stdout and stderr of tests
+        --generate-link-to-definition 
+                        Make the identifiers in the HTML source code pages
+                        navigable
+        --scrape-examples-output-path collect function call information and output at the given path
+                        
+        --scrape-examples-target-crate collect function call information for functions from the target crate
+                        
+        --scrape-tests  Include test code when scraping examples
+        --with-examples path to function call information (for displaying examples in the documentation)
+                        
+        --disable-minification 
+                        removed
+        --plugin-path DIR
+                        removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+        --passes PASSES removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+        --plugins PLUGINS
+                        removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+        --no-defaults   removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+    -r, --input-format [rust]
+                        removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+
+    @path               Read newline separated options from `path`
+
+More information available at https://doc.rust-lang.org/$CHANNEL/rustdoc/what-is-rustdoc.html
diff --git a/tests/run-make/issue-88756-default-output/x.rs b/tests/run-make/issue-88756-default-output/x.rs
new file mode 100644
index 00000000000..5df7576133a
--- /dev/null
+++ b/tests/run-make/issue-88756-default-output/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/tests/run-make/issue-96498/Makefile b/tests/run-make/issue-96498/Makefile
new file mode 100644
index 00000000000..ce2b1b1ff7c
--- /dev/null
+++ b/tests/run-make/issue-96498/Makefile
@@ -0,0 +1,8 @@
+# only-windows
+# needs-rust-lld
+
+include ../../run-make-fulldeps/tools.mk
+
+# Ensure that LLD can link
+all:
+	$(RUSTC) -C linker=rust-lld foo.rs
diff --git a/tests/run-make/issue-96498/foo.rs b/tests/run-make/issue-96498/foo.rs
new file mode 100644
index 00000000000..93ac3641b09
--- /dev/null
+++ b/tests/run-make/issue-96498/foo.rs
@@ -0,0 +1,4 @@
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+extern "C" fn foo() {}
diff --git a/tests/run-make/libtest-thread-limit/Makefile b/tests/run-make/libtest-thread-limit/Makefile
new file mode 100644
index 00000000000..d43a89e60ca
--- /dev/null
+++ b/tests/run-make/libtest-thread-limit/Makefile
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-linux
+
+all:
+	$(RUSTC) test.rs --test --target $(TARGET)
+	$(shell ulimit -p 0 && $(call RUN,test))
diff --git a/tests/run-make/libtest-thread-limit/test.rs b/tests/run-make/libtest-thread-limit/test.rs
new file mode 100644
index 00000000000..26bc29216cf
--- /dev/null
+++ b/tests/run-make/libtest-thread-limit/test.rs
@@ -0,0 +1,20 @@
+#![feature(once_cell)]
+
+use std::{
+    io::ErrorKind,
+    sync::OnceLock,
+    thread::{self, Builder, ThreadId},
+};
+
+static THREAD_ID: OnceLock<ThreadId> = OnceLock::new();
+
+#[test]
+fn spawn_thread_would_block() {
+    assert_eq!(Builder::new().spawn(|| unreachable!()).unwrap_err().kind(), ErrorKind::WouldBlock);
+    THREAD_ID.set(thread::current().id()).unwrap();
+}
+
+#[test]
+fn run_in_same_thread() {
+    assert_eq!(*THREAD_ID.get().unwrap(), thread::current().id());
+}
diff --git a/tests/run-make/llvm-outputs/Makefile b/tests/run-make/llvm-outputs/Makefile
new file mode 100644
index 00000000000..a3f25eba0b2
--- /dev/null
+++ b/tests/run-make/llvm-outputs/Makefile
@@ -0,0 +1,5 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_ir/ --emit=llvm-ir
+	echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_bc/ --emit=llvm-bc
diff --git a/tests/run-make/macos-deployment-target/Makefile b/tests/run-make/macos-deployment-target/Makefile
new file mode 100644
index 00000000000..70fca043653
--- /dev/null
+++ b/tests/run-make/macos-deployment-target/Makefile
@@ -0,0 +1,21 @@
+# only-macos
+#
+# Check that a set deployment target actually makes it to the linker.
+# This is important since its a compatibility hazard. The linker will
+# generate load commands differently based on what minimum OS it can assume.
+
+include ../../run-make-fulldeps/tools.mk
+
+ifeq ($(strip $(shell uname -m)),arm64)
+	GREP_PATTERN = "minos 11.0"
+else
+ 	GREP_PATTERN = "version 10.9"
+endif
+
+OUT_FILE=$(TMPDIR)/with_deployment_target.dylib
+all:
+	env MACOSX_DEPLOYMENT_TARGET=10.9 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE)
+# XXX: The check is for either the x86_64 minimum OR the aarch64 minimum (M1 starts at macOS 11).
+# They also use different load commands, so we let that change with each too. The aarch64 check
+# isn't as robust as the x86 one, but testing both seems unneeded.
+	vtool -show-build $(OUT_FILE) | $(CGREP) -e $(GREP_PATTERN)
diff --git a/tests/run-make/macos-deployment-target/with_deployment_target.rs b/tests/run-make/macos-deployment-target/with_deployment_target.rs
new file mode 100644
index 00000000000..342fe0ecbcf
--- /dev/null
+++ b/tests/run-make/macos-deployment-target/with_deployment_target.rs
@@ -0,0 +1,4 @@
+#![crate_type = "cdylib"]
+
+#[allow(dead_code)]
+fn something_and_nothing() {}
diff --git a/tests/run-make/macos-fat-archive/Makefile b/tests/run-make/macos-fat-archive/Makefile
new file mode 100644
index 00000000000..cc99375db69
--- /dev/null
+++ b/tests/run-make/macos-fat-archive/Makefile
@@ -0,0 +1,10 @@
+# only-macos
+
+-include ../../run-make-fulldeps/tools.mk
+
+"$(TMPDIR)"/libnative-library.a: native-library.c
+	$(CC) -arch arm64 -arch x86_64 native-library.c -c -o "$(TMPDIR)"/native-library.o
+	$(AR) crs "$(TMPDIR)"/libnative-library.a "$(TMPDIR)"/native-library.o
+
+all: "$(TMPDIR)"/libnative-library.a
+	$(RUSTC) lib.rs --crate-type=lib -L "native=$(TMPDIR)" -l static=native-library
diff --git a/tests/run-make/macos-fat-archive/lib.rs b/tests/run-make/macos-fat-archive/lib.rs
new file mode 100644
index 00000000000..9943a266c3e
--- /dev/null
+++ b/tests/run-make/macos-fat-archive/lib.rs
@@ -0,0 +1,3 @@
+extern "C" {
+    pub fn native_func();
+}
diff --git a/tests/run-make/macos-fat-archive/native-library.c b/tests/run-make/macos-fat-archive/native-library.c
new file mode 100644
index 00000000000..d300fdf1c17
--- /dev/null
+++ b/tests/run-make/macos-fat-archive/native-library.c
@@ -0,0 +1 @@
+void native_func() {}
diff --git a/tests/run-make/native-link-modifier-bundle/Makefile b/tests/run-make/native-link-modifier-bundle/Makefile
new file mode 100644
index 00000000000..7c78d7783e0
--- /dev/null
+++ b/tests/run-make/native-link-modifier-bundle/Makefile
@@ -0,0 +1,33 @@
+# ignore-cross-compile
+# ignore-windows-msvc
+
+include ../../run-make-fulldeps/tools.mk
+
+# We're using the llvm-nm instead of the system nm to ensure it is compatible
+# with the LLVM bitcode generated by rustc.
+NM = "$(LLVM_BIN_DIR)"/llvm-nm
+
+all: $(call NATIVE_STATICLIB,native-staticlib)
+	# Build a staticlib and a rlib, the `native_func` symbol will be bundled into them
+	$(RUSTC) bundled.rs --crate-type=staticlib --crate-type=rlib
+	$(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "T _*native_func"
+	$(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "U _*native_func"
+	$(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "T _*native_func"
+	$(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "U _*native_func"
+
+	# Build a staticlib and a rlib, the `native_func` symbol will not be bundled into it
+	$(RUSTC) non-bundled.rs --crate-type=staticlib --crate-type=rlib
+	$(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -ve "T _*native_func"
+	$(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -e "U _*native_func"
+	$(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -ve "T _*native_func"
+	$(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -e "U _*native_func"
+
+	# Build a cdylib, `native-staticlib` will not appear on the linker line because it was bundled previously
+	# The cdylib will contain the `native_func` symbol in the end
+	$(RUSTC) cdylib-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -ve '-l[" ]*native-staticlib'
+	$(NM) $(call DYLIB,cdylib_bundled) | $(CGREP) -e "[Tt] _*native_func"
+
+	# Build a cdylib, `native-staticlib` will appear on the linker line because it was not bundled previously
+	# The cdylib will contain the `native_func` symbol in the end
+	$(RUSTC) cdylib-non-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -e '-l[" ]*native-staticlib'
+	$(NM) $(call DYLIB,cdylib_non_bundled) | $(CGREP) -e "[Tt] _*native_func"
diff --git a/tests/run-make/native-link-modifier-bundle/bundled.rs b/tests/run-make/native-link-modifier-bundle/bundled.rs
new file mode 100644
index 00000000000..0bbae8752d7
--- /dev/null
+++ b/tests/run-make/native-link-modifier-bundle/bundled.rs
@@ -0,0 +1,11 @@
+#[link(name = "native-staticlib", kind = "static", modifiers = "+bundle")]
+extern "C" {
+    pub fn native_func();
+}
+
+#[no_mangle]
+pub extern "C" fn wrapped_func() {
+    unsafe {
+        native_func();
+    }
+}
diff --git a/tests/run-make/native-link-modifier-bundle/cdylib-bundled.rs b/tests/run-make/native-link-modifier-bundle/cdylib-bundled.rs
new file mode 100644
index 00000000000..7291309168a
--- /dev/null
+++ b/tests/run-make/native-link-modifier-bundle/cdylib-bundled.rs
@@ -0,0 +1 @@
+extern crate bundled;
diff --git a/tests/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs b/tests/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs
new file mode 100644
index 00000000000..1df81fd101f
--- /dev/null
+++ b/tests/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs
@@ -0,0 +1 @@
+extern crate non_bundled;
diff --git a/tests/run-make/native-link-modifier-bundle/native-staticlib.c b/tests/run-make/native-link-modifier-bundle/native-staticlib.c
new file mode 100644
index 00000000000..d300fdf1c17
--- /dev/null
+++ b/tests/run-make/native-link-modifier-bundle/native-staticlib.c
@@ -0,0 +1 @@
+void native_func() {}
diff --git a/tests/run-make/native-link-modifier-bundle/non-bundled.rs b/tests/run-make/native-link-modifier-bundle/non-bundled.rs
new file mode 100644
index 00000000000..8181e6387c5
--- /dev/null
+++ b/tests/run-make/native-link-modifier-bundle/non-bundled.rs
@@ -0,0 +1,11 @@
+#[link(name = "native-staticlib", kind = "static", modifiers = "-bundle")]
+extern "C" {
+    pub fn native_func();
+}
+
+#[no_mangle]
+pub extern "C" fn wrapped_func() {
+    unsafe {
+        native_func();
+    }
+}
diff --git a/tests/run-make/native-link-modifier-verbatim-linker/Makefile b/tests/run-make/native-link-modifier-verbatim-linker/Makefile
new file mode 100644
index 00000000000..666e4084ce2
--- /dev/null
+++ b/tests/run-make/native-link-modifier-verbatim-linker/Makefile
@@ -0,0 +1,15 @@
+# ignore-cross-compile
+# ignore-macos
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	# Verbatim allows specify precise name.
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_some_strange_name.ext
+	$(RUSTC) main.rs -l static:+verbatim=local_some_strange_name.ext
+
+	# With verbatim any other name cannot be used (local).
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/liblocal_native_dep.a
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.a
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.lib
+	$(RUSTC) main.rs -l static:+verbatim=local_native_dep 2>&1 | $(CGREP) "local_native_dep"
diff --git a/tests/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs b/tests/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs
new file mode 100644
index 00000000000..59b6c92d293
--- /dev/null
+++ b/tests/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub fn local_native_f() -> i32 {
+    return 0;
+}
diff --git a/tests/run-make/native-link-modifier-verbatim-linker/main.rs b/tests/run-make/native-link-modifier-verbatim-linker/main.rs
new file mode 100644
index 00000000000..71b73a489c7
--- /dev/null
+++ b/tests/run-make/native-link-modifier-verbatim-linker/main.rs
@@ -0,0 +1,9 @@
+extern "C" {
+    fn local_native_f() -> i32;
+}
+
+pub fn main() {
+    unsafe {
+        assert!(local_native_f() == 0);
+    };
+}
diff --git a/tests/run-make/native-link-modifier-verbatim-rustc/Makefile b/tests/run-make/native-link-modifier-verbatim-rustc/Makefile
new file mode 100644
index 00000000000..6f01f37804a
--- /dev/null
+++ b/tests/run-make/native-link-modifier-verbatim-rustc/Makefile
@@ -0,0 +1,12 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	# Verbatim allows specify precise name.
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_some_strange_name.ext
+	$(RUSTC) rust_dep.rs -l static:+verbatim=upstream_some_strange_name.ext --crate-type rlib
+
+	# With verbatim any other name cannot be used (upstream).
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/libupstream_native_dep.a
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.a
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.lib
+	$(RUSTC) rust_dep.rs -l static:+verbatim=upstream_native_dep --crate-type rlib 2>&1 | $(CGREP) "upstream_native_dep"
diff --git a/tests/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs b/tests/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs
new file mode 100644
index 00000000000..e9517218e0d
--- /dev/null
+++ b/tests/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs
@@ -0,0 +1,9 @@
+extern "C" {
+    fn upstream_native_f() -> i32;
+}
+
+pub fn rust_dep() {
+    unsafe {
+        assert!(upstream_native_f() == 0);
+    }
+}
diff --git a/tests/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs b/tests/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs
new file mode 100644
index 00000000000..8396862333d
--- /dev/null
+++ b/tests/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub fn upstream_native_f() -> i32 {
+    return 0;
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/Makefile b/tests/run-make/native-link-modifier-whole-archive/Makefile
new file mode 100644
index 00000000000..f26bd864ced
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/Makefile
@@ -0,0 +1,52 @@
+# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
+
+# This test case makes sure that native libraries are linked with appropriate semantics
+# when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
+#
+# The test works by checking that the resulting executables produce the expected output,
+# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
+# that code would never make it into the final executable and we'd thus be missing some
+# of the output.
+
+include ../../run-make-fulldeps/tools.mk
+
+all: $(TMPDIR)/$(call BIN,directly_linked) \
+     $(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive) \
+     $(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive) \
+     $(TMPDIR)/$(call BIN,indirectly_linked) \
+     $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
+	$(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
+	$(call RUN,directly_linked_test_plus_whole_archive) --nocapture | $(CGREP) 'static-initializer.'
+	$(call RUN,directly_linked_test_minus_whole_archive) --nocapture | $(CGREP) -v 'static-initializer.'
+	$(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
+	$(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
+
+# Native lib linked directly into executable
+$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+	$(RUSTC) directly_linked.rs -l static:+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into test executable, +whole-archive
+$(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+	$(RUSTC) directly_linked_test_plus_whole_archive.rs --test -l static:+whole-archive=c_static_lib_with_constructor
+# Native lib linked into test executable, -whole-archive
+$(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+	$(RUSTC) directly_linked_test_minus_whole_archive.rs --test -l static:-whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
+	$(RUSTC) indirectly_linked.rs
+
+# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib
+	$(RUSTC) indirectly_linked_via_attr.rs
+
+# Native lib linked into rlib with via commandline
+$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+	$(RUSTC) rlib_with_cmdline_native_lib.rs --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into rlib via `#[link()]` attribute on extern block.
+$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+	$(RUSTC) native_lib_in_src.rs --crate-type=rlib
+
+$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp
+	$(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/tests/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp b/tests/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp
new file mode 100644
index 00000000000..c687eb0f092
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp
@@ -0,0 +1,11 @@
+#include <cstdio>
+
+// Since this is a global variable, its constructor will be called before
+// main() is executed. But only if the object file containing it actually
+// gets linked into the executable.
+struct Foo {
+    Foo() {
+        printf("static-initializer.");
+        fflush(stdout);
+    }
+} FOO;
diff --git a/tests/run-make/native-link-modifier-whole-archive/directly_linked.rs b/tests/run-make/native-link-modifier-whole-archive/directly_linked.rs
new file mode 100644
index 00000000000..17518e8b2f9
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/directly_linked.rs
@@ -0,0 +1,6 @@
+use std::io::Write;
+
+fn main() {
+    print!("directly_linked.");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs b/tests/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs
new file mode 100644
index 00000000000..20ed8d9d4cd
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs
@@ -0,0 +1,7 @@
+use std::io::Write;
+
+#[test]
+fn test_thing() {
+    print!("ran the test");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs b/tests/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs
new file mode 100644
index 00000000000..20ed8d9d4cd
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs
@@ -0,0 +1,7 @@
+use std::io::Write;
+
+#[test]
+fn test_thing() {
+    print!("ran the test");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/indirectly_linked.rs b/tests/run-make/native-link-modifier-whole-archive/indirectly_linked.rs
new file mode 100644
index 00000000000..c8b83fcfe03
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/indirectly_linked.rs
@@ -0,0 +1,5 @@
+extern crate rlib_with_cmdline_native_lib;
+
+fn main() {
+    rlib_with_cmdline_native_lib::hello();
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs b/tests/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs
new file mode 100644
index 00000000000..b9e347609b2
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs
@@ -0,0 +1,5 @@
+extern crate native_lib_in_src;
+
+fn main() {
+    native_lib_in_src::hello();
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs b/tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs
new file mode 100644
index 00000000000..971f3be7a61
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs
@@ -0,0 +1,11 @@
+use std::io::Write;
+
+#[link(name = "c_static_lib_with_constructor",
+       kind = "static",
+       modifiers = "-bundle,+whole-archive")]
+extern {}
+
+pub fn hello() {
+    print!("native_lib_in_src.");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs b/tests/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs
new file mode 100644
index 00000000000..ef2b702dd82
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs
@@ -0,0 +1,6 @@
+use std::io::Write;
+
+pub fn hello() {
+    print!("indirectly_linked.");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/tests/run-make/pass-linker-flags-from-dep/Makefile b/tests/run-make/pass-linker-flags-from-dep/Makefile
new file mode 100644
index 00000000000..b9426326aea
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-from-dep/Makefile
@@ -0,0 +1,10 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	# Build deps
+	$(RUSTC) native_dep_1.rs --crate-type=staticlib
+	$(RUSTC) native_dep_2.rs --crate-type=staticlib
+	$(RUSTC) rust_dep.rs -l static:-bundle=native_dep_1 -l link-arg=some_flag -l static:-bundle=native_dep_2 --crate-type=lib -Z unstable-options
+
+	# Check sequence of linker args
+	$(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2'
diff --git a/tests/run-make/pass-linker-flags-from-dep/main.rs b/tests/run-make/pass-linker-flags-from-dep/main.rs
new file mode 100644
index 00000000000..40952fb22b1
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-from-dep/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+    lib::f();
+}
diff --git a/tests/run-make/pass-linker-flags-from-dep/native_dep_1.rs b/tests/run-make/pass-linker-flags-from-dep/native_dep_1.rs
new file mode 100644
index 00000000000..fdb2d9ca68e
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-from-dep/native_dep_1.rs
@@ -0,0 +1 @@
+pub fn f1() {}
diff --git a/tests/run-make/pass-linker-flags-from-dep/native_dep_2.rs b/tests/run-make/pass-linker-flags-from-dep/native_dep_2.rs
new file mode 100644
index 00000000000..f788b771184
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-from-dep/native_dep_2.rs
@@ -0,0 +1 @@
+pub fn f2() {}
diff --git a/tests/run-make/pass-linker-flags-from-dep/rust_dep.rs b/tests/run-make/pass-linker-flags-from-dep/rust_dep.rs
new file mode 100644
index 00000000000..7f5df113934
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-from-dep/rust_dep.rs
@@ -0,0 +1,9 @@
+extern "C" {
+    pub fn foo();
+}
+
+pub fn f() {
+    unsafe {
+        foo();
+    }
+}
diff --git a/tests/run-make/pass-linker-flags/Makefile b/tests/run-make/pass-linker-flags/Makefile
new file mode 100644
index 00000000000..a3efb8df6ac
--- /dev/null
+++ b/tests/run-make/pass-linker-flags/Makefile
@@ -0,0 +1,4 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) rs.rs -Z unstable-options -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*a1.*l2.*a2.*d1.*a3'
diff --git a/tests/run-make/pass-linker-flags/rs.rs b/tests/run-make/pass-linker-flags/rs.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/pass-linker-flags/rs.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/Makefile b/tests/run-make/raw-dylib-alt-calling-convention/Makefile
new file mode 100644
index 00000000000..03f8778d25d
--- /dev/null
+++ b/tests/run-make/raw-dylib-alt-calling-convention/Makefile
@@ -0,0 +1,32 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
+
+# only-x86
+# only-windows
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
+ifdef IS_MSVC
+	$(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
+else
+	$(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll
+endif
+
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.txt output.txt
+else
+	$(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
+
+ifdef IS_MSVC
+	"$(TMPDIR)"/driver true > "$(TMPDIR)"/output.msvc.txt
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.msvc.txt output.msvc.txt
+else
+	$(DIFF) output.msvc.txt "$(TMPDIR)"/output.msvc.txt
+endif
+endif
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/driver.rs b/tests/run-make/raw-dylib-alt-calling-convention/driver.rs
new file mode 100644
index 00000000000..b7f372c6b2b
--- /dev/null
+++ b/tests/run-make/raw-dylib-alt-calling-convention/driver.rs
@@ -0,0 +1,8 @@
+extern crate raw_dylib_alt_calling_convention_test;
+
+fn main() {
+    raw_dylib_alt_calling_convention_test::library_function(
+        std::env::args().skip(1).next().map_or(
+            false,
+            |s| std::str::FromStr::from_str(&s).unwrap()));
+}
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/extern.c b/tests/run-make/raw-dylib-alt-calling-convention/extern.c
new file mode 100644
index 00000000000..344d4a6bf5a
--- /dev/null
+++ b/tests/run-make/raw-dylib-alt-calling-convention/extern.c
@@ -0,0 +1,193 @@
+#include <stdio.h>
+#include <stdint.h>
+
+struct S {
+    uint8_t x;
+    int32_t y;
+};
+
+struct S2 {
+    int32_t x;
+    uint8_t y;
+};
+
+struct S3 {
+    uint8_t x[5];
+};
+
+__declspec(dllexport) void __stdcall stdcall_fn_1(int i) {
+    printf("stdcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_2(uint8_t i, float f) {
+    printf("stdcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_3(double d) {
+    printf("stdcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("stdcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_5(struct S s, int i) {
+    printf("stdcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+// Test that stdcall support works correctly with the nullable pointer optimization.
+__declspec(dllexport) void __stdcall stdcall_fn_6(struct S* s) {
+    if (s) {
+        printf("stdcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("stdcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_7(struct S2 s, int i) {
+    printf("stdcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+// Verify that we compute the correct amount of space in the argument list for a 5-byte struct.
+__declspec(dllexport) void __stdcall stdcall_fn_8(struct S3 s, struct S3 t) {
+    printf("stdcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+// test whether f64/double values are aligned on 4-byte or 8-byte boundaries.
+__declspec(dllexport) void __stdcall stdcall_fn_9(uint8_t x, double y) {
+    printf("stdcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_10(int i) {
+    printf("stdcall_fn_10(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_1(int i) {
+    printf("fastcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_2(uint8_t i, float f) {
+    printf("fastcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_3(double d) {
+    printf("fastcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("fastcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_5(struct S s, int i) {
+    printf("fastcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_6(struct S* s) {
+    if (s) {
+        printf("fastcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("fastcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_7(struct S2 s, int i) {
+    printf("fastcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_8(struct S3 s, struct S3 t) {
+    printf("fastcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) {
+    printf("fastcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_10(int i) {
+    printf("fastcall_fn_10(%d)\n", i);
+    fflush(stdout);
+}
+
+// GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+#ifdef _MSC_VER
+__declspec(dllexport) void __vectorcall vectorcall_fn_1(int i) {
+    printf("vectorcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_2(uint8_t i, float f) {
+    printf("vectorcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_3(double d) {
+    printf("vectorcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("vectorcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_5(struct S s, int i) {
+    printf("vectorcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_6(struct S* s) {
+    if (s) {
+        printf("vectorcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("vectorcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_7(struct S2 s, int i) {
+    printf("vectorcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_8(struct S3 s, struct S3 t) {
+    printf("vectorcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_9(uint8_t x, double y) {
+    printf("vectorcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_10(int i) {
+    printf("vectorcall_fn_10(%d)\n", i);
+    fflush(stdout);
+}
+#endif
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/lib.rs b/tests/run-make/raw-dylib-alt-calling-convention/lib.rs
new file mode 100644
index 00000000000..22f222c12c3
--- /dev/null
+++ b/tests/run-make/raw-dylib-alt-calling-convention/lib.rs
@@ -0,0 +1,115 @@
+#![feature(abi_vectorcall)]
+#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
+
+#[repr(C)]
+#[derive(Clone)]
+struct S {
+    x: u8,
+    y: i32,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S2 {
+    x: i32,
+    y: u8,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S3 {
+    x: [u8; 5],
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "stdcall" {
+    fn stdcall_fn_1(i: i32);
+    fn stdcall_fn_2(c: u8, f: f32);
+    fn stdcall_fn_3(d: f64);
+    fn stdcall_fn_4(i: u8, j: u8, f: f32);
+    fn stdcall_fn_5(a: S, b: i32);
+    fn stdcall_fn_6(a: Option<&S>);
+    fn stdcall_fn_7(a: S2, b: i32);
+    fn stdcall_fn_8(a: S3, b: S3);
+    fn stdcall_fn_9(x: u8, y: f64);
+    #[link_name = "stdcall_fn_10"]
+    fn stdcall_fn_10_renamed(i: i32);
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "fastcall" {
+    fn fastcall_fn_1(i: i32);
+    fn fastcall_fn_2(c: u8, f: f32);
+    fn fastcall_fn_3(d: f64);
+    fn fastcall_fn_4(i: u8, j: u8, f: f32);
+    fn fastcall_fn_5(a: S, b: i32);
+    fn fastcall_fn_6(a: Option<&S>);
+    fn fastcall_fn_7(a: S2, b: i32);
+    fn fastcall_fn_8(a: S3, b: S3);
+    fn fastcall_fn_9(x: u8, y: f64);
+    #[link_name = "fastcall_fn_10"]
+    fn fastcall_fn_10_renamed(i: i32);
+}
+
+#[cfg(target_env = "msvc")]
+#[link(name = "extern", kind = "raw-dylib")]
+extern "vectorcall" {
+    fn vectorcall_fn_1(i: i32);
+    fn vectorcall_fn_2(c: u8, f: f32);
+    fn vectorcall_fn_3(d: f64);
+    fn vectorcall_fn_4(i: u8, j: u8, f: f32);
+    fn vectorcall_fn_5(a: S, b: i32);
+    fn vectorcall_fn_6(a: Option<&S>);
+    fn vectorcall_fn_7(a: S2, b: i32);
+    fn vectorcall_fn_8(a: S3, b: S3);
+    fn vectorcall_fn_9(x: u8, y: f64);
+    #[link_name = "vectorcall_fn_10"]
+    fn vectorcall_fn_10_renamed(i: i32);
+}
+
+pub fn library_function(run_msvc_only: bool) {
+    unsafe {
+        if !run_msvc_only {
+            stdcall_fn_1(14);
+            stdcall_fn_2(16, 3.5);
+            stdcall_fn_3(3.5);
+            stdcall_fn_4(1, 2, 3.0);
+            stdcall_fn_5(S { x: 1, y: 2 }, 16);
+            stdcall_fn_6(Some(&S { x: 10, y: 12 }));
+            stdcall_fn_7(S2 { x: 15, y: 16 }, 3);
+            stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+            stdcall_fn_9(1, 3.0);
+            stdcall_fn_10_renamed(19);
+
+            fastcall_fn_1(14);
+            fastcall_fn_2(16, 3.5);
+            fastcall_fn_3(3.5);
+            fastcall_fn_4(1, 2, 3.0);
+            fastcall_fn_6(Some(&S { x: 10, y: 12 }));
+            fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+            fastcall_fn_9(1, 3.0);
+            fastcall_fn_10_renamed(19);
+        } else {
+            // FIXME: 91167
+            // rustc generates incorrect code for the calls to fastcall_fn_5 and fastcall_fn_7
+            // on i686-pc-windows-gnu; disabling these until the indicated issue is fixed.
+            fastcall_fn_5(S { x: 1, y: 2 }, 16);
+            fastcall_fn_7(S2 { x: 15, y: 16 }, 3);
+
+            // GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+            #[cfg(target_env = "msvc")]
+            {
+                vectorcall_fn_1(14);
+                vectorcall_fn_2(16, 3.5);
+                vectorcall_fn_3(3.5);
+                vectorcall_fn_4(1, 2, 3.0);
+                vectorcall_fn_5(S { x: 1, y: 2 }, 16);
+                vectorcall_fn_6(Some(&S { x: 10, y: 12 }));
+                vectorcall_fn_7(S2 { x: 15, y: 16 }, 3);
+                vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+                vectorcall_fn_9(1, 3.0);
+                vectorcall_fn_10_renamed(19);
+            }
+        }
+    }
+}
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/output.msvc.txt b/tests/run-make/raw-dylib-alt-calling-convention/output.msvc.txt
new file mode 100644
index 00000000000..a216835c4b6
--- /dev/null
+++ b/tests/run-make/raw-dylib-alt-calling-convention/output.msvc.txt
@@ -0,0 +1,12 @@
+fastcall_fn_5(S { x: 1, y: 2 }, 16)
+fastcall_fn_7(S2 { x: 15, y: 16 }, 3)
+vectorcall_fn_1(14)
+vectorcall_fn_2(16, 3.5)
+vectorcall_fn_3(3.5)
+vectorcall_fn_4(1, 2, 3.0)
+vectorcall_fn_5(S { x: 1, y: 2 }, 16)
+vectorcall_fn_6(S { x: 10, y: 12 })
+vectorcall_fn_7(S2 { x: 15, y: 16 }, 3)
+vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+vectorcall_fn_9(1, 3.0)
+vectorcall_fn_10(19)
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/output.txt b/tests/run-make/raw-dylib-alt-calling-convention/output.txt
new file mode 100644
index 00000000000..7622d31618b
--- /dev/null
+++ b/tests/run-make/raw-dylib-alt-calling-convention/output.txt
@@ -0,0 +1,18 @@
+stdcall_fn_1(14)
+stdcall_fn_2(16, 3.5)
+stdcall_fn_3(3.5)
+stdcall_fn_4(1, 2, 3.0)
+stdcall_fn_5(S { x: 1, y: 2 }, 16)
+stdcall_fn_6(S { x: 10, y: 12 })
+stdcall_fn_7(S2 { x: 15, y: 16 }, 3)
+stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+stdcall_fn_9(1, 3.0)
+stdcall_fn_10(19)
+fastcall_fn_1(14)
+fastcall_fn_2(16, 3.5)
+fastcall_fn_3(3.5)
+fastcall_fn_4(1, 2, 3.0)
+fastcall_fn_6(S { x: 10, y: 12 })
+fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+fastcall_fn_9(1, 3.0)
+fastcall_fn_10(19)
diff --git a/tests/run-make/raw-dylib-c/Makefile b/tests/run-make/raw-dylib-c/Makefile
new file mode 100644
index 00000000000..f47ab24f4fb
--- /dev/null
+++ b/tests/run-make/raw-dylib-c/Makefile
@@ -0,0 +1,28 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
+
+# only-windows
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+	$(RUSTC) --crate-type bin --crate-name raw_dylib_test_bin lib.rs
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+ifdef IS_MSVC
+	$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll -noimplib
+	$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll -noimplib
+else
+	$(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll
+	$(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll
+endif
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+	"$(TMPDIR)"/raw_dylib_test_bin > "$(TMPDIR)"/output_bin.txt
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.txt output.txt
+else
+	$(DIFF) output.txt "$(TMPDIR)"/output.txt
+	$(DIFF) output.txt "$(TMPDIR)"/output_bin.txt
+endif
diff --git a/tests/run-make/raw-dylib-c/driver.rs b/tests/run-make/raw-dylib-c/driver.rs
new file mode 100644
index 00000000000..4059ede11fc
--- /dev/null
+++ b/tests/run-make/raw-dylib-c/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/tests/run-make/raw-dylib-c/extern_1.c b/tests/run-make/raw-dylib-c/extern_1.c
new file mode 100644
index 00000000000..5d695547d0f
--- /dev/null
+++ b/tests/run-make/raw-dylib-c/extern_1.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+__declspec(dllexport) int extern_variable = 0;
+
+__declspec(dllexport) void extern_fn_1() {
+    printf("extern_fn_1\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+    printf("extern_fn_2; didn't get the rename\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void print_extern_variable() {
+    printf("extern_variable value: %d\n", extern_variable);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_with_long_name() {
+    printf("extern_fn_with_long_name; got the rename\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_4() {
+    printf("extern_fn_4\n");
+    fflush(stdout);
+}
diff --git a/tests/run-make/raw-dylib-c/extern_2.c b/tests/run-make/raw-dylib-c/extern_2.c
new file mode 100644
index 00000000000..ae87fc3f821
--- /dev/null
+++ b/tests/run-make/raw-dylib-c/extern_2.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_3() {
+    printf("extern_fn_3\n");
+    fflush(stdout);
+}
diff --git a/tests/run-make/raw-dylib-c/lib.rs b/tests/run-make/raw-dylib-c/lib.rs
new file mode 100644
index 00000000000..5fb1204037c
--- /dev/null
+++ b/tests/run-make/raw-dylib-c/lib.rs
@@ -0,0 +1,37 @@
+#![feature(raw_dylib)]
+
+#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
+extern {
+    fn extern_fn_1();
+}
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+    fn extern_fn_3();
+}
+
+pub fn library_function() {
+    #[link(name = "extern_1", kind = "raw-dylib")]
+    extern {
+        fn extern_fn_2();
+        fn print_extern_variable();
+        static mut extern_variable: i32;
+        #[link_name = "extern_fn_4"]
+        fn extern_fn_4_renamed();
+    }
+
+    unsafe {
+        extern_fn_1();
+        extern_fn_2();
+        extern_fn_3();
+        extern_fn_4_renamed();
+        extern_variable = 42;
+        print_extern_variable();
+        extern_variable = -42;
+        print_extern_variable();
+    }
+}
+
+fn main() {
+    library_function();
+}
diff --git a/tests/run-make/raw-dylib-c/output.txt b/tests/run-make/raw-dylib-c/output.txt
new file mode 100644
index 00000000000..cc970cef7bc
--- /dev/null
+++ b/tests/run-make/raw-dylib-c/output.txt
@@ -0,0 +1,6 @@
+extern_fn_1
+extern_fn_2; didn't get the rename
+extern_fn_3
+extern_fn_4
+extern_variable value: 42
+extern_variable value: -42
diff --git a/tests/run-make/raw-dylib-import-name-type/Makefile b/tests/run-make/raw-dylib-import-name-type/Makefile
new file mode 100644
index 00000000000..fcc60e88e1a
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/Makefile
@@ -0,0 +1,22 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
+
+# only-x86
+# only-windows
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
+ifdef IS_MSVC
+	$(CC) "$(TMPDIR)"/extern.obj extern.msvc.def -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
+else
+	$(CC) "$(TMPDIR)"/extern.obj extern.gnu.def --no-leading-underscore -shared -o "$(TMPDIR)"/extern.dll
+endif
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.txt output.txt
+else
+	$(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/tests/run-make/raw-dylib-import-name-type/driver.rs b/tests/run-make/raw-dylib-import-name-type/driver.rs
new file mode 100644
index 00000000000..9a3cd9ebe1b
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/driver.rs
@@ -0,0 +1,133 @@
+#![feature(raw_dylib)]
+#![feature(abi_vectorcall)]
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
+extern "C" {
+    fn LooksLikeAPrivateGlobal(i: i32);
+    fn cdecl_fn_undecorated(i: i32);
+    #[link_name = "cdecl_fn_undecorated2"]
+    fn cdecl_fn_undecorated_renamed(i: i32);
+    static mut extern_variable_undecorated: i32;
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "noprefix")]
+extern "C" {
+    fn cdecl_fn_noprefix(i: i32);
+    static mut extern_variable_noprefix: i32;
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "decorated")]
+extern "C" {
+    fn cdecl_fn_decorated(i: i32);
+    static mut extern_variable_decorated: i32;
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
+extern "stdcall" {
+    fn stdcall_fn_undecorated(i: i32);
+    #[link_name = "stdcall_fn_undecorated2"]
+    fn stdcall_fn_undecorated_renamed(i: i32);
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "noprefix")]
+extern "stdcall" {
+    fn stdcall_fn_noprefix(i: i32);
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "decorated")]
+extern "stdcall" {
+    fn stdcall_fn_decorated(i: i32);
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
+extern "fastcall" {
+    fn fastcall_fn_undecorated(i: i32);
+    #[link_name = "fastcall_fn_undecorated2"]
+    fn fastcall_fn_undecorated_renamed(i: i32);
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "noprefix")]
+extern "fastcall" {
+    fn fastcall_fn_noprefix(i: i32);
+}
+
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "decorated")]
+extern "fastcall" {
+    fn fastcall_fn_decorated(i: i32);
+}
+
+#[cfg(target_env = "msvc")]
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
+extern "vectorcall" {
+    fn vectorcall_fn_undecorated(i: i32);
+    #[link_name = "vectorcall_fn_undecorated2"]
+    fn vectorcall_fn_undecorated_renamed(i: i32);
+}
+
+#[cfg(target_env = "msvc")]
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "noprefix")]
+extern "vectorcall" {
+    fn vectorcall_fn_noprefix(i: i32);
+}
+
+#[cfg(target_env = "msvc")]
+#[link(name = "extern", kind = "raw-dylib", import_name_type = "decorated")]
+extern "vectorcall" {
+    fn vectorcall_fn_decorated(i: i32);
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern {
+    fn print_extern_variable_undecorated();
+    fn print_extern_variable_noprefix();
+    fn print_extern_variable_decorated();
+}
+
+pub fn main() {
+    unsafe {
+        // Regression test for #104453
+        // On x86 LLVM uses 'L' as the prefix for private globals (PrivateGlobalPrefix), which
+        // causes it to believe that undecorated functions starting with 'L' are actually temporary
+        // symbols that it generated, which causes a later check to fail as the symbols we are
+        // creating don't have definitions (whereas all temporary symbols do).
+        LooksLikeAPrivateGlobal(13);
+
+        cdecl_fn_undecorated(1);
+        cdecl_fn_undecorated_renamed(10);
+        cdecl_fn_noprefix(2);
+        cdecl_fn_decorated(3);
+
+        stdcall_fn_undecorated(4);
+        stdcall_fn_undecorated_renamed(14);
+        stdcall_fn_noprefix(5);
+        stdcall_fn_decorated(6);
+
+        fastcall_fn_undecorated(7);
+        fastcall_fn_undecorated_renamed(17);
+        fastcall_fn_noprefix(8);
+        fastcall_fn_decorated(9);
+
+        extern_variable_undecorated = 42;
+        print_extern_variable_undecorated();
+        extern_variable_noprefix = 43;
+        print_extern_variable_noprefix();
+        extern_variable_decorated = 44;
+        print_extern_variable_decorated();
+
+        // GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+        #[cfg(target_env = "msvc")]
+        {
+            vectorcall_fn_undecorated(10);
+            vectorcall_fn_undecorated_renamed(20);
+            vectorcall_fn_noprefix(11);
+            vectorcall_fn_decorated(12);
+        }
+        #[cfg(not(target_env = "msvc"))]
+        {
+            println!("vectorcall_fn_undecorated(10)");
+            println!("vectorcall_fn_undecorated2(20)");
+            println!("vectorcall_fn_noprefix(11)");
+            println!("vectorcall_fn_decorated(12)");
+        }
+    }
+}
diff --git a/tests/run-make/raw-dylib-import-name-type/extern.c b/tests/run-make/raw-dylib-import-name-type/extern.c
new file mode 100644
index 00000000000..23c1e489e5e
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/extern.c
@@ -0,0 +1,108 @@
+#include <stdio.h>
+#include <stdint.h>
+
+void _cdecl LooksLikeAPrivateGlobal(int i) {
+    printf("LooksLikeAPrivateGlobal(%d)\n", i);
+    fflush(stdout);
+}
+
+void _cdecl cdecl_fn_undecorated(int i) {
+    printf("cdecl_fn_undecorated(%d)\n", i);
+    fflush(stdout);
+}
+
+void _cdecl cdecl_fn_undecorated2(int i) {
+    printf("cdecl_fn_undecorated2(%d)\n", i);
+    fflush(stdout);
+}
+
+void _cdecl cdecl_fn_noprefix(int i) {
+    printf("cdecl_fn_noprefix(%d)\n", i);
+    fflush(stdout);
+}
+
+void _cdecl cdecl_fn_decorated(int i) {
+    printf("cdecl_fn_decorated(%d)\n", i);
+    fflush(stdout);
+}
+
+void __stdcall stdcall_fn_undecorated(int i) {
+    printf("stdcall_fn_undecorated(%d)\n", i);
+    fflush(stdout);
+}
+
+void __stdcall stdcall_fn_undecorated2(int i) {
+    printf("stdcall_fn_undecorated2(%d)\n", i);
+    fflush(stdout);
+}
+
+void __stdcall stdcall_fn_noprefix(int i) {
+    printf("stdcall_fn_noprefix(%d)\n", i);
+    fflush(stdout);
+}
+
+void __stdcall stdcall_fn_decorated(int i) {
+    printf("stdcall_fn_decorated(%d)\n", i);
+    fflush(stdout);
+}
+
+void __fastcall fastcall_fn_undecorated(int i) {
+    printf("fastcall_fn_undecorated(%d)\n", i);
+    fflush(stdout);
+}
+
+void __fastcall fastcall_fn_undecorated2(int i) {
+    printf("fastcall_fn_undecorated2(%d)\n", i);
+    fflush(stdout);
+}
+
+void __fastcall fastcall_fn_noprefix(int i) {
+    printf("fastcall_fn_noprefix(%d)\n", i);
+    fflush(stdout);
+}
+
+void __fastcall fastcall_fn_decorated(int i) {
+    printf("fastcall_fn_decorated(%d)\n", i);
+    fflush(stdout);
+}
+
+int extern_variable_undecorated = 0;
+__declspec(dllexport) void print_extern_variable_undecorated() {
+    printf("extern_variable_undecorated value: %d\n", extern_variable_undecorated);
+    fflush(stdout);
+}
+
+int extern_variable_noprefix = 0;
+__declspec(dllexport) void print_extern_variable_noprefix() {
+    printf("extern_variable_noprefix value: %d\n", extern_variable_noprefix);
+    fflush(stdout);
+}
+
+int extern_variable_decorated = 0;
+__declspec(dllexport) void print_extern_variable_decorated() {
+    printf("extern_variable_decorated value: %d\n", extern_variable_decorated);
+    fflush(stdout);
+}
+
+// GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+#ifdef _MSC_VER
+void __vectorcall vectorcall_fn_undecorated(int i) {
+    printf("vectorcall_fn_undecorated(%d)\n", i);
+    fflush(stdout);
+}
+
+void __vectorcall vectorcall_fn_undecorated2(int i) {
+    printf("vectorcall_fn_undecorated2(%d)\n", i);
+    fflush(stdout);
+}
+
+void __vectorcall vectorcall_fn_noprefix(int i) {
+    printf("vectorcall_fn_noprefix(%d)\n", i);
+    fflush(stdout);
+}
+
+void __vectorcall vectorcall_fn_decorated(int i) {
+    printf("vectorcall_fn_decorated(%d)\n", i);
+    fflush(stdout);
+}
+#endif
diff --git a/tests/run-make/raw-dylib-import-name-type/extern.gnu.def b/tests/run-make/raw-dylib-import-name-type/extern.gnu.def
new file mode 100644
index 00000000000..498e90e862d
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/extern.gnu.def
@@ -0,0 +1,22 @@
+LIBRARY extern
+EXPORTS
+    LooksLikeAPrivateGlobal
+    cdecl_fn_undecorated
+    cdecl_fn_undecorated2
+    cdecl_fn_noprefix
+    cdecl_fn_decorated
+    stdcall_fn_undecorated
+    stdcall_fn_undecorated2
+    stdcall_fn_noprefix@4
+    fastcall_fn_undecorated
+    fastcall_fn_undecorated2
+    @fastcall_fn_decorated@4
+
+    ;ld doesn't handle fully-decorated stdcall, or no-prefix fastcall
+    _stdcall_fn_decorated@4=stdcall_fn_decorated@4
+    fastcall_fn_noprefix@4=@fastcall_fn_noprefix@4
+
+    ;Variables are never decorated
+    extern_variable_undecorated
+    extern_variable_noprefix
+    extern_variable_decorated
diff --git a/tests/run-make/raw-dylib-import-name-type/extern.msvc.def b/tests/run-make/raw-dylib-import-name-type/extern.msvc.def
new file mode 100644
index 00000000000..cddb88bb8b5
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/extern.msvc.def
@@ -0,0 +1,26 @@
+LIBRARY extern
+EXPORTS
+    LooksLikeAPrivateGlobal
+    cdecl_fn_undecorated
+    cdecl_fn_undecorated2
+    cdecl_fn_noprefix
+    cdecl_fn_decorated
+    stdcall_fn_undecorated
+    stdcall_fn_undecorated2
+    _stdcall_fn_decorated@4
+    fastcall_fn_undecorated
+    fastcall_fn_undecorated2
+    @fastcall_fn_decorated@4
+    vectorcall_fn_undecorated
+    vectorcall_fn_undecorated2
+    vectorcall_fn_decorated@@4
+    vectorcall_fn_noprefix@@4
+
+    ;MSVC doesn't seem to recognize the "no prefix" syntax.
+    stdcall_fn_noprefix@4=_stdcall_fn_noprefix@4
+    fastcall_fn_noprefix@4=@fastcall_fn_noprefix@4
+
+    ;Variables are never decorated
+    extern_variable_undecorated
+    extern_variable_noprefix
+    extern_variable_decorated
diff --git a/tests/run-make/raw-dylib-import-name-type/output.txt b/tests/run-make/raw-dylib-import-name-type/output.txt
new file mode 100644
index 00000000000..a2a2bfeec7d
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/output.txt
@@ -0,0 +1,20 @@
+LooksLikeAPrivateGlobal(13)
+cdecl_fn_undecorated(1)
+cdecl_fn_undecorated2(10)
+cdecl_fn_noprefix(2)
+cdecl_fn_decorated(3)
+stdcall_fn_undecorated(4)
+stdcall_fn_undecorated2(14)
+stdcall_fn_noprefix(5)
+stdcall_fn_decorated(6)
+fastcall_fn_undecorated(7)
+fastcall_fn_undecorated2(17)
+fastcall_fn_noprefix(8)
+fastcall_fn_decorated(9)
+extern_variable_undecorated value: 42
+extern_variable_noprefix value: 43
+extern_variable_decorated value: 44
+vectorcall_fn_undecorated(10)
+vectorcall_fn_undecorated2(20)
+vectorcall_fn_noprefix(11)
+vectorcall_fn_decorated(12)
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/Makefile b/tests/run-make/raw-dylib-inline-cross-dylib/Makefile
new file mode 100644
index 00000000000..9e603f95835
--- /dev/null
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/Makefile
@@ -0,0 +1,31 @@
+# Regression test for calling an inline function that uses a raw-dylib function.
+
+# only-windows
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type dylib --crate-name raw_dylib_test lib.rs -C prefer-dynamic
+	$(RUSTC) --crate-type dylib --crate-name raw_dylib_test_wrapper lib_wrapper.rs -C prefer-dynamic
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)" -C prefer-dynamic
+	# Make sure we don't find an import to the functions we expect to be inlined.
+	"$(LLVM_BIN_DIR)"/llvm-objdump -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function"
+	"$(LLVM_BIN_DIR)"/llvm-objdump -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function_calls_inline"
+	# Make sure we do find an import to the functions we expect to be imported.
+	"$(LLVM_BIN_DIR)"/llvm-objdump -p $(TMPDIR)/driver.exe | $(CGREP) -e "library_function"
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+ifdef IS_MSVC
+	$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll -noimplib
+	$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll -noimplib
+else
+	$(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll
+	$(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll
+endif
+	$(call RUN,driver) > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.txt output.txt
+else
+	$(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs b/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs
new file mode 100644
index 00000000000..f72ded7d9f6
--- /dev/null
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs
@@ -0,0 +1,21 @@
+#![feature(raw_dylib)]
+
+extern crate raw_dylib_test;
+extern crate raw_dylib_test_wrapper;
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+    fn extern_fn_2();
+}
+
+fn main() {
+    // NOTE: The inlined call to `extern_fn_2` links against the function in extern_2.dll instead
+    // of extern_1.dll since raw-dylib symbols from the current crate are passed to the linker
+    // first, so any ambiguous names will prefer the current crate's definition.
+    raw_dylib_test::inline_library_function();
+    raw_dylib_test::library_function();
+    raw_dylib_test_wrapper::inline_library_function_calls_inline();
+    unsafe {
+        extern_fn_2();
+    }
+}
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/extern_1.c b/tests/run-make/raw-dylib-inline-cross-dylib/extern_1.c
new file mode 100644
index 00000000000..e5baaf5f040
--- /dev/null
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/extern_1.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_1() {
+    printf("extern_fn_1\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+    printf("extern_fn_2 in extern_1\n");
+    fflush(stdout);
+}
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/extern_2.c b/tests/run-make/raw-dylib-inline-cross-dylib/extern_2.c
new file mode 100644
index 00000000000..30aa4692238
--- /dev/null
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/extern_2.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_2() {
+    printf("extern_fn_2 in extern_2\n");
+    fflush(stdout);
+}
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs b/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs
new file mode 100644
index 00000000000..00c2c1c42d1
--- /dev/null
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs
@@ -0,0 +1,21 @@
+#![feature(raw_dylib)]
+
+#[link(name = "extern_1", kind = "raw-dylib")]
+extern {
+    fn extern_fn_1();
+    fn extern_fn_2();
+}
+
+#[inline]
+pub fn inline_library_function() {
+    unsafe {
+        extern_fn_1();
+        extern_fn_2();
+    }
+}
+
+pub fn library_function() {
+    unsafe {
+        extern_fn_2();
+    }
+}
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/lib_wrapper.rs b/tests/run-make/raw-dylib-inline-cross-dylib/lib_wrapper.rs
new file mode 100644
index 00000000000..47191b8de21
--- /dev/null
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/lib_wrapper.rs
@@ -0,0 +1,6 @@
+extern crate raw_dylib_test;
+
+#[inline]
+pub fn inline_library_function_calls_inline() {
+    raw_dylib_test::inline_library_function();
+}
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/output.txt b/tests/run-make/raw-dylib-inline-cross-dylib/output.txt
new file mode 100644
index 00000000000..e7009baa0d4
--- /dev/null
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/output.txt
@@ -0,0 +1,6 @@
+extern_fn_1
+extern_fn_2 in extern_2
+extern_fn_2 in extern_1
+extern_fn_1
+extern_fn_2 in extern_2
+extern_fn_2 in extern_2
diff --git a/tests/run-make/raw-dylib-link-ordinal/Makefile b/tests/run-make/raw-dylib-link-ordinal/Makefile
new file mode 100644
index 00000000000..b55a94dbc46
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/Makefile
@@ -0,0 +1,22 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] and #[link_ordinal] on windows-msvc
+
+# only-windows
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+	$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
+ifdef IS_MSVC
+	$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
+else
+	$(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll
+endif
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.txt output.txt
+else
+	$(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/tests/run-make/raw-dylib-link-ordinal/driver.rs b/tests/run-make/raw-dylib-link-ordinal/driver.rs
new file mode 100644
index 00000000000..4059ede11fc
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/tests/run-make/raw-dylib-link-ordinal/exporter.c b/tests/run-make/raw-dylib-link-ordinal/exporter.c
new file mode 100644
index 00000000000..aabf32ff19f
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/exporter.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void exported_function() {
+    printf("exported_function\n");
+}
+
+int exported_variable = 0;
+
+void print_exported_variable() {
+    printf("exported_variable value: %d\n", exported_variable);
+    fflush(stdout);
+}
diff --git a/tests/run-make/raw-dylib-link-ordinal/exporter.def b/tests/run-make/raw-dylib-link-ordinal/exporter.def
new file mode 100644
index 00000000000..5d87c580a54
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/exporter.def
@@ -0,0 +1,5 @@
+LIBRARY exporter
+EXPORTS
+    exported_function @13 NONAME
+    exported_variable @5 NONAME
+    print_exported_variable @9 NONAME
diff --git a/tests/run-make/raw-dylib-link-ordinal/lib.rs b/tests/run-make/raw-dylib-link-ordinal/lib.rs
new file mode 100644
index 00000000000..bb25ac64c61
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/lib.rs
@@ -0,0 +1,21 @@
+#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern {
+    #[link_ordinal(13)]
+    fn imported_function();
+    #[link_ordinal(5)]
+    static mut imported_variable: i32;
+    #[link_ordinal(9)]
+    fn print_imported_variable();
+}
+
+pub fn library_function() {
+    unsafe {
+        imported_function();
+        imported_variable = 42;
+        print_imported_variable();
+        imported_variable = -42;
+        print_imported_variable();
+    }
+}
diff --git a/tests/run-make/raw-dylib-link-ordinal/output.txt b/tests/run-make/raw-dylib-link-ordinal/output.txt
new file mode 100644
index 00000000000..a4b2031d98b
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/output.txt
@@ -0,0 +1,3 @@
+exported_function
+exported_variable value: 42
+exported_variable value: -42
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/Makefile b/tests/run-make/raw-dylib-stdcall-ordinal/Makefile
new file mode 100644
index 00000000000..b9deb7729c2
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/Makefile
@@ -0,0 +1,23 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")], #[link_ordinal], and alternative calling conventions on i686 windows.
+
+# only-x86
+# only-windows
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+	$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
+ifdef IS_MSVC
+	$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
+else
+	$(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll
+endif
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/actual_output.txt expected_output.txt
+else
+	$(DIFF) expected_output.txt "$(TMPDIR)"/actual_output.txt
+endif
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/driver.rs b/tests/run-make/raw-dylib-stdcall-ordinal/driver.rs
new file mode 100644
index 00000000000..4059ede11fc
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/expected_output.txt b/tests/run-make/raw-dylib-stdcall-ordinal/expected_output.txt
new file mode 100644
index 00000000000..20157763745
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/expected_output.txt
@@ -0,0 +1,2 @@
+exported_function_stdcall(6)
+exported_function_fastcall(125)
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def b/tests/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def
new file mode 100644
index 00000000000..8d28d714b7e
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def
@@ -0,0 +1,4 @@
+LIBRARY exporter
+EXPORTS
+    exported_function_stdcall@4 @15 NONAME
+    @exported_function_fastcall@4 @18 NONAME
\ No newline at end of file
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def b/tests/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def
new file mode 100644
index 00000000000..5a4c79a58ed
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def
@@ -0,0 +1,4 @@
+LIBRARY exporter
+EXPORTS
+    _exported_function_stdcall@4 @15 NONAME
+    @exported_function_fastcall@4 @18 NONAME
\ No newline at end of file
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/exporter.c b/tests/run-make/raw-dylib-stdcall-ordinal/exporter.c
new file mode 100644
index 00000000000..1fb45bf010f
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/exporter.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+void __stdcall exported_function_stdcall(int i) {
+    printf("exported_function_stdcall(%d)\n", i);
+    fflush(stdout);
+}
+
+void __fastcall exported_function_fastcall(int i) {
+    printf("exported_function_fastcall(%d)\n", i);
+    fflush(stdout);
+}
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/lib.rs b/tests/run-make/raw-dylib-stdcall-ordinal/lib.rs
new file mode 100644
index 00000000000..b7921396a0f
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/lib.rs
@@ -0,0 +1,20 @@
+#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "stdcall" {
+    #[link_ordinal(15)]
+    fn imported_function_stdcall(i: i32);
+}
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "fastcall" {
+    #[link_ordinal(18)]
+    fn imported_function_fastcall(i: i32);
+}
+
+pub fn library_function() {
+    unsafe {
+        imported_function_stdcall(6);
+        imported_function_fastcall(125);
+    }
+}
diff --git a/tests/run-make/remap-path-prefix-dwarf/Makefile b/tests/run-make/remap-path-prefix-dwarf/Makefile
new file mode 100644
index 00000000000..fbaea7b68fe
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-dwarf/Makefile
@@ -0,0 +1,77 @@
+# This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo.
+# It tests several cases, each of them has a detailed description attached to it.
+
+# ignore-windows
+
+SRC_DIR := $(abspath .)
+SRC_DIR_PARENT := $(abspath ..)
+
+include ../../run-make-fulldeps/tools.mk
+
+all: \
+  abs_input_outside_working_dir \
+  rel_input_remap_working_dir \
+  rel_input_remap_working_dir_parent \
+  rel_input_remap_working_dir_child \
+  abs_input_inside_working_dir \
+  abs_input_outside_working_dir
+
+# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within
+# the working directory of the compiler. We are remapping the path that contains `src`.
+abs_input_inside_working_dir:
+	# We explicitly switch to a directory that *is* a prefix of the directory our
+	# source code is contained in.
+	cd $(SRC_DIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_inside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED
+	# We expect the path to the main source file to be remapped.
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not* within
+# the working directory of the compiler. We are remapping both the path that contains `src` and
+# the working directory to the same thing. This setup corresponds to a workaround that is needed
+# when trying to remap everything to something that looks like a local path.
+# Relative paths are interpreted as relative to the compiler's working directory (e.g. in
+# debuginfo). If we also remap the working directory, the compiler strip it from other paths so
+# that the final outcome is the desired one again.
+abs_input_outside_working_dir:
+	# We explicitly switch to a directory that is *not* a prefix of the directory our
+	# source code is contained in.
+	cd $(TMPDIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_outside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED --remap-path-prefix $(TMPDIR)=REMAPPED
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping the working directory of
+# the compiler, which naturally is an implicit prefix of our relative input path. Debuginfo will
+# expand the relative path to an absolute path and we expect the working directory to be remapped
+# in that expansion.
+rel_input_remap_working_dir:
+	cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) "REMAPPED/src/quux.rs"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY* of the
+# compiler's working directory. This test makes sure that that directory is remapped even though it
+# won't actually show up in this form in the compiler's SourceMap and instead is only constructed
+# on demand during debuginfo generation.
+rel_input_remap_working_dir_child:
+	cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)/src=REMAPPED"
+	# We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`.
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) "REMAPPED/quux.rs"
+	# We don't want to find the path that we just remapped anywhere in the DWARF
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "$(SRC_DIR)/src"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *PARENT DIRECTORY* of
+# the compiler's working directory.
+rel_input_remap_working_dir_parent:
+	cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR_PARENT)=REMAPPED"
+	# We expect `src/quux.rs` to have been remapped to `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`.
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) "REMAPPED/remap-path-prefix-dwarf/src/quux.rs"
+	# We don't want to find the path that we just remapped anywhere in the DWARF
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "$(SRC_DIR_PARENT)"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
diff --git a/tests/run-make/remap-path-prefix-dwarf/src/quux.rs b/tests/run-make/remap-path-prefix-dwarf/src/quux.rs
new file mode 100644
index 00000000000..38d5ef6194c
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-dwarf/src/quux.rs
@@ -0,0 +1,5 @@
+#![crate_type = "rlib"]
+
+pub fn foo() {
+    println!("foo");
+}
diff --git a/tests/run-make/repr128-dwarf/Makefile b/tests/run-make/repr128-dwarf/Makefile
new file mode 100644
index 00000000000..a840e3ee6d8
--- /dev/null
+++ b/tests/run-make/repr128-dwarf/Makefile
@@ -0,0 +1,16 @@
+# ignore-windows
+# This test should be replaced with one in src/test/debuginfo once GDB or LLDB support 128-bit
+# enums.
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) -Cdebuginfo=2 lib.rs -o $(TMPDIR)/repr128.rlib
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128A $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128B $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128C $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 )"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128D $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff )"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128A $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128B $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff )"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128C $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 )"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128D $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value	(<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 7f )"
diff --git a/tests/run-make/repr128-dwarf/lib.rs b/tests/run-make/repr128-dwarf/lib.rs
new file mode 100644
index 00000000000..63675441d4b
--- /dev/null
+++ b/tests/run-make/repr128-dwarf/lib.rs
@@ -0,0 +1,23 @@
+#![crate_type = "lib"]
+#![feature(repr128)]
+
+// Use .to_le() to ensure that the bytes are in the same order on both little- and big-endian
+// platforms.
+
+#[repr(u128)]
+pub enum U128Enum {
+    U128A = 0_u128.to_le(),
+    U128B = 1_u128.to_le(),
+    U128C = (u64::MAX as u128 + 1).to_le(),
+    U128D = u128::MAX.to_le(),
+}
+
+#[repr(i128)]
+pub enum I128Enum {
+    I128A = 0_i128.to_le(),
+    I128B = (-1_i128).to_le(),
+    I128C = i128::MIN.to_le(),
+    I128D = i128::MAX.to_le(),
+}
+
+pub fn f(_: U128Enum, _: I128Enum) {}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
new file mode 100644
index 00000000000..4574cf17f0e
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
@@ -0,0 +1,22 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# ignore-cross-compile
+
+# Make sure -Zpacked_bundled_libs is compatible with verbatim.
+
+# We're using the llvm-nm instead of the system nm to ensure it is compatible
+# with the LLVM bitcode generated by rustc.
+NM = "$(LLVM_BIN_DIR)"/llvm-nm
+
+all:
+	# Build strange-named dep.
+	$(RUSTC) native_dep.rs --crate-type=staticlib -o $(TMPDIR)/native_dep.ext
+
+	$(RUSTC) rust_dep.rs --crate-type=rlib -Zpacked_bundled_libs
+	$(NM) $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "U.*native_f1"
+	$(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) "native_dep.ext"
+
+	# Make sure compiler doesn't use files, that it shouldn't know about.
+	rm $(TMPDIR)/native_dep.ext
+
+	$(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib -Zpacked_bundled_libs
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/main.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/main.rs
new file mode 100644
index 00000000000..8d2b8a2859c
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/main.rs
@@ -0,0 +1,5 @@
+extern crate rust_dep;
+
+pub fn main() {
+    rust_dep::rust_dep();
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs
new file mode 100644
index 00000000000..321a8237e8a
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub fn native_f1() -> i32 {
+    return 1;
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs
new file mode 100644
index 00000000000..77e41e237d4
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs
@@ -0,0 +1,10 @@
+#[link(name = "native_dep.ext", kind = "static", modifiers = "+verbatim")]
+extern "C" {
+    fn native_f1() -> i32;
+}
+
+pub fn rust_dep() {
+    unsafe {
+        assert!(native_f1() == 1);
+    }
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/Makefile b/tests/run-make/rlib-format-packed-bundled-libs/Makefile
new file mode 100644
index 00000000000..0b991ac42e3
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs/Makefile
@@ -0,0 +1,34 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# ignore-cross-compile
+
+# Make sure rlib format with -Zpacked_bundled_libs is correct.
+
+# We're using the llvm-nm instead of the system nm to ensure it is compatible
+# with the LLVM bitcode generated by rustc.
+NM = "$(LLVM_BIN_DIR)"/llvm-nm
+
+all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3)
+	$(RUSTC) rust_dep_up.rs --crate-type=rlib -Zpacked_bundled_libs
+	$(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f2"
+	$(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f3"
+	$(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "T.*rust_dep_up"
+	$(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_2"
+	$(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_3"
+	$(RUSTC) rust_dep_local.rs --extern rlib=$(TMPDIR)/librust_dep_up.rlib -Zpacked_bundled_libs --crate-type=rlib
+	$(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "U.*native_f1"
+	$(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "T.*rust_dep_local"
+	$(AR) t $(TMPDIR)/librust_dep_local.rlib | $(CGREP) "native_dep_1"
+
+	# Make sure compiler doesn't use files, that it shouldn't know about.
+	rm $(TMPDIR)/*native_dep_*
+
+	$(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_local.rlib -o $(TMPDIR)/main.exe -Zpacked_bundled_libs --print link-args | $(CGREP) -e "native_dep_1.*native_dep_2.*native_dep_3"
+
+ifndef IS_MSVC
+	$(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f1"
+	$(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f2"
+	$(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f3"
+	$(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_local"
+	$(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_up"
+endif
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/main.rs b/tests/run-make/rlib-format-packed-bundled-libs/main.rs
new file mode 100644
index 00000000000..042a4879fe4
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs/main.rs
@@ -0,0 +1,4 @@
+extern crate rust_dep_local;
+pub fn main() {
+    rust_dep_local::rust_dep_local();
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/native_dep_1.c b/tests/run-make/rlib-format-packed-bundled-libs/native_dep_1.c
new file mode 100644
index 00000000000..07be8562c92
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs/native_dep_1.c
@@ -0,0 +1 @@
+int native_f1() { return 1; }
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/native_dep_2.c b/tests/run-make/rlib-format-packed-bundled-libs/native_dep_2.c
new file mode 100644
index 00000000000..a1b94e40dc0
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs/native_dep_2.c
@@ -0,0 +1 @@
+int native_f2() { return 2; }
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/native_dep_3.c b/tests/run-make/rlib-format-packed-bundled-libs/native_dep_3.c
new file mode 100644
index 00000000000..f81f397a4b1
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs/native_dep_3.c
@@ -0,0 +1 @@
+int native_f3() { return 3; }
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs b/tests/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs
new file mode 100644
index 00000000000..8280c7d6c51
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs
@@ -0,0 +1,13 @@
+#[link(name = "native_dep_1", kind = "static")]
+extern "C" {
+    fn native_f1() -> i32;
+}
+
+extern crate rust_dep_up;
+
+pub fn rust_dep_local() {
+    unsafe {
+        assert!(native_f1() == 1);
+    }
+    rust_dep_up::rust_dep_up();
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs b/tests/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs
new file mode 100644
index 00000000000..edcd7c52129
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs
@@ -0,0 +1,13 @@
+#[link(name = "native_dep_2", kind = "static")]
+#[link(name = "native_dep_3", kind = "static")]
+extern "C" {
+    fn native_f2() -> i32;
+    fn native_f3() -> i32;
+}
+
+pub fn rust_dep_up() {
+    unsafe {
+        assert!(native_f2() == 2);
+        assert!(native_f3() == 3);
+    }
+}
diff --git a/tests/run-make/rustc-macro-dep-files/Makefile b/tests/run-make/rustc-macro-dep-files/Makefile
new file mode 100644
index 00000000000..6ae659db2e9
--- /dev/null
+++ b/tests/run-make/rustc-macro-dep-files/Makefile
@@ -0,0 +1,11 @@
+include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+all:
+	$(BARE_RUSTC) $(ADDITIONAL_ARGS) foo.rs --out-dir $(TMPDIR)
+	$(RUSTC) bar.rs --target $(TARGET) --emit dep-info
+	$(CGREP) -v "proc-macro source" < $(TMPDIR)/bar.d
diff --git a/tests/run-make/rustc-macro-dep-files/bar.rs b/tests/run-make/rustc-macro-dep-files/bar.rs
new file mode 100644
index 00000000000..4a3b3364bf0
--- /dev/null
+++ b/tests/run-make/rustc-macro-dep-files/bar.rs
@@ -0,0 +1,8 @@
+#![no_std]
+#![crate_type = "lib"]
+
+#[macro_use]
+extern crate foo;
+
+#[derive(A)]
+struct A;
diff --git a/tests/run-make/rustc-macro-dep-files/foo.rs b/tests/run-make/rustc-macro-dep-files/foo.rs
new file mode 100644
index 00000000000..66db1a21736
--- /dev/null
+++ b/tests/run-make/rustc-macro-dep-files/foo.rs
@@ -0,0 +1,12 @@
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert!(input.contains("struct A ;"));
+    "struct B;".parse().unwrap()
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/Makefile b/tests/run-make/rustdoc-scrape-examples-invalid-expr/Makefile
new file mode 100644
index 00000000000..7786ff762cb
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/Makefile
@@ -0,0 +1,5 @@
+deps := ex
+
+include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs
new file mode 100644
index 00000000000..b342b5b0aae
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs
@@ -0,0 +1,2 @@
+pub struct Foo([usize; foobar::f()]);
+fn main() {}
diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs
new file mode 100644
index 00000000000..c30c99dec60
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs
@@ -0,0 +1 @@
+pub const fn f() -> usize { 5 }
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/Makefile b/tests/run-make/rustdoc-scrape-examples-multiple/Makefile
new file mode 100644
index 00000000000..453a7d4bc8b
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-multiple/Makefile
@@ -0,0 +1,5 @@
+deps := ex ex2
+
+include ./scrape.mk
+
+all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs
new file mode 100644
index 00000000000..01b730c6149
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs
@@ -0,0 +1,4 @@
+fn main() {
+    foobar::ok();
+    foobar::ok();
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs b/tests/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs
new file mode 100644
index 00000000000..f83cf2f2709
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs
@@ -0,0 +1,3 @@
+fn main() {
+    foobar::ok();
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk b/tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk
new file mode 100644
index 00000000000..7a28d2145d5
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk
@@ -0,0 +1,21 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+$(TMPDIR)/%.calls: $(TMPDIR)/libfoobar.rmeta
+	$(RUSTDOC) examples/$*.rs --crate-name $* --crate-type bin --output $(OUTPUT_DIR) \
+	  --extern foobar=$(TMPDIR)/libfoobar.rmeta \
+		-Z unstable-options \
+		--scrape-examples-output-path $@ \
+		--scrape-examples-target-crate foobar \
+		$(extra_flags)
+
+$(TMPDIR)/lib%.rmeta: src/lib.rs
+	$(RUSTC) src/lib.rs --crate-name $* --crate-type lib --emit=metadata
+
+scrape: $(foreach d,$(deps),$(TMPDIR)/$(d).calls)
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
+		-Z unstable-options \
+		$(foreach d,$(deps),--with-examples $(TMPDIR)/$(d).calls)
+
+	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
new file mode 100644
index 00000000000..bdfeda92d79
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
@@ -0,0 +1,6 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//*[@class="prev"]' ''
+// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' ''
+// @has src/ex/ex.rs.html
+// @has foobar/fn.ok.html '//a[@href="../src/ex/ex.rs.html#2"]' ''
+
+pub fn ok() {}
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/Makefile b/tests/run-make/rustdoc-scrape-examples-ordering/Makefile
new file mode 100644
index 00000000000..bf45b8148c0
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-ordering/Makefile
@@ -0,0 +1,5 @@
+deps := ex1 ex2
+
+include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs b/tests/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
new file mode 100644
index 00000000000..05c18007b0c
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
@@ -0,0 +1,11 @@
+fn main() {
+    foobar::ok(0);
+
+    // this is a
+
+    //  ..
+
+    // BIG
+
+    // item
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs b/tests/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
new file mode 100644
index 00000000000..de21d9061f8
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
@@ -0,0 +1,8 @@
+fn main() {
+    foobar::ok(1);
+    // small item
+}
+
+fn f() {
+    foobar::ok(2);
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
new file mode 100644
index 00000000000..c53c987a7cb
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
@@ -0,0 +1,6 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2'
+// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' 'ok'
+// @has foobar/fn.ok.html '//*[@class="highlight"]' 'ok'
+
+pub fn ok(_x: i32) {}
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/Makefile b/tests/run-make/rustdoc-scrape-examples-remap/Makefile
new file mode 100644
index 00000000000..7786ff762cb
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-remap/Makefile
@@ -0,0 +1,5 @@
+deps := ex
+
+include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-remap/examples/ex.rs
new file mode 100644
index 00000000000..1438fdba707
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-remap/examples/ex.rs
@@ -0,0 +1,4 @@
+fn main() {
+    foobar::b::foo();
+    foobar::c::foo();
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/src/a.rs b/tests/run-make/rustdoc-scrape-examples-remap/src/a.rs
new file mode 100644
index 00000000000..b76b4321d62
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-remap/src/a.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-remap/src/lib.rs
new file mode 100644
index 00000000000..f525a4270dd
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-remap/src/lib.rs
@@ -0,0 +1,8 @@
+// @has foobar/b/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs'
+// @has foobar/c/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs'
+
+#[path = "a.rs"]
+pub mod b;
+
+#[path = "a.rs"]
+pub mod c;
diff --git a/tests/run-make/rustdoc-scrape-examples-test/Makefile b/tests/run-make/rustdoc-scrape-examples-test/Makefile
new file mode 100644
index 00000000000..1235ead6751
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-test/Makefile
@@ -0,0 +1,6 @@
+extra_flags := --scrape-tests
+deps := ex
+
+include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs
new file mode 100644
index 00000000000..d1a9a74e782
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs
@@ -0,0 +1,6 @@
+fn main() {}
+
+#[test]
+fn a_test() {
+  foobar::ok();
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-test/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-test/src/lib.rs
new file mode 100644
index 00000000000..22be1ad4101
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-test/src/lib.rs
@@ -0,0 +1,3 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' ''
+
+pub fn ok() {}
diff --git a/tests/run-make/rustdoc-scrape-examples-whitespace/Makefile b/tests/run-make/rustdoc-scrape-examples-whitespace/Makefile
new file mode 100644
index 00000000000..7786ff762cb
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-whitespace/Makefile
@@ -0,0 +1,5 @@
+deps := ex
+
+include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs
new file mode 100644
index 00000000000..44ff689dfc8
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs
@@ -0,0 +1,8 @@
+struct Foo;
+impl Foo {
+  fn bar() { foobar::ok(); }
+}
+
+fn main() {
+  Foo::bar();
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs
new file mode 100644
index 00000000000..28c34716c2f
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs
@@ -0,0 +1,3 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//code' '  '
+
+pub fn ok() {}
diff --git a/tests/run-make/rustdoc-verify-output-files/Makefile b/tests/run-make/rustdoc-verify-output-files/Makefile
new file mode 100644
index 00000000000..bfabbbc6586
--- /dev/null
+++ b/tests/run-make/rustdoc-verify-output-files/Makefile
@@ -0,0 +1,36 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+TMP_OUTPUT_DIR := "$(TMPDIR)/tmp-rustdoc"
+
+all:
+	# Generate html docs
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
+
+	# Copy first output for to check if it's exactly same after second compilation
+	cp -R $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
+
+	# Generate html docs once again on same output
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
+
+	# Check if everything exactly same
+	$(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
+
+	# Generate json doc on the same output
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json
+
+	# Check if expected json file is generated
+	[ -e $(OUTPUT_DIR)/foobar.json ]
+
+	# TODO
+	# We should re-generate json doc once again and compare the diff with previously
+	# generated one. Because layout of json docs changes in each compilation, we can't
+	# do that currently.
+	#
+	# See https://github.com/rust-lang/rust/issues/103785#issuecomment-1307425590 for details.
+
+	# remove generated json doc
+	rm $(OUTPUT_DIR)/foobar.json
+
+	# Check if json doc compilation broke any of the html files generated previously
+	$(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
diff --git a/tests/run-make/rustdoc-verify-output-files/src/lib.rs b/tests/run-make/rustdoc-verify-output-files/src/lib.rs
new file mode 100644
index 00000000000..5df7576133a
--- /dev/null
+++ b/tests/run-make/rustdoc-verify-output-files/src/lib.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/tests/run-make/rustdoc-with-out-dir-option/Makefile b/tests/run-make/rustdoc-with-out-dir-option/Makefile
new file mode 100644
index 00000000000..b3c3f5230c1
--- /dev/null
+++ b/tests/run-make/rustdoc-with-out-dir-option/Makefile
@@ -0,0 +1,8 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+all:
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
+
+	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/tests/run-make/rustdoc-with-out-dir-option/src/lib.rs b/tests/run-make/rustdoc-with-out-dir-option/src/lib.rs
new file mode 100644
index 00000000000..044bb6acb19
--- /dev/null
+++ b/tests/run-make/rustdoc-with-out-dir-option/src/lib.rs
@@ -0,0 +1,2 @@
+// @has foobar/fn.ok.html
+pub fn ok() {}
diff --git a/tests/run-make/rustdoc-with-output-option/Makefile b/tests/run-make/rustdoc-with-output-option/Makefile
new file mode 100644
index 00000000000..02093a35cfc
--- /dev/null
+++ b/tests/run-make/rustdoc-with-output-option/Makefile
@@ -0,0 +1,8 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+all:
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR)
+
+	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/tests/run-make/rustdoc-with-output-option/src/lib.rs b/tests/run-make/rustdoc-with-output-option/src/lib.rs
new file mode 100644
index 00000000000..044bb6acb19
--- /dev/null
+++ b/tests/run-make/rustdoc-with-output-option/src/lib.rs
@@ -0,0 +1,2 @@
+// @has foobar/fn.ok.html
+pub fn ok() {}
diff --git a/tests/run-make/rustdoc-with-short-out-dir-option/Makefile b/tests/run-make/rustdoc-with-short-out-dir-option/Makefile
new file mode 100644
index 00000000000..dc5056a86dd
--- /dev/null
+++ b/tests/run-make/rustdoc-with-short-out-dir-option/Makefile
@@ -0,0 +1,8 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+all:
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib -o $(OUTPUT_DIR)
+
+	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/tests/run-make/rustdoc-with-short-out-dir-option/src/lib.rs b/tests/run-make/rustdoc-with-short-out-dir-option/src/lib.rs
new file mode 100644
index 00000000000..044bb6acb19
--- /dev/null
+++ b/tests/run-make/rustdoc-with-short-out-dir-option/src/lib.rs
@@ -0,0 +1,2 @@
+// @has foobar/fn.ok.html
+pub fn ok() {}
diff --git a/tests/run-make/static-pie/Makefile b/tests/run-make/static-pie/Makefile
new file mode 100644
index 00000000000..e71770636ee
--- /dev/null
+++ b/tests/run-make/static-pie/Makefile
@@ -0,0 +1,18 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-x86_64
+# only-linux
+# ignore-gnux32
+
+# How to manually run this
+# $ ./x.py test --target x86_64-unknown-linux-[musl,gnu] src/test/run-make/static-pie
+
+all: test-clang test-gcc
+
+test-%:
+	if ./check_$*_version.sh; then\
+		${RUSTC} -Clinker=$* -Clinker-flavor=gcc --target ${TARGET} -C target-feature=+crt-static test-aslr.rs; \
+		! readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) INTERP; \
+		readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) DYNAMIC; \
+		$(call RUN,test-aslr) --test-aslr; \
+	fi
diff --git a/tests/run-make/static-pie/check_clang_version.sh b/tests/run-make/static-pie/check_clang_version.sh
new file mode 100755
index 00000000000..b8e97c3da7d
--- /dev/null
+++ b/tests/run-make/static-pie/check_clang_version.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -euo pipefail
+
+if command -v clang > /dev/null
+then
+  CLANG_VERSION=$(echo __clang_major__ | clang -E -x c - | grep -v -e '^#' )
+  echo "clang version $CLANG_VERSION detected"
+  if (( $CLANG_VERSION >= 9 ))
+  then
+    echo "clang supports -static-pie"
+    exit 0
+  else
+    echo "clang too old to support -static-pie, skipping test"
+    exit 1
+  fi
+else
+  echo "No clang version detected"
+  exit 2
+fi
diff --git a/tests/run-make/static-pie/check_gcc_version.sh b/tests/run-make/static-pie/check_gcc_version.sh
new file mode 100755
index 00000000000..d07e1d151df
--- /dev/null
+++ b/tests/run-make/static-pie/check_gcc_version.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -euo pipefail
+
+if command -v gcc > /dev/null
+then
+  GCC_VERSION=$(echo __GNUC__ | gcc -E -x c - | grep -v -e '^#' )
+  echo "gcc version $GCC_VERSION detected"
+  if (( $GCC_VERSION >= 8 ))
+  then
+    echo "gcc supports -static-pie"
+    exit 0
+  else
+    echo "gcc too old to support -static-pie, skipping test"
+    exit 1
+  fi
+else
+  echo "No gcc version detected"
+  exit 2
+fi
diff --git a/tests/run-make/static-pie/test-aslr.rs b/tests/run-make/static-pie/test-aslr.rs
new file mode 100644
index 00000000000..96b17af46df
--- /dev/null
+++ b/tests/run-make/static-pie/test-aslr.rs
@@ -0,0 +1,43 @@
+const NUM_RUNS: usize = 10;
+
+fn run_self(exe: &str) -> usize {
+    use std::process::Command;
+    let mut set = std::collections::HashSet::new();
+
+    let mut cmd = Command::new(exe);
+    cmd.arg("--report");
+    (0..NUM_RUNS).for_each(|_| {
+        set.insert(cmd.output().expect("failed to execute process").stdout);
+    });
+    set.len()
+}
+
+fn main() {
+    let mut args = std::env::args();
+    let arg0 = args.next().unwrap();
+    match args.next() {
+        Some(s) if s.eq("--report") => {
+            println!("main = {:#?}", &main as *const _);
+        }
+        Some(s) if s.eq("--test-no-aslr") => {
+            let cnt = run_self(&arg0);
+            if cnt != 1 {
+                eprintln!("FAIL: {} most likely ASLR", arg0);
+                std::process::exit(1);
+            }
+            println!("PASS: {} does no ASLR", arg0);
+        }
+        Some(s) if s.eq("--test-aslr") => {
+            let cnt = run_self(&arg0);
+            if cnt == 1 {
+                eprintln!("FAIL: {} most likely no ASLR", arg0);
+                std::process::exit(1);
+            }
+            println!("PASS: {} does ASLR", arg0);
+        }
+        Some(_) | None => {
+            println!("Usage: {} --test-no-aslr | --test-aslr", arg0);
+            std::process::exit(1);
+        }
+    }
+}
diff --git a/tests/run-make/test-benches/Makefile b/tests/run-make/test-benches/Makefile
new file mode 100644
index 00000000000..8fc122515d0
--- /dev/null
+++ b/tests/run-make/test-benches/Makefile
@@ -0,0 +1,11 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-cross-compile
+
+all:
+	# Smoke-test that `#[bench]` isn't entirely broken.
+	$(RUSTC) --test smokebench.rs -O
+	$(call RUN,smokebench --bench)
+	$(call RUN,smokebench --bench noiter)
+	$(call RUN,smokebench --bench yesiter)
+	$(call RUN,smokebench)
diff --git a/tests/run-make/test-benches/smokebench.rs b/tests/run-make/test-benches/smokebench.rs
new file mode 100644
index 00000000000..ef5e5a62068
--- /dev/null
+++ b/tests/run-make/test-benches/smokebench.rs
@@ -0,0 +1,14 @@
+#![feature(test)]
+extern crate test;
+
+#[bench]
+fn smoke_yesiter(b: &mut test::Bencher) {
+    let mut i = 0usize;
+    b.iter(|| {
+        i = i.wrapping_add(1);
+        i
+    })
+}
+
+#[bench]
+fn smoke_noiter(_: &mut test::Bencher) {}
diff --git a/tests/run-make/thumb-none-cortex-m/Makefile b/tests/run-make/thumb-none-cortex-m/Makefile
new file mode 100644
index 00000000000..aa046af95da
--- /dev/null
+++ b/tests/run-make/thumb-none-cortex-m/Makefile
@@ -0,0 +1,38 @@
+include ../../run-make-fulldeps/tools.mk
+
+# How to run this
+# $ ./x.py clean
+# $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi src/test/run-make
+
+# Supported targets:
+# - thumbv6m-none-eabi (Bare Cortex-M0, M0+, M1)
+# - thumbv7em-none-eabi (Bare Cortex-M4, M7)
+# - thumbv7em-none-eabihf (Bare Cortex-M4F, M7F, FPU, hardfloat)
+# - thumbv7m-none-eabi (Bare Cortex-M3)
+
+# only-thumb
+
+# For cargo setting
+RUSTC := $(RUSTC_ORIGINAL)
+LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+WORK_DIR := $(TMPDIR)
+
+HERE := $(shell pwd)
+
+CRATE := cortex-m
+CRATE_URL := https://github.com/rust-embedded/cortex-m
+CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0
+
+# Don't make lints fatal, but they need to at least warn or they break Cargo's target info parsing.
+export RUSTFLAGS := --cap-lints=warn
+
+all:
+	env
+	mkdir -p $(WORK_DIR)
+	-cd $(WORK_DIR) && rm -rf $(CRATE)
+	cd $(WORK_DIR) && bash -x $(HERE)/../git_clone_sha1.sh $(CRATE) $(CRATE_URL) $(CRATE_SHA1)
+	# HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
+	# These come from the top-level Rust workspace, that this crate is not a
+	# member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
+	cd $(WORK_DIR) && cd $(CRATE) && env RUSTC_BOOTSTRAP=1 $(BOOTSTRAP_CARGO) build --target $(TARGET) -v
diff --git a/tests/run-make/thumb-none-qemu/Makefile b/tests/run-make/thumb-none-qemu/Makefile
new file mode 100644
index 00000000000..328758d41ba
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/Makefile
@@ -0,0 +1,27 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-thumb
+
+# How to run this
+# $ ./x.py clean
+# $ ./x.py test --target thumbv7m-none-eabi src/test/run-make
+
+# For cargo setting
+export RUSTC := $(RUSTC_ORIGINAL)
+export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+export WORK_DIR := $(TMPDIR)
+export HERE := $(shell pwd)
+
+## clean up unused env variables which might cause harm.
+unexport RUSTC_LINKER
+unexport RUSTC_BOOTSTRAP
+unexport RUST_BUILD_STAGE
+unexport RUST_TEST_THREADS
+unexport RUST_TEST_TMPDIR
+unexport AR
+unexport CC
+unexport CXX
+
+all:
+	bash script.sh
diff --git a/tests/run-make/thumb-none-qemu/example/.cargo/config b/tests/run-make/thumb-none-qemu/example/.cargo/config
new file mode 100644
index 00000000000..8b30310e7d4
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/example/.cargo/config
@@ -0,0 +1,45 @@
+[target.thumbv6m-none-eabi]
+# FIXME: Should be Cortex-M0, but Qemu used by CI is too old
+runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv7m-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv7em-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m4 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv7em-none-eabihf]
+runner = "qemu-system-arm -cpu cortex-m4 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.base-none-eabi]
+# FIXME: Should be the Cortex-M23, bt Qemu does not currently support it
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.main-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.main-none-eabihf]
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.'cfg(all(target_arch = "arm", target_os = "none"))']
+# uncomment ONE of these three option to make `cargo run` start a GDB session
+# which option to pick depends on your system
+# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
+# runner = "gdb-multiarch -q -x openocd.gdb"
+# runner = "gdb -q -x openocd.gdb"
+
+rustflags = [
+  # LLD (shipped with the Rust toolchain) is used as the default linker
+  "-C", "link-arg=-Tlink.x",
+
+  # if you run into problems with LLD switch to the GNU linker by commenting out
+  # this line
+  # "-C", "linker=arm-none-eabi-ld",
+
+  # if you need to link to pre-compiled C libraries provided by a C toolchain
+  # use GCC as the linker by commenting out both lines above and then
+  # uncommenting the three lines below
+  # "-C", "linker=arm-none-eabi-gcc",
+  # "-C", "link-arg=-Wl,-Tlink.x",
+  # "-C", "link-arg=-nostartfiles",
+]
diff --git a/tests/run-make/thumb-none-qemu/example/Cargo.lock b/tests/run-make/thumb-none-qemu/example/Cargo.lock
new file mode 100644
index 00000000000..687b962a8b6
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/example/Cargo.lock
@@ -0,0 +1,199 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aligned"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "as-slice 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "as-slice"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bare-metal"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-rt"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cortex-m-rt-macros 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-rt-macros"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-semihosting"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "example"
+version = "0.1.0"
+dependencies = [
+ "cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cortex-m-rt 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "panic-halt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "r0"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "syn"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "typenum"
+version = "1.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "vcell"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "volatile-register"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eb1ce8b3382016136ab1d31a1b5ce807144f8b7eb2d5f16b2108f0f07edceb94"
+"checksum as-slice 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "be6b7e95ac49d753f19cab5a825dea99a1149a04e4e3230b33ae16e120954c04"
+"checksum bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
+"checksum cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2954942fbbdd49996704e6f048ce57567c3e1a4e2dc59b41ae9fde06a01fc763"
+"checksum cortex-m-rt 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "33a716cd7d8627fae3892c2eede9249e50d2d79aedfb43ca28dad9a2b23876d9"
+"checksum cortex-m-rt-macros 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "72b1073338d1e691b3b7aaf6bd61993e589ececce9242a02dfa5453e1b98918d"
+"checksum cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "113ef0ecffee2b62b58f9380f4469099b30e9f9cbee2804771b4203ba1762cfa"
+"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
+"checksum generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
+"checksum panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
+"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
+"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
+"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
+"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+"checksum vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
+"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
diff --git a/tests/run-make/thumb-none-qemu/example/Cargo.toml b/tests/run-make/thumb-none-qemu/example/Cargo.toml
new file mode 100644
index 00000000000..63eb5f90aec
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/example/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "example"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+cortex-m = "0.6.2"
+cortex-m-rt = "0.6.11"
+panic-halt = "0.2.0"
+cortex-m-semihosting = "0.3.1"
diff --git a/tests/run-make/thumb-none-qemu/example/memory.x b/tests/run-make/thumb-none-qemu/example/memory.x
new file mode 100644
index 00000000000..dc7ad967a42
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/example/memory.x
@@ -0,0 +1,23 @@
+/* Device specific memory layout */
+
+/* This file is used to build the cortex-m-rt examples,
+   but not other applications using cortex-m-rt. */
+
+MEMORY
+{
+  /* FLASH and RAM are mandatory memory regions */
+  /* Update examples/data_overflow.rs if you change these sizes. */
+  FLASH : ORIGIN = 0x00000000, LENGTH = 256K
+  RAM : ORIGIN = 0x20000000, LENGTH = 64K
+
+  /* More memory regions can declared: for example this is a second RAM region */
+  /* CCRAM : ORIGIN = 0x10000000, LENGTH = 8K */
+}
+
+/* The location of the stack can be overridden using the `_stack_start` symbol.
+   By default it will be placed at the end of the RAM region */
+/* _stack_start = ORIGIN(CCRAM) + LENGTH(CCRAM); */
+
+/* The location of the .text section can be overridden using the `_stext` symbol.
+   By default it will place after .vector_table */
+/* _stext = ORIGIN(FLASH) + 0x40c; */
\ No newline at end of file
diff --git a/tests/run-make/thumb-none-qemu/example/src/main.rs b/tests/run-make/thumb-none-qemu/example/src/main.rs
new file mode 100644
index 00000000000..2abfde8e75f
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/example/src/main.rs
@@ -0,0 +1,24 @@
+#![no_main]
+#![no_std]
+use core::fmt::Write;
+use cortex_m::asm;
+use cortex_m_rt::entry;
+use cortex_m_semihosting as semihosting;
+
+use panic_halt as _;
+
+#[entry]
+fn main() -> ! {
+    let x = 42;
+
+    loop {
+        asm::nop();
+
+        // write something through semihosting interface
+        let mut hstdout = semihosting::hio::hstdout().unwrap();
+        let _ = write!(hstdout, "x = {}\n", x);
+
+        // exit from qemu
+        semihosting::debug::exit(semihosting::debug::EXIT_SUCCESS);
+    }
+}
diff --git a/tests/run-make/thumb-none-qemu/script.sh b/tests/run-make/thumb-none-qemu/script.sh
new file mode 100644
index 00000000000..a8aa72af184
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/script.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+set -exuo pipefail
+
+CRATE=example
+
+env | sort
+mkdir -p $WORK_DIR
+pushd $WORK_DIR
+    rm -rf $CRATE || echo OK
+    cp -a $HERE/example .
+    pushd $CRATE
+        # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
+        # These come from the top-level Rust workspace, that this crate is not a
+        # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
+        env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \
+            $BOOTSTRAP_CARGO run --target $TARGET           | grep "x = 42"
+        env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \
+            $BOOTSTRAP_CARGO run --target $TARGET --release | grep "x = 42"
+    popd
+popd
diff --git a/tests/run-make/track-path-dep-info/Makefile b/tests/run-make/track-path-dep-info/Makefile
new file mode 100644
index 00000000000..ee853943f8b
--- /dev/null
+++ b/tests/run-make/track-path-dep-info/Makefile
@@ -0,0 +1,13 @@
+include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+
+all:
+	# Proc macro
+	$(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs
+	EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs
+	$(CGREP) "emojis.txt:" < $(TMPDIR)/macro_use.d
diff --git a/tests/run-make/track-path-dep-info/emojis.txt b/tests/run-make/track-path-dep-info/emojis.txt
new file mode 100644
index 00000000000..e1a728461f3
--- /dev/null
+++ b/tests/run-make/track-path-dep-info/emojis.txt
@@ -0,0 +1 @@
+👾👾👾👾👾👾
diff --git a/tests/run-make/track-path-dep-info/macro_def.rs b/tests/run-make/track-path-dep-info/macro_def.rs
new file mode 100644
index 00000000000..8777ce21f8b
--- /dev/null
+++ b/tests/run-make/track-path-dep-info/macro_def.rs
@@ -0,0 +1,11 @@
+#![feature(track_path)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn access_tracked_paths(_: TokenStream) -> TokenStream {
+    tracked_path::path("emojis.txt");
+    TokenStream::new()
+}
diff --git a/tests/run-make/track-path-dep-info/macro_use.rs b/tests/run-make/track-path-dep-info/macro_use.rs
new file mode 100644
index 00000000000..3c49fd05dd9
--- /dev/null
+++ b/tests/run-make/track-path-dep-info/macro_use.rs
@@ -0,0 +1,6 @@
+#[macro_use]
+extern crate macro_def;
+
+access_tracked_paths!();
+
+fn main() {}
diff --git a/tests/run-make/track-pgo-dep-info/Makefile b/tests/run-make/track-pgo-dep-info/Makefile
new file mode 100644
index 00000000000..60b59c04aa9
--- /dev/null
+++ b/tests/run-make/track-pgo-dep-info/Makefile
@@ -0,0 +1,26 @@
+# needs-profiler-support
+# ignore-windows-gnu
+
+-include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+
+all:
+	# Generate PGO profiles
+	$(BARE_RUSTC) $(ADDITIONAL_ARGS) -Cprofile-generate=$(TMPDIR)/profiles --out-dir $(TMPDIR) main.rs
+	$(TMPDIR)/main
+
+	# Merge profiles
+	"$(LLVM_BIN_DIR)/llvm-profdata" merge \
+		-o "$(TMPDIR)/merged.profdata" \
+		"$(TMPDIR)/profiles" || exit 1
+
+	# Use the profile
+	$(RUSTC) -Cprofile-use=$(TMPDIR)/merged.profdata --emit dep-info main.rs
+
+	# Check that profile file is in depinfo
+	$(CGREP) "merged.profdata" < $(TMPDIR)/main.d
diff --git a/tests/run-make/track-pgo-dep-info/main.rs b/tests/run-make/track-pgo-dep-info/main.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/track-pgo-dep-info/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/translation/Makefile b/tests/run-make/translation/Makefile
new file mode 100644
index 00000000000..20e86c7f9a0
--- /dev/null
+++ b/tests/run-make/translation/Makefile
@@ -0,0 +1,72 @@
+include ../../run-make-fulldeps/tools.mk
+
+# This test uses `ln -s` rather than copying to save testing time, but its
+# usage doesn't work on Windows.
+# ignore-windows
+
+SYSROOT:=$(shell $(RUSTC) --print sysroot)
+FAKEROOT=$(TMPDIR)/fakeroot
+
+all: normal custom sysroot
+
+# Check that the test works normally, using the built-in fallback bundle.
+normal: test.rs
+	$(RUSTC) $< 2>&1 | grep "struct literal body without path"
+
+# Check that a primary bundle can be loaded and will be preferentially used
+# where possible.
+custom: test.rs working.ftl
+	$(RUSTC) $< -Ztranslate-additional-ftl=$(CURDIR)/working.ftl 2>&1 | grep "this is a test message"
+
+# Check that a primary bundle with a broken message (e.g. a interpolated
+# variable is missing) will use the fallback bundle.
+missing: test.rs missing.ftl
+	$(RUSTC) $< -Ztranslate-additional-ftl=$(CURDIR)/missing.ftl 2>&1 | grep "struct literal body without path"
+
+# Check that a primary bundle without the desired message will use the fallback
+# bundle.
+broken: test.rs broken.ftl
+	$(RUSTC) $< -Ztranslate-additional-ftl=$(CURDIR)/broken.ftl 2>&1 | grep "struct literal body without path"
+
+# Check that a locale can be loaded from the sysroot given a language
+# identifier by making a local copy of the sysroot and adding the custom locale
+# to it.
+sysroot: test.rs working.ftl
+	mkdir $(FAKEROOT)
+	ln -s $(SYSROOT)/* $(FAKEROOT)
+	rm -f $(FAKEROOT)/lib
+	mkdir $(FAKEROOT)/lib
+	ln -s $(SYSROOT)/lib/* $(FAKEROOT)/lib
+	rm -f $(FAKEROOT)/lib/rustlib
+	mkdir $(FAKEROOT)/lib/rustlib
+	ln -s $(SYSROOT)/lib/rustlib/* $(FAKEROOT)/lib/rustlib
+	rm -f $(FAKEROOT)/lib/rustlib/src
+	mkdir $(FAKEROOT)/lib/rustlib/src
+	ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src
+	mkdir -p $(FAKEROOT)/share/locale/zh-CN/
+	ln -s $(CURDIR)/working.ftl $(FAKEROOT)/share/locale/zh-CN/basic-translation.ftl
+	$(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 | grep "this is a test message"
+
+# Check that the compiler errors out when the sysroot requested cannot be
+# found. This test might start failing if there actually exists a Klingon
+# translation of rustc's error messages.
+sysroot-missing: 
+	$(RUSTC) $< -Ztranslate-lang=tlh 2>&1 || grep "missing locale directory"
+
+# Check that the compiler errors out when the sysroot requested cannot be
+# found. This test might start failing if there actually exists a Klingon
+# translation of rustc's error messages.
+sysroot-invalid: test.rs working.ftl
+	mkdir $(FAKEROOT)
+	ln -s $(SYSROOT)/* $(FAKEROOT)
+	rm -f $(FAKEROOT)/lib
+	mkdir $(FAKEROOT)/lib
+	ln -s $(SYSROOT)/lib/* $(FAKEROOT)/lib
+	rm -f $(FAKEROOT)/lib/rustlib
+	mkdir $(FAKEROOT)/lib/rustlib
+	ln -s $(SYSROOT)/lib/rustlib/* $(FAKEROOT)/lib/rustlib
+	rm -f $(FAKEROOT)/lib/rustlib/src
+	mkdir $(FAKEROOT)/lib/rustlib/src
+	ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src
+	touch $(FAKEROOT)/share/locale/zh-CN/
+	$(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 || grep "`\$sysroot/share/locales/\$locale` is not a directory"
diff --git a/tests/run-make/translation/broken.ftl b/tests/run-make/translation/broken.ftl
new file mode 100644
index 00000000000..f1dd6ff0bbd
--- /dev/null
+++ b/tests/run-make/translation/broken.ftl
@@ -0,0 +1,3 @@
+# `foo` isn't provided by this diagnostic so it is expected that the fallback message is used.
+parse_struct_literal_body_without_path = this is a {$foo} message
+    .suggestion = this is a test suggestion
diff --git a/tests/run-make/translation/missing.ftl b/tests/run-make/translation/missing.ftl
new file mode 100644
index 00000000000..6be24dc7bb9
--- /dev/null
+++ b/tests/run-make/translation/missing.ftl
@@ -0,0 +1,3 @@
+# `parse_struct_literal_body_without_path` isn't provided by this resource at all, so the
+# fallback should be used.
+foo = bar
diff --git a/tests/run-make/translation/test.rs b/tests/run-make/translation/test.rs
new file mode 100644
index 00000000000..b8f5bff3153
--- /dev/null
+++ b/tests/run-make/translation/test.rs
@@ -0,0 +1,18 @@
+// Exact error being tested isn't relevant, it just needs to be known that it uses Fluent-backed
+// diagnostics.
+
+struct Foo {
+    val: (),
+}
+
+fn foo() -> Foo {
+    val: (),
+}
+
+fn main() {
+    let x = foo();
+    x.val == 42;
+    let x = {
+        val: (),
+    };
+}
diff --git a/tests/run-make/translation/working.ftl b/tests/run-make/translation/working.ftl
new file mode 100644
index 00000000000..50d126e3fbf
--- /dev/null
+++ b/tests/run-make/translation/working.ftl
@@ -0,0 +1,2 @@
+parse_struct_literal_body_without_path = this is a test message
+    .suggestion = this is a test suggestion
diff --git a/tests/run-make/unstable-flag-required/Makefile b/tests/run-make/unstable-flag-required/Makefile
new file mode 100644
index 00000000000..d3a734fae77
--- /dev/null
+++ b/tests/run-make/unstable-flag-required/Makefile
@@ -0,0 +1,4 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
diff --git a/tests/run-make/unstable-flag-required/README.md b/tests/run-make/unstable-flag-required/README.md
new file mode 100644
index 00000000000..e5251fdf9b5
--- /dev/null
+++ b/tests/run-make/unstable-flag-required/README.md
@@ -0,0 +1,3 @@
+This is a collection of tests that verify `--unstable-options` is required.
+It should eventually be removed in favor of UI tests once compiletest stops
+passing --unstable-options by default (#82639).
diff --git a/tests/run-make/unstable-flag-required/output-format-json.stderr b/tests/run-make/unstable-flag-required/output-format-json.stderr
new file mode 100644
index 00000000000..fb4079beb27
--- /dev/null
+++ b/tests/run-make/unstable-flag-required/output-format-json.stderr
@@ -0,0 +1,2 @@
+error: the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)
+
diff --git a/tests/run-make/unstable-flag-required/x.rs b/tests/run-make/unstable-flag-required/x.rs
new file mode 100644
index 00000000000..5df7576133a
--- /dev/null
+++ b/tests/run-make/unstable-flag-required/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/tests/run-make/valid-print-requests/Makefile b/tests/run-make/valid-print-requests/Makefile
new file mode 100644
index 00000000000..c325e536e7c
--- /dev/null
+++ b/tests/run-make/valid-print-requests/Makefile
@@ -0,0 +1,4 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --print uwu 2>&1 | diff - valid-print-requests.stderr
diff --git a/tests/run-make/valid-print-requests/valid-print-requests.stderr b/tests/run-make/valid-print-requests/valid-print-requests.stderr
new file mode 100644
index 00000000000..5191e467648
--- /dev/null
+++ b/tests/run-make/valid-print-requests/valid-print-requests.stderr
@@ -0,0 +1,2 @@
+error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args`, `split-debuginfo`
+
diff --git a/tests/run-make/wasm-abi/Makefile b/tests/run-make/wasm-abi/Makefile
new file mode 100644
index 00000000000..e713ca1876d
--- /dev/null
+++ b/tests/run-make/wasm-abi/Makefile
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(NODE) foo.js $(TMPDIR)/foo.wasm
diff --git a/tests/run-make/wasm-abi/foo.js b/tests/run-make/wasm-abi/foo.js
new file mode 100644
index 00000000000..9e9a65401af
--- /dev/null
+++ b/tests/run-make/wasm-abi/foo.js
@@ -0,0 +1,22 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+const m = new WebAssembly.Module(buffer);
+const i = new WebAssembly.Instance(m, {
+  host: {
+    two_i32: () => [100, 101],
+    two_i64: () => [102n, 103n],
+    two_f32: () => [104, 105],
+    two_f64: () => [106, 107],
+    mishmash: () => [108, 109, 110, 111n, 112, 113],
+  }
+});
+
+assert.deepEqual(i.exports.return_two_i32(), [1, 2])
+assert.deepEqual(i.exports.return_two_i64(), [3, 4])
+assert.deepEqual(i.exports.return_two_f32(), [5, 6])
+assert.deepEqual(i.exports.return_two_f64(), [7, 8])
+assert.deepEqual(i.exports.return_mishmash(), [9, 10, 11, 12, 13, 14])
+i.exports.call_imports();
diff --git a/tests/run-make/wasm-abi/foo.rs b/tests/run-make/wasm-abi/foo.rs
new file mode 100644
index 00000000000..0678eb3ff51
--- /dev/null
+++ b/tests/run-make/wasm-abi/foo.rs
@@ -0,0 +1,87 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+#![feature(wasm_abi)]
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoI32 {
+    pub a: i32,
+    pub b: i32,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_i32() -> TwoI32 {
+    TwoI32 { a: 1, b: 2 }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoI64 {
+    pub a: i64,
+    pub b: i64,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_i64() -> TwoI64 {
+    TwoI64 { a: 3, b: 4 }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoF32 {
+    pub a: f32,
+    pub b: f32,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_f32() -> TwoF32 {
+    TwoF32 { a: 5., b: 6. }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoF64 {
+    pub a: f64,
+    pub b: f64,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_f64() -> TwoF64 {
+    TwoF64 { a: 7., b: 8. }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct Mishmash {
+    pub a: f64,
+    pub b: f32,
+    pub c: i32,
+    pub d: i64,
+    pub e: TwoI32,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_mishmash() -> Mishmash {
+    Mishmash { a: 9., b: 10., c: 11, d: 12, e: TwoI32 { a: 13, b: 14 } }
+}
+
+#[link(wasm_import_module = "host")]
+extern "wasm" {
+    fn two_i32() -> TwoI32;
+    fn two_i64() -> TwoI64;
+    fn two_f32() -> TwoF32;
+    fn two_f64() -> TwoF64;
+    fn mishmash() -> Mishmash;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn call_imports() {
+    assert_eq!(two_i32(), TwoI32 { a: 100, b: 101 });
+    assert_eq!(two_i64(), TwoI64 { a: 102, b: 103 });
+    assert_eq!(two_f32(), TwoF32 { a: 104., b: 105. });
+    assert_eq!(two_f64(), TwoF64 { a: 106., b: 107. });
+    assert_eq!(
+        mishmash(),
+        Mishmash { a: 108., b: 109., c: 110, d: 111, e: TwoI32 { a: 112, b: 113 } }
+    );
+}
diff --git a/tests/run-make/wasm-custom-section/Makefile b/tests/run-make/wasm-custom-section/Makefile
new file mode 100644
index 00000000000..92b0802e30a
--- /dev/null
+++ b/tests/run-make/wasm-custom-section/Makefile
@@ -0,0 +1,8 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown
+	$(NODE) foo.js $(TMPDIR)/bar.wasm
diff --git a/tests/run-make/wasm-custom-section/bar.rs b/tests/run-make/wasm-custom-section/bar.rs
new file mode 100644
index 00000000000..c95f3e1438b
--- /dev/null
+++ b/tests/run-make/wasm-custom-section/bar.rs
@@ -0,0 +1,13 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+
+extern crate foo;
+
+#[link_section = "foo"]
+pub static A: [u8; 2] = [5, 6];
+
+#[link_section = "baz"]
+pub static B: [u8; 2] = [7, 8];
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/tests/run-make/wasm-custom-section/foo.js b/tests/run-make/wasm-custom-section/foo.js
new file mode 100644
index 00000000000..57a0f50732d
--- /dev/null
+++ b/tests/run-make/wasm-custom-section/foo.js
@@ -0,0 +1,36 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let sections = WebAssembly.Module.customSections(m, "baz");
+console.log('section baz', sections);
+assert.strictEqual(sections.length, 1);
+let section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 2);
+assert.strictEqual(section[0], 7);
+assert.strictEqual(section[1], 8);
+
+sections = WebAssembly.Module.customSections(m, "bar");
+console.log('section bar', sections);
+assert.strictEqual(sections.length, 1, "didn't pick up `bar` section from dependency");
+section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 2);
+assert.strictEqual(section[0], 3);
+assert.strictEqual(section[1], 4);
+
+sections = WebAssembly.Module.customSections(m, "foo");
+console.log('section foo', sections);
+assert.strictEqual(sections.length, 1, "didn't create `foo` section");
+section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 4, "didn't concatenate `foo` sections");
+assert.strictEqual(section[0], 5);
+assert.strictEqual(section[1], 6);
+assert.strictEqual(section[2], 1);
+assert.strictEqual(section[3], 2);
+
+process.exit(0);
diff --git a/tests/run-make/wasm-custom-section/foo.rs b/tests/run-make/wasm-custom-section/foo.rs
new file mode 100644
index 00000000000..61f81f024b5
--- /dev/null
+++ b/tests/run-make/wasm-custom-section/foo.rs
@@ -0,0 +1,8 @@
+#![crate_type = "rlib"]
+#![deny(warnings)]
+
+#[link_section = "foo"]
+pub static A: [u8; 2] = [1, 2];
+
+#[link_section = "bar"]
+pub static B: [u8; 2] = [3, 4];
diff --git a/tests/run-make/wasm-custom-sections-opt/Makefile b/tests/run-make/wasm-custom-sections-opt/Makefile
new file mode 100644
index 00000000000..e5b45d96310
--- /dev/null
+++ b/tests/run-make/wasm-custom-sections-opt/Makefile
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs -O --target wasm32-unknown-unknown
+	$(NODE) foo.js $(TMPDIR)/foo.wasm
diff --git a/tests/run-make/wasm-custom-sections-opt/foo.js b/tests/run-make/wasm-custom-sections-opt/foo.js
new file mode 100644
index 00000000000..9663f377ef4
--- /dev/null
+++ b/tests/run-make/wasm-custom-sections-opt/foo.js
@@ -0,0 +1,15 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+
+sections = WebAssembly.Module.customSections(m, "foo");
+console.log('section foo', sections);
+assert.strictEqual(sections.length, 1, "didn't create `foo` section");
+section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 4, "didn't concatenate `foo` sections");
+
+process.exit(0);
diff --git a/tests/run-make/wasm-custom-sections-opt/foo.rs b/tests/run-make/wasm-custom-sections-opt/foo.rs
new file mode 100644
index 00000000000..9af7728b7f3
--- /dev/null
+++ b/tests/run-make/wasm-custom-sections-opt/foo.rs
@@ -0,0 +1,21 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+
+#[link_section = "foo"]
+pub static A: [u8; 2] = [1, 2];
+
+// make sure this is in another CGU
+pub mod another {
+    #[link_section = "foo"]
+    pub static FOO: [u8; 2] = [3, 4];
+
+    pub fn foo() {}
+}
+
+#[no_mangle]
+pub extern fn foo() {
+    // This will import `another::foo` through ThinLTO passes, and it better not
+    // also accidentally import the `FOO` custom section into this module as
+    // well
+    another::foo();
+}
diff --git a/tests/run-make/wasm-export-all-symbols/Makefile b/tests/run-make/wasm-export-all-symbols/Makefile
new file mode 100644
index 00000000000..834f4d258db
--- /dev/null
+++ b/tests/run-make/wasm-export-all-symbols/Makefile
@@ -0,0 +1,19 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(NODE) verify.js $(TMPDIR)/foo.wasm
+	$(RUSTC) main.rs --target wasm32-unknown-unknown
+	$(NODE) verify.js $(TMPDIR)/main.wasm
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify.js $(TMPDIR)/foo.wasm
+	$(RUSTC) main.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify.js $(TMPDIR)/main.wasm
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+	$(NODE) verify.js $(TMPDIR)/foo.wasm
+	$(RUSTC) main.rs --target wasm32-unknown-unknown -C lto
+	$(NODE) verify.js $(TMPDIR)/main.wasm
diff --git a/tests/run-make/wasm-export-all-symbols/bar.rs b/tests/run-make/wasm-export-all-symbols/bar.rs
new file mode 100644
index 00000000000..ac9c20a57e5
--- /dev/null
+++ b/tests/run-make/wasm-export-all-symbols/bar.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
+
+#[no_mangle]
+pub static FOO: u64 = 42;
diff --git a/tests/run-make/wasm-export-all-symbols/foo.rs b/tests/run-make/wasm-export-all-symbols/foo.rs
new file mode 100644
index 00000000000..4811b24bc6b
--- /dev/null
+++ b/tests/run-make/wasm-export-all-symbols/foo.rs
@@ -0,0 +1,3 @@
+#![crate_type = "cdylib"]
+
+extern crate bar;
diff --git a/tests/run-make/wasm-export-all-symbols/main.rs b/tests/run-make/wasm-export-all-symbols/main.rs
new file mode 100644
index 00000000000..0edda7d7b88
--- /dev/null
+++ b/tests/run-make/wasm-export-all-symbols/main.rs
@@ -0,0 +1,3 @@
+extern crate bar;
+
+fn main() {}
diff --git a/tests/run-make/wasm-export-all-symbols/verify.js b/tests/run-make/wasm-export-all-symbols/verify.js
new file mode 100644
index 00000000000..72db3356f56
--- /dev/null
+++ b/tests/run-make/wasm-export-all-symbols/verify.js
@@ -0,0 +1,32 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.exports(m);
+console.log('exports', list);
+
+const my_exports = {};
+let nexports = 0;
+
+for (const entry of list) {
+  if (entry.kind == 'function'){
+    nexports += 1;
+  }
+  my_exports[entry.name] = entry.kind;
+}
+
+if (my_exports.foo != "function")
+  throw new Error("`foo` wasn't defined");
+
+if (my_exports.FOO != "global")
+  throw new Error("`FOO` wasn't defined");
+
+if (my_exports.main === undefined) {
+  if (nexports != 1)
+    throw new Error("should only have one function export");
+} else {
+  if (nexports != 2)
+    throw new Error("should only have two function exports");
+}
diff --git a/tests/run-make/wasm-import-module/Makefile b/tests/run-make/wasm-import-module/Makefile
new file mode 100644
index 00000000000..18cef16aac3
--- /dev/null
+++ b/tests/run-make/wasm-import-module/Makefile
@@ -0,0 +1,8 @@
+include ../../run-make-fulldeps/tools.mk
+
+ # only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown
+	$(NODE) foo.js $(TMPDIR)/bar.wasm
diff --git a/tests/run-make/wasm-import-module/bar.rs b/tests/run-make/wasm-import-module/bar.rs
new file mode 100644
index 00000000000..1b988c78321
--- /dev/null
+++ b/tests/run-make/wasm-import-module/bar.rs
@@ -0,0 +1,18 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+
+extern crate foo;
+
+#[link(wasm_import_module = "./me")]
+extern "C" {
+    #[link_name = "me_in_dep"]
+    fn dep();
+}
+
+#[no_mangle]
+pub extern "C" fn foo() {
+    unsafe {
+        foo::dep();
+        dep();
+    }
+}
diff --git a/tests/run-make/wasm-import-module/foo.js b/tests/run-make/wasm-import-module/foo.js
new file mode 100644
index 00000000000..3ea47fcc930
--- /dev/null
+++ b/tests/run-make/wasm-import-module/foo.js
@@ -0,0 +1,18 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let imports = WebAssembly.Module.imports(m);
+console.log('imports', imports);
+assert.strictEqual(imports.length, 2);
+
+assert.strictEqual(imports[0].kind, 'function');
+assert.strictEqual(imports[1].kind, 'function');
+
+let modules = [imports[0].module, imports[1].module];
+modules.sort();
+
+assert.strictEqual(modules[0], './dep');
+assert.strictEqual(modules[1], './me');
diff --git a/tests/run-make/wasm-import-module/foo.rs b/tests/run-make/wasm-import-module/foo.rs
new file mode 100644
index 00000000000..bbeaf99bc77
--- /dev/null
+++ b/tests/run-make/wasm-import-module/foo.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+#![deny(warnings)]
+
+#[link(wasm_import_module = "./dep")]
+extern "C" {
+    pub fn dep();
+}
diff --git a/tests/run-make/wasm-panic-small/Makefile b/tests/run-make/wasm-panic-small/Makefile
new file mode 100644
index 00000000000..2af9f71357e
--- /dev/null
+++ b/tests/run-make/wasm-panic-small/Makefile
@@ -0,0 +1,17 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg a
+	wc -c < $(TMPDIR)/foo.wasm
+	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "1024" ]
+	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg b
+	wc -c < $(TMPDIR)/foo.wasm
+	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
+	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg c
+	wc -c < $(TMPDIR)/foo.wasm
+	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
+	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg d
+	wc -c < $(TMPDIR)/foo.wasm
+	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
diff --git a/tests/run-make/wasm-panic-small/foo.rs b/tests/run-make/wasm-panic-small/foo.rs
new file mode 100644
index 00000000000..6df52affe39
--- /dev/null
+++ b/tests/run-make/wasm-panic-small/foo.rs
@@ -0,0 +1,27 @@
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+#[cfg(a)]
+pub fn foo() {
+    panic!("test");
+}
+
+#[no_mangle]
+#[cfg(b)]
+pub fn foo() {
+    panic!("{}", 1);
+}
+
+#[no_mangle]
+#[cfg(c)]
+pub fn foo() {
+    panic!("{}", "a");
+}
+
+#[no_mangle]
+#[cfg(d)]
+pub fn foo() -> usize {
+    use std::cell::Cell;
+    thread_local!(static A: Cell<Vec<u32>> = Cell::new(Vec::new()));
+    A.try_with(|x| x.take().len()).unwrap_or(0)
+}
diff --git a/tests/run-make/wasm-spurious-import/Makefile b/tests/run-make/wasm-spurious-import/Makefile
new file mode 100644
index 00000000000..6f50e6e554e
--- /dev/null
+++ b/tests/run-make/wasm-spurious-import/Makefile
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) main.rs -C overflow-checks=yes -C panic=abort -C lto -C opt-level=z --target wasm32-unknown-unknown
+	$(NODE) verify.js $(TMPDIR)/main.wasm
diff --git a/tests/run-make/wasm-spurious-import/main.rs b/tests/run-make/wasm-spurious-import/main.rs
new file mode 100644
index 00000000000..fcbead5e28b
--- /dev/null
+++ b/tests/run-make/wasm-spurious-import/main.rs
@@ -0,0 +1,14 @@
+#![crate_type = "cdylib"]
+#![no_std]
+
+#[panic_handler]
+fn my_panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[no_mangle]
+pub fn multer(a: i128, b: i128) -> i128 {
+    // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported
+    // panic function in case of a bug. We verify that no imports exist in our verifier.
+    a * b
+}
diff --git a/tests/run-make/wasm-spurious-import/verify.js b/tests/run-make/wasm-spurious-import/verify.js
new file mode 100644
index 00000000000..d3b2101b662
--- /dev/null
+++ b/tests/run-make/wasm-spurious-import/verify.js
@@ -0,0 +1,9 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let imports = WebAssembly.Module.imports(m);
+console.log('imports', imports);
+assert.strictEqual(imports.length, 0);
diff --git a/tests/run-make/wasm-stringify-ints-small/Makefile b/tests/run-make/wasm-stringify-ints-small/Makefile
new file mode 100644
index 00000000000..2fa2c954d4a
--- /dev/null
+++ b/tests/run-make/wasm-stringify-ints-small/Makefile
@@ -0,0 +1,10 @@
+include ../../run-make-fulldeps/tools.mk
+
+ifeq ($(TARGET),wasm32-unknown-unknown)
+all:
+	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown
+	wc -c < $(TMPDIR)/foo.wasm
+	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "25000" ]
+else
+all:
+endif
diff --git a/tests/run-make/wasm-stringify-ints-small/foo.rs b/tests/run-make/wasm-stringify-ints-small/foo.rs
new file mode 100644
index 00000000000..7a947f013ad
--- /dev/null
+++ b/tests/run-make/wasm-stringify-ints-small/foo.rs
@@ -0,0 +1,33 @@
+#![crate_type = "cdylib"]
+
+extern "C" {
+    fn observe(ptr: *const u8, len: usize);
+}
+
+macro_rules! s {
+    ( $( $f:ident -> $t:ty );* $(;)* ) => {
+        $(
+            extern "C" {
+                fn $f() -> $t;
+            }
+            let s = $f().to_string();
+            observe(s.as_ptr(), s.len());
+        )*
+    };
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn foo() {
+    s! {
+        get_u8 -> u8;
+        get_i8 -> i8;
+        get_u16 -> u16;
+        get_i16 -> i16;
+        get_u32 -> u32;
+        get_i32 -> i32;
+        get_u64 -> u64;
+        get_i64 -> i64;
+        get_usize -> usize;
+        get_isize -> isize;
+    }
+}
diff --git a/tests/run-make/wasm-symbols-different-module/Makefile b/tests/run-make/wasm-symbols-different-module/Makefile
new file mode 100644
index 00000000000..9e657222dea
--- /dev/null
+++ b/tests/run-make/wasm-symbols-different-module/Makefile
@@ -0,0 +1,28 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+
+	$(RUSTC) baz.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/baz.wasm sqlite/allocate sqlite/deallocate
+
+	$(RUSTC) log.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/log.wasm test/log
diff --git a/tests/run-make/wasm-symbols-different-module/bar.rs b/tests/run-make/wasm-symbols-different-module/bar.rs
new file mode 100644
index 00000000000..7567060d781
--- /dev/null
+++ b/tests/run-make/wasm-symbols-different-module/bar.rs
@@ -0,0 +1,33 @@
+//! Issue #50021
+
+#![crate_type = "cdylib"]
+
+mod m1 {
+    #[link(wasm_import_module = "m1")]
+    extern "C" {
+        pub fn f();
+    }
+    #[link(wasm_import_module = "m1")]
+    extern "C" {
+        pub fn g();
+    }
+}
+
+mod m2 {
+    #[link(wasm_import_module = "m2")]
+    extern "C" {
+        pub fn f(_: i32);
+    }
+}
+
+#[no_mangle]
+pub unsafe fn run() {
+    m1::f();
+    m1::g();
+
+    // In generated code, expected:
+    // (import "m2" "f" (func $f (param i32)))
+    // but got:
+    // (import "m1" "f" (func $f (param i32)))
+    m2::f(0);
+}
diff --git a/tests/run-make/wasm-symbols-different-module/baz.rs b/tests/run-make/wasm-symbols-different-module/baz.rs
new file mode 100644
index 00000000000..fbb78619bb8
--- /dev/null
+++ b/tests/run-make/wasm-symbols-different-module/baz.rs
@@ -0,0 +1,22 @@
+//! Issue #63562
+
+#![crate_type = "cdylib"]
+
+mod foo {
+    #[link(wasm_import_module = "sqlite")]
+    extern "C" {
+        pub fn allocate(size: usize) -> i32;
+        pub fn deallocate(ptr: i32, size: usize);
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn allocate() {
+    unsafe {
+        foo::allocate(1);
+        foo::deallocate(1, 2);
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn deallocate() {}
diff --git a/tests/run-make/wasm-symbols-different-module/foo.rs b/tests/run-make/wasm-symbols-different-module/foo.rs
new file mode 100644
index 00000000000..a4ba7e714cc
--- /dev/null
+++ b/tests/run-make/wasm-symbols-different-module/foo.rs
@@ -0,0 +1,23 @@
+#![crate_type = "cdylib"]
+
+mod a {
+    #[link(wasm_import_module = "a")]
+    extern "C" {
+        pub fn foo();
+    }
+}
+
+mod b {
+    #[link(wasm_import_module = "b")]
+    extern "C" {
+        pub fn foo();
+    }
+}
+
+#[no_mangle]
+pub fn start() {
+    unsafe {
+        a::foo();
+        b::foo();
+    }
+}
diff --git a/tests/run-make/wasm-symbols-different-module/log.rs b/tests/run-make/wasm-symbols-different-module/log.rs
new file mode 100644
index 00000000000..ea3e0b4b2be
--- /dev/null
+++ b/tests/run-make/wasm-symbols-different-module/log.rs
@@ -0,0 +1,16 @@
+//! Issue #56309
+
+#![crate_type = "cdylib"]
+
+#[link(wasm_import_module = "test")]
+extern "C" {
+    fn log(message_data: u32, message_size: u32);
+}
+
+#[no_mangle]
+pub fn main() {
+    let message = "Hello, world!";
+    unsafe {
+        log(message.as_ptr() as u32, message.len() as u32);
+    }
+}
diff --git a/tests/run-make/wasm-symbols-different-module/verify-imports.js b/tests/run-make/wasm-symbols-different-module/verify-imports.js
new file mode 100644
index 00000000000..7e9f90cf8bd
--- /dev/null
+++ b/tests/run-make/wasm-symbols-different-module/verify-imports.js
@@ -0,0 +1,32 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.imports(m);
+console.log('imports', list);
+if (list.length !== process.argv.length - 3)
+  throw new Error("wrong number of imports")
+
+const imports = new Map();
+for (let i = 3; i < process.argv.length; i++) {
+  const [module, name] = process.argv[i].split('/');
+  if (!imports.has(module))
+    imports.set(module, new Map());
+  imports.get(module).set(name, true);
+}
+
+for (let i of list) {
+  if (imports.get(i.module) === undefined || imports.get(i.module).get(i.name) === undefined)
+    throw new Error(`didn't find import of ${i.module}::${i.name}`);
+  imports.get(i.module).delete(i.name);
+
+  if (imports.get(i.module).size === 0)
+    imports.delete(i.module);
+}
+
+console.log(imports);
+if (imports.size !== 0) {
+  throw new Error('extra imports');
+}
diff --git a/tests/run-make/wasm-symbols-not-exported/Makefile b/tests/run-make/wasm-symbols-not-exported/Makefile
new file mode 100644
index 00000000000..60b0dee001f
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-exported/Makefile
@@ -0,0 +1,13 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(NODE) verify-exported-symbols.js $(TMPDIR)/foo.wasm
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify-exported-symbols.js $(TMPDIR)/foo.wasm
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown
+	$(NODE) verify-exported-symbols.js $(TMPDIR)/bar.wasm
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify-exported-symbols.js $(TMPDIR)/bar.wasm
diff --git a/tests/run-make/wasm-symbols-not-exported/bar.rs b/tests/run-make/wasm-symbols-not-exported/bar.rs
new file mode 100644
index 00000000000..6ffbd3ec690
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-exported/bar.rs
@@ -0,0 +1,35 @@
+#![feature(panic_handler, alloc_error_handler)]
+#![crate_type = "cdylib"]
+#![no_std]
+
+use core::alloc::*;
+
+struct B;
+
+unsafe impl GlobalAlloc for B {
+    unsafe fn alloc(&self, x: Layout) -> *mut u8 {
+        1 as *mut u8
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, x: Layout) {
+    }
+}
+
+#[global_allocator]
+static A: B = B;
+
+#[no_mangle]
+pub extern fn foo(a: u32) -> u32 {
+    assert_eq!(a, 3);
+    a * 2
+}
+
+#[alloc_error_handler]
+fn a(_: core::alloc::Layout) -> ! {
+    loop {}
+}
+
+#[panic_handler]
+fn b(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/tests/run-make/wasm-symbols-not-exported/foo.rs b/tests/run-make/wasm-symbols-not-exported/foo.rs
new file mode 100644
index 00000000000..d46baee01b9
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-exported/foo.rs
@@ -0,0 +1,7 @@
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+pub extern fn foo() {
+    println!("foo");
+    panic!("test");
+}
diff --git a/tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js b/tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js
new file mode 100644
index 00000000000..afc8a7241f5
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js
@@ -0,0 +1,21 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.exports(m);
+console.log('exports', list);
+
+let bad = false;
+for (let i = 0; i < list.length; i++) {
+  const e = list[i];
+  if (e.name == "foo" || e.kind != "function")
+    continue;
+
+  console.log('unexpected exported symbol:', e.name);
+  bad = true;
+}
+
+if (bad)
+  process.exit(1);
diff --git a/tests/run-make/wasm-symbols-not-imported/Makefile b/tests/run-make/wasm-symbols-not-imported/Makefile
new file mode 100644
index 00000000000..dc7618c19a7
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-imported/Makefile
@@ -0,0 +1,13 @@
+include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
+	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
diff --git a/tests/run-make/wasm-symbols-not-imported/foo.rs b/tests/run-make/wasm-symbols-not-imported/foo.rs
new file mode 100644
index 00000000000..b25bdc9800d
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-imported/foo.rs
@@ -0,0 +1,14 @@
+#![crate_type = "cdylib"]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[no_mangle]
+pub extern fn foo() {
+    panic!()
+}
+
+#[panic_handler]
+fn panic(_info: &PanicInfo) -> ! {
+    loop {}
+}
diff --git a/tests/run-make/wasm-symbols-not-imported/verify-no-imports.js b/tests/run-make/wasm-symbols-not-imported/verify-no-imports.js
new file mode 100644
index 00000000000..90e3df1d98d
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-imported/verify-no-imports.js
@@ -0,0 +1,10 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.imports(m);
+console.log('imports', list);
+if (list.length !== 0)
+  throw new Error("there are some imports");
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
new file mode 100644
index 00000000000..84dcd239351
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
@@ -0,0 +1,23 @@
+include ../../run-make-fulldeps/tools.mk
+
+#only-x86_64-fortanix-unknown-sgx
+
+# For cargo setting
+export RUSTC := $(RUSTC_ORIGINAL)
+export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+export WORK_DIR := $(TMPDIR)
+export TEST_DIR := $(shell pwd)
+
+## clean up unused env variables which might cause harm.
+unexport RUSTC_LINKER
+unexport RUSTC_BOOTSTRAP
+unexport RUST_BUILD_STAGE
+unexport RUST_TEST_THREADS
+unexport RUST_TEST_TMPDIR
+unexport AR
+unexport CC
+unexport CXX
+
+all:
+	bash script.sh
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks
new file mode 100644
index 00000000000..e839c200bbb
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks
@@ -0,0 +1,8 @@
+CHECK: cc_plus_one_asm
+CHECK-NEXT: movl
+CHECK-NEXT: lfence
+CHECK-NEXT: inc
+CHECK-NEXT: notq (%rsp)
+CHECK-NEXT: notq (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks
new file mode 100644
index 00000000000..b93b33afb3f
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks
@@ -0,0 +1,6 @@
+CHECK: cc_plus_one_c
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks
new file mode 100644
index 00000000000..d1fae3d495f
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks
@@ -0,0 +1,15 @@
+CHECK: cc_plus_one_c_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks
new file mode 100644
index 00000000000..f96f152c02f
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks
@@ -0,0 +1,6 @@
+CHECK: cc_plus_one_cxx
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks
new file mode 100644
index 00000000000..e704bf41724
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cc_plus_one_cxx_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      movl
+CHECK:      lfence
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp     0x{{[[:xdigit:]]+}} <cc_plus_one_cxx_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks
new file mode 100644
index 00000000000..78b18ccbfcb
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks
@@ -0,0 +1,7 @@
+CHECK: cmake_plus_one_asm
+CHECK-NEXT: movl
+CHECK-NEXT: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks
new file mode 100644
index 00000000000..f551356b2ff
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks
@@ -0,0 +1,6 @@
+CHECK: cmake_plus_one_c
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks
new file mode 100644
index 00000000000..87c806f137a
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cmake_plus_one_c_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      movl
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp     0x{{[[:xdigit:]]+}} <cmake_plus_one_c_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks
new file mode 100644
index 00000000000..4b66cc5bc83
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: cmake_plus_one_c_global_asm
+CHECK: lfence
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks
new file mode 100644
index 00000000000..0f403e0203c
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks
@@ -0,0 +1,6 @@
+CHECK: cmake_plus_one_cxx
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks
new file mode 100644
index 00000000000..9cac8711ea8
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cmake_plus_one_cxx_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      movl
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp     0x{{[[:xdigit:]]+}} <cmake_plus_one_cxx_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
new file mode 100644
index 00000000000..d4a3d447901
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: cmake_plus_one_cxx_global_asm
+CHECK: lfence
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml
new file mode 100644
index 00000000000..3a97c37e951
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "enclave"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+
+[build-dependencies]
+cc = "1.0"
+cmake = "0.1"
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs
new file mode 100644
index 00000000000..3a7aa1be868
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs
@@ -0,0 +1,30 @@
+fn main() {
+    cc::Build::new()
+        .file("foo.c")
+        .compile("foo_c");
+
+    cc::Build::new()
+        .file("foo_asm.s")
+        .compile("foo_asm");
+
+    cc::Build::new()
+        .cpp(true)
+        .cpp_set_stdlib(None)
+        .file("foo_cxx.cpp")
+        .compile("foo_cxx");
+
+    // When the cmake crate detects the clang compiler, it passes the
+    //  "--target" argument to the linker which subsequently fails. The
+    //  `CMAKE_C_COMPILER_FORCED` option makes sure that `cmake` does not
+    //  tries to test the compiler. From version 3.6 the option
+    //  `CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY` can be used
+    //  https://cmake.org/cmake/help/v3.5/module/CMakeForceCompiler.html
+    let dst = cmake::Config::new("libcmake_foo")
+                .build_target("cmake_foo")
+                .define("CMAKE_C_COMPILER_FORCED", "1")
+                .define("CMAKE_CXX_COMPILER_FORCED", "1")
+                .define("CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY", "1")
+                .build();
+    println!("cargo:rustc-link-search=native={}/build/", dst.display());
+    println!("cargo:rustc-link-lib=static=cmake_foo");
+}
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c
new file mode 100644
index 00000000000..dd76d4f303a
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c
@@ -0,0 +1,18 @@
+int cc_plus_one_c(int *arg) {
+    return *arg + 1;
+}
+
+int cc_plus_one_c_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s
new file mode 100644
index 00000000000..6d56214e87e
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s
@@ -0,0 +1,7 @@
+    .text
+    .global cc_plus_one_asm
+    .type cc_plus_one_asm, @function
+cc_plus_one_asm:
+    movl (%rdi), %eax
+    inc %eax
+    retq
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp
new file mode 100644
index 00000000000..ac6f64ac413
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp
@@ -0,0 +1,21 @@
+extern "C" int cc_plus_one_cxx(int *arg);
+extern "C" int cc_plus_one_cxx_asm(int *arg);
+
+int cc_plus_one_cxx(int *arg) {
+    return *arg + 1;
+}
+
+int cc_plus_one_cxx_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt
new file mode 100644
index 00000000000..27cdf2ecf82
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt
@@ -0,0 +1,33 @@
+enable_language(C CXX ASM)
+
+set(C_SOURCES
+    src/foo.c
+    )
+
+set_source_files_properties(${C_SOURCES}
+                            PROPERTIES
+                            LANGUAGE C)
+
+set(CXX_SOURCES
+    src/foo_cxx.cpp
+    )
+
+set_source_files_properties(${CXX_SOURCES}
+                            PROPERTIES
+                            LANGUAGE CXX)
+
+set(ASM_SOURCES
+    src/foo_asm.s
+    )
+
+set_source_files_properties(${ASM_SOURCES}
+                            PROPERTIES
+                            LANGUAGE ASM)
+
+set(SOURCES
+    ${C_SOURCES}
+    ${CXX_SOURCES}
+    ${ASM_SOURCES})
+        
+add_library(cmake_foo STATIC
+    ${SOURCES})
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c
new file mode 100644
index 00000000000..c3b731a2d50
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c
@@ -0,0 +1,26 @@
+int cmake_plus_one_c(int *arg) {
+    return *arg + 1;
+}
+
+int cmake_plus_one_c_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
+
+asm(".text\n"
+"    .global cmake_plus_one_c_global_asm\n"
+"    .type cmake_plus_one_c_global_asm, @function\n"
+"cmake_plus_one_c_global_asm:\n"
+"    movl (%rdi), %eax\n"
+"    inc %eax\n"
+"    retq\n" );
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s
new file mode 100644
index 00000000000..64b6b430eea
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s
@@ -0,0 +1,7 @@
+    .text
+    .global cmake_plus_one_asm
+    .type cmake_plus_one_asm, @function
+cmake_plus_one_asm:
+    movl (%rdi), %eax
+    inc %eax
+    retq
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp
new file mode 100644
index 00000000000..824e2afebcc
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp
@@ -0,0 +1,29 @@
+extern "C" int cmake_plus_one_cxx(int *arg);
+extern "C" int cmake_plus_one_cxx_asm(int *arg);
+
+int cmake_plus_one_cxx(int *arg) {
+    return *arg + 1;
+}
+
+int cmake_plus_one_cxx_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
+
+asm(".text\n"
+"    .global cmake_plus_one_cxx_global_asm\n"
+"    .type cmake_plus_one_cxx_global_asm, @function\n"
+"cmake_plus_one_cxx_global_asm:\n"
+"    movl (%rdi), %eax\n"
+"    inc %eax\n"
+"    retq\n" );
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
new file mode 100644
index 00000000000..cde38aacf7f
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
@@ -0,0 +1,49 @@
+std::arch::global_asm!(
+    r#"
+    .text
+    .global rust_plus_one_global_asm
+    .type rust_plus_one_global_asm, @function
+rust_plus_one_global_asm:
+    movl (%rdi), %eax
+    inc %eax
+    retq
+"#,
+    options(att_syntax)
+);
+
+extern "C" {
+    fn cc_plus_one_c(arg: &u32) -> u32;
+    fn cc_plus_one_c_asm(arg: &u32) -> u32;
+    fn cc_plus_one_cxx(arg: &u32) -> u32;
+    fn cc_plus_one_cxx_asm(arg: &u32) -> u32;
+    fn cc_plus_one_asm(arg: &u32) -> u32;
+    fn cmake_plus_one_c(arg: &u32) -> u32;
+    fn cmake_plus_one_c_asm(arg: &u32) -> u32;
+    fn cmake_plus_one_cxx(arg: &u32) -> u32;
+    fn cmake_plus_one_cxx_asm(arg: &u32) -> u32;
+    fn cmake_plus_one_c_global_asm(arg: &u32) -> u32;
+    fn cmake_plus_one_cxx_global_asm(arg: &u32) -> u32;
+    fn cmake_plus_one_asm(arg: &u32) -> u32;
+    fn rust_plus_one_global_asm(arg: &u32) -> u32;
+}
+
+fn main() {
+    let value: u32 = 41;
+    let question = "Answer to the Ultimate Question of Life, the Universe, and Everything:";
+
+    unsafe {
+        println!("{}: {}!", question, rust_plus_one_global_asm(&value));
+        println!("{}: {}!", question, cc_plus_one_c(&value));
+        println!("{}: {}!", question, cc_plus_one_c_asm(&value));
+        println!("{}: {}!", question, cc_plus_one_cxx(&value));
+        println!("{}: {}!", question, cc_plus_one_cxx_asm(&value));
+        println!("{}: {}!", question, cc_plus_one_asm(&value));
+        println!("{}: {}!", question, cmake_plus_one_c(&value));
+        println!("{}: {}!", question, cmake_plus_one_c_asm(&value));
+        println!("{}: {}!", question, cmake_plus_one_cxx(&value));
+        println!("{}: {}!", question, cmake_plus_one_cxx_asm(&value));
+        println!("{}: {}!", question, cmake_plus_one_c_global_asm(&value));
+        println!("{}: {}!", question, cmake_plus_one_cxx_global_asm(&value));
+        println!("{}: {}!", question, cmake_plus_one_asm(&value));
+    }
+}
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks
new file mode 100644
index 00000000000..15211e3ade7
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks
@@ -0,0 +1,8 @@
+CHECK: libunwind::Registers_x86_64::jumpto
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks
new file mode 100644
index 00000000000..0fe88141b24
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks
@@ -0,0 +1,7 @@
+CHECK: print
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      popq
+CHECK:      callq 0x{{[[:xdigit:]]*}} <_Unwind_Resume>
+CHECK-NEXT: ud2
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks
new file mode 100644
index 00000000000..fe6777537fb
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: rust_plus_one_global_asm
+CHECK: lfence
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
new file mode 100644
index 00000000000..944343df6e5
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+set -exuo pipefail
+
+function build {
+    CRATE=enclave
+
+    mkdir -p $WORK_DIR
+    pushd $WORK_DIR
+        rm -rf $CRATE
+        cp -a $TEST_DIR/enclave .
+        pushd $CRATE
+            echo ${WORK_DIR}
+            # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
+            # These come from the top-level Rust workspace, that this crate is not a
+            # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
+            env RUSTC_BOOTSTRAP=1
+                cargo -v run --target $TARGET
+        popd
+    popd
+}
+
+function check {
+    local func=$1
+    local checks="${TEST_DIR}/$2"
+    local asm=$(mktemp)
+    local objdump="${BUILD_DIR}/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-objdump"
+    local filecheck="${BUILD_DIR}/x86_64-unknown-linux-gnu/llvm/build/bin/FileCheck"
+
+    ${objdump} --disassemble-symbols=${func} --demangle \
+      ${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave > ${asm}
+    ${filecheck} --input-file ${asm} ${checks}
+}
+
+build
+
+check unw_getcontext unw_getcontext.checks
+check "libunwind::Registers_x86_64::jumpto()" jumpto.checks
+check "std::io::stdio::_print::h87f0c238421c45bc" print.checks
+check rust_plus_one_global_asm rust_plus_one_global_asm.checks \
+  || echo "warning: module level assembly currently not hardened"
+
+check cc_plus_one_c cc_plus_one_c.checks
+check cc_plus_one_c_asm cc_plus_one_c_asm.checks
+check cc_plus_one_cxx cc_plus_one_cxx.checks
+check cc_plus_one_cxx_asm cc_plus_one_cxx_asm.checks
+check cc_plus_one_asm cc_plus_one_asm.checks \
+  || echo "warning: the cc crate forwards assembly files to the CC compiler." \
+           "Clang uses its own integrated assembler, which does not include the LVI passes."
+
+check cmake_plus_one_c cmake_plus_one_c.checks
+check cmake_plus_one_c_asm cmake_plus_one_c_asm.checks
+check cmake_plus_one_c_global_asm cmake_plus_one_c_global_asm.checks \
+  || echo "warning: module level assembly currently not hardened"
+check cmake_plus_one_cxx cmake_plus_one_cxx.checks
+check cmake_plus_one_cxx_asm cmake_plus_one_cxx_asm.checks
+check cmake_plus_one_cxx_global_asm cmake_plus_one_cxx_global_asm.checks \
+  || echo "warning: module level assembly currently not hardened"
+check cmake_plus_one_asm cmake_plus_one_asm.checks
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks
new file mode 100644
index 00000000000..4b7615b115d
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks
@@ -0,0 +1,6 @@
+CHECK: unw_getcontext
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq