aboutsummaryrefslogtreecommitdiff
path: root/src/arch/wasm/CodeGen.zig
AgeCommit message (Collapse)Author
2022-03-23wasm: Implement opt_payload_ptrLuuk de Gram
Implements lowering constants for pointers of value 'opt_payload_ptr'. The offset is calculated by determining the abi size of the full type and then substracting the payload size.
2022-03-23wasm: Fix switching on errorsLuuk de Gram
Error sets contain the entire global error set. Users are often switching on specific errors only present within that operand. This means that cases are almost always sparse and not contiguous. For this reason, we will instead emit the default case for error values not present in that specific operand error set. This is fine as those cases will never be hit, as prevented by the type system. By still allowing jump tables for those cases, rather than if-else chains, we save runtime cost as well as binary size.
2022-03-23wasm: Implement `@errorName`Luuk de Gram
This implements the `error_name` instruction, which is emit for runtime `@errorName` callsites. The implementation works by creating 2 symbols and corresponding atoms. The initial symbol contains a table which each element consisting of a slice where the ptr field points towards the error name, and the len field contains the error name length without the sentinel. The secondary symbol contains a list of all error names from the global error set. During the error_name instruction, we first get a pointer to the first symbol. Then based on the operand we perform pointer arithmetic, to get the correct index into this table. e.g. error index 2 = ptr + (2 * ptr size). The result of this will be stored in a local and then returned as instruction result. During `flush()` we populate the error names table by looping over the global error set and creating a relocation for each error name. This relocation is appended to the table symbol. Then finally, this name is written to the names list itself. Finally, both symbols' atom are allocated within the rest of the binary. When no error name is referenced, the `error_name_symbol` is never set, and therefore no error name table will be emit into the final binary.
2022-03-22stage2: lazy `@alignOf`Andrew Kelley
Add a `target` parameter to every function that deals with Type and Value.
2022-03-21wasm: Implement @popCountLuuk de Gram
2022-03-21stage2: add AIR instruction `cmp_vector`William Sengir
The existing `cmp_*` instructions get their result type from `lhs`, but vector comparison will always return a vector of bools with only the length derived from its operands. This necessitates the creation of a new AIR instruction.
2022-03-19Merge pull request #11233 from Luukdegram/wasm-testsAndrew Kelley
stage2: wasm - union_init and passing tests
2022-03-19wasm: All union/tuple/array tests passingLuuk de Gram
This implements improvements/fixes to get all the union, tuple, and array behavior tests passing. Previously, we lowered parent pointers for field_ptr and element_ptr incompletely. This has now been improved to recursively lower such pointer. Also a fix was done to `generateSymbol` when checking a container's layout. Previously it was assumed to always be a struct. However, the type can also be a tuple, and therefore panicking. Updating to ask a type's container layout instead allows us to keep a singular branch for both cases.
2022-03-19wasm: Implement `union_init` instructionLuuk de Gram
Implements the `@unionInit` builtin instruction.
2022-03-19stage2: add dbg_block_{begin,end} instructionVeikka Tuominen
2022-03-17Merge pull request #11200 from Luukdegram/wasm-memcpyAndrew Kelley
stage2: wasm - Implement memcpy instruction
2022-03-17stage2: implement `@reduce`Andrew Kelley
Notably, Value.eql and Value.hash are improved to treat NaN as equal to itself, so that Type/Value can be hash map keys. Likewise float hashing normalizes the float value before computing the hash.
2022-03-17wasm: Improve memset implementationLuuk de Gram
When the length is comptime-known, we perform an inline loop instead of emitting a runtime loop into the binary. This also allows us to easily write 'undefined' to aggregate types. We now do this when we set the error tag of an error union where the payload will be set to undefined.
2022-03-17wasm: Implement 'memcpy' instructionLuuk de Gram
This implements the `memcpy` instruction and also updates the inline memcpy calls to make use of the same implementation. We use the fast-loop when the length is comptime known, and use a runtime loop when the length is runtime known. We also perform feature-dection to emit a simply wasm memory.copy instruction when the feature 'bulk-memory' is enabled. (off by default).
2022-03-16stage2 llvm: keep track of inlined functionsVeikka Tuominen
2022-03-16Sema: emit dbg_func around inline callsVeikka Tuominen
2022-03-13stage2: add debug info for locals in the LLVM backendAndrew Kelley
Adds 2 new AIR instructions: * dbg_var_ptr * dbg_var_val Sema no longer emits dbg_stmt AIR instructions when strip=true. LLVM backend: fixed lowerPtrToVoid when calling ptrAlignment on the element type is problematic. LLVM backend: fixed alloca instructions improperly getting debug location annotated, causing chaotic debug info behavior. zig_llvm.cpp: fixed incorrect bindings for a function that should use unsigned integers for line and column. A bunch of C test cases regressed because the new dbg_var AIR instructions caused their operands to be alive, exposing latent bugs. Mostly it's just a problem that the C backend lowers mutable and const slices to the same C type, so we need to represent that in the C backend instead of printing two duplicate typedefs.
2022-03-11stage2: implement `@shuffle` at runtimeVeikka Tuominen
2022-03-11stage2: passing threadlocal tests for x86_64-linuxAndrew Kelley
* use the real start code for LLVM backend with x86_64-linux - there is still a check for zig_backend after initializing the TLS area to skip some stuff. * introduce new AIR instructions and implement them for the LLVM backend. They are the same as `call` except with a modifier. - call_always_tail - call_never_tail - call_never_inline * LLVM backend calls hasRuntimeBitsIgnoringComptime in more places to avoid unnecessarily depending on comptimeOnly being resolved for some types. * LLVM backend: remove duplicate code for setting linkage and value name. The canonical place for this is in `updateDeclExports`. * LLVM backend: do some assembly template massaging to make `%%` rendered as `%`. More hacks will be needed to make inline assembly catch up with stage1.
2022-03-09wasm: Implement `field_parent_ptr`Luuk de Gram
2022-03-09wasm: Implement `errunion_payload_ptr_set`Luuk de Gram
This also fixes `ret_ptr` where the pointee type is zero-sized.
2022-03-09wasm: Preliminary `fptrunc` supportLuuk de Gram
This implements the initial fptrunc instruction. For all other floating-point truncating, a call to compiler-rt is required. (This also updates fpext to emit the same error).
2022-03-09wasm: Implement fpextLuuk de Gram
This implements initial support for floating-point promotion for bitsizes <= 64
2022-03-09wasm: Improve switch implementationLuuk de Gram
- Implement switching over booleans and pointers. - Fix sparse-detection where the lowest value was never truly set as it started at a non-zero number and the case was > 50. - Fix indexing the jump table by ensuring it starts indexing from 0.
2022-03-06stage2: implement `@mulAdd` for scalar floatsJohn Schmidt
2022-03-06wasm: Unify function generationLuuk de Gram
Like decl code generation, also unify the wasm backend and the wasm linker to call into the general purpose `codegen.zig` to generate the code for a function.
2022-03-06wasm: Remove old DeclGen/genTypedValueLuuk de Gram
2022-03-06wasm: Call `generateSymbol` for updateDeclLuuk de Gram
To unify the wasm backend with the other backends, we will now call `generateSymbol` to lower a Decl into bytes. This means we also have to change some function signatures to comply with the linker interface. Since the general purpose generateSymbol is less featureful than wasm's, some tests are temporarily disabled.
2022-03-03stage2: cleanups to wasm memory intrinsicsAndrew Kelley
* AIR: use pl_op instead of ty_pl for wasm_memory_size. No need to store the type because the type is always `u32`. * AstGen: use coerced_ty for `@wasmMemorySize` and `@wasmMemoryGrow` and do the coercions in Sema. * Sema: use more accurate source locations for errors. * Provide more information in the compiler error message. * Codegen: use liveness data to avoid lowering unused `@wasmMemorySize`. * LLVM backend: add implementation - I wasn't able to test it because we are hitting a linker error for `-target wasm32-wasi -fLLVM`. * C backend: use `zig_unimplemented()` instead of silently doing wrong behavior for these builtins. * behavior tests: branch only on stage2_arch for inclusion of the wasm.zig file. We would change it to `builtin.cpu.arch` but that is causing a compiler crash on some backends.
2022-03-03cbe: Implement wasm builtinsLuuk de Gram
This implements the wasm builtins by lowering to builtins that are supported by c-compilers. In this case: Clang. This also simplifies the `AIR` instruction as it now uses the payload field of `ty_pl` and `pl_op` directly to store the index argument rather than storing it inside Extra. This saves us 4 bytes per builtin call.
2022-03-03wasm: Implement `@wasmMemoryGrow` builtinLuuk de Gram
Similarly to the other wasm builtin, this implements the grow variation where the memory index is a comptime known value. The operand as well as the result are runtime values. This also verifies during semantic analysis the target we're building for is wasm, or else emits a compilation error. This means that other backends do not have to handle this AIR instruction, other than the wasm and LLVM backends.
2022-03-03wasm: Implement `@wasmMemorySize()` builtinLuuk de Gram
This implements the `wasmMemorySize` builtin, in Sema and the Wasm backend. The Stage2 implementation differs from stage1 in the way that `index` must be a comptime value. The stage1 variant is incorrect, as the index is part of the instruction encoding, and therefore, cannot be a runtime value.
2022-02-28stage2: fix frame_address AIR instructionAndrew Kelley
Various places were assuming different union tags. Now it is consistently a no-op instruction, just like the similar instruction ret_addr.
2022-02-28stage2: implement `@frameAddress`Veikka Tuominen
2022-02-26stage2: implement `@unionInit`Andrew Kelley
The ZIR instruction `union_init_ptr` is renamed to `union_init`. I made it always use by-value semantics for now, not taking the time to invest in result location semantics, in case we decide to change the rules for unions. This way is much simpler. There is a new AIR instruction: union_init. This is for a comptime known tag, runtime-known field value. vector_init is renamed to aggregate_init, which solves a TODO comment.
2022-02-25wasm: Fix error union's size/alignmentLuuk de Gram
Previously error unions were packed in memory. Now each 'field' is correctly aligned to the error union's alignment.
2022-02-25wasm: Refactor lowerUnnamedConstLuuk de Gram
Rather than ping ponging between codegen and the linker to generate the symbols/atoms for a local constant and its relocations. We now create all neccesary objects within the linker. This simplifies the code as we can now simply call `lowerUnnamedConst` from anywhere in codegen, allowing us to further improve lowering constants into .rodata so we do not have to sacrifice lowering certain types such as decl_ref's where its type is a slice.
2022-02-24stage2: implement fieldParentPtrVeikka Tuominen
2022-02-23wasm-linker: Implement `updateDeclExports`Luuk de Gram
We now correctly implement exporting decls. This means it is possible to export a decl with a different name than the decl that is doing the export. This also sets the symbols with the correct flags, so when we emit a relocatable object file, a linker can correctly resolve symbols and/or export the symbol to the host environment. This commit also includes fixes to ensure relocations have the correct offset to how other linkers will expect the offset, rather than what we use internally. Other linkers accept the offset, relative to the section. Internally we use an offset relative to the atom.
2022-02-19stage2: implement errunion_payload_ptr_setVeikka Tuominen
2022-02-18stage2: Implement `@bitReverse` and `@byteSwap`Cody Tapscott
This change implements the above built-ins for Sema and the LLVM backend. Other backends have had placeholders added for lowering.
2022-02-10wasm: Implement 'field_ptr' constantsLuuk de Gram
This implements the `field_ptr` value for pointers. As the value only provides us with the index, we must calculate the offset from the container type using said index. (i.e. the offset from a struct field at index 2). Besides this, small miscellaneous fixes/updates were done to get remaining behavior tests passing: - We start the function table index at 1, so unresolved function pointers don't can be null-checked properly. - Implement genTypedValue for floats up to f64. - Fix zero-sized arguments by only creating `args` for non-zero-sized types. - lowerConstant now works for all decl_ref's. - lowerConstant properly lowers optional pointers, so `null` pointers are lowered to `0`.
2022-02-09stage2: implement all builtin floatops for f{16,32,64}John Schmidt
- Merge `floatop.zig` and `floatop_stage1.zig` since most tests now pass on stage2. - Add more behavior tests for a bunch of functions.
2022-02-08wasm: Store stack-offset as WValueLuuk de Gram
Rather than using runtime to perform pointer arithmetic to set the stack offset as a pointer into a local, we now store the offset as a WValue from the bottom of the stack. This has the benefit of less instructions, few locals, and less performance impact when we allocate a value on the virtual stack.
2022-02-08stage2: tiny improvements all over the placeJakub Konka
* pass more x64 behavior tests * return with a TODO error when lowering a decl with no runtime bits * insert some debug logs for tracing recursive descent down the type-value tree when lowering types * print `Decl`'s name when print debugging `decl_ref` value
2022-02-08wasm: update test runnerLuuk de Gram
This updates the test runner for stage2 to emit to stdout with the passed, skipped and failed tests similar to the LLVM backend. Another change to this is the start function, as it's now more in line with stage1's. The stage2 test infrastructure for wasm/wasi has been updated to reflect this as well.
2022-02-07stage2: implement @sqrt for f{16,32,64}John Schmidt
Support for f128, comptime_float, and c_longdouble require improvements to compiler_rt and will implemented in a later PR. Some of the code in this commit could be made more generic, for instance `llvm.airSqrt` could probably be `llvm.airUnaryMath`, but let's cross that bridge when we get to it.
2022-02-06stage2: add new Decl subtype, ExternFnJakub Konka
`ExternFn` will contain a maybe-lib-name if it was defined with the `extern` keyword like so ```zig extern "c" fn write(usize, usize, usize) usize; ``` `lib_name` will live as long as `ExternFn` decl does.
2022-02-03Move passing behavior testsLuuk de Gram
Singular tests (such as in the bug ones) are moved to top level with exclusions for non-passing backends. The big behavior tests such as array_llvm and slice are moved to the inner scope with the C backend disabled. They all pass for the wasm backend now
2022-02-03wasm: Refactor stack to account for alignmentLuuk de Gram
We now calculate the total stack size required for the current frame. The default alignment of the stack is 16 bytes, and will be overwritten when the alignment of a given type is larger than that. After we have generated all instructions for the body, we calculate the total stack size by forward aligning the stack size while accounting for the max alignment. We then insert a prologue into the body, where we substract this size from the stack pointer and save it inside a bottom stackframe local. We use this local then, to calculate the stack pointer locals of all variables we allocate into the stack. In a future iteration we can improve this further by storing the offsets as a new `stack_offset` `WValue`. This has the benefit of not having to spend runtime cost of storing those offsets, but instead we append those offsets whenever we need the value that lives in the stack.