Kick-start initial work on new cross-platform abstraction for
sockets. Adds a test for read timeouts and a test for creating
a non-blocking socket pair on Linux.
The new Socket abstraction is barebones and is made to support both
blocking and non-blocking abstractions, alongside different socket
protocols and domains.
Support for platform-dependant socket options that handles unsupported
platforms gracefully via. comptime checks is provided for the new Socket
abstraction.
This also marks the first out of many commits for introducing breaking
changes to the standard library in a separate `x` folder, which was
pre-approved by @andrewrk.
The intent for the new `x` package is to introduce new async, event loop,
networking, and operating system abstractions that would require breaking
the standard library significantly. By having the `x` package, code in the
standard library and compiler may then slowly be refactored to use the `x`
package. Once modules in the `x` package are stabilized, they can be moved
out of the `x` package, and a global 'grep' can be done to update import
paths that resolve to the stabilized module in the `x` package.
This branch adds "builtin" and "std" to the import table when using the
self-hosted backend.
"builtin" gains one additional item:
```
pub const zig_is_stage2 = true; // false when using stage1 backend
```
This allows the std lib to do conditional compilation based on detecting
which backend is being used. This will be removed from builtin as soon
as self-hosted catches up to feature parity with stage1.
Keep a sharp eye out - people are going to be tempted to abuse this.
The general rule of thumb is do not use `builtin.zig_is_stage2`. However
this commit breaks the rule so that we can gain limited start.zig support
as we incrementally improve the self-hosted compiler.
This commit also implements `fullyQualifiedNameHash` and related
functionality, which effectively puts all Decls in their proper
namespaces. `fullyQualifiedName` is not yet implemented.
Stop printing "todo" log messages for test decls unless we are in test
mode.
Add "previous definition here" error notes for Decl name collisions.
This commit does not bring us yet to a newly passing test case.
Here's what I'm working towards:
```zig
const std = @import("std");
export fn main() c_int {
const a = std.fs.base64_alphabet[0];
return a - 'A';
}
```
Current output:
```
$ ./zig-cache/bin/zig build-exe test.zig
test.zig:3:1: error: TODO implement more analyze elemptr
zig-cache/lib/zig/std/start.zig:38:46: error: TODO implement structInitExpr ty
```
So the next steps are clear:
* Sema: improve elemptr
* AstGen: implement structInitExpr
Conflicts:
* lib/std/zig/ast.zig
* lib/std/zig/parse.zig
* lib/std/zig/parser_test.zig
* lib/std/zig/render.zig
* src/Module.zig
* src/zir.zig
I resolved some of the conflicts by reverting a small portion of
@tadeokondrak's stage2 logic here regarding `callconv(.Inline)`.
It will need to get reworked as part of this branch.
Also known as "Struct-Of-Arrays" or "SOA". The purpose of this data
structure is to provide a similar API to ArrayList but instead of
the element type being a struct, the fields of the struct are in N
different arrays, all with the same length and capacity.
Having this abstraction means we can put them in the same allocation,
avoiding overhead with the allocator. It also saves a tiny bit of
overhead from the redundant capacity and length fields, since each
struct element shares the same value.
This is an alternate implementation to #7854.
* move concurrency primitives that always operate on kernel threads to
the std.Thread namespace
* remove std.SpinLock. Nobody should use this in a non-freestanding
environment; the other primitives are always preferable. In
freestanding, it will be necessary to put custom spin logic in there,
so there are no use cases for a std lib version.
* move some std lib files to the top level fields convention
* add std.Thread.spinLoopHint
* add std.Thread.Condition
* add std.Thread.Semaphore
* new implementation of std.Thread.Mutex for Windows and non-pthreads Linux
* add std.Thread.RwLock
Implementations provided by @kprotty
* split std.ResetEvent into:
- ResetEvent - requires init() at runtime and it can fail. Also
requires deinit().
- StaticResetEvent - can be statically initialized and requires no
deinitialization. Initialization cannot fail.
* the POSIX sem_t implementation can in fact fail on initialization
because it is allowed to be implemented as a file descriptor.
* Completely define, clarify, and explain in detail the semantics of
these APIs. Remove the `isSet` function.
* `ResetEvent.timedWait` returns an enum instead of a possible error.
* `ResetEvent.init` takes a pointer to the ResetEvent instead of
returning a copy.
* On Darwin, `ResetEvent` is implemented using Grand Central Dispatch,
which is exposed by libSystem.
stage2 changes:
* ThreadPool: use a single, pre-initialized `ResetEvent` per worker.
* WaitGroup: now requires init() and deinit() and init() can fail.
- Add a `reset` function.
- Compilation initializes one for the work queue in creation and
re-uses it for every update.
- Rename `stop` to `finish`.
- Simplify the implementation based on the usage pattern.
We generally get away with atomic primitives, however a lock is required
around the refresh function since it traverses the Node graph, and we
need to be sure no references to Nodes remain after end() is called.
I spent a long time working on this data structure, and I still think
it's a neat idea, but it has no business being in the std lib.
I'm aware of the few remaining references to SegmentedList that exist in
the std lib, but they are dead code, and so I'm leaving the dead
references as a clue that the code is dead. Cleaning up dead code will
be a separate effort that involves code coverage tools to make sure we
find it all.
std-lib-orphanage commit: 2c36a7894c689ecbaf63d5f489bb0c68773410c4
closes#7190
* Move leb128 out of debug and remove trivial *mem functions as discussed in #5588
* Turns out one of the *Mem functions was used by MachO. Replaced with trivial use of FixedBufferStream.
I want to take the design of this in a different direction. I think this
abstraction is too high level. I want to start bottom-up.
std-lib-orphanage commit 179ae67d61455758d71037434704fd4a17a635a9
https://github.com/ziglang/std-lib-orphanage/
This code is not used by anything else in the standard library or by the
compiler or any of its tools and therefore it's a great candidate
to be maintained by a third party.
The API is pretty specific to the implementationt details of the
self-hosted compiler. I don't want to have to independently support
and maintain this as part of the standard library, and be obligated
to not make breaking changes to it with changes to the implementation of
stage2.
* std.Mutex API is improved to not have init() deinit(). This API is
designed to support static initialization and does not require any
resource cleanup. This also happens to work around some kind of
stage1 behavior that wasn't letting the new allocator mutex code
get compiled.
* the general purpose allocator now returns a bool from deinit()
which tells if there were any leaks. This value is used by the test
runner to fail the tests if there are any.
* self-hosted compiler is updated to use the general purpose allocator
when not linking against libc.
std.log provides 8 log levels and corresponding logging functions. It
allows the user to override the logging "backend" by defining root.log
and to override the default log level by defining root.log_level.
Logging functions accept a scope parameter which allows the implementer
of the logging "backend" to filter logging by library as well as level.
Using the standardized syslog [1] log levels ensures that std.log will
be flexible enough to work for as many use-cases as possible. If we were
to stick with only 3/4 log levels, std.log would be insufficient for
large and/or complex projects such as a kernel or display server.
[1]: https://tools.ietf.org/html/rfc5424#section-6.2.1
* introduce std.ArrayListUnmanaged for when you have the allocator
stored elsewhere
* move std.heap.ArenaAllocator implementation to its own file. extract
the main state into std.heap.ArenaAllocator.State, which can be
stored as an alternative to storing the entire ArenaAllocator, saving
24 bytes per ArenaAllocator on 64 bit targets.
* std.LinkedList.Node pointer field now defaults to being null
initialized.
* Rework self-hosted compiler Package API
* Delete almost all the bitrotted self-hosted compiler code. The only bit
rotted code left is in main.zig and compilation.zig
* Add call instruction to ZIR
* self-hosted compiler ir API and link API are reworked to support
a long-running compiler that incrementally updates declarations
* Introduce the concept of scopes to ZIR semantic analysis
* ZIR text format supports referencing named decls that are declared
later in the file
* Figure out how memory management works for the long-running compiler
and incremental compilation. The main roots are top level
declarations. There is a table of decls. The key is a cryptographic
hash of the fully qualified decl name. Each decl has an arena
allocator where all of the memory related to that decl is stored.
Each code block has its own arena allocator for the lifetime of
the block. Values that want to survive when going out of scope in
a block must get copied into the outer block. Finally, values must
get copied into the Decl arena to be long-lived.
* Delete the unused MemoryCell struct. Instead, comptime pointers are
based on references to Decl structs.
* Figure out how caching works. Each Decl will store a set of other
Decls which must be recompiled when it changes.
This branch is still work-in-progress; this commit breaks the build.
This new name (and the fact that it is a function returning a type) will
make it more clear which use cases are better suited for ArrayList and
which are better suited for ArrayListSentineled.
Also for consistency with ArrayList,
* `append` => `appendSlice`
* `appendByte` => `append`
Thanks daurnimator for pointing out the confusion of std.Buffer.
Previously, the compiler had special logic to determine whether to
include the startup code, which was in `std/special/start.zig`. Now,
the file is moved to `std/start.zig`, and there is no special logic
in the compiler. Instead, the standard library unconditionally imports
the `start.zig` file, which then has a `comptime` block that does the
logic of determining what, if any, start symbols to export. Instead of
`start.zig` being in its own special package, it is just another normal
file that is part of the standard library.
`std.builtin.TestFn` is now part of the standard library rather than
specially generated by the compiler.