Commit graph

2504 commits

Author SHA1 Message Date
mlugg
e9bd2d45d4
Sema: rewrite semantic analysis of function calls
This rewrite improves some error messages, hugely simplifies the logic,
and fixes several bugs. One of these bugs is technically a new rule
which Andrew and I agreed on: if a parameter has a comptime-only type
but is not declared `comptime`, then the corresponding call argument
should not be *evaluated* at comptime; only resolved. Implementing this
required changing how function types work a little, which in turn
required allowing a new kind of function coercion for some generic use
cases: function coercions are now allowed to implicitly *remove*
`comptime` annotations from parameters with comptime-only types. This is
okay because removing the annotation affects only the call site.

Resolves: #22262
2025-01-09 06:46:47 +00:00
Jacob Young
3f95003d4c cbe: fix miscomps of x86_64 backend 2025-01-08 19:33:45 -05:00
Alex Rønne Petersen
c1ae99efb3
test: Disable align(N) on functions and @alignCast functions for thumbeb too. 2025-01-06 16:31:32 +01:00
Alex Rønne Petersen
52e9fd7c3c
test: Disable vector behavior tests affected by #22060 for thumbeb too. 2025-01-06 16:20:27 +01:00
mlugg
252c203101 Sema: correctly label block_comptime for restoring error return trace index
Resolves: #22384
2025-01-02 16:26:50 +00:00
Andrew Kelley
271452d225
Merge pull request #22344 from Techatrix/slice-of-slice
fix incorrect slicing by length detection cases
2024-12-29 13:41:17 -05:00
Travis Staloch
45e4b16caf add @Type behavior tests from #19985 2024-12-29 13:37:39 -05:00
David Rubin
b99dbb6fb5 Value: implement orderAgainstZeroInner for errors 2024-12-29 13:36:52 -05:00
Techatrix
5b6326ec65
fix slice of slice with sentinel on the lhs slice
example:
```zig
test {
    var foo: [2:0]u8 = .{ 1, 2 };
    _ = foo[0.. :1][0..2];
}
```

A `.slice_open` ast node will not have a end index nor sentinel.
2024-12-29 07:00:39 +01:00
Techatrix
5d51d4474a
fix slice of slice with sentinel but no end index
example:
```zig
test {
	var foo = "";
	_ = foo[0..][0.. :0];
}
```

A `.slice_sentinel` ast node may not have an end index.
2024-12-29 07:00:35 +01:00
mlugg
01081cc8e8 AstGen: lower function addrspace expression correctly
Also, add some basic behavior tests for addrspace and linksection which
would have caught this bug in CI.
2024-12-28 02:15:00 +00:00
mlugg
3afda4322c
compiler: analyze type and value of global declaration separately
This commit separates semantic analysis of the annotated type vs value
of a global declaration, therefore allowing recursive and mutually
recursive values to be declared.

Every `Nav` which undergoes analysis now has *two* corresponding
`AnalUnit`s: `.{ .nav_val = n }` and `.{ .nav_ty = n }`. The `nav_val`
unit is responsible for *fully resolving* the `Nav`: determining its
value, linksection, addrspace, etc. The `nav_ty` unit, on the other
hand, resolves only the information necessary to construct a *pointer*
to the `Nav`: its type, addrspace, etc. (It does also analyze its
linksection, but that could be moved to `nav_val` I think; it doesn't
make any difference).

Analyzing a `nav_ty` for a declaration with no type annotation will just
mark a dependency on the `nav_val`, analyze it, and finish. Conversely,
analyzing a `nav_val` for a declaration *with* a type annotation will
first mark a dependency on the `nav_ty` and analyze it, using this as
the result type when evaluating the value body.

The `nav_val` and `nav_ty` units always have references to one another:
so, if a `Nav`'s type is referenced, its value implicitly is too, and
vice versa. However, these dependencies are trivial, so, to save memory,
are only known implicitly by logic in `resolveReferences`.

In general, analyzing ZIR `decl_val` will only analyze `nav_ty` of the
corresponding `Nav`. There are two exceptions to this. If the
declaration is an `extern` declaration, then we immediately ensure the
`Nav` value is resolved (which doesn't actually require any more
analysis, since such a declaration has no value body anyway).
Additionally, if the resolved type has type tag `.@"fn"`, we again
immediately resolve the `Nav` value. The latter restriction is in place
for two reasons:

