370 Commits

Author SHA1 Message Date
Robin Voetter
a2958a4ede stage2: allow multiple inferred error sets per Fn
This allows the inferred error set of comptime and inline invocations to be
resolved separately from the inferred error set of the runtime version or other
comptime/inline invocations.
2021-12-21 01:41:50 +01:00
Robin Voetter
b2343e63bd stage2: move inferred error set state into func 2021-12-21 01:41:50 +01:00
Robin Voetter
cd733ceb85 stage2: replace ErrorSet and ErrorSetMerged arrays with hash maps 2021-12-21 01:41:50 +01:00
Andrew Kelley
274555be21 stage2: improve handling of the generated file builtin.zig
All Zig code is eligible to `@import("builtin")` which is mapped to a
generated file, build.zig, based on the target and other settings.

Zig invocations which share the same target settings will generate the
same builtin.zig file and thus the path to builtin.zig is in a shared
cache folder, and different projects can sometimes use the same file.

Before this commit, this led to race conditions where multiple
invocations of `zig` would race to write this file. If one process
wanted to *read* the file while the other process *wrote* the file, the
reading process could observe a truncated or partially written
builtin.zig file.

This commit makes the following improvements:
 - limitations:
   - avoid clobbering the inode, mtime in the hot path
   - avoid creating a partially written file
   - builtin.zig needs to be on disk for debug info / stack trace purposes
   - don't mark the task as complete until the file is finished being populated
     (possibly by an external process)
 - strategy:
   - create the `@import("builtin")` `Module.File` during the AstGen
     work, based on generating the contents in memory rather than
     loading from disk.
   - write builtin.zig in a separate task that doesn't have
     to complete until the end of the AstGen work queue so that it
     can be done in parallel with everything else.
   - when writing the file, first stat the file path. If it exists, we are done.
   - otherwise, write the file to a temp file in the same directory and atomically
     rename it into place (clobbering the inode, mtime in the cold path).
 - summary:
   - all limitations respected
   - hot path: one stat() syscall that happens in a worker thread

This required adding a missing function to the standard library:
`std.fs.Dir.statFile`. In this commit, it does open() and then fstat()
which is two syscalls. It should be improved in a future commit to only
make one.

Fixes #9439.
2021-12-06 23:30:18 -08:00
Andrew Kelley
ca974de521 stage2: fix double-free when error reading cached ZIR
We already had a `keep_zir` flag. No need to call deinit manually.
2021-12-06 14:29:49 -07:00
Luuk de Gram
9e03cf9489 wasm: Initial behavior tests succeeding
- Correctly load slice value on stack
- Implement WrapErrorUnionErr and payload
- Implement trunc, fix sliceLen and write undefined
- Implement slice as return type and argument

Note: This also fixes a memory leak for inferred error sets, and for usingnamespace
2021-12-05 12:19:01 -08:00
Andrew Kelley
f7cbd92e6c Revert "Merge pull request #10270 from Luukdegram/behaviour-tests"
This reverts commit 725267f7c20f0ba588b472048a8c1fe1a328c714, reversing
changes made to 2dae860de3494f97c9477af9282fe0131ff5c4cb.

This test is failing:

```zig
pub fn main() u8 {
    var e = foo();
    const i = e catch 69;
    return i;
}

fn foo() anyerror!u8 {
    return 5;
}
```

