| Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
The astgen for switch expressions did not respect the ZIR rules of only
referencing instructions that are in scope:
%14 = block_comptime_flat({
%15 = block_comptime_flat({
%16 = const(TypedValue{ .ty = comptime_int, .val = 1})
})
%17 = block_comptime_flat({
%18 = const(TypedValue{ .ty = comptime_int, .val = 2})
})
})
%19 = block({
%20 = ref(%5)
%21 = deref(%20)
%22 = switchbr(%20, [%15, %17], {
%15 => {
%23 = const(TypedValue{ .ty = comptime_int, .val = 1})
%24 = store(%10, %23)
%25 = const(TypedValue{ .ty = void, .val = {}})
%26 = break("label_19", %25)
},
%17 => {
%27 = const(TypedValue{ .ty = comptime_int, .val = 2})
%28 = store(%10, %27)
%29 = const(TypedValue{ .ty = void, .val = {}})
%30 = break("label_19", %29)
}
}, {
%31 = unreachable_safe()
}, special_prong=else)
})
In this snippet you can see that the comptime expr referenced %15 and
%17 which are not in scope. There also was no test coverage for runtime
switch expressions.
Switch expressions will have to be re-introduced to follow these rules
and with some test coverage. There is some usable code being deleted in
this commit; it will be useful to reference when re-implementing switch
later.
A few more improvements to do while we're at it:
* only use .ref result loc on switch target if any prongs obtain the
payload with |*syntax|
- this improvement should be done to if, while, and for as well.
- this will remove the needless ref/deref instructions above
* remove switchbr and add switch_block, which is both a block and a
switch branch.
- similarly we should remove loop and add loop_block.
This commit introduces a "force_comptime" flag into the GenZIR
scope. The main purpose of this will be to choose the "comptime"
variants of certain key zir instructions, such as function calls and
branches. We will be moving away from using the block_comptime_flat
ZIR instruction, and eventually deleting it.
This commit also contains miscellaneous fixes to this branch that bring
it to the state of passing all the tests.
|
|
breaks correctly
|
|
|
|
|
|
The following AST avoids unnecessary derefs now:
* error set decl
* field access
* array access
* for loops: replace ensure_indexable and deref on the len_ptr with a
special purpose ZIR instruction called indexable_ptr_len.
Added an error note when for loop operand is the wrong type.
I also accidentally implemented `@field`.
|
|
There was just some untested code that did not work. .isnull -> .isnonnull
and I had to add a .ref resultloc to make types match up.
|
|
stage2: wasm - Refactor codegen for wasm similar to other backends
|
|
When codegen ends in failure, we need to manually clean up any fixups
that may have been gathered during that `codegen.generateSymbol` call.
Otherwise, we will end trapping.
|
|
Fix typo in `nop` implementation.
Simplify `aarch64` macOS tests.
|
|
Also fix incorrectly destroying notes.
This work is based on Vexu's patch in #7555.
|
|
* Implement error notes
- note: other symbol exported here
- note: previous else prong is here
- note: previous '_' prong is here
* Add Compilation.CObject.ErrorMsg. This object properly converts to
AllErrors.Message when the time comes.
* Add Compilation.CObject.failure_retryable. Properly handles
out-of-memory and other transient failures.
* Introduce Module.SrcLoc which has not only a byte offset but also
references the file which the byte offset applies to.
* Scope.Block now contains both a pointer to the "owner" Decl and the
"source" Decl. As an example, during inline function call, the
"owner" will be the Decl of the caller and the "source" will be the
Decl of the callee.
* Module.ErrorMsg now sports a `file_scope` field so that notes can
refer to source locations in a file other than the parent error
message.
* Some instances where a `*Scope` was stored, now store a
`*Scope.Container`.
* Some methods in the `Scope` namespace were moved to the more specific
type, since there was only an implementation for one particular tag.
- `removeDecl` moved to `Scope.Container`
- `destroy` moved to `Scope.File`
* Two kinds of Scope deleted:
- zir_module
- decl
* astgen: properly use DeclVal / DeclRef. DeclVal was incorrectly
changed to be a reference; this commit fixes it. Fewer ZIR
instructions processed as a result.
- declval_in_module is renamed to declval
- previous declval ZIR instruction is deleted; it was only for .zir
files.
* Test harness: friendlier diagnostics when an unexpected set of errors
is encountered.
* zir_sema: fix analyzeInstBlockFlat by properly calling resolvingInst
on the last zir instruction in the block.
Compile log implementation:
* Write to a buffer rather than directly to stderr.
* Only keep track of 1 callsite per Decl.
* No longer mutate the ZIR Inst struct data.
* "Compile log statement found" errors are only emitted when there are
no other compile errors.
-femit-zir and support for .zir source files is regressed. If we wanted
to support this again, outputting .zir would need to be done as yet
another backend rather than in the haphazard way it was previously
implemented.
For parsing .zir, it was implemented previously in a way that was not
helpful for debugging. We need tighter integration with the test harness
for it to be useful; so clearly a rewrite is needed. Given that a
rewrite is needed, and it was getting in the way of progress and
organization of the rest of stage2, I regressed the feature.
|
|
|
|
In rare occassions, it may happen that string table is allocated free
space preceeding symbol table. This is an error in the eyes of the `dyld`
dynamic loader and thus has to forbidden by the linker.
|
|
|
|
|
|
A simple `while(true) {}` loop generates the following LLVMIR:
```
define i32 @main() {
Entry:
br label %Loop
Loop: ; preds = %Loop, %Entry
br label %Loop
}
```
Also implement TZIR printing for loops and add a corresponding test.
|
|
The following TZIR instrutions have been implemented in the backend:
- all cmp operators (lt, lte, gt, gte, eq, neq)
- block
- br
- condbr
The following LLVMIR is generated for a simple assert function:
```
define void @assert(i1 %0) {
Entry:
%1 = alloca i1, align 1
store i1 %0, i1* %1, align 1
%2 = load i1, i1* %1, align 1
%3 = xor i1 %2, true
br i1 %3, label %Then, label %Else
Then: ; preds = %Entry
call void @llvm.debugtrap()
unreachable
Else: ; preds = %Entry
br label %Block
Block: ; preds = %Else
ret void
}
```
See tests for more examples.
|
|
stage2: improvements to LLVM backend
|
|
|
|
|
|
Also adds support for extern functions, simple pointer and simple array
types and values.
A simple hello world now compiles:
`zig build-exe example.zig -fLLVM -lc`
```
extern fn puts(s: [*:0]const u8) c_int;
export fn main() c_int {
_ = puts("hello world!");
return 0;
}
```
|
|
|
|
and also mark functions as `extern "C"` as appropriate to support c++
compilers.
|
|
All C backend tests passing now, except for emit-h tests. Next task in
the branch is to restore emit-h.
|
|
* std.ArrayList gains `moveToUnmanaged` and dead code
`ArrayListUnmanaged.appendWrite` is deleted.
* emit_h state is attached to Module rather than Compilation.
* remove the implementation of emit-h because it did not properly
integrate with incremental compilation. I will re-implement it
in a follow-up commit.
* Compilation: use the .codegen_failure tag rather than
.dependency_failure tag for when `bin_file.updateDecl` fails.
C backend:
* Use a CValue tagged union instead of strings for C values.
* Cleanly separate state into Object and DeclGen:
- Object is present only when generating a .c file
- DeclGen is present for both generating a .c and .h
* Move some functions into their respective Object/DeclGen namespace.
* Forward decls are managed by the incremental compilation frontend; C
backend no longer renders function signatures based on callsites.
For simplicity, all functions always get forward decls.
* Constants are managed by the incremental compilation frontend. C
backend no longer has a "constants" section.
* Participate in incremental compilation. Each Decl gets an ArrayList
for its generated C code and it is updated when the Decl is updated.
During flush(), all these are joined together in the output file.
* The new CValue tagged union is used to clean up using of assigning to
locals without an additional pointer local.
* Fix bug with bitcast of non-pointers making the memcpy destination
immutable.
|
|
* CBE buffers are only valid during a flush()
* the file is reopened and truncated during each flush()
* CBE now explicitly ignores updateDecl and deleteDecl
* CBE updateDecl is gone
* test case is enabled
|
|
`@setEvalBranchQuota` can be called before the comptime/inline call
stack is created.
For example:
```zig
@setEvalBranchQuota(100);
comptime {
while (true) {}
}
```
Here we need to set the branch_quota before the comptime block creates a
scope for the branch_count.
|
|
stage2: basic fn args for aarch64
|
|
Fix missing string format specifier in Mach-O used to generate
path to debug symbols bundle.
|
|
To make sure that we don't have to rebuild libc for every case, we now
have a seperate cache directory for the global cache, which remains
the same between test runs.
Also make sure to destory the Compilation before executing a child process,
otherwise the compiler deadlocks. (#7596)
|
|
zir.Inst no longer has an `analyzed_inst` field. This is previously how
we mapped ZIR to their TZIR counterparts, however with the way inline
and comptime function calls work, we can potentially have the same ZIR
structure being analyzed by multiple different analyses, such as during
a recursive inline function call. This would cause the `analyzed_inst`
field to become clobbered. So instead, we use a table to map the
instructions to their semantically analyzed counterparts. This will help
with multi-threaded compilation as well.
Scope.Block.Inlining is split into 2 different layers of "sharedness".
The first layer is shared by the whole inline/comptime function call
stack. It contains the callsite where something is being inlined and the
branch count/quota. The second layer is different per function call but
shared by all the blocks within the function being inlined.
Add support for debug dumping br and brvoid TZIR instructions.
Remove the "unreachable code" error. It was happening even for this case:
```zig
if (comptime_condition) return;
bar(); // error: unreachable code
```
We will need smarter logic for when it is legal to emit this compile
error.
Remove the ZIR test cases. These are redundant with other higher level
Zig source tests we have, and maintaining support for ZIRModule as a
first-class top level abstraction is getting in the way of clean
compiler design for the main use case. We will have ZIR/TZIR based test
cases someday to help with testing optimization passes and ZIR to TZIR
analysis, but as is, these test cases are not accomplishing that, and
they are getting in the way.
|
|
* scopes properly inherit inlining information
* compile errors of inline function calls are properly attached to the
caller rather than the callee.
- added a test case for this
* --watch still opens a repl if compile errors happen.
|
|
Instead of freeing ZIR after semantic analysis, we keep it around so
that it can be used for comptime calls, inline calls, and generic
function calls. ZIR memory is now managed by the Decl arena.
Debug dump() functions are conditionally compiled; only available in
Debug builds of the compiler.
Add a test for an inline function call.
|
|
* remove the -Ddump-zir thing. that's handled through --verbose-ir
* rework Fn to have an is_inline flag without requiring any more memory
on the heap per function.
* implement a rough first version of dumping typed zir (tzir) which is
a lot more helpful for debugging than what we had before. We don't
have a way to parse it though.
* keep track of whether the inline-ness of a function changes because
if it does we have to go update callsites.
* add compile error for inline and export used together.
inline function calls and comptime function calls are implemented the
same way. A block instruction is set up to capture the result, and then
a scope is set up that has a flag for is_comptime and some state if the
scope is being inlined.
when analyzing `ret` instructions, zig looks for inlining state in the
scope, and if found, treats `ret` as a `break` instruction instead, with
the target block being the one set up at the inline callsite.
Follow-up items:
* Complete out the debug TZIR dumping code.
* Don't redundantly generate ZIR for each inline/comptime function
call. Instead we should add a new state enum tag to Fn.
* comptime and inlining branch quotas.
* Add more test cases.
|
|
* Function calls that happen in a comptime scope get called at
compile-time. We do this by putting the parameters in place as
constant values and then running regular function analysis on the
body.
* Added `Scope.Block.dump()` for debugging purposes.
* Fixed some code to call `identifierTokenString` rather than
`tokenSlice`, making it work for `@""` syntax.
* Implemented `Value.copy` for big integers.
Follow-up issues to tackle:
* Adding compile errors to the callsite instead of the callee Decl.
* Proper error notes for "called from here".
- Related: #7555
* Branch quotas.
* ZIR support?
|
|
|
|
|
|
|
|
This patch introduces the following new things:
Types:
- inferred_alloc
- This is a special value that tracks a set of types that have been stored
to an inferred allocation. It does not support most of the normal type queries.
However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
- The payload for this type simply points to the corresponding Value
payload.
Values:
- inferred_alloc
- This is a special value that tracks a set of types that have been stored
to an inferred allocation. It does not support any of the normal value queries.
ZIR instructions:
- store_to_inferred_ptr,
- Same as `store` but the type of the value being stored will be used to infer
the pointer type.
- resolve_inferred_alloc
- Each `store_to_inferred_ptr` puts the type of the stored value into a set,
and then `resolve_inferred_alloc` triggers peer type resolution on the set.
The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
is the allocation that needs to have its type inferred.
Changes to the C backend:
* Implements the bitcast instruction. If the source and dest types
are both pointers, uses a cast, otherwise uses memcpy.
* Tests are run with -Wno-declaration-after-statement. Someday we can
conform to this but not today.
In ZIR form it looks like this:
```zir
fn_body main { // unanalyzed
%0 = dbg_stmt()
=>%1 = alloc_inferred()
%2 = declval_in_module(Decl(add))
%3 = deref(%2)
%4 = param_type(%3, 0)
%5 = const(TypedValue{ .ty = comptime_int, .val = 1})
%6 = as(%4, %5)
%7 = param_type(%3, 1)
%8 = const(TypedValue{ .ty = comptime_int, .val = 2})
%9 = as(%7, %8)
%10 = call(%3, [%6, %9], modifier=auto)
=>%11 = store_to_inferred_ptr(%1, %10)
=>%12 = resolve_inferred_alloc(%1)
%13 = dbg_stmt()
%14 = ret_type()
%15 = const(TypedValue{ .ty = comptime_int, .val = 3})
%16 = sub(%10, %15)
%17 = as(%14, %16)
%18 = return(%17)
} // fn_body main
```
I have not played around with very many test cases yet. Some interesting
ones that I want to look at before merging:
```zig
var x = blk: {
var y = foo();
y.a = 1;
break :blk y;
};
```
In the above test case, x and y are supposed to alias.
```zig
var x = if (bar()) blk: {
var y = foo();
y.a = 1;
break :blk y;
} else blk: {
var z = baz();
z.b = 1;
break :blk z;
};
```
In the above test case, x, y, and z are supposed to alias.
I also haven't tested with `var` instead of `const` yet.
|
|
* Module: improve doc comments
* C backend: improve const-correctness
* C backend: introduce renderTypeAndName
* C backend: put `static` on functions when appropriate
* C backend: fix not handling errors in genBinOp
* C backend: handle more IR instructions
- alloc, store, boolean comparisons, ret_ptr
* C backend: call instruction properly stores its result
* test harness: ensure execution tests have empty stderr
|
|
|
|
|
|
|
|
The addition of `addDeclErr` introduced a memory leak at every call
site, and I also would like to push back on having more than 1
compilation error per `Decl`.
This reverts commit 1634d45f1d53c8d7bfefa56ab4d2fa4cc8218b6d.
|
|
|
|
|
|
stage2 continue
|