395 Commits

Author SHA1 Message Date
Jakub Konka
a615425b51 Merge branch 'linker-eport-symbols' of github.com:Luukdegram/zig into Luukdegram-linker-eport-symbols 2022-01-11 11:30:53 +01:00
Luuk de Gram
247b638ccf
Pass --allow-unknown-exports to wasmtime
Also skip exporting non-function symbols when we're building a WASI command using the stage2 llvm backend.
2022-01-07 18:35:08 +01:00
Meghan
c08b190c69
lint: duplicate import (#10519) 2022-01-07 00:06:06 -05:00
Luuk de Gram
6d951aff7e
wasm-linker: Only export symbols notated as such
This exposes a function from stage2 to stage1 to append symbols to automatically export them.

This happends under the following conditions:
- Target is wasm
- User has not provided --export/--rdynamic flags themselves.
2022-01-06 20:19:47 +01:00
Andrew Kelley
1c24ef0d0b stage2: introduce std.builtin.CompilerBackend
This allows Zig code to perform conditional compilation based on a tag
by which a Zig compiler implementation identifies itself.

See the doc comment in this commit for more details.
2022-01-04 18:12:45 -07:00
Andrew Kelley
d94303be2b stage2: introduce renameTmpIntoCache into the linker API
Doc comments reproduced here:

This function is called by the frontend before flush(). It communicates that
`options.bin_file.emit` directory needs to be renamed from
`[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`.
The frontend would like to simply perform a file system rename, however,
some linker backends care about the file paths of the objects they are linking.
So this function call tells linker backends to rename the paths of object files
to observe the new directory path.
Linker backends which do not have this requirement can fall back to the simple
implementation at the bottom of this function.
This function is only called when CacheMode is `whole`.

This solves stack trace regressions on Windows and macOS because the
linker backends do not observe object file paths until flush().
2022-01-03 14:49:35 -07:00
Andrew Kelley
663ffa5a7a stage2: fix missing items from whole cache mode hash
Without this, Zig would re-use a compiler-rt built with stage2 when one
built by stage1 was needed.
2022-01-02 18:54:47 -07:00
Andrew Kelley
9dc25dd0b6 stage2: fix UAF of system_libs 2022-01-02 13:16:17 -07:00
Andrew Kelley
55243cfb31 stage2: fix implibs
Broken by the introduction of `CacheMode.whole`, they are now working
again by using the same mechanism as emitted binary files.
2022-01-02 13:16:17 -07:00
Andrew Kelley
013c286e43 stage2: fix memory leak in addNonIncrementalStuffToCacheManifest
I accidentally used errdefer instead of defer for the function-local
arena.
2022-01-02 13:16:17 -07:00
Andrew Kelley
73ba6bf30b stage2: fix memory leak of emit_bin.sub_path
Instead of juggling GPA-allocated sub_path (and ultimately dropping the
ball, in this analogy), `Compilation.create` allocates an
already-exactly-correct size `sub_path` that has the digest unpopulated.

This is then overwritten in place as necessary and used as the
`emit_bin.sub_path` value, and no allocations/frees are performed for
this file path.
2022-01-02 13:16:17 -07:00
Andrew Kelley
208a6c7d6a stage2: fix not calling deinit() on whole_cache_manifest
Need to mark it as "needing cleanup" a bit earlier in the function.
2022-01-02 13:16:17 -07:00
Andrew Kelley
0ad2a99675 stage2: CacheMode.whole: trigger loading zig source files
Previously the code asserted source files were already loaded, but this
is not the case when cached ZIR is loaded. Now it will trigger .zig
source code to be loaded for the purposes of hashing the source for
`CacheMode.whole`.

This additionally refactors stat_size, stat_inode, and stat_mtime fields
into using the `Cache.File.Stat` struct.
2022-01-02 13:16:17 -07:00
Andrew Kelley
d6c5602d46 stage2: fix CLI not populating output binary files
This fixes a regression in this branch that can be reproduced with the
following steps:

1. `zig build-exe hello.zig`
2. delete the "hello" binary
3. `zig build-exe hello.zig`
4. observe that the "hello" binary is missing

This happened because it was a cache hit, but nothing got copied to the
output directory.

This commit sets CacheMode to incremental - even for stage1 - when the
CLI requests `disable_lld_caching` (this option should be renamed),
resulting in the main Compilation to be repeated (uncached) for stage1,
populating the binary into the cwd as expected.

For stage2 the result is even better: the incremental compilation system
will look for build artifacts to incrementally compile, and start fresh
if not found.
2022-01-02 13:16:17 -07:00
Andrew Kelley
67e31807df stage2: CacheMode.whole fixes
* Logic to check whether a bin file is not emitted is more complicated
   in between `Compilation.create` and `Compilation.update`. Fixed the
   logic that decides whether to build compiler-rt and other support
   artifacts.
 * Basically, one cannot inspect the value of `comp.bin_file.emit` until
   after update() is called - fixed another instance of this happening
   in the CLI.
 * In the CLI, `runOrTest` is updated to properly use the result value
   of `comp.bin_file.options.emit` rather than guessing whether the
   output binary is.
 * Don't assume that the emit output has no directory components in
   sub_path. In other words, don't assume that the emit directory is the
   final directory; there may be sub-directories.
2022-01-02 13:16:17 -07:00
Andrew Kelley
e3bed8d81d stage2: introduce CacheMode
The two CacheMode values are `whole` and `incremental`.
`incremental` is what we had before; `whole` is new.
Whole cache mode uses everything as inputs to the cache hash;
and when a hit occurs it skips everything including linking.
This is ideal for when source files change rarely and for backends that
do not have good incremental compilation support, for example
compiler-rt or libc compiled with LLVM with optimizations on.
This is the main motivation for the additional mode, so that we can have
LLVM-optimized compiler-rt/libc builds, without waiting for the LLVM
backend every single time Zig is invoked.

Incremental cache mode hashes only the input file path and a few target
options, intentionally relying on collisions to locate already-existing
build artifacts which can then be incrementally updated.

The bespoke logic for caching stage1 backend build artifacts
is removed since we now have a global caching mechanism for
when we want to cache the entire compilation, *including* linking.
Previously we had to get "creative" with libs.txt and a special
byte in the hash id to communicate flags, so that when the cached
artifacts were re-linked, we had this information from stage1
even though we didn't actually run it. Now that `CacheMode.whole`
includes linking, this extra information does not need to be
preserved for cache hits. So although this changeset introduces
complexity, it also removes complexity.

The main trickiness here comes from the inherent differences between the
two modes: `incremental` wants a directory immediately to operate on,
while `whole` doesn't know the output directory until the compilation is
complete. This commit deals with this problem mostly inside `update()`,
where, on a cache miss, it replaces `zig_cache_artifact_directory` with a
temporary directory, and then renames it into place once the compilation is
complete.

Items remaining before this branch can be merged:

* [ ] make sure these things make it into the cache manifest:
  - @import files
  - @embedFile files
  - we already add dep files from c but make sure the main .c files make
    it in there too, not just the included files

* [ ] double check that the emit paths of other things besides the binary
  are working correctly.

* [ ] test `-fno-emit-bin` + `-fstage1`
* [ ] test `-femit-bin=foo` + `-fstage1`

* [ ] implib emit directory copies bin_file_emit directory in create() and needs
  to be adjusted to be overridden as well.

* [ ] make sure emit-h is handled correctly in the cache hash
* [ ] Cache: detect duplicate files added to the manifest

Some preliminary performance measurements of wall clock time and
peak RSS used:

stage1 behavior (1077 tests), llvm backend, release build:
 * cold global cache: 4.6s, 1.1 GiB
 * warm global cache: 3.4s, 980 MiB

stage2 master branch behavior (575 tests), llvm backend, release build:
 * cold global cache: 0.62s, 191 MiB
 * warm global cache: 0.40s, 128 MiB

stage2 this branch behavior (575 tests), llvm backend, release build:
 * cold global cache: 0.62s, 179 MiB
 * warm global cache: 0.27s, 90 MiB
2022-01-02 13:16:17 -07:00
Andrew Kelley
6229d37dcf stage2: handle function dependency failures without crashing 2021-12-28 20:20:30 -07:00
Andrew Kelley
2cbeb85a96 stage2: error check for mixing --import-table and --export-table
is moved from the linker to the frontend. This is a follow-up from
4cb2f11693b1bf13770b8ad6a8b8a1e37101a516.
2021-12-21 18:21:42 -07:00
Luuk de Gram
4cb2f11693 wasm-linker: Implement the --export-table and --import-table flags.
This implements the flags for both the linker frontend as well as the self-hosted linker.

Closes #5790
2021-12-21 12:38:50 -08:00
Jakub Konka
a08137330c macho: handle -install_name option for dylibs/MachO
The status quo for the `build.zig` build system is preserved in
the sense that, if the user does not explicitly override
`dylib.setInstallName(...);` in their build script, the default
of `@rpath/libname.dylib` applies. However, should they want to
override the default behaviour, they can either:

1) unset it with