It's returning 69 instead of the expected value 5.
2021-12-04 21:55:50 -07:00
Luuk de Gram
74a5f4d848
wasm: Initial behavior tests succeeding
Note: This also fixes a memory leak for inferred error sets, and for usingnamespace
2021-12-04 21:17:17 +01:00
Lee Cannon
67ec6e73fb
allocgate: use correct allocator in populateTestFunctions 2021-12-01 10:24:03 +00:00
Lee Cannon
1093b09a98
allocgate: renamed getAllocator function to allocator 2021-11-30 23:32:47 +00:00
Lee Cannon
75548b50ff
allocgate: stage 1 and 2 building 2021-11-30 23:32:47 +00:00
Lee Cannon
85de022c56
allocgate: std Allocator interface refactor 2021-11-30 23:32:47 +00:00
Andrew Kelley
902df103c6 std lib API deprecations for the upcoming 0.9.0 release
See #3811
2021-11-30 00:13:07 -07:00
Andrew Kelley
b560f46c87 stage2: fix unwrap function call with optional pointer return value 2021-11-24 22:44:33 -07:00
Andrew Kelley
e266ede6e3 stage2: fix cleanup code for @import errors
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 #9404
closes #9939
2021-11-24 19:10:58 -07:00
Andrew Kelley
fdcac5ecbd stage2: add cleanup logic for EmbedFile
It was never implemented, leading to a memory leak that was caught when
test coverage for the compile error was added.
2021-11-24 16:58:01 -07:00
Andrew Kelley
6afcaf4a08 stage2: fix the build for 32-bit architectures
* 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
2021-11-21 19:43:08 -07:00
Andrew Kelley
008b0ec5e5 std.Thread.Mutex: change API to lock() and unlock()
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 #8051
Closes #8246
Closes #10105
2021-11-09 18:31:03 -07:00
Ryan Liptak
a343758141 Update ensureTotalCapacity to ensureTotalCapacityPrecise where it makes sense
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.
2021-11-01 00:57:33 -07:00
Andrew Kelley
d2f9646d98 C backend: fix enough that zig test works
* 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
2021-10-28 15:59:14 -07:00
Andrew Kelley
e494ce7604 stage2: fix small memory leak of test_functions when using zig test
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.
2021-10-27 14:52:00 -07:00
Andrew Kelley
3af9731600 stage2: implement runtime pointer access to global constants
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.
2021-10-26 22:41:19 -07:00
Andrew Kelley
01c1f41520 stage2: slice and alignment fixes
* 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.
2021-10-22 17:12:12 -07:00
Andrew Kelley
f0dcdd7931 stage2: fix Decl addrspace being undefined 2021-10-22 15:53:59 -07:00
Andrew Kelley
069c83d58c stage2: change @bitCast to always be by-value
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.
2021-10-22 15:35:35 -07:00
Meghan Denny
0ef2e2520a stage2: implement @hasField
struct and union are kept in stage1 because struct/unionFieldCount are returning zero
2021-10-17 21:42:22 -07:00
Andrew Kelley
e5dac0a0b3 stage2: implement @embedFile 2021-10-17 18:59:11 -07:00
Andrew Kelley
6534f2ef4f stage2: implement error wrapping
* 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`.
2021-10-17 14:55:32 -07:00
Andrew Kelley
4d6d6977b0 stage2: fixes to extern variables
* 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`
2021-10-16 12:26:06 -07:00
Andrew Kelley
682cdeceaa stage2: optional comparison and 0-bit payloads
* 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.
2021-10-15 18:37:09 -07:00
Andrew Kelley
8b88274781 stage2: improved union support
* `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.
2021-10-14 17:44:46 -07:00
Andrew Kelley
df7d6d263e stage2: implement opaque declarations
* Module: implement opaque type namespace lookup
 * Add `Type.type` for convenience
 * Sema: fix `validateVarType` for pointer-to-opaque
 * x86_64 ABI: implement support for pointers
 * LLVM backend: fix lowering of opaque types
 * Type: implement equality checking for opaques
2021-10-13 17:53:28 -07:00
Andrew Kelley
a3104a4a78 stage2: fix comptime stores and sentinel-terminated arrays
* 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.
2021-10-12 21:38:46 -07:00
Andrew Kelley
6d6cf59847 stage2: support nested structs and arrays and sret
* 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.
2021-10-11 11:39:12 -07:00
Martin Wickham
272bad3f12 Delete Module.Scope, move Block into Sema 2021-10-02 15:21:49 -05:00
Martin Wickham
fd60012c21 Change *Scope to *Scope.Block, use Sema when required 2021-10-02 15:21:49 -05:00
Martin Wickham
01e08c92b3 Revert collateral changes, clarify abortAnonDecl() 2021-10-02 15:21:49 -05:00
Martin Wickham
53a36eacfa Remove my dumb "namespace decl" hack 2021-10-02 15:21:48 -05:00
Martin Wickham
f7c11acb7f Resolve struct fields in a separate sema context 2021-10-02 15:21:48 -05:00
Martin Wickham
806eee8e99 Fix abortAnonDecl() 2021-10-02 15:21:48 -05:00
Martin Wickham
0b8ddb4478 Improve debug names of decls 2021-10-02 15:21:48 -05:00
Martin Wickham
7ef5938450 Fix decl removal from namespace when destroyed 2021-10-02 15:21:48 -05:00
Martin Wickham
b1e5081826 Fix rendering of type names 2021-10-02 15:21:48 -05:00
Martin Wickham
269e548770 Fix namespace references for deeply nested structs 2021-10-02 15:21:48 -05:00
Andrew Kelley
ea6706b6f4 stage2: LLVM backend: implement struct type fwd decls
Makes struct types able to refer to themselves.
2021-09-29 14:04:52 -07:00
Andrew Kelley
c0aa4a1a42 stage2: implement basic unions
* 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.
2021-09-27 19:53:29 -07:00
Andrew Kelley
1f2f9f05c2 stage2: implement zirCoerceResultPtr
and remove Module.simplePtrType and Module.ptrType in favor of `Type.ptr`.
2021-09-25 22:18:43 -07:00
Martin Wickham
1e7009a9d9 Fix error references across inline and comptime functions 2021-09-24 13:49:18 -04:00
Josh Soref
664941bf14
Spelling corrections (#9833)
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
2021-09-24 13:39:20 -04:00
Andrew Kelley
f215d98043 stage2: LLVM backend: improved naming and exporting
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.
2021-09-23 23:46:45 -07:00