241 Commits

Author SHA1 Message Date
Andrew Kelley
eee989d2a0 Sema: Type.abiSize asserts instead of using max with alignment
ABI size is guaranteed to always be >= alignment.
2022-03-14 00:11:46 -07:00
Andrew Kelley
b3259b47ad Type.eql: check fn attributes before params
slightly better for cache locality
2022-03-11 22:49:08 -07:00
Andrew Kelley
491e3ba6b1 LLVM: fix debug info for pointers to void 2022-03-11 21:00:07 -07:00
Andrew Kelley
55ba335e0f Sema: fix resolution of inferred error sets
Introduce `Module.ensureFuncBodyAnalyzed` and corresponding `Sema`
function. This mirrors `ensureDeclAnalyzed` except also waits until the
function body has been semantically analyzed, meaning that inferred
error sets will have been populated.

Resolving error sets can now emit a "unable to resolve inferred error
set" error instead of producing an incorrect error set type. Resolving
error sets now calls `ensureFuncBodyAnalyzed`. Closes #11046.

`coerceInMemoryAllowedErrorSets` now does a lot more work to avoid
resolving an inferred error set if possible. Same with
`wrapErrorUnionSet`.

Inferred error set types no longer check the `func` field to determine if
they are equal. That was incorrect because an inline or comptime function
call produces a unique error set which has the same `*Module.Fn` value for
this field. Instead we use the `*Module.Fn.InferredErrorSet` pointers to
test equality of inferred error sets.
2022-03-11 19:38:07 -07:00
Andrew Kelley
078037ab9b stage2: passing threadlocal tests for x86_64-linux
* use the real start code for LLVM backend with x86_64-linux
   - there is still a check for zig_backend after initializing the TLS
     area to skip some stuff.
 * introduce new AIR instructions and implement them for the LLVM
   backend. They are the same as `call` except with a modifier.
   - call_always_tail
   - call_never_tail
   - call_never_inline
 * LLVM backend calls hasRuntimeBitsIgnoringComptime in more places to
   avoid unnecessarily depending on comptimeOnly being resolved for some
   types.
 * LLVM backend: remove duplicate code for setting linkage and value
   name. The canonical place for this is in `updateDeclExports`.
 * LLVM backend: do some assembly template massaging to make `%%`
   rendered as `%`. More hacks will be needed to make inline assembly
   catch up with stage1.
2022-03-11 00:04:42 -07:00
Andrew Kelley
9f163310f2 stage2: improve Type.eql and Type.hash for error sets
* Reduce branching in Type.eql and Type.hash for error sets.
 * `Type.eql` uses element-wise bytes comparison since it can rely on
   the error sets being pre-sorted.
 * Avoid unnecessarily skipping tests that are passing.
2022-03-10 14:21:37 -07:00
Mitchell Hashimoto
569870ca41 stage2: error_set_merged type equality
This implements type equality for error sets. This is done
through element-wise error set comparison.

Inferred error sets are always distinct types and other error sets are
always sorted. See #11022.
2022-03-10 14:20:16 -07:00
Andrew Kelley
f32a77b30d Sema: implement pointer-to-tuple coercion to slice and struct 2022-03-09 17:33:01 -07:00
Andrew Kelley
3b6e8fa59e Sema: fix crash with @sizeOf on unions 2022-03-09 16:02:42 -07:00
Andrew Kelley
bb73775d40 Sema: implement coercion of tuples to structs 2022-03-08 22:19:25 -07:00
Andrew Kelley
fb4ad37e0b LLVM: fix memory leak of debug type names
This required adjusting `Type.nameAlloc` to be used with a
general-purpose allocator and added `Type.nameAllocArena` for the arena
use case (avoids allocation sometimes).
2022-03-08 15:03:03 -07:00
Andrew Kelley
fa57335ec6 stage2: implement Type.getOwnerDecl for opaque types 2022-03-08 14:58:54 -07:00
Jonathan Marler
d805adddd6 deprecated TypeInfo in favor of Type
Co-authored-by: Veikka Tuominen <git@vexu.eu>
2022-03-08 20:38:12 +02:00
Andrew Kelley
71b8760d3b stage2: rework @mulAdd
* mul_add AIR instruction: use `pl_op` instead of `ty_pl`. The type is
   always the same as the operand; no need to waste bytes redundantly
   storing the type.
 * AstGen: use coerced_ty for all the operands except for one which we
   use to communicate the type.
 * Sema: use the correct source location for requireRuntimeBlock in
   handling of `@mulAdd`.
 * native backends: handle liveness even for the functions that are
   TODO.
 * C backend: implement `@mulAdd`. It lowers to libc calls.
 * LLVM backend: make `@mulAdd` handle all float types.
   - improved fptrunc and fpext to handle f80 with compiler-rt calls.
 * Value.mulAdd: handle all float types and use the `@mulAdd` builtin.
 * behavior tests: revert the changes to testing `@mulAdd`. These
   changes broke the test coverage, making it only tested at
   compile-time.