* Functions are special, in that their externs are allowed to trivially
  alias; i.e. with a declaration `extern fn foo(...)`, you can write
  `const bar = foo;`. This is not allowed for non-function externs, and
  it means that function types are the only place where it is possible
  for a declaration `Nav` to have a `.@"extern"` value without actually
  being declared `extern`. We need to identify this situation
  immediately so that the `decl_ref` can create a pointer to the *real*
  extern `Nav`, not this alias.
* In certain situations, such as taking a pointer to a `Nav`, Sema needs
  to queue analysis of a runtime function if the value is a function. To
  do this, the function value needs to be known, so we need to resolve
  the value immediately upon `&foo` where `foo` is a function.

This restriction is simple to codify into the eventual language
specification, and doesn't limit the utility of this feature in
practice.

A consequence of this commit is that codegen and linking logic needs to
be more careful when looking at `Nav`s. In general:

* When `updateNav` or `updateFunc` is called, it is safe to assume that
  the `Nav` being updated (the owner `Nav` for `updateFunc`) is fully
  resolved.
* Any `Nav` whose value is/will be an `@"extern"` or a function is fully
  resolved; see `Nav.getExtern` for a helper for a common case here.
* Any other `Nav` may only have its type resolved.

This didn't seem to be too tricky to satisfy in any of the existing
codegen/linker backends.

Resolves: #131
2024-12-24 02:18:41 +00:00
mlugg
eac87ea8d6
compiler: disallow align etc annotations on comptime-only globals
This includes function aliases, but not function declarations.

Also, re-introduce a target check for function alignment which was
inadvertently removed in the prior commit.
2024-12-19 03:21:56 +00:00
mlugg
7408679234
compiler: disallow callconv etc from depending on function parameters
Resolves: #22261
2024-12-18 23:06:35 +00:00
Alex Rønne Petersen
d5c2f527b4
Merge pull request #22219 from alexrp/arm-big-endian
Add `armeb-linux-*`, `thumbeb-linux-*`, and `aarch64_be-linux-*` to CI
2024-12-15 01:41:46 +01:00
David Rubin
09a8fa2120 ensure InstMap capacity before remapping error code 2024-12-14 16:41:17 -05:00
Alex Rønne Petersen
1e61399537
test: Disable some vector behavior tests on armeb.
https://github.com/ziglang/zig/issues/22060
2024-12-13 03:13:14 +01:00
Jacob Young
bd0ace5c4e
cbe: prevent tautological-compare warnings in generated code 2024-12-08 10:53:50 +00:00
mlugg
03f5b967f0
AstGen: correctly deduplicate ref of param and alloc_inferred
Both of these instructions were previously under a special case in
`rvalue` which resulted in every reference to such an instruction adding
a new `ref` instruction. This had the effect that, for instance,
`&a != &a` for parameters. Deduplicating these `ref` instructions was
problematic for different reasons.

For `alloc_inferred`, the problem was that it's not valid to `ref` the
alloc until the allocation has been resolved (`resolve_inferred_alloc`),
but `AstGen.appendBodyWithFixups` would place the `ref` directly after
the `alloc_inferred`. This is solved by bringing
`resolve_inferred_alloc` in line with `make_ptr_const` by having it
*return* the final pointer, rather than modifying `sema.inst_map` of the
original `alloc_inferred`. That way, the `ref` refers to the
`resolve_inferred_alloc` instruction, so is placed immediately after it,
avoiding this issue.

