181 Commits

Author SHA1 Message Date
Jakub Konka
b25cf7db02 stage2 aarch64: add basic function pro/epilogue
Fix typo in `nop` implementation.
Simplify `aarch64` macOS tests.
2021-01-17 14:57:53 +01:00
Andrew Kelley
8deb21c58a stage2: add compile error for label redefinition
Also fix incorrectly destroying notes.

This work is based on Vexu's patch in #7555.
2021-01-17 00:15:25 -07:00
Andrew Kelley
8c9ac4db97 stage2: implement error notes and regress -femit-zir
* 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.
2021-01-16 22:51:01 -07:00
Jakub Konka
b204ea0349 macho: ensure that strtab always follows symtab
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.
2021-01-15 23:22:28 +01:00
Jakub Konka
4ffa8952cc macho: add x86_64 tests 2021-01-13 23:55:56 +01:00
Jakub Konka
7d40aaad2b macho: document more code + add test case 2021-01-13 23:55:18 +01:00
Timon Kruiper
e1d8073d2f stage2: add support for loops in LLVM backend
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.
2021-01-10 17:47:34 -08:00
Timon Kruiper
56c059077c stage2: add initial impl of control flow in LLVM backend
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.
2021-01-08 19:30:52 +01:00
Andrew Kelley
76870a2265
Merge pull request #7700 from FireFox317/more-stage2-stuff-llvm
stage2: improvements to LLVM backend
2021-01-06 16:06:32 -08:00
Andrew Kelley
efe94a9a12 stage2: C backend: support unused Decls 2021-01-06 16:47:09 -07:00
Timon Kruiper
b1cfa923be stage2: rename and move files related to LLVM backend 2021-01-06 10:52:20 +01:00
Timon Kruiper
70f6d16ae2 stage2: add initial impl for generating global decls in 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;
}
```
2021-01-06 10:52:07 +01:00
g-w1
ab5f7b5156 stage2: add compile log statement 2021-01-05 18:43:41 -07:00
Andrew Kelley
1a2dd85570 stage2: C backend: re-implement emit-h
and also mark functions as `extern "C"` as appropriate to support c++
compilers.
2021-01-05 17:41:14 -07:00
Andrew Kelley
cd95444e47 stage2: C backend: remove format() hackery
All C backend tests passing now, except for emit-h tests. Next task in
the branch is to restore emit-h.
2021-01-05 17:41:14 -07:00
Andrew Kelley
7b8cede61f stage2: rework the C backend
* 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.
2021-01-05 17:41:14 -07:00
Noam Preil
9360e5887c integrate CBE with Compilation.update pipeline (closes #7589)
* 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
2021-01-05 17:41:14 -07:00
g-w1
638f93ebdc stage2: implementation of @setEvalBranchQuota:
`@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.
2021-01-04 12:42:52 -07:00
Andrew Kelley
53a0b7997d
Merge pull request #7681 from kubkon/stage2-aarch64-fn-args
stage2: basic fn args for aarch64
2021-01-03 19:51:38 -08:00
Jakub Konka
807dc56fd6 stage2: add aarch64 stage2 tests
Fix missing string format specifier in Mach-O used to generate
path to debug symbols bundle.
2021-01-03 23:20:09 +01:00
Timon Kruiper
0151f3b76a stage2: Add support for testing LLVM enabled builds in test-stage2
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)
2021-01-03 21:13:38 +01:00
Andrew Kelley
654832253a stage2: support recursive inline/comptime functions
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.
2021-01-02 22:42:07 -07:00
Andrew Kelley
50a530196c stage2: fix handling compile error in inline fn call
* 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.
2021-01-02 19:11:56 -07:00
Andrew Kelley
006e7f6805 stage2: re-use ZIR for comptime and inline calls
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.
2021-01-02 19:11:55 -07:00
Andrew Kelley
9362f382ab stage2: implement function call inlining in the frontend
* 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.
2021-01-02 19:11:19 -07:00
Andrew Kelley
fea8659b82 stage2: comptime function calls
* 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?
2021-01-02 19:10:11 -07:00
joachimschmidt557
a2ab2fb9b0
stage2 ARM: Add simple tests for conditional branching 2021-01-01 12:22:17 +01:00
Andrew Kelley
982acc22fd stage2: compile error for invalid var type 2020-12-31 17:25:42 -07:00
Andrew Kelley
7deb1f4f6c stage2: type inference for local var 2020-12-31 02:42:48 -07:00
Andrew Kelley
a46d24af1c stage2: inferred local variables
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.
2020-12-31 01:54:02 -07:00
Andrew Kelley
d18b6785bb stage2: C backend improvements
* 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
2020-12-29 17:56:30 -07:00
Andrew Kelley
813d3308cc stage2: update C backend test cases for new output 2020-12-28 20:32:13 -07:00
Andrew Kelley
7561fca435 stage2: improve test harness to support executing generated C code 2020-12-28 20:01:17 -07:00
Andrew Kelley
a54ccd8537 stage2: C backend: implement @breakpoint and clean up test harness 2020-12-28 18:43:01 -07:00
Andrew Kelley
f75d4cbe56 Revert "stage2: add compile log statement (#7191)"
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.
2020-12-28 11:24:53 -07:00
g-w1
d6e9862049 add test for @compileError in zig code, not only zir 2020-12-26 11:34:15 -05:00
g-w1
7f512f2236 fix test cases to use str zir inst instead of just a quoted string 2020-12-26 11:22:16 -05:00
Veikka Tuominen
641bf4c46e
Merge pull request #7552 from Vexu/stage2-continue
stage2 continue
2020-12-26 12:26:16 +02:00
g-w1
1634d45f1d
stage2: add compile log statement (#7191) 2020-12-26 02:40:49 +02:00
Veikka Tuominen
a50759325c
stage2: add error for unused labels 2020-12-26 02:36:12 +02:00
Veikka Tuominen
40aad4f47e
stage2: break and continue out of loops 2020-12-26 02:26:53 +02:00
Veikka Tuominen
ce7dcf2294
Merge pull request #7507 from joachimschmidt557/stage2-arm
stage2 ARM: implement basic binary bitwise operations
2020-12-23 12:17:40 +02:00
g-w1
cb3198af2a
stage2: @TypeOf (#7475)
* stage2: add @TypeOf

* stage2: discriminate on what type of @builtinCall in nodeMayNeedMemoryLocation

* merge upstream into my stash

* add type equality to make easier to test and defer free the types

* remove addDeclErr, I dont know why I added it, its from a different branch that im working on

* add tests

* update error message to match stage1

* use ComptimeStringMap and update which nodes don't need memory from vexu's suggestions

* fix typo

Co-authored-by: Veikka Tuominen <git@vexu.eu>

* make @TypeOf(single_arg) go to .typeof zir inst and add test for that

* unioninit, as, reduce change mayneedmemorylocation

Co-authored-by: Veikka Tuominen <git@vexu.eu>
2020-12-23 01:26:36 +02:00
Alex Cameron
58bd6c5f8e Add tests for emit-h functionality. 2020-12-23 01:14:35 +11:00
Noam Preil
8538053940 Add header test harness 2020-12-23 01:14:35 +11:00
joachimschmidt557
45a88be573
stage2 ARM: add test cases for binary bitwise operations 2020-12-21 19:24:23 +01:00
g-w1
6294c1136c
stage2: variable shadowing detection (#6969) 2020-12-06 19:36:49 +02:00
Andrew Kelley
2ed1ed9b32 stage2: introduce Module.failed_root_source_file
Use case:

zig build-exe non_existent_file.zig

Previous behavior:

error.FileNotFound, followed by an error return trace

Behavior after this commit:

error: unable to read non_existent_file.zig: FileNotFound
(end of stderr, exit code 1)

This turns AllErrors.Message into a tagged union which now has the
capability to represent both "plain" errors as well as source-based
errors (with file, line, column, byte offset). The "no entry point found"
error has moved to be a plain error message.
2020-12-04 17:21:55 -07:00
Timon Kruiper
ac85e1f2c8 stage2: make sure to emit the ZIR instructions of exported functions
Previously the emitted ZIR code would not have the ZIR instructions
of the exported functions.
2020-12-03 11:46:35 -08:00
joachimschmidt557
ceebcb2b4d
stage2 ARM: add test case for addition 2020-11-28 23:26:17 +01:00