Improved f80 support:
 * std.math.fma handles f80
 * move fma functions from freestanding libc to compiler-rt
   - add __fmax and fmal
   - make __fmax and fmaq only exported when they don't alias fmal.
   - make their linkage weak just like the rest of compiler-rt symbols.
 * removed `longDoubleIsF128` and replaced it with `longDoubleIs` which
   takes a type as a parameter. The implementation is now more accurate
   and handles more targets. Similarly, in stage2 the function
   CTypes.sizeInBits is more accurate for long double for more targets.
2022-03-06 16:11:39 -07:00
Andrew Kelley
e532b0c0b5 stage2: cleanups to wasm memory intrinsics
* AIR: use pl_op instead of ty_pl for wasm_memory_size. No need to
   store the type because the type is always `u32`.
 * AstGen: use coerced_ty for `@wasmMemorySize` and `@wasmMemoryGrow`
   and do the coercions in Sema.
 * Sema: use more accurate source locations for errors.
 * Provide more information in the compiler error message.
 * Codegen: use liveness data to avoid lowering unused
   `@wasmMemorySize`.
 * LLVM backend: add implementation
   - I wasn't able to test it because we are hitting a linker error for
     `-target wasm32-wasi -fLLVM`.
 * C backend: use `zig_unimplemented()` instead of silently doing wrong
   behavior for these builtins.
 * behavior tests: branch only on stage2_arch for inclusion of the
   wasm.zig file. We would change it to `builtin.cpu.arch` but that is
   causing a compiler crash on some backends.
2022-03-03 18:31:55 -07:00
Veikka Tuominen
69bd2c243e stage2: remove opaque type workaround from Type.ptrAlignment 2022-03-03 22:16:49 +02:00
Andrew Kelley
365aca0e90 Sema: allow pointers to opaques to be aligned 2022-03-03 13:11:06 -07:00
Cody Tapscott
b6a6f05c0d stage2: support @ptrCast for slices with an offset 2022-03-03 13:08:14 -07:00
Andrew Kelley
06b1a88a15 Sema: implement cast from anon struct ptr to union ptr 2022-03-02 20:18:22 -07:00
Andrew Kelley
220708e7c3 LLVM: aggregate_init supports structs
in addition to tuples
2022-03-02 13:35:15 -07:00
Veikka Tuominen
403a1fe5d7 stage2: add cast from ?*T to ?*anyopaque 2022-03-02 12:26:04 +02:00
Andrew Kelley
ed2364a148 stage2: introduce anonymous struct literals 2022-03-01 23:46:57 -07:00
Andrew Kelley
6f303c01f3 LLVM: add extra padding to structs and tuples sometimes
* Sema: resolve type fully when emitting an alloc AIR instruction to
   avoid tripping assertion for checking struct field alignment.
 * LLVM backend: keep a reference to the LLVM target data alive during
   lowering so that we can ask LLVM what it thinks the ABI alignment
   and size of LLVM types are. We need this in order to lower tuples and
   structs so that we can put in extra padding bytes when Zig disagrees
   with LLVM about the size or alignment of something.
 * LLVM backend: make the LLVM struct type packed that contains the most
   aligned union field and the padding. This prevents the struct from
   being too big according to LLVM. In the future, we may want to
   consider instead emitting unions in a "flat" manner; putting the tag,
   most aligned union field, and padding all in the same struct field
   space.
 * LLVM backend: make structs with 2 or fewer fields return isByRef=false.
   This results in more efficient codegen. This required lowering of
   bitcast to sometimes store the struct into an alloca, ptrcast, and
   then load because LLVM does not allow bitcasting structs.
 * enable more passing behavior tests.
