mlugg 9c3670fc93
compiler: implement analysis-local comptime-mutable memory
This commit changes how we represent comptime-mutable memory
(`comptime var`) in the compiler in order to implement the intended
behavior that references to such memory can only exist at comptime.

It does *not* clean up the representation of mutable values, improve the
representation of comptime-known pointers, or fix the many bugs in the
comptime pointer access code. These will be future enhancements.

Comptime memory lives for the duration of a single Sema, and is not
permitted to escape that one analysis, either by becoming runtime-known
or by becoming comptime-known to other analyses. These restrictions mean
that we can represent comptime allocations not via Decl, but with state
local to Sema - specifically, the new `Sema.comptime_allocs` field. All
comptime-mutable allocations, as well as any comptime-known const allocs
containing references to such memory, live in here. This allows for
relatively fast checking of whether a value references any
comptime-mtuable memory, since we need only traverse values up to
pointers: pointers to Decls can never reference comptime-mutable memory,
and pointers into `Sema.comptime_allocs` always do.

This change exposed some faulty pointer access logic in `Value.zig`.
I've fixed the important cases, but there are some TODOs I've put in
which are definitely possible to hit with sufficiently esoteric code. I
plan to resolve these by auditing all direct accesses to pointers (most
of them ought to use Sema to perform the pointer access!), but for now
this is sufficient for all realistic code and to get tests passing.

This change eliminates `Zcu.tmp_hack_arena`, instead using the Sema
arena for comptime memory mutations, which is possible since comptime
memory is now local to the current Sema.

This change should allow `Decl` to store only an `InternPool.Index`
rather than a full-blown `ty: Type, val: Value`. This commit does not
perform this refactor.
2024-03-25 14:49:41 +00:00
..

Test Case Quick Reference

Use comments at the end of the file to indicate metadata about the test case. Here are examples of different kinds of tests:

Compile Error Test

If you want it to be run with zig test and match expected error messages:

// error
// is_test=true
//
// :4:13: error: 'try' outside function scope

Execution

This will do zig run on the code and expect exit code 0.

// run

Translate-c

If you want to test translating C code to Zig use translate-c:

// translate-c
// c_frontend=aro,clang
// target=x86_64-linux
//
// pub const foo = 1;
// pub const immediately_after_foo = 2;
//
// pub const somewhere_else_in_the_file = 3:

Run Translated C

If you want to test translating C code to Zig and then executing it use run-translated-c:

// run-translated-c
// c_frontend=aro,clang
// target=x86_64-linux
//
// Hello world!

Incremental Compilation

Make multiple files that have ".", and then an integer, before the ".zig" extension, like this:

hello.0.zig
hello.1.zig
hello.2.zig

Each file can be a different kind of test, such as expecting compile errors, or expecting to be run and exit(0). The test harness will use these to simulate incremental compilation.

At the time of writing there is no way to specify multiple files being changed as part of an update.

Subdirectories

Subdirectories do not have any semantic meaning but they can be used for organization since the test harness will recurse into them. The full directory path will be prepended as a prefix on the test case name.

Limiting which Backends and Targets are Tested

// run
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos

Possible backends are:

  • stage1: equivalent to -fstage1.
  • stage2: equivalent to passing -fno-stage1 -fno-LLVM.
  • llvm: equivalent to -fLLVM -fno-stage1.