607 Commits

Author SHA1 Message Date
mlugg
b8e6c42688 compiler: provide result type for @memset value
Resolves: #16986
2023-08-28 12:33:36 -07:00
mlugg
8d036d1d78 Sema: allow cast builtins on vectors
The following cast builtins did not previously work on vectors, and have
been made to:

* `@floatCast`
* `@ptrFromInt`
* `@intFromPtr`
* `@floatFromInt`
* `@intFromFloat`
* `@intFromBool`

Resolves: #16267
2023-08-28 12:32:02 -07:00
Andrew Kelley
ada0010471 compiler: move unions into InternPool
There are a couple concepts here worth understanding:

Key.UnionType - This type is available *before* resolving the union's
fields. The enum tag type, number of fields, and field names, field
types, and field alignments are not available with this.

InternPool.UnionType - This one can be obtained from the above type with
`InternPool.loadUnionType` which asserts that the union's enum tag type
has been resolved. This one has all the information available.

Additionally:

* ZIR: Turn an unused bit into `any_aligned_fields` flag to help
  semantic analysis know whether a union has explicit alignment on any
  fields (usually not).
* Sema: delete `resolveTypeRequiresComptime` which had the same type
  signature and near-duplicate logic to `typeRequiresComptime`.
  - Make opaque types not report comptime-only (this was inconsistent
    between the two implementations of this function).
* Implement accepted proposal #12556 which is a breaking change.
2023-08-22 13:54:14 -07:00
mlugg
283afb50b5 AstGen: disallow '-0' integer literal
The intent here is ambiguous: this resolves to the comptime_int '0', but
it's likely the user meant to use a floating-point literal.

Resolves: #16890
2023-08-21 11:47:31 +03:00
mlugg
321961d860 AstGen: add result location analysis pass
The main motivation for this change is eliminating the `block_ptr`
result location and corresponding `store_to_block_ptr` ZIR instruction.
This is achieved through a simple pass over the AST before AstGen which
determines, for AST nodes which have a choice on whether to provide a
result location, which choice to make, based on whether the result
pointer is consumed non-trivially.

This eliminates so much logic from AstGen that we almost break even on
line count! AstGen no longer has to worry about instruction rewriting
based on whether or not a result location was consumed: it always knows
what to do ahead of time, which simplifies a *lot* of logic. This also
incidentally fixes a few random AstGen bugs related to result location
handling, leading to the changes in `test/` and `lib/std/`.

This opens the door to future RLS improvements by making them much
easier to implement correctly, and fixes many bugs. Most ZIR is made
more compact after this commit, mainly due to not having redundant
`store_to_block_ptr` instructions lying around, but also due to a few
bugs in the old system which are implicitly fixed here.
2023-08-20 11:58:14 -07:00
mlugg
083ee8e0e2
InternPool: preserve indices of builtin types when resolved
Some builtin types have a special InternPool index (e.g.
`.type_info_type`) so that AstGen can refer to them before semantic
analysis. Unfortunately, this previously led to a second index existing
to refer to the type once it was resolved, complicating Sema by having
the concept of an "unresolved" type index.

This change makes Sema modify these InternPool indices in-place to
contain the expanded representation when resolved. The analysis of the
corresponding decls is caught in `Module.semaDecl`, and a field is set
on Sema telling it which index to place struct/union/enum types at. This
system could break if `std.builtin` contained complex decls which
evaluate multiple struct types, but this will be caught by the
assertions in `InternPool.resolveBuiltinType`.

The AstGen result types which were disabled in 6917a8c have been
re-enabled.

Resolves: #16603
2023-08-15 11:45:23 +01:00
Jacob Young
09b0070e87 AstGen: cleanup @as invasion 2023-08-12 02:22:46 -04:00
Jacob Young
41575fa868 AstGen: fix src loc for invalid switch expression rls coercions 2023-08-12 02:22:26 -04:00
Jacob Young
ce7acf1296 AstGen: fix src loc for invalid coercion in breaks 2023-08-12 01:57:15 -04:00
Jacob Young
2b5bd56a67 AstGen: fix src loc for invalid coercions in tuple literals 2023-08-12 01:57:11 -04:00
Jacob Young
ffc116de78 AstGen: fix src loc for invalid if expression rls coercions
Closes #12509
2023-08-12 01:57:07 -04:00
mlugg
93e53d1e00
compiler: fix crash on invalid result type for @splat
This introduces a new ZIR instruction, `vec_elem_type`.

Co-Authored-By: Ali Chraghi <alichraghi@proton.me>
Resolves: #16567
2023-08-09 19:46:58 +01:00
mlugg
6917a8c258
AstGen: handle ty result location for struct and array init correctly
Well, this was a journey!

The original issue I was trying to fix is covered by the new behavior
test in array.zig: in essence, `ty` and `coerced_ty` result locations
were not correctly propagated.