2022-03-01 18:24:00 -07:00
Andrew Kelley
8878f085dc Sema: correct implementation of comptimeOnly for tuples
This makes formatted printing work when mixing comptime and runtime
fields.
2022-03-01 15:26:31 -07:00
Andrew Kelley
18e42661dc Sema: eliminate use of resolveAlreadyCoercedInt 2022-03-01 14:03:32 -07:00
Andrew Kelley
4763fd1a41 Sema: clean up peer resolution of errors
* Fix compile error for `zirErrorUnionType`.
 * Convert zirMergeErrorSets logic to call `Type.errorSetMerge`.
   It does not need to create a Decl as the TODO comment hinted.
 * Extract out a function called `resolveInferredErrorSetTy`.
 * Rework `resolvePeerTypes` with respect to error unions and
   error sets. This is a less complex implementation that passes all the
   same tests and uses many fewer lines of code by taking advantage of
   the function `coerceInMemoryAllowedErrorSets`.
   - Always merge error sets in the order that makes sense, even when
     that means `@typeInfo` incompatibility with stage1.
 * `Type.errorSetMerge` no longer overallocates.
 * Don't skip passing tests.
2022-02-28 23:15:58 -07:00
Mitchell Hashimoto
bfada7c514 stage2: implement peer type resolution between error unions 2022-02-28 20:42:13 -07:00
Andrew Kelley
d5131e91eb Sema: complete the Type.hash function
Similar to how Type.eql was reworked in the previous commit, this commit
reworks Type.hash to check all the different kinds of tags that a Type
can be represented with. It also completes the implementation for all
types except error sets, which need to have Type.eql enhanced as well.
2022-02-28 20:05:21 -07:00
Andrew Kelley
157f66ec07 Sema: fix pointer type hash and equality functions
Several issues with pointer types are fixed:

Prior to this commit, Zig would not canonicalize a pointer type with
an explicit alignment to alignment=0 if it matched the pointee ABI
alignment. In order to fix this, `Type.ptr` now takes a Target
parameter. I also moved the host_size canonicalization to `Type.ptr`
since target is now available. Similarly, is_allowzero in the case of
C pointers is now treated as a canonicalization done by the function
rather than a precondition.

in-memory coercion for pointers now properly checks ABI alignment
of pointee types instead of incorrectly treating the 0 value as an
alignment.

Type equality is completely reworked based on the tag() rather than the
zigTypeTag(). It's still semantically based on zigTypeTag() but that
knowledge is implied rather than dictating the control flow of the
logic. Importantly, this fixes cases for opaques, structs, tuples,
enums, and unions, where type equality was incorrectly returning based
on whether the tag() values were equal.

Additionally, pointer type equality now takes into account alignment.
Because we canonicalize non-zero alignment which equals pointee type ABI
alignment to alignment=0, this now can be a simple integer comparison.

Type hashing is implemented for pointers and floats. Array types now
additionally hash their sentinels.

This regressed some behavior tests that were passing but only because
of bugs regarding type equality.

