aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
AgeCommit message (Collapse)Author
2024-04-17compiler: rework comptime pointer representation and accessmlugg
We've got a big one here! This commit reworks how we represent pointers in the InternPool, and rewrites the logic for loading and storing from them at comptime. Firstly, the pointer representation. Previously, pointers were represented in a highly structured manner: pointers to fields, array elements, etc, were explicitly represented. This works well for simple cases, but is quite difficult to handle in the cases of unusual reinterpretations, pointer casts, offsets, etc. Therefore, pointers are now represented in a more "flat" manner. For types without well-defined layouts -- such as comptime-only types, automatic-layout aggregates, and so on -- we still use this "hierarchical" structure. However, for types with well-defined layouts, we use a byte offset associated with the pointer. This allows the comptime pointer access logic to deal with reinterpreted pointers far more gracefully, because the "base address" of a pointer -- for instance a `field` -- is a single value which pointer accesses cannot exceed since the parent has undefined layout. This strategy is also more useful to most backends -- see the updated logic in `codegen.zig` and `codegen/llvm.zig`. For backends which do prefer a chain of field and elements accesses for lowering pointer values, such as SPIR-V, there is a helpful function in `Value` which creates a strategy to derive a pointer value using ideally only field and element accesses. This is actually more correct than the previous logic, since it correctly handles pointer casts which, after the dust has settled, end up referring exactly to an aggregate field or array element. In terms of the pointer access code, it has been rewritten from the ground up. The old logic had become rather a mess of special cases being added whenever bugs were hit, and was still riddled with bugs. The new logic was written to handle the "difficult" cases correctly, the most notable of which is restructuring of a comptime-only array (for instance, converting a `[3][2]comptime_int` to a `[2][3]comptime_int`. Currently, the logic for loading and storing work somewhat differently, but a future change will likely improve the loading logic to bring it more in line with the store strategy. As far as I can tell, the rewrite has fixed all bugs exposed by #19414. As a part of this, the comptime bitcast logic has also been rewritten. Previously, bitcasts simply worked by serializing the entire value into an in-memory buffer, then deserializing it. This strategy has two key weaknesses: pointers, and undefined values. Representations of these values at comptime cannot be easily serialized/deserialized whilst preserving data, which means many bitcasts would become runtime-known if pointers were involved, or would turn `undefined` values into `0xAA`. The new logic works by "flattening" the datastructure to be cast into a sequence of bit-packed atomic values, and then "unflattening" it; using serialization when necessary, but with special handling for `undefined` values and for pointers which align in virtual memory. The resulting code is definitely slower -- more on this later -- but it is correct. The pointer access and bitcast logic required some helper functions and types which are not generally useful elsewhere, so I opted to split them into separate files `Sema/comptime_ptr_access.zig` and `Sema/bitcast.zig`, with simple re-exports in `Sema.zig` for their small public APIs. Whilst working on this branch, I caught various unrelated bugs with transitive Sema errors, and with the handling of `undefined` values. These bugs have been fixed, and corresponding behavior test added. In terms of performance, I do anticipate that this commit will regress performance somewhat, because the new pointer access and bitcast logic is necessarily more complex. I have not yet taken performance measurements, but will do shortly, and post the results in this PR. If the performance regression is severe, I will do work to to optimize the new logic before merge. Resolves: #19452 Resolves: #19460
2024-04-13cbe: fix optional codegenJacob Young
Also reduce ctype pool string memory usage, remove self assignments, and enable more warnings.
2024-04-08InternPool: remove slice from byte aggregate keysJacob Young
This deletes a ton of lookups and avoids many UAF bugs. Closes #19485
2024-04-08cbe: fix struct field location computationJacob Young
2024-04-08cbe: remove threadlocal variables in single threaded modeJacob Young
2024-04-06Builder: fix encoding big integers in bitcodeJacob Young
Closes #19543
2024-03-30cbe: fix uncovered bugsJacob Young
2024-03-30cbe: rewrite `CType`Jacob Young
Closes #14904
2024-03-30cbe: fix bugs revealed by an upcoming commitJacob Young
Closes #18023
2024-03-26compiler: eliminate most usages of TypedValuemlugg
2024-03-26Zcu: eliminate `Decl.alive` fieldmlugg
Legacy anon decls now have three uses: * Type owner decls * Function owner decls * `@export` and `@extern` Therefore, there are no longer any cases where we wish to explicitly omit legacy anon decls from the binary. This means we can remove the concept of an "alive" vs "dead" `Decl`, which also allows us to remove the separate `anon_work_queue` in `Compilation`.
2024-03-26compiler: eliminate legacy Value representationmlugg
Good riddance! Most of these changes are trivial. There's a fix for a minor bug this exposed in `Value.readFromPackedMemory`, but aside from that, it's all just things like changing `intern` calls to `toIntern`.
2024-03-26Zcu.Decl: remove `ty` fieldmlugg
`Decl` can no longer store un-interned values, so this field is now unnecessary. The type can instead be fetched with the new `typeOf` helper method, which just gets the type of the Decl's `Value`.
2024-03-25compiler: implement analysis-local comptime-mutable memorymlugg
This commit changes how we represent comptime-mutable memory (`comptime var`) in the compiler in order to implement the intended behavior that references to such memory can only exist at comptime. It does *not* clean up the representation of mutable values, improve the representation of comptime-known pointers, or fix the many bugs in the comptime pointer access code. These will be future enhancements. Comptime memory lives for the duration of a single Sema, and is not permitted to escape that one analysis, either by becoming runtime-known or by becoming comptime-known to other analyses. These restrictions mean that we can represent comptime allocations not via Decl, but with state local to Sema - specifically, the new `Sema.comptime_allocs` field. All comptime-mutable allocations, as well as any comptime-known const allocs containing references to such memory, live in here. This allows for relatively fast checking of whether a value references any comptime-mtuable memory, since we need only traverse values up to pointers: pointers to Decls can never reference comptime-mutable memory, and pointers into `Sema.comptime_allocs` always do. This change exposed some faulty pointer access logic in `Value.zig`. I've fixed the important cases, but there are some TODOs I've put in which are definitely possible to hit with sufficiently esoteric code. I plan to resolve these by auditing all direct accesses to pointers (most of them ought to use Sema to perform the pointer access!), but for now this is sufficient for all realistic code and to get tests passing. This change eliminates `Zcu.tmp_hack_arena`, instead using the Sema arena for comptime memory mutations, which is possible since comptime memory is now local to the current Sema. This change should allow `Decl` to store only an `InternPool.Index` rather than a full-blown `ty: Type, val: Value`. This commit does not perform this refactor.
2024-03-17cbe: rework StringLiteral to decide between string literal or array ↵kcbanner
initializator syntax This fixes an issue with boostrapping the compiler using MSVC. There is a CircularBuffer with an array of length 65536 initialized to undefined, and because the undefined path of `renderValue` was using `StringLiteral` to render this, the resulting zig2.c would fail to compile using MSVC. The solution was to move the already-existing array initializer path (used in the non-undefined path) into StringLiteral, and make StringLiteral aware of the total length so it could decide between which style of initialization to use. We prefer to use string literals if we can, as this results in the least amount of emitted C source.
2024-03-17AstGen: disallow alignment on function typesJacob Young
A pointer type already has an alignment, so this information does not need to be duplicated on the function type. This already has precedence with addrspace which is already disallowed on function types for this reason. Also fixes `@TypeOf(&func)` to have the correct addrspace and alignment.
2024-03-11std.builtin: make atomic order fields lowercaseTristan Ross
2024-03-11std.builtin: make global linkage fields lowercaseTristan Ross
2024-03-11std.builtin: make container layout fields lowercaseTristan Ross
2024-03-06Fix incorrectly resolved merge conflictsmlugg
To be honest, I can't be bothered to figure out which commits these changes should be in.
2024-03-06InternPool: create specialized functions for loading namespace typesmlugg
Namespace types (`struct`, `enum`, `union`, `opaque`) do not use structural equality - equivalence is based on their Decl index (and soon will change to AST node + captures). However, we previously stored all other information in the corresponding `InternPool.Key` anyway. For logical consistency, it makes sense to have the key only be the true key (that is, the Decl index) and to load all other data through another function. This introduces those functions, by the name of `loadStructType` etc. It's a big diff, but most of it is no-brainer changes. In future, it might be nice to eliminate a bunch of the loaded state in favour of accessor functions on the `LoadedXyzType` types (like how we have `LoadedUnionType.size()`), but that can be explored at a later date.
2024-03-02Air: replace `.dbg_inline_*` with `.dbg_inline_block`Jacob Young
This prevents the possibility of not emitting a `.dbg_inline_end` instruction and reduces the allocation requirements of the backends. Closes #19093
2024-02-26move Zcu.LazySrcLoc to std.zig.LazySrcLocAndrew Kelley
Part of an effort to ship more of the compiler in source form.
2024-02-26compiler: decide dbg_var scoping based on AIR blocksmlugg
This commit eliminates the `dbg_block_{begin,end}` instructions from both ZIR and AIR. Instead, lexical scoping of `dbg_var_{ptr,val}` instructions is decided based on the AIR block they exist within. This is a much more robust system, and also results in a huge drop in ZIR bytes - around 7% for Sema.zig. This required some enhancements to Sema to prevent elision of blocks when they are required for debug variable scoping. This can be observed by looking at the AIR for the following simple test program with and without `-fstrip`: ```zig export fn f() void { { var a: u32 = 0; _ = &a; } { var a: u32 = 0; _ = &a; } } ``` When `-fstrip` is passed, no AIR blocks are generated. When `-fno-strip` is passed, the ZIR blocks are lowered to true AIR blocks to give correct lexical scoping to the debug vars. The changes here incidentally reolve #19060. A corresponding behavior test has been added. Resolves: #19060
2024-02-25x86_64: implement optional comparisonsJacob Young
Closes #18959
2024-02-25Sema: implement vector coercionsJacob Young
These used to be lowered elementwise in air, and now are a single air instruction that can be lowered elementwise in the backend if necessary.
2024-02-19cbe: make more use of `InternPool.Index.Slice`Jacob Young
Attempts to fix the current CI failures introduced by #18983.
2024-02-16InternPool: make more use of `NullTerminatedString.Slice`Jacob Young
This should avoid the random pointer invalidation crashes. Closes #18954
2024-02-07Merge pull request #17634 from ianprime0509/type-erased-writerAndrew Kelley
Add type-erased writer and GenericWriter
2024-02-05compiler: rename value.zig to Value.zigAndrew Kelley
This commit only does the file rename to be friendlier to version control conflicts.
2024-02-02InternPool: use separate key for slicesmlugg
This change eliminates some problematic recursive logic in InternPool, and provides a safer API.
2024-01-29llvm: ensure returned undef is 0xaa bytes when runtime safety is enabledVeikka Tuominen
Closes #13178
2024-01-29Introduce type-erased writers to C backend codegenIan Johnson
This reduces generic instantiations of several write functions. Before: ``` @as(type, io.writer.Writer(*array_list.ArrayListAligned(u8,null),error{OutOfMemory},(function 'appendWrite'))) @as(type, io.writer.Writer(*codegen.c.IndentWriter(io.writer.Writer(*array_list.ArrayListAligned(u8,null),error{OutOfMemory},(function 'appendWrite'))),error{OutOfMemory},(function 'write'))) ``` After: ``` @as(type, io.GenericWriter(io.Writer,error{OutOfMemory},(function 'write'))) ```
2024-01-03cbe: fix non-msvc externs and exportsJacob Young
Closes #17817
2024-01-03Reapply "Merge pull request #17824 from kcbanner/fixup_msvc_fmax"Jacob Young
This reverts commit 2b589783602c5428ecde9dbb3f41a81f85eb0f25.
2024-01-01Revert "Merge pull request #17824 from kcbanner/fixup_msvc_fmax"Andrew Kelley
This reverts commit 7161ed79c4abcaccdd56fe0b4fbd3d93472d41b8, reversing changes made to 3f2a65594e1d3c0a4f4943a4ea522e8405db81e0. Unfortunately, this sat in the PR queue too long and the merge broke the zig1.wasm bootstrap process.
2024-01-01Merge pull request #17824 from kcbanner/fixup_msvc_fmaxAndrew Kelley
cbe: add a system for avoiding collisions with C compiler intrinsics
2023-12-03Air: use typesafe `Air.Inst.Index`Jacob Young
I need some indices for a thing...
2023-11-26move Module.Decl.Index and Module.Namespace.Index to InternPoolMeghan Denny
2023-11-25convert `toType` and `toValue` to `Type.fromInterned` and `Value.fromInterned`Techatrix
2023-11-12rework memory management of Module.Namespace hash mapsAndrew Kelley
The motivating problem here was a memory leak in the hash maps of Module.Namespace. The commit deletes more of the legacy incremental compilation implementation. It had things like use of orderedRemove and trying to do too much OOP-style creation and deletion of objects. Instead, this commit iterates over all the namespaces on Module deinit and calls deinit on the hash map fields. This logic is much simpler to reason about. Similarly, change global inline assembly to an array hash map since iterating over the values is a primary use of it, and clean up the remaining values on Module deinit, solving another memory leak. After this there are no more memory leaks remaining when using the x86 backend in a libc-less compiler.
2023-11-07cbe: support rendering union values that have no defined tag typekcbanner
This was regressed in d657b6c0e2ab7c47f5416dc4df1abb2bfbecd4b6, when the comptime memory model for unions was changed to allow them to have no defined tag type.
2023-11-05cbe: handle underscore prexfix on macos, don't mangle extern function nameskcbanner
2023-11-05cbe: add DeclVisibility and zig_extern_mangled to handle exporting mangled ↵kcbanner
symbols under a different name
2023-11-05cbe: avoid collisions with builtins and intrinsicskcbanner
Changes: - Add `isMangledIdent` to determine if `fmtIdent` would make any edits to the identifier - Any function that has a mangled identifier is referred to using the mangled identifer within the current file, but if it is exported the first export will be with the non-mangled name. - Add `zig_import` to import a symbol under a different name - Add a level of indirection to float function names. Now, they are referred to as `zig_float_fn_<float type>_<operation>`. The definitions in zig.h are wrapped with `zig_import` to import the symbol under the real name. The specific problem that sparked this change was the combination of `zig_libc_name_f80(name) __##name##x` with the input `fma`, resulting in `__fmax`, which is a new intrinsic in recent versions of cl.exe. With the above changes in place, compiler_rt can output the following: ``` static zig_weak_linkage_fn zig_f80 zig_e___fmax(zig_f80, zig_f80, zig_f80); zig_export(zig_weak_linkage_fn zig_f80 zig_e___fmax(zig_f80, zig_f80, zig_f80), __fmax, "__fmax"); ``` Within compiler_rt, `zig_e___fmax` is used to refer to the function, but consumers will import `__fmax`, which maps to their `zig_float_fn_f80_fma` definition from zig.h.
2023-10-31cbe: fix `@bitCast` warningsJacob Young
2023-10-31std.builtin.Endian: make the tags lower caseAndrew Kelley
Let's take this breaking change opportunity to fix the style of this enum.
2023-10-25C backend: remove some `@as`Andrew Kelley
2023-10-25cbe: update `DeclGen.decl_index` to support anon declsJacob Young
2023-10-24InternPool: remove runtime_value representationmlugg
The main goal of this commit is to remove the `runtime_value` field from `InternPool.Key` (and its associated representation), but there are a few dominos. Specifically, this mostly eliminates the "maybe runtime" concept from value resolution in Sema: so some resolution functions like `resolveMaybeUndefValAllowVariablesMaybeRuntime` are gone. This required a small change to struct/union/array initializers, to no longer use `runtime_value` if a field was a `variable` - I'm not convinced this case was even reachable, as `variable` should only ever exist as the trivial value of a global runtime `var` decl. Now, the only case in which a `Sema.resolveMaybeUndefVal`-esque function can return the `variable` key is `resolveMaybeUndefValAllowVariables`, which is directly called from `Sema.resolveInstValueAllowVariables` (previously `Sema.resolveInstValue`), which is only used for resolving the value of a Decl from `Module.semaDecl`. While changing these functions, I also slightly reordered and restructured some of them, and updated their doc comments.