When adding test coverage, I noticed an inconsistency in which source
location the compile error was pointing to for `@embedFile` errors vs
`@import` errors. They now both point to the same place, the string
operand.
closes#9404closes#9939
* Introduce a mechanism into Sema for emitting a compile error when an
integer is too big and we need it to fit into a usize.
* Add `@intCast` where necessary
* link/MachO: fix an unnecessary allocation when all that was happening
was appending zeroes to an ArrayList.
* Add `error.Overflow` as a possible error to some codepaths, allowing
usage of `math.intCast`.
closes#9710
This is a breaking change. Before, usage looked like this:
```zig
const held = mutex.acquire();
defer held.release();
```
Now it looks like this:
```zig
mutex.lock();
defer mutex.unlock();
```
The `Held` type was an idea to make mutexes slightly safer by making it
more difficult to forget to release an aquired lock. However, this
ultimately caused more problems than it solved, when any data structures
needed to store a held mutex. Simplify everything by reducing the API
down to the primitives: lock() and unlock().
Closes#8051Closes#8246Closes#10105
These calls are all late-initialization of ArrayList's that were initialized outside the current scope. This allows us to still get the potential memory-saving benefits of the 'precision' of initCapacity.
* test_functions: properly add dependencies of the array on test
functions and test names so that the order comes out correctly.
* fix lowering of struct literals to add parentheses around the type
name.
* omit const qualifier in slices because otherwise slices cannot be
reassigned even when they are local variables.
* special case pointer to functions and double pointer to functions in
renderTypeAndName. This code will need to be cleaned up but for now
it helps us make progress on other C backend stuff.
* fix slice element access to lower to `.ptr[` instead of `[`.
* airSliceElemVal: respect volatile slices
The way `zig test` works is that it uses a stand-in
var test_functions: []const TestFn = undefined;
during semantic analysis, but then just before codegen, it swaps out the
value with a constant like this:
const test_functions: []const TestFn = .{foo, bar, baz, etc};
Before this commit, the `Module.Variable` associated with the stand-in
value was leaked; now it is properly cleaned up before being replaced.
The main problem that motivated these changes is that global constants
which are referenced by pointer would not be emitted into the binary.
This happened because `semaDecl` did not add `codegen_decl` tasks for
global constants, instead relying on the constant values being copied as
necessary. However when the global constants are referenced by pointer,
they need to be sent to the linker to be emitted.
After making global const arrays, structs, and unions get emitted, this
uncovered a latent issue: the anonymous decls that they referenced would
get garbage collected (via `deleteUnusedDecl`) even though they would
later be referenced by the global const.
In order to solve this problem, I introduced `anon_work_queue` which is
the same as `work_queue` except a lower priority. The `codegen_decl`
task for anon decls goes into the `anon_work_queue` ensuring that the
owner decl gets a chance to mark its anon decls as alive before they are
possibly deleted.
This caused a few regressions, which I made the judgement call to add
workarounds for. Two steps forward, one step back, is still progress.
The regressions were:
* Two behavior tests having to do with unions. These tests were
intentionally exercising the LLVM constant value lowering, however,
due to the bug with garbage collection that was fixed in this commit,
the LLVM code was not getting exercised, and union types/values were
not implemented correctly, due to me forgetting that LLVM does not
allow bitcasting aggregate values.
- This is worked around by allowing those 2 test cases to regress,
moving them to the "passing for stage1 only" section.
* The test-stage2 test cases (in test/cases/*) for non-LLVM backends
previously did not have any calls to lower struct values, but now
they do. The code that was there was just `@panic("TODO")`. I
replaced that code with a stub that generates the wrong value. This
is an intentional miscompilation that will obviously need to get
fixed before any struct behavior tests pass. None of the current
tests we have exercise loading any values from these global const
structs, so there is not a problem until we try to improve these
backends.
* Fix backend using wrong union field of the slice instruction.
* LLVM backend properly sets alignment on global variables.
* Sema: add coercion for *T to *[1]T
* Sema: pointers to Decls with explicit alignment now have alignment
metadata in them.
After a discussion about language specs, this seems like the best way to
go, because it's simpler to reason about both for humans and compilers.
The `bitcast_result_ptr` ZIR instruction is no longer needed.
This commit also implements writing enums, arrays, and vectors to
virtual memory at compile-time.
This unlocked some more of compiler-rt being able to build, which
in turn unlocks saturating arithmetic behavior tests.
There was also a memory leak in the comptime closure system which is now
fixed.
* Sema: fix returned operands not coercing to the function return type
in some cases.
- When returning an error or an error union from a function with an
inferred error set, it will now populate the inferred error set.
- Implement error set coercion for the common case of inferred error
set to inferred error set, without forcing a full resolution.
* LLVM backend: update instruction lowering that handles error unions
to respect `isByRef`.
- Also implement `wrap_err_union_err`.
* Relax compile error for "unable to export type foo" to allow
integers, structs, arrays, and floats. This will need to be further
improved to do the same checks as we do for C ABI struct field types.
* LLVM backend: fix extern variables
* LLVM backend: implement AIR instruction `wrap_err_union_payload`
* Sema: implement peer type resolution for optionals and null.
* Rename `Module.optionalType` to `Type.optional`.
* LLVM backend: re-use anonymous values. This is especially useful when
isByRef()=true because it means re-using the same generated LLVM globals.
* LLVM backend: rework the implementation of is_null and is_non_null
AIR instructions. Generate slightly better LLVM code, and also fix
the behavior for optionals whose payload type is 0-bit.
* LLVM backend: improve `cmp` AIR instruction lowering to support
pointer-like optionals.
* `Value`: implement support for equality-checking optionals.
* `Module.Union.getFullyQualifiedName` returns a sentinel-terminated
slice so that backends that need null-termination do not need an
additional copy.
* Module.Union: implement a `getLayout` function which returns
information about ABI size and alignment so that the LLVM backend can
properly lower union types into llvm types.
* Sema: `resolveType` now returns `error.GenericPoison` rather than a
Type with tag `generic_poison`. Callsites that want to allow that
need to bypass this higher-level function.
* Sema: implement coercion of enums and enum literals to unions.
* Sema: fix comptime mutation of pointers to unions
* LLVM backend: fully implement proper lowering of union types and
values according to the union layout, and update the handling of AIR
instructions that deal with unions to support union layouts.
* LLVM backend: handle `decl_ref_mut`
- Maybe this should be unreachable since comptime vars should be
changed to be non-mutable when they go out of scope, but it's
harmless for the LLVM backend to support lowering the value.
* Type: fix `requiresComptime` for optionals, pointers, and some other
types. This function is still wrong for structs, unions, and enums.
* ZIR: the `array_type_sentinel` now has a source node attached to it
for proper error reporting.
* Refactor: move `Module.arrayType` to `Type.array`
* Value: the `bytes` and `array` tags now include the sentinel, if the
type has one. This simplifies comptime evaluation logic.
* Sema: fix `zirStructInitEmpty` to properly handle when the type is
void or a sentinel-terminated array. This handles the syntax `void{}`
and `[0:X]T{}`.
* Sema: fix the logic for reporting "cannot store runtime value in
compile time variable" as well as for emitting a runtime store when a
pointer value is comptime known but it is a global variable.
* Sema: implement elemVal for double pointer to array. This can happen
with this code for example: `var a: *[1]u8 = undefined; _ = a[0];`
* Sema: Rework the `storePtrVal` function to properly handle nested
structs and arrays.
- Also it now handles comptime stores through a bitcasted pointer.
When the pointer element type and the type according to the Decl
don't match, the element value is bitcasted before storage.
* Add AIR instructions: ret_ptr, ret_load
- This allows Sema to be blissfully unaware of the backend's decision
to implement by-val/by-ref semantics for struct/union/array types.
Backends can lower these simply as alloc, load, ret instructions,
or they can take advantage of them to use a result pointer.
* Add AIR instruction: array_elem_val
- Allows for better codegen for `Sema.elemVal`.
* Implement calculation of ABI alignment and ABI size for unions.
* Before appending the following AIR instructions to a block,
resolveTypeLayout is called on the type:
- call - return type
- ret - return type
- store_ptr - elem type
* Sema: fix memory leak in `zirArrayInit` and other cleanups to this
function.
* x86_64: implement the full x86_64 C ABI according to the spec
* Type: implement `intInfo` for error sets.
* Type: implement `intTagType` for tagged unions.
The Zig type tag `Fn` is now used exclusively for function bodies.
Function pointers are modeled as `*const T` where `T` is a `Fn` type.
* The `call` AIR instruction now allows a function pointer operand as
well as a function operand.
* Sema now has a coercion from function body to function pointer.
* Function type syntax, e.g. `fn()void`, now returns zig tag type of
Pointer with child Fn, rather than Fn directly.
- I think this should probably be reverted. Will discuss the lang
specs before doing this. Idea being that function pointers would
need to be specified as `*const fn()void` rather than `fn() void`.
LLVM backend:
* Enable calling the panic handler (previously this just
emitted `@breakpoint()` since the backend could not handle the panic
function).
* Implement sret
* Introduce `isByRef` and implement it for structs and arrays. Types
that are `isByRef` are now passed as pointers to functions, and e.g.
`elem_val` will return a pointer instead of doing a load.
* Move the function type creating code from `resolveLlvmFunction` to
`llvmType` where it belongs; now there is only 1 instance of this
logic instead of two.
* Add the `nonnull` attribute to non-optional pointer parameters.
* Fix `resolveGlobalDecl` not using fully-qualified names and not using
the `decl_map`.
* Implement `genTypedValue` for pointer-like optionals.
* Fix memory leak when lowering `block` instruction and OOM occurs.
* Implement volatile checks where relevant.
* AIR instructions struct_field_ptr and related functions now are also
emitted by the frontend for unions. Backends must inspect the type
of the pointer operand to lower the instructions correctly.
- These will be renamed to `agg_field_ptr` (short for "aggregate") in
the future.
* Introduce the new `set_union_tag` AIR instruction.
* Introduce `Module.EnumNumbered` and associated `Type` methods. This
is for enums which have no decls, but do have the possibility of
overriding the integer tag type and tag values.
* Sema: Implement support for union tag types in both the
auto-generated and explicitly-provided cases, as well as explicitly
provided enum tag values in union declarations.
* LLVM backend: implement lowering union types, union field pointer
instructions, and the new `set_union_tag` instruction.
Introduce an explicit decl_map for *Decl to LLVMValueRef. Doc comment
reproduced here:
Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to
LLVM function, but that has some downsides:
* we have to compute the fully qualified name every time we want to do the lookup
* for externally linked functions, the name is not fully qualified, but when
a Decl goes from exported to not exported and vice-versa, we would use the wrong
version of the name and incorrectly get function not found in the llvm module.
* it works for functions not all globals.
Therefore, this table keeps track of the mapping.
Non-exported functions now use fully-qualified symbol names.
`Module.Decl.getFullyQualifiedName` now returns a sentinel-terminated
slice which is useful to pass to LLVMAddFunction.
Instead of using aliases for all external symbols, now the LLVM backend
takes advantage of LLVMSetValueName to rename functions that become
exported. Aliases are still used for the second and remaining exports.
freeDecl is now handled properly in the LLVM backend, deleting the
LLVMValueRef corresponding to the Decl being deleted. The linker
backends for ELF, COFF, Mach-O, and Wasm had to be updated to forward
the freeDecl call to the LLVM backend.
* `Type.hasCodeGenBits` this function is used to find out if it ever
got sent to a linker backend for lowering. In the case that a struct
never has its struct fields resolved, this will be false. In such a
case, no corresponding `freeDecl` needs to be issued to the linker
backend. So instead of asserting the fields of a struct are resolved,
this function now returns `false` for this case.
* `Module.clearDecl` there was logic that asserted when there is no
outdated_decls map, any dependants of a Decl being cleared had to be
in the deletion set. However there is a possible scenario where the
dependant is not in the deletion set *yet* because there is a Decl
which depends on it, about to be deleted. If it were added to an
outdated_decls map, it would be subsequently removed from the map
when it gets deleted recursively through its dependency being
deleted.
These issues were uncovered via unrelated changes which are the two
commits immediately preceding this one.
* prepare compiler-rt to support being compiled by stage2
- put in a few minor workarounds that will be removed later, such as
using `builtin.stage2_arch` rather than `builtin.cpu.arch`.
- only try to export a few symbols for now - we'll move more symbols
over to the "working in stage2" section as they become functional
and gain test coverage.
- use `inline fn` at function declarations rather than `@call` with an
always_inline modifier at the callsites, to avoid depending on the
anonymous array literal syntax language feature (for now).
* AIR: replace floatcast instruction with fptrunc and fpext for
shortening and widening floating point values, respectively.
* Introduce a new ZIR instruction, `export_value`, which implements
`@export` for the case when the thing to be exported is a local
comptime value that points to a function.
- AstGen: fix `@export` not properly reporting ambiguous decl
references.
* Sema: handle ExportOptions linkage. The value is now available to all
backends.
- Implement setting global linkage as appropriate in the LLVM
backend. I did not yet inspect the LLVM IR, so this still needs to
be audited. There is already a pending task to make sure the alias
stuff is working as intended, and this is related.
- Sema almost handles section, just a tiny bit more code is needed in
`resolveExportOptions`.
* Sema: implement float widening and shortening for both `@floatCast`
and float coercion.
- Implement the LLVM backend code for this as well.
Previously, linker backends or machine code backends were able to hold
on to references to inside Sema's temporary arena. However there can
be large objects stored there that we want to free after machine code is
generated.
The primary change in this commit is to use a temporary arena for Sema
of function bodies that gets freed after machine code backend finishes
handling `updateFunc` (at the same time that Air and Liveness get freed).
The other changes in this commit are fixing issues that fell out from
the primary change.
* The C linker backend is rewritten to handle updateDecl and updateFunc
separately. Also, all Decl updates get access to typedefs and
fwd_decls, not only functions.
* The C linker backend is updated to the new API that does not depend
on allocateDeclIndexes and does not have to handle garbage collected
decls.
* The C linker backend uses an arena for Type/Value objects that
`typedefs` references. These can be garbage collected every so often
after flush(), however that garbage collection code is not
implemented at this time. It will be pretty simple, just allocate a
new arena, copy all the Type objects to it, update the keys of the
hash map, free the old arena.
* Sema: fix a handful of instances of not copying Type/Value objects
from the temporary arena into the appropriate Decl arena.
* Type: fix some function types not reporting hasCodeGenBits()
correctly.
This is a property which solely belongs to pointers to functions,
not to the functions themselves. This cannot be properly represented by
stage 2 at the moment, as type with zigTypeTag() == .Fn is overloaded for
for function pointers and function prototypes.
Validity checks are also based on context; whether the entity being validated
is a mutable/constant value, a pointer (that is ascripted with an addrspace
attribute) or a function with an addrspace attribute. Error messages are
relatively simple for now.