The C backend has a noticeable problem with lowering differently-aligned
pointers (particularly slices) as the same type, causing C compilation
errors due to duplicate declarations.
2022-02-28 19:22:16 -07:00
Veikka Tuominen
dfeffcfbf8 stage2: tuple mul/cat 2022-02-28 13:09:14 -07:00
Veikka Tuominen
1bbca4f935 stage2: fix bitcast to optional ptr in llvm backend; omit safety check for intToPtr on optional ptr 2022-02-27 12:15:49 +02:00
Andrew Kelley
32e89a98d8 Sema: implement union value equality at comptime
Still TODO is extern unions.
2022-02-26 20:59:23 -07:00
Veikka Tuominen
bf3c88b68d stage2: various fixes to get one test passing
* resolve error sets before merging them
* implement tupleFieldPtr
* make ret_ptr behave like alloc with zero sized types in llvm backend
2022-02-26 18:44:23 -05:00
Veikka Tuominen
ee149aaa03 stage2: actually coerce in coerce_result_ptr at comptime 2022-02-26 12:51:23 -07:00
Andrew Kelley
6249a24e81 stage2: integer-backed packed structs
This implements #10113 for the self-hosted compiler only. It removes the
ability to override alignment of packed struct fields, and removes the
ability to put pointers and arrays inside packed structs.

After this commit, nearly all the behavior tests pass for the stage2 llvm
backend that involve packed structs.

I didn't implement the compile errors or compile error tests yet. I'm
waiting until we have stage2 building itself and then I want to rework
the compile error test harness with inspiration from Vexu's arocc test
harness. At that point it should be a much nicer dev experience to work
on compile errors.
2022-02-23 23:59:25 -07:00
Veikka Tuominen
92beb2b490 stage2: misc fixes in Sema 2022-02-23 10:40:40 +02:00
Andrew Kelley
7d9e3840bb Sema: fix inline break from a non-comptime scope to outer one
Prior to this, the compiler would hit an assertion because the
break_inline would not successfully move the compile-time control flow.
2022-02-20 00:20:29 -07:00
Andrew Kelley
746435a954 Sema: implement @typeInfo for list literals 2022-02-19 15:11:18 -07:00
Andrew Kelley
a024aff932 make f80 less hacky; lower as u80 on non-x86
Get rid of `std.math.F80Repr`. Instead of trying to match the memory
layout of f80, we treat it as a value, same as the other floating point
types. The functions `make_f80` and `break_f80` are introduced to
compose an f80 value out of its parts, and the inverse operation.

stage2 LLVM backend: fix pointer to zero length array tripping LLVM
assertion. It now checks for when the element type is a zero-bit type
and lowers such thing the same way that pointers to other zero-bit types
are lowered.

Both stage1 and stage2 LLVM backends are adjusted so that f80 is lowered
as x86_fp80 on x86_64 and i386 architectures, and identical to a u80 on
others. LLVM constants are lowered in a less hacky way now that #10860
is fixed, by using the expression `(exp << 64) | fraction` using llvm
constants.

Sema is improved to handle c_longdouble by recursively handling it
correctly for whatever the float bit width is. In both stage1 and
stage2.
2022-02-12 11:18:23 +01:00
Andrew Kelley
97019bc56d Sema: handle inferred error set tail call
When Sema sees a store_node instruction, it now checks for
the possibility of this pattern:
  %a = ret_ptr
  %b = store(%a, %c)
Where %c is an error union. In such case we need to add to the
current function's inferred error set, if any.

Coercion from error union to error union will be handled ideally if the
operand is comptime known. In such case it does the appropriate
unwrapping, then wraps again.

In the future, coercion from error union to error union should do the
same thing for a runtime value; emitting a runtime branch to check if
the value is an error or not.

`Value.arrayLen` for structs returns the number of fields. This is so
that Liveness can use it for the `vector_init` instruction (soon to be
renamed to `aggregate_init`).
2022-02-09 00:10:53 -07:00
Andrew Kelley
f4fa32a632 Sema: fix @typeInfo for pointers returning 0 alignment 2022-02-08 23:02:13 -07:00
Andrew Kelley
95fbce2b95 Sema: fixes to fieldVal, resolveStructFully, Type.eql
fieldVal handles pointer to pointer to array. This can happen for
example, if a pointer to an array is used as the condition expression of
a for loop.

resolveStructFully handles tuples (by doing nothing).