While fixing this, I noticed a similar bug in struct inits: the type was
propagated to *fields* fine, but the actual struct init was
unnecessarily anonymous, which could lead to unnecessary copies. Note
that the behavior test added in struct.zig was already passing - the bug
here didn't change any easy-to-test behavior - but I figured I'd add it
anyway.

This is a little harder than it seems, because the result type may not
itself be an array/struct type: it could be an optional / error union
wrapper. A new ZIR instruction is introduced to unwrap these.

This is also made a little tricky by the fact that it's possible for
result types to be unknown at the time of semantic analysis (due to
`anytype` parameters), leading to generic poison. In these cases, we
must essentially downgrade to an anonymous initialization.

Fixing these issues exposed *another* bug, related to type resolution in
Sema. That issue is now tracked by #16603. As a temporary workaround for
this bug, a few result locations for builtin function operands have been
disabled in AstGen. This is technically a breaking change, but it's very
minor: I doubt it'll cause any breakage in the wild.
2023-08-09 19:46:55 +01:00
Andrew Kelley
e66190025f frontend: make fn calls byval; fix false positive isNonErr
This commit does two things which seem unrelated at first, but,
together, solve a miscompilation, and potentially slightly speed up
compiler perf, at the expense of making #2765 trickier to implement in
the future.

Sema: avoid returning a false positive for whether an inferred error set
is comptime-known to be empty.

AstGen: mark function calls as not being interested in a result
location. This prevents the test case "ret_ptr doesn't cause own
inferred error set to be resolved" from being regressed. If we want to
accept and implement #2765 in the future, it will require solving this
problem a different way, but the principle of YAGNI tells us to go ahead
with this change.

Old ZIR looks like this:

  %97 = ret_ptr()
  %101 = store_node(%97, %100)
  %102 = load(%97)
  %103 = ret_is_non_err(%102)

New ZIR looks like this:

  %97 = ret_type()
  %101 = as_node(%97, %100)
  %102 = ret_is_non_err(%101)