For `param`, the problem is a bit trickier: `param` instructions live in
a body which must contain only `param` instructions, then a
`func{,_inferred,_fancy}`, then a `break_inline`. Moreover, `param`
instructions may be referenced not only by the function body, but also
by other parameters, the return type expression, etc. Each of these
bodies requires separate `ref` instructions. This is solved by pulling
entries out of `ref_table` after evaluating each component of the
function declaration, and appending the refs later on when actually
putting the bodies together. This gives way to another issue: if you
write `fn f(x: T) @TypeOf(x.foo())`, then since `x.foo()` takes a
reference to `x`, this `ref` instruction is now in a comptime context
(outside of the `@TypeOf` ZIR body), so emits a compile error. This is
solved by loosening the rules around `ref` instructions; because they
are not side-effecting, it is okay to allow `ref` of runtime values at
comptime, resulting in a runtime-known value in a comptime scope. We
already apply this mechanism in some cases; for instance, it's why
`runtime_array.len` works in a `comptime` context. In future, we will
want to give similar treatment to many operations in Sema: in general,
it's fine to apply runtime operations at comptime provided they don't
have side effects!

Resolves: #22140
2024-12-08 10:53:50 +00:00
David Rubin
77f16d457b
test: adjust behaviour test to new concat/mul semantics 2024-11-28 18:05:36 -08:00
xdBronch
5f3a70ed5f Fix peer type resolution with allowzero pointers 2024-11-20 02:09:50 +02:00
Jacob Young
a8ec306b49 Sema: fix peer resolution alignment between slice and empty struct
An empty struct that coerces to an empty array should not force
`align(1)` on the resulting slice type.
2024-11-16 21:22:57 -05:00
Alex Rønne Petersen
9d0bb7ada8
test: Disable 128-bit atomics behavior tests on aarch64_be.
See: https://github.com/ziglang/zig/issues/21892
2024-11-04 08:29:42 +01:00
Alex Rønne Petersen
2958a90515
test: Disable some vector behavior tests on aarch64_be.
See: https://github.com/ziglang/zig/issues/21893
2024-11-04 08:29:42 +01:00
Alex Rønne Petersen
96ea7d3e1c
test: Disable reinterpret packed union on all big endian targets.
See: https://github.com/ziglang/zig/issues/21050
2024-11-04 08:29:42 +01:00
Alex Rønne Petersen
c9e67e71c1
std.Target: Replace isARM() with isArmOrThumb() and rename it to isArm().
The old isARM() function was a portability trap. With the name it had, it seemed
like the obviously correct function to use, but it didn't include Thumb. In the
vast majority of cases where someone wants to ask "is the target Arm?", Thumb
*should* be included.

There are exactly 3 cases in the codebase where we do actually need to exclude
Thumb, although one of those is in Aro and mirrors a check in Clang that is
itself likely a bug. These rare cases can just add an extra isThumb() check.
2024-11-03 09:29:30 +01:00
mlugg
d11bbde5f9
compiler: remove anonymous struct types, unify all tuples
This commit reworks how anonymous struct literals and tuples work.

Previously, an untyped anonymous struct literal
(e.g. `const x = .{ .a = 123 }`) was given an "anonymous struct type",
which is a special kind of struct which coerces using structural
equivalence. This mechanism was a holdover from before we used
RLS / result types as the primary mechanism of type inference. This
commit changes the language so that the type assigned here is a "normal"
struct type. It uses a form of equivalence based on the AST node and the
type's structure, much like a reified (`@Type`) type.

Additionally, tuples have been simplified. The distinction between
"simple" and "complex" tuple types is eliminated. All tuples, even those
explicitly declared using `struct { ... }` syntax, use structural
equivalence, and do not undergo staged type resolution. Tuples are very
restricted: they cannot have non-`auto` layouts, cannot have aligned
fields, and cannot have default values with the exception of `comptime`
fields. Tuples currently do not have optimized layout, but this can be
changed in the future.

This change simplifies the language, and fixes some problematic
coercions through pointers which led to unintuitive behavior.