```dylib.setIntallName(null);```

2) set it to an explicit string with

```dylib.setInstallName("somename.dylib");```

When it comes to the command line however, the default is not to
use `@rpath` for the install name when creating a dylib. The user
will now be required to explicitly specify the `@rpath` as part
of the desired install name should they choose so like so:

1) with `build-lib`

```
zig build-lib -dynamic foo.zig -install_name @rpath/libfoo.dylib
```

2) with `cc`

```
zig cc -shared foo.c -o libfoo.dylib -Wl,"-install_name=@rpath/libfoo.dylib"
```
2021-12-18 17:55:53 -08:00
Andrew Kelley
c9863c0a0c CLI: helpful error message when libc requested but not provided 2021-12-16 03:01:13 -07:00
Andrew Kelley
e977455f7c glibc: improve RISC-V support
* omit crti.o / crtn.o for this architecture
 * add missing entry.h header from upstream
2021-12-15 18:34:27 -07:00
Andrew Kelley
4d48948b52 glibc: pass -D__GLIBC_MINOR__=XX
instead of hard-coding it. This means that C code has accurate glibc
version information in the preprocessor.
2021-12-15 17:52:27 -07:00
Luuk de Gram
50201e1c30 wasm-linker: Allow specifying symbols to be exported
Notating a symbol to be exported in code will only tell the linker
where to find this symbol, so other object files can find it. However, this does not mean
said symbol will also be exported to the host environment. Currently, we 'fix' this by force
exporting every single symbol that is visible. This creates bigger binaries and means host environments
have access to symbols that they perhaps shouldn't have. Now, users can tell Zig which symbols
are to be exported, meaning all other symbols that are not specified will not be exported.

