| Age | Commit message (Collapse) | Author |
|
Previously it was incorrectly assumed that all memcopy's generated by
the `memcpy` AIR instruction had an element size of 1 byte. However,
this would result in miscompilations for pointer's to arrays where
the element size of the array was larger than 1 byte. We now corectly
calculate this size.
|
|
* move `ptrBitWidth` from Arch to Target since it needs to know about the abi
* double isn't always 8 bits
* AVR uses 1-byte alignment for everything in GCC
|
|
|
|
When initializing a packed struct, we must ensure the result local
is zero'd. Previously we would do this by ensuring a new local is
allocated. Although a local is always zero by default, it meant that
if such an initialization was being done inside a loop, it would re-
use that very same local that could potentially still hold a different
value. Because this value is `or`'d with the value, it would result
in a miscompilation. By manually setting this result to 0, we guarantee
the correct behavior.
|
|
For floats we would previously only do the division, but not
the truncation for floats. This would result in incorrect values
being returned.
|
|
Previously we incorrectly assumed all memset's to have its element
abi-size be 1 byte. This would set the region of memory incorrectly.
We now have a more efficient loop, as well as support any element
type by re-using the `store` function for each element and moving
the pointer by 1 element.
|
|
|
|
Previously we would use the address of the slice itself, which would
result in miscompilations and accidently setting the memory region
of the slice itself, rather than based on the `ptr` field.
|
|
Previously when lowering a value of `elem_ptr` we would multiply the
abisize of the parent type by the index, rather than the element type.
This would result in an invalid pointer way beyond the correct pointer.
We now also pass the current offset to each recursive call to ensure
we do not miss inner offsets.
|
|
When we have a `ret_load` instruction with a zero-sized type which was
not an error, we would not emit any instruction. This resulted in
no `return` instruction and also not correctly resetting the global
stack_pointer.
This commit also enables the regular test runner for the WebAssembly
backend.
|
|
A copy was being made of a WValue variable, which meant the call
to `free` would insert the local that was being held by said WValue
was appended to the free list twice. This led to the same local being
reused even though it wasn't free and would lead to it being over-
written by a new value.
|
|
Rather than adding all values that were generated in the child branch,
we simply discard them as outer branches cannot refer to values
produced from an inner branch.
|
|
This new tag is used for freed locals that are not allowed to have any
remaining references pointing to it. This new tag allows us to easily
identify liveness bugs. Previously we would set the entire region to
`undefined` which would incorrectly set the tag to `function_index`,
making codegen think it was a valid `WValue` while it wasn't.
|
|
|
|
Make sure to increase the reference count for `intcast` when the
operand doesn't require any casting of the respective WebAssembly type.
Function arguments have a reserved slot, and therefore cannot be
re-used arbitrarily
|
|
This fix ensures that when we are shifting left or right,
both operands have the same WebAssembly type. e.g. it's not possible
to shift a 64 bit integer and 32 bit integer together and will fail
WebAssembly's validator. By first coercing the values to the same
type, we ensure we satisfy the validator.
|
|
Currently we only support exact 128 bit *unsigned* integers
|
|
|
|
Uses compiler-rt for multiplication and shifting left, while lowers
it down using regular instructions for xor.
|
|
|
|
wasm: implement atomic instructions
|
|
|
|
|
|
Uses the `atomic.fence` instruction for multi-thread-enabled builds
where the `atomics` feature is enabled for the wasm32 target.
In all other cases, this lowers to a nop.
|
|
Implements the lowering of the `@atomicRmw` builtin. Uses the atomic
opcodes when the cpu feature `atomics` is enabled. Otherwise lowers
it to regular instructions. For the operations that do not lower to
a direct atomic opcode, we use a loop in combiantion with a cmpxchg
to ensure the swapping of values is doing atomically.
|
|
Uses the atomic instructions when cpu feature is enabled, otherwise
lowers it down to a regular load.
|
|
When the user passes the cpu feature `atomics` to the target triple,
the backend will lower the AIR instruction using opcodes from the
atomics feature instead of manually lowering it.
|
|
|
|
store:
The value to store may be undefined, in which case the destination
memory region has undefined bytes after this instruction is
evaluated. In such case ignoring this instruction is legal
lowering.
store_safe:
Same as `store`, except if the value to store is undefined, the
memory region should be filled with 0xaa bytes, and any other
safety metadata such as Valgrind integrations should be notified of
this memory region being undefined.
|
|
|
|
Also introduce memset_safe AIR tag and support it in C backend and LLVM
backend.
|
|
|
|
Rather than using a function call to verify if an error fits within
the global error set's length, we now store the error set' size in
the .rodata segment of the linear memory and load that value onto
the stack to check with the integer value.
|
|
This implements the safety check for error casts. The instruction
generates a jump table with 2 possibilities. The operand is used
as an index into the jump table. For cases where the value does
not exist within the error set, it will generate a jump to the
'false' block. For cases where it does exist, it will generate
a jump to the 'true' block. By calculating the highest and lowest
value we can keep the jump table smaller, as it doesn't need to
contain an index into the entire error set.
|
|
Creates a global undefined symbol when this instruction is called.
The linker will then resolve it as a lazy symbol, ensuring it is
only generated when the symbol was created. In `flush` it will then
generate the function as only then, all errors are known and we can
generate the function body. This logic allows us to re-use the same
functionality of linker-synthetic-functions.
|
|
Uses the new liveness behaviour. This also removes useless calls
to `processDeath` on branches that were just initialized. Branch
consolidation and processing deaths on branches inside `condbr`
is still a TODO, just like before.
This also skips var_args on other native backends as they do not
support this feature yet.
|
|
This is a partial rewrite of Liveness, so has some other notable changes:
- A proper multi-pass system to prevent code duplication
- Better logging
- Minor bugfixes
|
|
|
|
|
|
When we lower the instruction for `@tagName` we generate a new
function if it doesn't exist yet for that decl. This function creates
an if-else chain to determine which value was provided. Each tag
generates a constant that contains its name as the value. For each
tag we generate a case where the pointer of the string is stored in
the result slice. The length of the tagname is comptime-known, therefore
will be stored in the slice directly without having it being part of
the tagname symbol. In the future this can use a jump table instead
of an if-else chain, similar to the `switch` instruction.
|
|
|
|
|
|
|
|
|
|
wasm: implement float operations with compiler-rt
|
|
Liveness: defer deaths of externally-scoped instructions in loop bodies
|
|
|
|
|
|
* @workItemId returns the index of the work item in a work group for a
dimension.
* @workGroupId returns the index of the work group in the kernel dispatch for a
dimension.
* @workGroupSize returns the size of the work group for a dimension.
These builtins are mainly useful for GPU backends. They are currently only
implemented for the AMDGCN LLVM backend.
|
|
|