This also fixes performing relocations for data symbols
of which the target symbol exists in an external object file.
We do this by checking if the target symbol was discarded,
and if so: get the new location so that we can find the
corresponding atom that belongs to said new location. Previously
it would always assume the symbol would live in the same file
as the atom/symbol that is doing the relocation.
Given that COFF will want to support PIC from ground-up, there is no
point in leaving outdated code for COFF in other backends such as
arm or aarch64. Instead, when we are ready to look into those, we
can start figuring out what to add and where.
Previously, Zig had inconsistent semantics for an enum like this:
`enum(u8){zero = 0}`
Although in theory this can only hold one possible value, the tag
`zero`, Zig no longer will treat the type this way. It will do loads and
stores, as if the type has runtime bits.
Closes#12619
Tests passed locally:
* test-behavior
* test-cases
Rather than storing it in a local and returning that,
we now keep this on the stack as all internal functions
expect it to be on the stack already and therefore were
generating extra `local.set` instructions.
Add handling for these additional `MCValue`s:
* `.immediate` - lower to `DW.OP.consts` or `DW.OP.constu` depending
on signedness followed by popping off the DWARF stack with
`DW.OP.stack_value`
* `.undef` - lower to `DW.OP.implicit_value`
* `.none` - lower to `DW.OP.lit0` followed by popping off the DWARF
stack with `DW.OP.stack_value`
For any remaining unhandled case, we generate `DW.OP.nop` in order
not to mess up remaining DWARF info.
When a local is no longer referenced or used, free it
so the local can be re-used by another instruction.
This means we generate less locals. Freeing this local
is a manual action and must only be used on temporaries
or where we are sure the local is not referenced by a
different AIR instruction, as that creates UB.
We now also no longer store a `WValue` when its tag is set to `none`
as those may never be referenced by any AIR instruction.
An assertion is done to make sure we never store a reference to a
`stack` value in our resolved instructions.
We internally use a lot of `load`'s that used to put
the result in a newly created local. For instance, when is considered
byRef or when we need a specific field/element/bytes from a larger type.
However, sometimes we want to directly use this value and then forget about
it, which means storing it in a local first is wasted instructions as well
as wasted locals that shouldn't be generated in the first place.
With this change it's explicit and requires the usage of `toLocal`.
This also does it for `wrapBinOp` which internally uses the already
refactored `binOp` and `wrapOperand` heavily simplifying this
function and not duplicate the logic from `binOp`
By keeping the result on the stack, we prevent codegen
from generating unneccesary locals when we have subsequent instructions
that do not have to be re-used.
Rather than always creating a new local and storing the result of
a binary operation into said local, we now leave it on top of the stack.
This allows for better codegen as we need less instructions, as well
as less total amount of locals.
When a local is no longer needed (for instance, it was used as
a temporary during arithmetic), it can be appended to one of
the typed freelists. This allows us to re-use locals and therefore
require less locals, reducing the binary size, as well as runtime
initialization.
Removed the copy of param_names inside of Fn and changed to
implementation of getParamName to fetch to parameter name from the ZIR.
The signature of getParamName was also changed to take an additional
*Module argument.
When lowering the return type for Wasm if the calling convention is `C`,
it now correctly lower it according to what clang does as specified in:
https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
This makes use of the same logic as the Wasm backend, ensuring the
generated code does not diverge in function signatures.
When passing arguments accross the C-ABI for the Wasm target,
we want slightly different behavior than x86_64.
For instance: a struct with multiple fields must always be passed
by reference, even if its ABI size fits in a single integer.
However, we do pass larger integers such as 128bit by value,
which LLVM will correctly lower to use double arguments instead.
Now, each object file will store a mutable table of symbols that it
defines. Upon symbol resolution between object files, the symbol
will be updated with a globally allocated section ordinal and address
in virtual memory. If the object defines a globally available symbol,
its location only (comprising of the symbol index and object index)
will be stored in the globals map for easy access when relocating, etc.
This approach cleans up the symbol management significantly, and matches
the status quo used in zld/ELF.
Additionally, this makes scoping symbol stabs easier too as they are
now naturally contained within each object file.