closes #15669
2023-07-27 10:12:08 -07:00
Jacob Young
7201e69454 AstGen: fix missing deferred ref
Closes #16524
2023-07-26 22:19:30 -07:00
Andrew Kelley
6cee98eb30 frontend: forbid packed and extern tuples 2023-07-25 21:45:33 -07:00
Andrew Kelley
4b7fa0fce9 AstGen: avoid unnecessary mutable local 2023-07-25 21:45:33 -07:00
r00ster91
279ebabd7d fix some whitespace formatting in switchs
If you view this commit with `git show -w`, there is no diff.
2023-07-21 23:05:41 +02:00
Andrew Kelley
45a8c6c1f4 AstGen: idiomatic use of switch 2023-07-18 19:02:06 -07:00
antlilja
4bce7b1db9 Remove len parameter from splat builtin function
Resolve the result type of the splat builtin instead of requiring a
length parameter.
2023-07-12 15:35:57 -07:00
Anton Lilja
ff0e2ab398
Fixes wrong error location for unionInit when first parameter is not a type (#16384) 2023-07-11 23:35:50 -07:00
r00ster91
0b1e8690da AstGen: make sure for range start and end are usizes
Fixes #16311

The actual cause of #16311 is the `start_is_zero` special case:
```zig
                const range_len = if (end_val == .none or start_is_zero)
                    end_val
                else
                    try parent_gz.addPlNode(.sub, input, Zir.Inst.Bin{
                        .lhs = end_val,
                        .rhs = start_val,
                    });
```
It only happens if the range start is 0. In that case we would not perform any type checking.
Only in the other cases coincidentally `.sub` performs type checking in Sema, but the errors are still rather poor:
```
$ zig test x.zig
x.zig:9:15: error: invalid operands to binary expression: 'Pointer' and 'Pointer'
    for ("abc".."def") |val| {
         ~~~~~^~~~~~~
```
Note how it's the same as if I use `-`:
```
x.zig:9:11: error: invalid operands to binary expression: 'Pointer' and 'Pointer'
    "abc" - "def";
    ~~~~~~^~~~~~~
```
Now after this PR, the errors are much clearer for both range start and end:
```
x.zig:9:10: error: expected type 'usize', found '*const [3:0]u8'
    for ("abc".."def") |val| {
         ^~~~~
```
This is why I decided to use `.ty` instead of `.coerced_ty` for both range start and end rather than
just perform type checking in that `end_val == .none or start_is_zero` case.
2023-07-10 10:51:55 -07:00
mlugg
88284c124a AstGen: fix result locations for elements of typed array init
Resolves: #16226
2023-06-26 16:20:33 -07:00
Andrew Kelley
df389b62de
Merge pull request #16192 from mlugg/builtins-infer-dest-ty-fixes
Follow-up to cast builtin result type inference
2023-06-25 12:38:56 -07:00
Jacob Young
b9c4857ed6 AstGen: add source location to certain const initializers
Before:

    assign_local_bad_coercion.zig:5:1: error: expected type 'u32', found 'u64'
    export fn constEntry() u32 {
    ^~~~~~
    assign_local_bad_coercion.zig:11:19: error: expected type 'u32', found 'u64'
        var x: u32 = g();
                     ~^~

After:

    assign_local_bad_coercion.zig:6:21: error: expected type 'u32', found 'u64'
        const x: u32 = g();
                       ~^~
    assign_local_bad_coercion.zig:11:19: error: expected type 'u32', found 'u64'
        var x: u32 = g();
                     ~^~
2023-06-25 12:00:48 -07:00
mlugg
569ae762e1
compiler: allow cast builtins to coerce result to error union or optional
Also improves some error messages
2023-06-25 13:28:32 +01:00
mlugg
8afadee45a
AstGen: use usize as result type of for loop range operands 2023-06-25 13:28:31 +01:00
mlugg
f26dda2117 all: migrate code to new cast builtin syntax
Most of this migration was performed automatically with `zig fmt`. There
were a few exceptions which I had to manually fix:

* `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten
* `@truncate`'s fixup is incorrect for vectors
* Test cases are not formatted, and their error locations change
2023-06-24 16:56:39 -07:00
mlugg
be0c69957e compiler: remove destination type from cast builtins
Resolves: #5909
2023-06-24 16:47:49 -07:00
Eric Joldasov
50339f595a all: zig fmt and rename "@XToY" to "@YFromX"
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>
2023-06-19 12:34:42 -07:00
Eric Joldasov
a6c8ee5231 compiler: rename "@XToY" to "@YFromX", zig fmt: rewrite them
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>
2023-06-19 12:34:24 -07:00
mlugg
85e94fed1e
Eliminate switch_cond[_ref] ZIR tags
This finishes the process of consolidating switch expressions in ZIR
into as simple and compact a representation as is possible. There are
now just two ZIR tags dedicated to switch expressions: switch_block and
switch_block_ref, with the latter being for an operand passed by
reference.
2023-06-13 12:55:15 +01:00
mlugg
39510cc7d1
Eliminate switch_capture_tag ZIR instruction
This is a follow-up to a previous commit which eliminated switch_capture
and switch_capture_ref. All captures are now handled directly by
`switch_block`, which has also eliminated some unnecessary Block data in
Sema.
2023-06-13 12:55:01 +01:00
mlugg
00609e7edb
Eliminate switch_capture and switch_capture_ref ZIR tags
These tags are unnecessary, as this information can be more efficiently
encoded within the switch_block instruction itself. We also use a neat
little trick to avoid needing a dummy instruction (like is used for
errdefer captures): since the switch_block itself cannot otherwise be
referenced within a prong, we can repurpose its index within prongs to
refer to the captured value.
2023-06-13 12:53:18 +01:00
mlugg
cebd80032a
Move switch case value coercion from AstGen to Sema
This is in preparation for #2473. Also fixes a bug where switching on
bools allows invalid case combinations.
2023-06-13 12:50:49 +01:00
mlugg
a377bf87ce
Zir: remove unnecessary switch_capture_multi instructions
By indexing from the very first switch case rather than into scalar and
multi cases separately, the instructions for capturing in multi cases
become unnecessary, freeing up 2 ZIR tags.
2023-06-13 12:42:31 +01:00
Andrew Kelley
270f9e24dd AstGen: generate tests with anyerror!void
rather than inferred error sets. This avoids extra unnecessary work for
the compiler since inferred error sets are unique types.
2023-06-10 20:47:56 -07:00
Jacob Young
6e0de1d116 InternPool: port most of value tags 2023-06-10 20:47:54 -07:00
Andrew Kelley
5881a2d637 stage2: move enum types into the InternPool
Unlike unions and structs, enums are actually *encoded* into the
InternPool directly, rather than using the SegmentedList trick. This
results in them being quite compact, and greatly improved the ergonomics
of using enum types throughout the compiler.

It did however require introducing a new concept to the InternPool which
is an "incomplete" item - something that is added to gain a permanent
Index, but which is then mutated in place. This was necessary because
enum tag values and tag types may reference the namespaces created by
the enum itself, which required constructing the namespace, decl, and
calling analyzeDecl on the decl, which required the decl value, which
required the enum type, which required an InternPool index to be
assigned and for it to be meaningful.

The API for updating enums in place turned out to be quite slick and
efficient - the methods directly populate pre-allocated arrays and
return the information necessary to output the same compilation errors
as before.
2023-06-10 20:42:30 -07:00
Andrew Kelley
9d422bff18 stage2: move all integer types to InternPool 2023-06-10 20:40:04 -07:00
Andrew Kelley
9aec2758cc stage2: start the InternPool transition
Instead of doing everything at once which is a hopelessly large task,
this introduces a piecemeal transition that can be done in small
increments at a time.

This is a minimal changeset that keeps the compiler compiling. It only
uses the InternPool for a small set of types.

Behavior tests are not passing.

Air.Inst.Ref and Zir.Inst.Ref are separated into different enums but
compile-time verified to have the same fields in the same order.

The large set of changes is mainly to deal with the fact that most Type
and Value methods now require a Module to be passed in, so that the
InternPool object can be accessed.
2023-06-10 20:40:03 -07:00
mlugg
bf4b43a2f7 AstGen: handle ref_table for params
This is kind of similar to 1a4b0d9. In this case, we need to handle
ref_table when appending the body of param instructions.

Resolves: #15952
2023-06-10 07:18:05 +03:00
mlugg
1a4b0d9790 AstGen: handle ref_table for errdefer captures
Resolves: #15861
2023-06-03 13:36:44 -07:00
mlugg
38b83d9d93 Zir: eliminate field_call_bind and field_call_bind_named
This commit removes the `field_call_bind` and `field_call_bind_named` ZIR
instructions, replacing them with a `field_call` instruction which does the bind
and call in one.

`field_call_bind` is an unfortunate instruction. It's tied into one very
specific usage pattern - its result can only be used as a callee. This means
that it creates a value of a "pseudo-type" of sorts, `bound_fn` - this type used
to exist in Zig, but now we just hide it from the user and have AstGen ensure
it's only used in one way. This is quite silly - `Type` and `Value` should, as
much as possible, reflect real Zig types and values.

It makes sense to instead encode the `a.b()` syntax as its own ZIR instruction,
so that's what we do here. This commit introduces a new instruction,
`field_call`. It's like `call`, but rather than a callee ref, it contains a ref
to the object pointer (`&a` in `a.b()`) and the string field name (`b`). This
eliminates `bound_fn` from the language, and slightly decreases the size of
generated ZIR - stats below.

This commit does remove a few usages which used to be allowed:
- `@field(a, "b")()`
- `@call(.auto, a.b, .{})`
- `@call(.auto, @field(a, "b"), .{})`

These forms used to work just like `a.b()`, but are no longer allowed. I believe
this is the correct choice for a few reasons:
- `a.b()` is a purely *syntactic* form; for instance, `(a.b)()` is not valid.
  This means it is *not* inconsistent to not allow it in these cases; the
  special case here isn't "a field access as a callee", but rather this exact
  syntactic form.
- The second argument to `@call` looks much more visually distinct from the
  callee in standard call syntax. To me, this makes it seem strange for that
  argument to not work like a normal expression in this context.
- A more practical argument: it's confusing! `@field` and `@call` are used in
  very different contexts to standard function calls: the former normally hints
  at some comptime machinery, and the latter that you want more precise control
  over parts of a function call. In these contexts, you don't want implicit
  arguments adding extra confusion: you want to be very explicit about what
  you're doing.

Lastly, some stats. I mentioned before that this change slightly reduces the
size of ZIR - this is due to two instructions (`field_call_bind` then `call`)
being replaced with one (`field_call`). Here are some numbers:

+--------------+----------+----------+--------+
| File         | Before   | After    | Change |
+--------------+----------+----------+--------+
| Sema.zig     | 4.72M    | 4.53M    | -4%    |
| AstGen.zig   | 1.52M    | 1.48M    | -3%    |
| hash_map.zig | 283.9K   | 276.2K   | -3%    |
| math.zig     | 312.6K   | 305.3K   | -2%    |
+--------------+----------+----------+--------+
2023-05-20 12:27:48 -07:00
zooster
3d64ed0353
make @trap return unreachable/noreturn (#15749)
`@trap` is a special function that we know never returns so it should
behave just like `@panic` and `@compileError` do currently and cause the
"unreachable code" + "control flow is diverted here" compile error.
Currently, `@trap(); @trap();` does not cause this error. Now it does.
2023-05-18 17:00:35 -04:00
Andrew Kelley
7f7bd206dc
Merge pull request #15519 from dweiller/issue-15482
Optimize lowering of `s[start..][0..len]`
2023-05-11 08:59:44 -07:00
Dominic
e1f5ad3cc8
Fix parsing of hexadecimal literals 2023-05-07 08:05:53 +00:00
dweiller
64e319f555 add optional sentinel to slice_length ZIR 2023-05-07 15:55:21 +10:00
dweiller
9fb5b047e9 astgen: lower s[start..][0..len] to slice_length ZIR 2023-05-07 15:55:20 +10:00
dweiller
a62b5d84d8 zir: add slice_length tag 2023-05-07 15:55:20 +10:00