* introduce a dump() function on Module.Fn which helpfully prints to
stderr the ZIR representation of a function (can be called before
attempting to codegen it). This is a debugging tool.
* implement x86 codegen for loops
* liveness: fix analysis of conditional branches. The logic was buggy
in a couple ways:
- it never actually saved the results into the IR instruction (fixed now)
- it incorrectly labeled operands as dying when their true death was
after the conditional branch ended (fixed now)
* zir rendering is enhanced to show liveness analysis results. this
helps when debugging liveness analysis.
* fix bug in zir rendering not numbering instructions correctly
closes#6021
* `optimize_mode` is passed to `link.File` and stored there
* improve the debugging function `Module.dumpInst`
* get rid of `Value.the_one_possible_value` in favor of a few more
specific values for different types. This is less buggy, one less
footgun.
* `Type.onePossibleValue` now returns a `?Value` instead of `bool`.
* codegen handles undefined values. `undef` is a new `MCValue` tag.
It uses 0xaa values depending on optimization mode. However
optimization mode does not yet support scope overrides.
* link.zig: move the `Options` field from `File.Elf` and `File.C` to
the base struct.
- fix the Tag enum to adhere to style conventions
* ZIR now supports emitting undefined values.
* Fix the logic of comptime math to properly compare against zero using
the `compareWithZero` function.
* implement sema for runtime deref, store pointer, coerce_to_ptr_elem,
and store
* identifiers support being lvalues, except for decls is still TODO
* codegen supports load, store, ref, alloc
* introduce more MCValue union tags to support pointers
* add load, ref, store typed IR instructions
* add Type.isVolatilePtr
Comment out non-x86_64 architectures for now in codegen.zig, because
they all have compile errors for their codepaths anyway, and it was
bloating the compilation speed and memory usage when stage1 tried to
build self-hosted. Here's the panic message:
"Backend architectures that don't have good support yet are commented
out, to improve compilation performance. If you are interested in one
of these other backends feel free to uncomment them. Eventually these
will be completed, but stage1 is slow and a memory hog."
This is a workaround to lower the time it takes to build self-hosted
with stage1 as well as use less memory. It should fix the CI.
Additionally:
* Add `single_mut_pointer` support to `Type`
* Trivial implementation of stack allocation in codegen.zig. It does
not deal with freeing yet, and it's missing the stack pointer
adjustment prologue.
* Add the `alloc` IR instruction and semantic analysis for `alloc` ZIR
instruction.
These are now supported enough that this example code hits the
limitations of the register allocator:
fn add(a: u32, b: u32) void {
const c = a + b; // 7
const d = a + c; // 10
const e = d + b; // 14
assert(e == 14);
}
// error: TODO implement copyToNewRegister
So now the next step is to implement register allocation as planned.
* Take advantage of coercing anonymous struct literals to struct types.
* Reworks Module to favor Zig source as the primary use case.
Breaks ZIR compilation, which will have to be restored in a future commit.
* Decl uses src_index rather then src, pointing to an AST Decl node
index, or ZIR Module Decl index, rather than a byte offset.
* ZIR instructions have an `analyzed_inst` field instead of Module
having a hash table.
* Module.Fn loses the `fn_type` field since it is redundant with
its `owner_decl` `TypedValue` type.
* Implement Type and Value copying. A ZIR Const instruction's TypedValue
is copied to the Decl arena during analysis, which allows freeing the
ZIR text instructions post-analysis.
* Don't flush the ELF file if there are compilation errors.
* Function return types allow arbitrarily complex expressions.
* AST->ZIR for function calls and return statements.
After this commit there are no more bit rotted files.
The testing program that was in ir.zig has been moved to main.zig
Unsupported command line options have been deleted, or error messages
added.
The compiler repl is available from the build-exe, build-lib,
build-obj commands with the --watch option.
The main zig build script now builds the self-hosted compiler
unconditionally. Linking against LLVM is behind a -Denable-llvm
flag that defaults to off.
* add TypedValue.Managed which represents a Type, a Value, and some
kind of memory management strategy.
* introduce an analysis queue
* flesh out how incremental compilation works with respect to exports
* ir.text.Module is only capable of one error message during parsing
* link.zig no longer has a decl table map and instead has structs that
exist directly on ir.Module.Decl and ir.Module.Export
* implement primitive .text block allocation
* implement linker code for updating Decls and Exports
* implement null Type
Some supporting std lib changes:
* add std.ArrayList.appendSliceAssumeCapacity
* add std.fs.File.copyRange and copyRangeAll
* fix std.HashMap having modification safety on in ReleaseSmall builds
* add std.HashMap.putAssumeCapacityNoClobber
* introduce std.ArrayListUnmanaged for when you have the allocator
stored elsewhere
* move std.heap.ArenaAllocator implementation to its own file. extract
the main state into std.heap.ArenaAllocator.State, which can be
stored as an alternative to storing the entire ArenaAllocator, saving
24 bytes per ArenaAllocator on 64 bit targets.
* std.LinkedList.Node pointer field now defaults to being null
initialized.
* Rework self-hosted compiler Package API
* Delete almost all the bitrotted self-hosted compiler code. The only bit
rotted code left is in main.zig and compilation.zig
* Add call instruction to ZIR
* self-hosted compiler ir API and link API are reworked to support
a long-running compiler that incrementally updates declarations
* Introduce the concept of scopes to ZIR semantic analysis
* ZIR text format supports referencing named decls that are declared
later in the file
* Figure out how memory management works for the long-running compiler
and incremental compilation. The main roots are top level
declarations. There is a table of decls. The key is a cryptographic
hash of the fully qualified decl name. Each decl has an arena
allocator where all of the memory related to that decl is stored.
Each code block has its own arena allocator for the lifetime of
the block. Values that want to survive when going out of scope in
a block must get copied into the outer block. Finally, values must
get copied into the Decl arena to be long-lived.
* Delete the unused MemoryCell struct. Instead, comptime pointers are
based on references to Decl structs.
* Figure out how caching works. Each Decl will store a set of other
Decls which must be recompiled when it changes.
This branch is still work-in-progress; this commit breaks the build.
Now there are 3 types:
* std.math.big.int.Const
- the memory is immutable, only stores limbs and is_positive
- all methods operating on constant data go here
* std.math.big.int.Mutable
- the memory is mutable, stores capacity in addition to limbs and
is_positive
- methods here have some Mutable parameters and some Const
parameters. These methods expect callers to pre-calculate the
amount of resources required, and asserts that the resources are
available.
* std.math.big.int.Managed
- the memory is mutable and additionally stores an allocator.
- methods here perform the resource calculations for the programmer.
- this is the high level abstraction from before
Each of these 3 types can be converted to the other ones.
You can see the use case for this in the self-hosted compiler, where we
only store limbs, and construct the big ints as needed.
This gets rid of the hack where the allocator was optional and the
notion of "fixed" versions of the struct. Such things are now modeled
with the `big.int.Const` type.