fixed Type comparison for tuples to handle comptime fields properly.
2022-02-03 23:59:32 -07:00
Andrew Kelley
0893326e0e Sema: slice improvements
* resolve_inferred_alloc now gives a proper mutability attribute to the
   corresponding alloc instruction. Previously, it would fail to mark
   things const.
 * slicing: fix the detection for when the end index equals the length
   of the underlying object. Previously it was using `end - start` but
   it should just use the end index directly. It also takes into account
   when slicing a comptime-known slice.
 * `Type.sentinel`: fix not handling all slice tags
2022-02-03 21:05:10 -07:00
Andrew Kelley
39983d7ff5 stage2: update to new ArrayHashMap API 2022-01-31 21:12:37 -07:00
Veikka Tuominen
a31a749c42 stage1: add f80 type 2022-01-28 11:45:04 -07:00
Andrew Kelley
a2abbeef90 stage2: rework a lot of stuff
AstGen:
 * rename the known_has_bits flag to known_non_opv to make it better
   reflect what it actually means.
 * add a known_comptime_only flag.
 * make the flags take advantage of identifiers of primitives and the
   fact that zig has no shadowing.
 * correct the known_non_opv flag for function bodies.

Sema:
 * Rename `hasCodeGenBits` to `hasRuntimeBits` to better reflect what it
   does.
   - This function got a bit more complicated in this commit because of
     the duality of function bodies: on one hand they have runtime bits,
     but on the other hand they require being comptime known.
 * WipAnonDecl now takes a LazySrcDecl parameter and performs the type
   resolutions that it needs during finish().
 * Implement comptime `@ptrToInt`.

Codegen:
 * Improved handling of lowering decl_ref; make it work for
   comptime-known ptr-to-int values.
   - This same change had to be made many different times; perhaps we
     should look into merging the implementations of `genTypedValue`
     across x86, arm, aarch64, and riscv.
2022-01-24 21:53:57 -07:00
Andrew Kelley
b34f994c0b stage2: type system treats fn ptr and body separately
This commit updates stage2 to enforce the property that the syntax
`fn()void` is a function *body* not a *pointer*. To get a pointer, the
syntax `*const fn()void` is required.

ZIR puts function alignment into the func instruction rather than the
decl because this way it makes it into function types. LLVM backend
respects function alignments.

Struct and Union have methods `fieldSrcLoc` to help look up source
locations of their fields. These trigger full loading, tokenization, and
parsing of source files, so should only be called once it is confirmed
that an error message needs to be printed.

There are some nice new error hints for explaining why a type is
required to be comptime, particularly for structs that contain function
body types.

`Type.requiresComptime` is now moved into Sema because it can fail and
might need to trigger field type resolution. Comptime pointer loading
takes into account types that do not have a well-defined memory layout
and does not try to compute a byte offset for them.

`fn()void` syntax no longer secretly makes a pointer. You get a function
body type, which requires comptime. However a pointer to a function body
can be runtime known (obviously).

Compile errors that report "expected pointer, found ..." are factored
out into convenience functions `checkPtrOperand` and `checkPtrType` and
have a note about function pointers.

Implemented `Value.hash` for functions, enum literals, and undefined values.

stage1 is not updated to this (yet?), so some workarounds and disabled
tests are needed to keep everything working. Should we update stage1 to
these new type semantics? Yes probably because I don't want to add too
much conditional compilation logic in the std lib for the different
backends.
2022-01-24 21:47:53 -07:00
Andrew Kelley
c9ae24503d
Merge pull request #10649 from ziglang/stage2-tuples
stage2: implement tuples
2022-01-20 18:24:01 -05:00
Luuk de Gram
f763000dc9 Fix abi size of optional slices
Previously, optional slices returned the pointer size as abi size.
We now account for slices to calculate the correct size which is abi-alignment + slice ABI size.
2022-01-20 18:19:20 -05:00
Andrew Kelley
4fccc95b01 Sema: fix requiresComptime infinite recursion
When asking a struct or union whether the type requires comptime, it may
need to ask itself recursively, for example because of a field which is
a pointer to itself. This commit adds a field to each to keep track of
when computing the "requires comptime" value and returns `false` if the
check is already ongoing.
2022-01-20 16:17:16 -07:00