Another change is we now support `-rdynamic` in the wasm linker as well, meaning all symbols will
be put in the dynamic symbol table. This is the same behavior as with ELF. This means there's a 3rd strategy
users will have to build their wasm binary.
2021-12-14 14:02:23 -08:00
Stephen Gutekanst
e563b166b2 Fix compilation cache updating bug leading to slow builds
While investigating slow build times with [a large project](https://github.com/hexops/mach/issues/124),
I found that the compiler was reading from disk nearly every C source file in my project
when rebuilding despite no changes having been made. This accounted for several seconds of
time (approx. 20-30% of running `zig build` without any changes to the sources.)

The cause of this was that comparisons of file mtimes would _always_ fail (the mtime of the file on
disk was always newer than that stored in the cache manifest), and so the cache logic would always
fall back to byte-for-byte file content comparisons with what is on disk vs. in the cache-reading every
C source file in my project from disk during each rebuild. Because file contents were the same, a cache
hit occurred, and _despite the mtime being different the cache manifest would not be updated._

One can reproduce this by building a Zig project so the cache is populated, and then changing mtimes
of their C source files to be newer than what is in the cache (without altering file contents.)

The fix is rather simple: we should always write the updated cache manifest regardless of
whether or not a cache hit occurred (a cache hit doesn't indicate if a manifest is dirty) Luckily,
`writeManifest` already contains logic to determine if a manifest is dirty and becomes no-op if no
change to the manifest file is necessary-so we merely need to ensure it is invoked.

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
2021-12-14 13:56:35 -08:00
Andrew Kelley
274555be21 stage2: improve handling of the generated file builtin.zig
All Zig code is eligible to `@import("builtin")` which is mapped to a
generated file, build.zig, based on the target and other settings.

Zig invocations which share the same target settings will generate the
same builtin.zig file and thus the path to builtin.zig is in a shared
cache folder, and different projects can sometimes use the same file.

Before this commit, this led to race conditions where multiple
invocations of `zig` would race to write this file. If one process
wanted to *read* the file while the other process *wrote* the file, the
reading process could observe a truncated or partially written
builtin.zig file.

This commit makes the following improvements:
 - limitations:
   - avoid clobbering the inode, mtime in the hot path
   - avoid creating a partially written file
   - builtin.zig needs to be on disk for debug info / stack trace purposes
   - don't mark the task as complete until the file is finished being populated
     (possibly by an external process)
 - strategy:
   - create the `@import("builtin")` `Module.File` during the AstGen
     work, based on generating the contents in memory rather than
     loading from disk.
   - write builtin.zig in a separate task that doesn't have
     to complete until the end of the AstGen work queue so that it
     can be done in parallel with everything else.
   - when writing the file, first stat the file path. If it exists, we are done.
   - otherwise, write the file to a temp file in the same directory and atomically
     rename it into place (clobbering the inode, mtime in the cold path).
 - summary:
   - all limitations respected
   - hot path: one stat() syscall that happens in a worker thread

This required adding a missing function to the standard library:
`std.fs.Dir.statFile`. In this commit, it does open() and then fstat()
which is two syscalls. It should be improved in a future commit to only
make one.

Fixes #9439.
2021-12-06 23:30:18 -08:00
Andrew Kelley
4c1a62326b stage2: use Target.Abi instead of introducing Target.TargetAbi
This branch introduced std.Target.TargetAbi when we already had
std.Target.Abi which was, unsurprisingly, already suited for this task.

Also pull out the -mabi= cc flag addition to the common area instead of
duplicating it for assembly and c files.
2021-12-03 17:33:20 -07:00
vole-dev
9ede943e07 turn off LTO by default for RISCV even in Release mode 2021-12-03 16:53:33 -07:00
vole-dev
ff38f56040 default mabi based on RISC-V extensions and -mabi build option
The target abi can also be set in build.zig via LibExeObjStep.target_abi

The value passed in is checked that it is a valid value in
std.Target.TargetAbi

The target abi is also validated against the target cpu
2021-12-03 16:53:33 -07:00
Andrew Kelley
7355a20133
Merge pull request #10055 from leecannon/allocator_refactor
Allocgate
2021-11-30 18:48:31 -08:00
Andrew Kelley
40f5e5dfc6 CLI: introduce -fsingle-threaded/-fno-single-threaded
Previously there was only `--single-threaded`.

This flag now matches other boolean flags, instead of only being able to
opt in to single-threaded builds, you can now force multi-threaded
builds. Currently this only has the possibility to emit an error
message, but it is a better user experience to understand why one cannot
choose to enable threads in some cases.

This is breaking change to the CLI.

Related: #10143
2021-11-30 19:21:29 -07:00
Lee Cannon
1093b09a98
allocgate: renamed getAllocator function to allocator 2021-11-30 23:32:47 +00:00
Lee Cannon
75548b50ff
allocgate: stage 1 and 2 building 2021-11-30 23:32:47 +00:00
Lee Cannon
85de022c56
allocgate: std Allocator interface refactor 2021-11-30 23:32:47 +00:00
Andrew Kelley
20e19e75fd add clang_argv to stage1 cache hash
closes #9304
2021-11-29 20:57:50 -07:00
Andrew Kelley
19eaf54bc9 update libc linux headers to v5.16-rc3
* Add missing Linux headers. Closes #9837
 * Update existing headers to latest Linux.
 * Consolidate headers that are the same for multiple Zig target CPU
   architectures. For example, Linux has only an x86 directory for both
   x86_64 and x86 CPU architectures. Now Zig only ships an x86 directory
   for Linux headers, and will emit the proper corresponding -isystem
   flags.
 * tools/update-linux-headers.zig is now available for upgrading to
   newer Linux headers, and the update process is now documented on the
   wiki.
2021-11-29 18:05:11 -07:00
Jakub Konka
0f63f3eeb7
Merge pull request #10223 from g-w1/print-mir
stage2: initial implementation of print_mir
2021-11-28 21:43:54 +01:00
Jacob G-W
bd19f5e611 initial implementation of print_mir 2021-11-27 10:56:04 -05:00
Jakub Konka
8317dbd1cb macos: detect SDK path and version, then pass to the linker
Since we are already detecting the path to the native SDK,
if available, also fetch SDK's version and route that to the linker.
The linker can then use it to correctly populate LC_BUILD_VERSION
load command.
2021-11-26 16:26:44 +01:00
Jakub Konka
02d8ca71f9 macos: always use Zig shipped libc headers when no native SDK
If Zig didn't detect native SDK, always use shipped libc headers
when targeting macOS.
2021-11-26 12:44:49 +01:00
Andrew Kelley
7b78b4fff0 stage2: better error message when copying artifacts fails 2021-11-25 17:43:27 -07:00
Jakub Konka
4270f234db Skip detecting native libc dirs on darwin
This is handled before by detecting and adding SDK path which
is a centralised point for the native libc installation on darwin.
2021-11-25 12:19:16 +01:00
Jakub Konka
1954cdc106 Autofetch macOS SDK if native target on macOS only
This means that I am purposefully regressing linking iOS and related
which will require manual specification of the sysroot path, etc.
2021-11-25 12:19:16 +01:00
Jakub Konka
42a351e099 infer and match macos sdk version for libc headers 2021-11-25 12:19:16 +01:00
Andrew Kelley
36c8adf589
Merge pull request #10073 from hoanga/haiku-support-build2
more haiku support
2021-11-24 18:42:30 -08:00
Andrew Kelley
20cc7af8e6 stage2: support LLD -O flags on ELF
In 7e23b3245a9bf6e002009e6c18c10a9995671afa I made -O flags to the
linker emit a warning that the argument does nothing. That was not
correct however; LLD does have some logic that does different things
depending on -O0, -O1, and -O2. It defaults to -O1, and it does less
optimizations with -O0 and more with -O2.

With this commit, e.g. `-Wl,-O1` is supported by the `zig cc` frontend,
and by default we pass `-O0` to LLD in debug mode, and `-O3` in release
modes.

I also fixed a bug in the LLD ELF linker line which was incorrectly
passing `-O` flags instead of `--lto-O` flags for LTO.
2021-11-24 18:46:32 -07:00
Andrew Kelley
27c5c7fb23 stage2: proper -femit-implib frontend support
* Improve the logic for determining whether emitting an import lib is
   eligible, and improve the error message when the user provides
   contradictory arguments.
 * Integrate with the EmitLoc / Emit system that already exists, and use
   the `-femit-implib[=path]`/`-fno-emit-implib` convention that already
   exists.
 * Proper integration with the caching system.
 * CLI: fix bug in error reporting for resolving EmitLoc values for
   other parameters.
2021-11-24 18:12:56 -07:00
Andrew Kelley
7e23b3245a stage2: remove extra_lld_args
This mechanism for sending arbitrary linker args to LLD has no place in
the Zig frontend, because our goal is for the frontend to understand all
the arguments and not treat linker args like a black box.

For example we have self-hosted linking in addition to LLD, so we want to
have the options make sense to both linking codepaths, not just the LLD one.

Passing -O linker args will now result in a warning that the arg does
nothing.
2021-11-24 17:14:20 -07:00
Kurt Kartaltepe
a950cb42bd Coff linker: Add IMPLIB support
Allow --out-implib and -implib as passed by cmake and meson to be
correctly passed through to the linker to generate import libraries.
2021-11-24 17:14:20 -07:00
Jakub Konka
0c1d610015 zld: handle -current_version and -compatibility_version
and transfer them correctly to the generated dylib as part of the dylib
id load command.
2021-11-23 15:59:49 +01:00