load("@prelude//platforms:defs.bzl", "host_configuration")
load("//build:bench.bzl", "rust_benchmark")

rust_library(
    name = "mem-mmu",
    srcs = glob(["src/**/*.rs"]),
    deps = [
        "//lib/mem-core:mem-core",
        "//lib/arrayvec:arrayvec",
        "//third-party:log",
    ],
    visibility = ["PUBLIC"],
)

# Tests live in `tests/` as out-of-crate integration tests so they can depend on the
# std-backed `mem-testkit` harness (which depends on `mem-mmu`) without a cycle. They see
# only the public API.
_TEST_DEPS = [
    ":mem-mmu",
    "//lib/mem-core:mem-core",
    "//lib/mem-testkit:mem-testkit",
    "//third-party:proptest",
    "//third-party:test-log",
    "//third-party:tracing-subscriber",
]

_TEST_ENV = {
    # miri blocks getcwd so we need to disable proptest's getcwd-based failure persistence.
    "PROPTEST_DISABLE_FAILURE_PERSISTENCE": "true",
}

rust_test(
    name = "flush_tests",
    srcs = ["tests/flush.rs"],
    crate_root = "tests/flush.rs",
    deps = _TEST_DEPS,
    env = _TEST_ENV,
    target_compatible_with = [host_configuration.os, host_configuration.cpu],
    visibility = ["PUBLIC"],
)

rust_test(
    name = "utils_tests",
    srcs = ["tests/utils.rs"],
    crate_root = "tests/utils.rs",
    deps = _TEST_DEPS,
    env = _TEST_ENV,
    target_compatible_with = [host_configuration.os, host_configuration.cpu],
    visibility = ["PUBLIC"],
)

rust_test(
    name = "table_tests",
    srcs = ["tests/table.rs"],
    crate_root = "tests/table.rs",
    deps = _TEST_DEPS,
    env = _TEST_ENV,
    target_compatible_with = [host_configuration.os, host_configuration.cpu],
    visibility = ["PUBLIC"],
)

rust_test(
    name = "address_space_tests",
    srcs = ["tests/address_space.rs"],
    crate_root = "tests/address_space.rs",
    deps = _TEST_DEPS,
    env = _TEST_ENV,
    target_compatible_with = [host_configuration.os, host_configuration.cpu],
    visibility = ["PUBLIC"],
)

# Host-only criterion micro-benchmarks for the page-table walk. Uses a flat,
# raw-pointer `Arch` backend (see benches/walk.rs) rather than the `mem-testkit`
# emulator so the walk's bookkeeping — not emulation overhead — is what's timed.
rust_benchmark(
    name = "mem-mmu_benchmarks",
    srcs = ["benches/walk.rs"],
    crate_root = "benches/walk.rs",
    deps = [
        ":mem-mmu",
        "//lib/mem-core:mem-core",
        "//lib/mem-testkit:mem-testkit",
        "//third-party:criterion",
    ],
    visibility = ["PUBLIC"],
)
