| Age | Commit message (Collapse) | Author |
|
Removes the `files` field from the Wasm linker, storing the ZigObject
as its own field instead using a tagged union.
This removes a layer of indirection when accessing the ZigObject, and
untangles logic so that we can introduce a "pre-link" phase that
prepares the linker state to handle only incremental updates to the
ZigObject and then minimize logic inside flush().
Furthermore, don't make array elements store their own indexes, that's
always a waste.
Flattens some of the file system hierarchy and unifies variable names
for easier refactoring.
Introduces type safety for optional object indexes.
|
|
|
|
|
|
this patch renames ComptimeStringMap to StaticStringMap, makes it
accept only a single type parameter, and return a known struct type
instead of an anonymous struct. initial motivation for these changes
was to reduce the 'very long type names' issue described here
https://github.com/ziglang/zig/pull/19682.
this breaks the previous API. users will now need to write:
`const map = std.StaticStringMap(T).initComptime(kvs_list);`
* move `kvs_list` param from type param to an `initComptime()` param
* new public methods
* `keys()`, `values()` helpers
* `init(allocator)`, `deinit(allocator)` for runtime data
* `getLongestPrefix(str)`, `getLongestPrefixIndex(str)` - i'm not sure
these belong but have left in for now incase they are deemed useful
* performance notes:
* i posted some benchmarking results here:
https://github.com/travisstaloch/comptime-string-map-revised/issues/1
* i noticed a speedup reducing the size of the struct from 48 to 32
bytes and thus use u32s instead of usize for all length fields
* i noticed speedup storing KVs as a struct of arrays
* latest benchmark shows these wall_time improvements for
debug/safe/small/fast builds: -6.6% / -10.2% / -19.1% / -8.9%. full
output in link above.
|
|
Structs were previously using `SegmentedList` to be given indexes, but
were not actually backed by the InternPool arrays.
After this, the only remaining uses of `SegmentedList` in the compiler
are `Module.Decl` and `Module.Namespace`. Once those last two are
migrated to become backed by InternPool arrays as well, we can introduce
state serialization via writing these arrays to disk all at once.
Unfortunately there are a lot of source code locations that touch the
struct type API, so this commit is still work-in-progress. Once I get it
compiling and passing the test suite, I can provide some interesting
data points such as how it affected the InternPool memory size and
performance comparison against master branch.
I also couldn't resist migrating over a bunch of alignment API over to
use the log2 Alignment type rather than a mismash of u32 and u64 byte
units with 0 meaning something implicitly different and special at every
location. Turns out you can do all the math you need directly on the
log2 representation of alignments.
|
|
Most of this migration was performed automatically with `zig fmt`. There
were a few exceptions which I had to manually fix:
* `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten
* `@truncate`'s fixup is incorrect for vectors
* Test cases are not formatted, and their error locations change
|
|
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>
|
|
|
|
When the user enables shared-memory, we must ensure the linked objects
have the 'atomics' and 'bulk-memory' features allowed.
|
|
Linker now parses segments with regards to TLS segments. If the name
represents a TLS segment but does not contain the TLS flag, we set it
manually as the object file is created using an older compiler (LLVM).
For now we panic when we find a TLS relocation and implement those
later.
|
|
When any object files provides an undefined reference to the __heap_base
symbol, we create a new defined symbol for it. During setupMemory we
set the virtual address of this symbol so it can be used for relocations.
This symbol represents where the heap starts and allocators can use
this value for its allocations when it needs to determine where the heap
lives.
|
|
Considering all possible features are known by the linker during
compile-time, we can create arrays on the stack instead of
dynamically allocating hash maps. We use a simple bitset to determine
whether a feature is enabled or not, and from which object file
it originates. This allows us to make feature validation slightly
faster and use less runtime memory.
In the future this could be enhanced further by having a single
array instead with a more sophisticated bitset.
|
|
The list of features a Wasm object/binary file can emit can differ
from the list of cpu features. The reason for this is because the
"target_features" section also contains linker features. An example
of this is the "shared-mem" feature, which is a feature for the linker
and not that of the cpu target as defined by LLVM.
|
|
Verifies disallowed and used/required features. After verifying,
all errors will be emit to notify the user about incompatible
features. When the user did not define any featureset, we infer
the features from the linked objects instead.
|
|
Addends in relocations are signed integers as theoretically it could
be a negative number. As Atom's offsets are relative to their parent
section, the relocation value should still result in a postive number.
For this reason, the final result is stored as an unsigned integer.
Also, rather than using `null` for relocations that do not support
addends. We set the value to 0 for those that do not support addends,
and have to call `addendIsPresent` to determine if an addend exists
or not. This means each Relocation costs 4 bytes less than before,
saving memory while linking.
|
|
|
|
Decls will now be put into their respective segment.
e.g. a constant decl will be inserted into the "rodata" segment,
whereas an uninitialized decl will be put in the "bss" segment instead.
|
|
Rather than checking if the user wants to use LLVM for the current compilation,
check for the existance of LLVM as part of the compiler. This is temporarily,
until other backends gain the ability to compiler LLVM themselves.
This means that when a user passed `-fno-LLVM` we will use the native
backend for the user's code, but use LLVM for compiler-rt.
This also fixes emitting names for symbols in the Wasm linker,
by deduplicating symbol names when multiple symbols point the same object.
|
|
When linking with an object file, verify if a relocation is a table index relocation.
If that's the case, add the relocation target to the function table.
|
|
Symbols that have globals used to have their lookup key be the symbol name.
This key is now the offset into the string table.
Imports have both the module name (library name) and name (of the symbol), those strings are now
also being interned. This can save us up to 24bytes per import which have both their module name and name de-duplicated.
Module names are almost entirely the same for all imports, providing us with a big chance of saving us 12 bytes at least.
Just like imports, exports can also have a seperate name than the internal symbol name. Rather than storing the slice,
we now store the offset of this string instead.
|
|
When creating a relocatable object file, we do no longer perform the following actions:
- Merge data segments
- Calculate stack size
- Relocations
We now also make the stack pointer symbol `undefined` for this use case as well as add the symbol
as an import.
|
|
- Converts previous `DeclBlock` into `Atom`'s to also make them compatible when
the rest of zlwd gets upstreamed and we can link with other object files.
- Resolves function signatures and removes any duplicates, saving us a lot of
potential bytes for larger projects.
- We now create symbols for each decl of the respective type
- We can now (but not implemented yet) perform proper relocations.
- Having symbols and segment_info allows us to create an object file
for wasm.
|