Resolves: #16865
2024-10-31 20:42:53 +00:00
Matthew Lugg
6bf52b0505
Merge pull request #21697 from mlugg/callconv
Replace `std.builtin.CallingConvention` with a tagged union, eliminating `@setAlignStack`
2024-10-23 16:48:33 +01:00
kcbanner
2d888a8e63 tests: re-enable tests that now pass on aarch64-windows 2024-10-22 11:39:29 +02:00
mlugg
f7d679ceae
riscv: disable failing test
Looks like the self-hosted riscv64 backend can't handle `std.meta.eql`
involving the new `CallingConvention` right now.
2024-10-19 20:06:04 +01:00
mlugg
4be0cf30fc
test: update for CallingConvention changes
This also includes some compiler and std changes to correct error
messages which weren't properly updated before.
2024-10-19 19:15:23 +01:00
mlugg
097766bba3 compiler: implement @FieldType
Resolves: #21702
2024-10-18 08:50:40 +01:00
Robin Voetter
e2e79960d2
Merge pull request #21688 from Snektron/spirv-fix
spirv: fix some bitrot
2024-10-13 22:33:03 +02:00
David Rubin
e131a2c8e2
implement packed struct equality (#21679) 2024-10-12 20:59:12 -07:00
Robin Voetter
86b88ea7da
spirv: skip range switch tests
This is not yet implemented
2024-10-13 01:58:11 +02:00
mlugg
c96f9a017a Sema: implement @splat for arrays
Resolves: #20433
2024-10-10 11:22:49 +01:00
Pavel Verigo
4b89a4c7cb stage2-wasm: airRem + airMod for floats 2024-10-08 20:58:15 +02:00
David Rubin
043b1adb8d
remove @fence (#21585)
closes #11650
2024-10-04 22:21:27 +00:00
Alex Rønne Petersen
354ea625e5
test: Re-enable "bitcast nan float does not modify signaling bit" for LLVM + arm.
This now passes on all targets that we test in CI.

See: https://github.com/ziglang/zig/issues/14366
2024-10-02 04:08:24 +02:00
Meghan Denny
5e4da1ff30
std: add arch bits for s390x-linux (#21342)
see #21402
2024-09-24 13:35:12 -07:00
Alex Rønne Petersen
f8719c4197 test: Re-enable store vector with memset for LLVM.
Closes #16177.
2024-09-19 18:20:21 -07:00
Alex Rønne Petersen
bdae7d97b9 test: Disable @bitCast of packed struct containing pointer temporarily.
TODO: Figure out what to do about this.

Context: https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179

After changing our emit strategy for packed structs to just write to memory:

test-behavior
└─ run test behavior-x86_64-linux.6.5...6.5-gnu.2.38-x86_64-ReleaseSmall-libc
   └─ zig test ReleaseSmall native failure
error: thread 44346 panic: attempt to unwrap error: ReinterpretDeclRef
/home/alexrp/Source/zig/src/Value.zig:571:42: 0x1f33514 in writeToPackedMemory (zig)
            if (!val.ptrHasIntAddr(mod)) return error.ReinterpretDeclRef;
                                         ^
/home/alexrp/Source/zig/src/Value.zig:548:17: 0x1f32f45 in writeToPackedMemory (zig)
                try field_val.writeToPackedMemory(field_ty, pt, buffer, bit_offset + bits);
                ^
/home/alexrp/Source/zig/src/codegen/llvm.zig:3706:89: 0x1ca2366 in lowerValueToInt (zig)
        val.writeToPackedMemory(ty, pt, std.mem.sliceAsBytes(limbs)[0..bytes], 0) catch unreachable;
                                                                                        ^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4083:49: 0x1a33800 in lowerValue (zig)
                        return o.lowerValueToInt(llvm_int_ty, arg_val);
                                                ^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4798:42: 0x2ec4e6a in resolveValue (zig)
        const llvm_val = try o.lowerValue(val.toIntern());
                                         ^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4789:47: 0x2ec4bd3 in resolveInst (zig)
        const llvm_val = try self.resolveValue((try self.air.value(inst, self.ng.object.pt)).?);
                                              ^
/home/alexrp/Source/zig/src/codegen/llvm.zig:8996:49: 0x2f022e9 in airStore (zig)
        const src_operand = try self.resolveInst(bin_op.rhs);
                                                ^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4967:53: 0x29f7260 in genBody (zig)
                .store          => try self.airStore(inst, false),
                                                    ^
/home/alexrp/Source/zig/src/codegen/llvm.zig:1682:19: 0x29f147c in updateFunc (zig)
        fg.genBody(air.getMainBody()) catch |err| switch (err) {
                  ^
/home/alexrp/Source/zig/src/link/Elf.zig:2916:70: 0x2eb0f15 in updateFunc (zig)
    if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
                                                                     ^
/home/alexrp/Source/zig/src/link.zig:426:82: 0x29fbef5 in updateFunc (zig)
                return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, air, liveness);
                                                                                 ^
/home/alexrp/Source/zig/src/Zcu/PerThread.zig:876:22: 0x25f3d9e in linkerUpdateFunc (zig)
        lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
                     ^
/home/alexrp/Source/zig/src/Compilation.zig:3975:36: 0x21768fe in processOneCodegenJob (zig)
            try pt.linkerUpdateFunc(func.func, func.air);
                                   ^
/home/alexrp/Source/zig/src/Compilation.zig:3928:36: 0x2176541 in queueCodegenJob (zig)
        return processOneCodegenJob(tid, comp, codegen_job);
                                   ^
/home/alexrp/Source/zig/src/Compilation.zig:3682:37: 0x1e9d37f in processOneJob (zig)
            try comp.queueCodegenJob(tid, .{ .func = .{
                                    ^
/home/alexrp/Source/zig/src/Compilation.zig:3638:30: 0x1c1f6c1 in performAllTheWorkInner (zig)
            try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job, main_progress_node);
                             ^
/home/alexrp/Source/zig/src/Compilation.zig:3508:36: 0x1ab6e10 in performAllTheWork (zig)
    try comp.performAllTheWorkInner(main_progress_node);
                                   ^
/home/alexrp/Source/zig/src/Compilation.zig:2269:31: 0x1ab25b9 in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/home/alexrp/Source/zig/src/main.zig:4156:32: 0x1b01351 in serve (zig)
                try comp.update(main_progress_node);
                               ^
/home/alexrp/Source/zig/src/main.zig:3453:22: 0x1b20d7c in buildOutputType (zig)
            try serve(
                     ^
/home/alexrp/Source/zig/src/main.zig:267:31: 0x1969c54 in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .zig_test);
                              ^
/home/alexrp/Source/zig/src/main.zig:199:20: 0x19669c5 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/home/alexrp/Source/zig/lib/std/start.zig:614:37: 0x19664ee in main (zig)
            const result = root.main() catch |err| {
                                    ^
../sysdeps/nptl/libc_start_call_main.h:58:16: 0x7a453da2814f in __libc_start_call_main (../sysdeps/x86/libc-start.c)
../csu/libc-start.c:360:3: 0x7a453da28208 in __libc_start_main_impl (../sysdeps/x86/libc-start.c)
???:?:?: 0x1966134 in ??? (???)
???:?:?: 0x0 in ??? (???)
2024-09-19 18:20:21 -07:00
mlugg
2111f4c38b Sema: mark export on owner nav when exporting function alias
Resolves: #20847
2024-09-18 21:42:47 +01:00
Matthew Lugg
41330c96ae
Merge pull request #21428 from mlugg/compare-to-undef
Sema: return undefined on comparison of runtime value against undefined
2024-09-17 14:34:10 +01:00
mlugg
4650e5b9fc
Sema: clean up cmpNumeric
There is one minor language change here, which is that comparisons of
the form `comptime_inf < runtime_f32` have their results comptime-known.
This is consistent with comparisons against comptime NaN for instance,
which are always comptime known. A corresponding behavior test is added.

This fixes a bug with int comparison elision which my previous commit
somehow triggered. `Sema.compareIntsOnlyPossibleResult` is much cleaner
now!
2024-09-17 11:00:38 +01:00
mlugg
1365be5d02
compiler: provide correct result types to += and -=
Resolves: #21341
2024-09-16 16:42:42 +01:00
mlugg
258236ec1b Sema: don't emit instruction when casting @min/@max result to OPV type
Resolves: #21408
2024-09-15 17:52:35 +01:00
mlugg
19924ca289 Sema: give try operand error{} result type in non-errorable functions
Resolves: #21414
2024-09-15 16:51:26 +01:00
David Rubin
bc161430b0 riscv: implement optional_payload_ptr_set 2024-09-12 20:29:10 -04:00
xdBronch
0329b8387c make decl literals work with single item pointers 2024-09-12 20:29:10 -04:00