89 Commits

Author SHA1 Message Date
Jacob G-W
2e6ce11eb2 stage2: implement shr and boilerplate for shl
This implements it in the llvm and c backends.
x86_64 will have to be a little more work.
2021-08-19 16:18:40 -04:00
Andrew Kelley
799fedf612 stage2: pass some error union tests
* Value: rename `error_union` to `eu_payload` and clarify the intended
   usage in the doc comments. The way error unions is represented with
   Value is fixed to not have ambiguous values.
 * Fix codegen for error union constants in all the backends.
 * Implement the AIR instructions having to do with error unions in the
   LLVM backend.
2021-08-07 20:34:28 -07:00
Andrew Kelley
f81b2531cb stage2: pass some pointer tests
* New AIR instructions: ptr_add, ptr_sub, ptr_elem_val, ptr_ptr_elem_val
   - See the doc comments for details.
 * Sema: implement runtime pointer arithmetic.
 * Sema: implement elem_val for many-pointers.
 * Sema: support coercion from `*[N:s]T` to `[*]T`.
 * Type: isIndexable handles many-pointers.
2021-08-07 15:46:53 -07:00
Andrew Kelley
ddf14323ea stage2: implement @truncate 2021-08-01 16:13:58 -07:00
Andrew Kelley
040c6eaaa0 stage2: garbage collect unused anon decls
After this change, the frontend and backend cooperate to keep track of
which Decls are actually emitted into the machine code. When any backend
sees a `decl_ref` Value, it must mark the corresponding Decl `alive`
field to true.

This prevents unused comptime data from spilling into the output object
files. For example, if you do an `inline for` loop, previously, any
intermediate value calculations would have gone into the object file.
Now they are garbage collected immediately after the owner Decl has its
machine code generated.

In the frontend, when it is time to send a Decl to the linker, if it has
not been marked "alive" then it is deleted instead.

Additional improvements:
 * Resolve type ABI layouts after successful semantic analysis of a
   Decl. This is needed so that the backend has access to struct fields.
 * Sema: fix incorrect logic in resolveMaybeUndefVal. It should return
   "not comptime known" instead of a compile error for global variables.
 * `Value.pointerDeref` now returns `null` in the case that the pointer
   deref cannot happen at compile-time. This is true for global
   variables, for example. Another example is if a comptime known
   pointer has a hard coded address value.
 * Binary arithmetic sets the requireRuntimeBlock source location to the
   lhs_src or rhs_src as appropriate instead of on the operator node.
 * Fix LLVM codegen for slice_elem_val which had the wrong logic for
   when the operand was not a pointer.

As noted in the comment in the implementation of deleteUnusedDecl, a
future improvement will be to rework the frontend/linker interface to
remove the frontend's responsibility of calling allocateDeclIndexes.

I discovered some issues with the plan9 linker backend that are related
to this, and worked around them for now.
2021-07-29 19:30:37 -07:00
Andrew Kelley
a5c6e51f03 stage2: more principled approach to comptime references
* AIR no longer has a `variables` array. Instead of the `varptr`
   instruction, Sema emits a constant with a `decl_ref`.
 * AIR no longer has a `ref` instruction. There is no longer any
   instruction that takes a value and returns a pointer to it. If this
   is desired, Sema must either create an anynomous Decl and return a
   constant `decl_ref`, or in the case of a runtime value, emit an
   `alloc` instruction, `store` the value to it, and then return the
   `alloc`.
 * The `ref_val` Value Tag is eliminated. `decl_ref` should be used
   instead. Also added is `eu_payload_ptr` which points to the payload
   of an error union, given an error union pointer.

In general, Sema should avoid calling `analyzeRef` if it can be helped.
For example in the case of field_val and elem_val, there should never be
a reason to create a temporary (alloc or decl). Recent previous commits
made progress along that front.

There is a new abstraction in Sema, which looks like this:

    var anon_decl = try block.startAnonDecl();
    defer anon_decl.deinit();
    // here 'anon_decl.arena()` may be used
    const decl = try anon_decl.finish(ty, val);
    // decl is typically now used with `decl_ref`.

This pattern is used to upgrade `ref_val` usages to `decl_ref` usages.

Additional improvements:

 * Sema: fix source location resolution for calling convention
   expression.
 * Sema: properly report "unable to resolve comptime value" for loads of
   global variables. There is now a set of functions which can be
   called if the callee wants to obtain the Value even if the tag is
   `variable` (indicating comptime-known address but runtime-known value).
 * Sema: `coerce` resolves builtin types before checking equality.
 * Sema: fix `u1_type` missing from `addType`, making this type have a
   slightly more efficient representation in AIR.
 * LLVM backend: fix `genTypedValue` for tags `decl_ref` and `variable`
   to properly do an LLVMConstBitCast.
 * Remove unused parameter from `Value.toEnum`.

After this commit, some test cases are no longer passing. This is due to
the more principled approach to comptime references causing more
anonymous decls to get sent to the linker for codegen. However, in all
these cases the decls are not actually referenced by the runtime machine
code. A future commit in this branch will implement garbage collection
of decls so that unused decls do not get sent to the linker for codegen.
This will make the tests go back to passing.
2021-07-29 15:59:51 -07:00
Andrew Kelley
dc88864c97 stage2: implement @boolToInt
This is the first commit in which some behavior tests are passing for
both stage1 and stage2.
2021-07-27 17:08:37 -07:00
Andrew Kelley
31a59c229c stage2: improvements towards zig test
* Add AIR instruction: struct_field_val
   - This is part of an effort to eliminate the AIR instruction `ref`.
   - It's implemented for C backend and LLVM backend so far.
 * Rename `resolvePossiblyUndefinedValue` to `resolveMaybeUndefVal` just
   to save some columns on long lines.
 * Sema: add `fieldVal` alongside `fieldPtr` (renamed from
   `namedFieldPtr`). This is part of an effort to eliminate the AIR
   instruction `ref`. The idea is to avoid unnecessary loads, stores,
   stack usage, and IR instructions, by paying a DRY cost.

LLVM backend improvements:

 * internal linkage vs exported linkage is implemented, along with
   aliases. There is an issue with incremental updates due to missing
   LLVM API for deleting aliases; see the relevant comment in this commit.
   - `updateDeclExports` is hooked up to the LLVM backend now.
 * Fix usage of `Type.tag() == .noreturn` rather than calling `isNoReturn()`.
 * Properly mark global variables as mutable/constant.
 * Fix llvm type generation of function pointers
 * Fix codegen for calls of function pointers
 * Implement llvm type generation of error unions and error sets.
 * Implement AIR instructions: addwrap, subwrap, mul, mulwrap, div,
   bit_and, bool_and, bit_or, bool_or, xor, struct_field_ptr,
   struct_field_val, unwrap_errunion_err, add for floats, sub for
   floats.

After this commit, `zig test` on a file with `test "example" {}`
correctly generates and executes a test binary. However the
`test_functions` slice is undefined and just happens to be going into
the .bss section, causing the length to be 0. The next step towards
`zig test` will be replacing the `test_functions` Decl Value with the
set of test function pointers, before it is sent to linker/codegen.
2021-07-26 19:27:49 -07:00
Andrew Kelley
7b8cb881df stage2: improvements towards zig test
* There is now a main_pkg in addition to root_pkg. They are usually the
   same. When using `zig test`, main_pkg is the user's source file and
   root_pkg has the test runner.
 * scanDecl no longer looks for test decls outside the package being
   tested. honoring `--test-filter` is still TODO.
 * test runner main function has a void return value rather than
   `anyerror!void`
 * Sema is improved to generate better AIR for for loops on slices.
 * Sema: fix incorrect capacity calculation in zirBoolBr
 * Sema: add compile errors for trying to use slice fields as an lvalue.
 * Sema: fix type coercion for error unions
 * Sema: fix analyzeVarRef generating garbage AIR
 * C codegen: fix renderValue for error unions with 0 bit payload
 * C codegen: implement function pointer calls
 * CLI: fix usage text

 Adds 4 new AIR instructions:

  * slice_len, slice_ptr: to get the ptr and len fields of a slice.
  * slice_elem_val, ptr_slice_elem_val: to get the element value of
    a slice, and a pointer to a slice.

AstGen gains a new functionality:

 * One of the unused flags of struct decls is now used to indicate
   structs that are known to have non-zero size based on the AST alone.
2021-07-23 22:42:31 -07:00
Andrew Kelley
f47cf93b47 stage2: C backend: fix ret AIR instruction
when operand has 0 runtime bits
2021-07-20 15:56:42 -07:00
Andrew Kelley
9c652cc650 stage2: C backend: implement support for switch_br AIR 2021-07-20 15:52:58 -07:00
Jacob G-W
414b144257 cbe: fix not (it is a ty_op, not un_op) 2021-07-20 12:19:16 -07:00
Andrew Kelley
4a0f38bb76 stage2: update LLVM backend to new AIR memory layout
Also fix compile errors when not using -Dskip-non-native
2021-07-20 12:19:16 -07:00
Andrew Kelley
761f36ff93 stage2: rework C backend for new AIR memory layout 2021-07-20 12:19:16 -07:00
Andrew Kelley
c09b973ec2 stage2: compile error fixes for AIR memory layout branch
Now the branch is compiling again, provided that one uses
`-Dskip-non-native`, but many code paths are disabled. The code paths
can now be re-enabled one at a time and updated to conform to the new
AIR memory layout.
2021-07-20 12:19:16 -07:00
Andrew Kelley
0f38f68696 stage2: Air and Liveness are passed ephemerally
to the link infrastructure, instead of being stored with Module.Fn. This
moves towards a strategy to make more efficient use of memory by not
storing Air or Liveness data in the Fn struct, but computing it on
demand, immediately sending it to the backend, and then immediately
freeing it.

Backends which want to defer codegen until flush() such as SPIR-V
must move the Air/Liveness data upon `updateFunc` being called and keep
track of that data in the backend implementation itself.
2021-07-20 12:19:16 -07:00
Andrew Kelley
5d6f7b44c1 stage2: rework AIR memory layout
This commit changes the AIR file and the documentation of the memory
layout. The actual work of modifying the surrounding code (in Sema and
codegen) is not yet done.
2021-07-20 12:18:14 -07:00
Andrew Kelley
28dd9d478d C backend: TypedefMap is now ArrayHashMap
The C backend depends on insertion order into this map so that type
definitions will be declared before they are used.
2021-07-12 12:40:32 -07:00
Andrew Kelley
9dbe684854 C backend: cleanups to wrapping int operations
* less branching by passing parameters in the main op code switch.
 * properly pass the target when asking the type system for int info.
 * handle u8, i16, etc when it is represented using
   int_unsigned/int_signed tag.
 * compile error instead of assertion failure for unimplemented cases
   (greater than 64 bits integer).
 * control flow cleanups
 * zig.h: expand macros into inline functions
 * reduce the complexity of the test case by making it one test case
   that calls multiple functions. Also fix the problem of c_int max
   value mismatch between host and target.
2021-07-08 11:21:06 -07:00
Matt Knight
fb16633ecb C backend: add/sub/mul wrapping for the C backend 2021-07-08 09:56:40 -07:00
Andrew Kelley
c2e66d9bab stage2: basic inferred error set support
* Inferred error sets are stored in the return Type of the function,
   owned by the Module.Fn. So it cleans up that memory in deinit().
 * Sema: update the inferred error set in zirRetErrValue
   - Update relevant code in wrapErrorUnion
 * C backend: improve some some instructions to take advantage of
   liveness analysis to avoid being emitted when unused.
 * C backend: when an error union has a payload type with no runtime
   bits, emit the error union as the same type as the error set.
2021-07-07 20:47:21 -07:00
Andrew Kelley
5c8bd443d9 stage2: fix if expressions on error unions
AstGen had the then-else logic backwards for if expressions
on error unions. This commit fixes it.

Turns out AstGen only really needs `is_non_null` and `is_non_err`,
and does not need the `is_null` or `is_err` variants. So I removed the
`is_null{,_ptr}` and `is_err{,_ptr}` ZIR instructions (-4) and
added `is_non_err`, `is_non_err_ptr` ZIR instructions (+2) for
a total of (-2) ZIR instructions, giving us a tiny bit more headroom
within the 256 tag limit. This required swapping the order of
then/else blocks in a handful of cases, but ultimately means the
ZIR will be in the same as source order, which is convenient
when debugging.

AIR code on the other hand, gains the `is_non_err` and `is_non_err_ptr`
instructions.

Sema: fix logic in zirErrUnionCode and zirErrUnionCodePtr returning the
wrong result type.
2021-07-07 19:50:56 -07:00
Andrew Kelley
13f04e3012 stage2: implement @panic and beginnigs of inferred error sets
* ZIR: add two instructions:
   - ret_err_value_code
   - ret_err_value
 * AstGen: add countDefers and utilize it to emit more efficient ZIR for
   return expressions in the presence of defers.
 * AstGen: implement |err| payloads for `errdefer` syntax.
   - There is not an "unused capture" error for it yet.
 * AstGen: `return error.Foo` syntax gets a hot path in return
   expressions, using the new ZIR instructions. This also is part of
   implementing inferred error sets, since we need to tell Sema to add
   an error value to the inferred error set before it gets coerced.
 * Sema: implement `@setCold`.
   - Implement `@setCold` support for C backend.
 * `@panic` and regular safety panics such as `unreachable` now properly
   invoke `std.builtin.panic`.
 * C backend: improve pointer and function value rendering.
 * C linker: fix redundant typedefs.
 * Add Type.error_set_inferred.
 * Fix Value.format for enum_literal, enum_field_index, bytes.
 * Remove the C backend test that checks for identical text

I measured a 14% reduction in Total ZIR Bytes from master branch
for std/os.zig.
2021-07-07 00:39:23 -07:00
Jacob G-W
9fffffb07b fix code broken from previous commit 2021-06-21 17:03:03 -07:00
Jacob G-W
641ecc260f std, src, doc, test: remove unused variables 2021-06-21 17:03:03 -07:00
Jacob G-W
a95fdb0635 stage2: simplify codegen for errorToInt and intToError
We can just use bitcast instead of error_to_int, int_to_error since
errorToInt and intToError do not actually do anything, just change types.
This allows us to remove 2 air ops that were the exact same as bitcast
2021-06-21 18:45:28 +03:00
Martin Wickham
fc9430f567 Breaking hash map changes for 0.8.0
- hash/eql functions moved into a Context object
- *Context functions pass an explicit context
- *Adapted functions pass specialized keys and contexts
- new getPtr() function returns a pointer to value
- remove functions renamed to fetchRemove
- new remove functions return bool
- removeAssertDiscard deleted, use assert(remove(...)) instead
- Keys and values are stored in separate arrays
- Entry is now {*K, *V}, the new KV is {K, V}
- BufSet/BufMap functions renamed to match other set/map types
- fixed iterating-while-modifying bug in src/link/C.zig
2021-06-03 17:02:16 -05:00
joachimschmidt557
e8236551ab stage2: Move BlockData out of ir.Inst.Block 2021-05-22 21:15:25 -04:00
Andrew Kelley
79dee75b1c stage2: rename ir.zig to air.zig
We've settled on the nomenclature for the artifacts the compiler
pipeline produces:

1. Tokens
2. AST (Abstract Syntax Tree)
3. ZIR (Zig Intermediate Representation)
4. AIR (Analyzed Intermediate Representation)
5. Machine Code

Renaming `ir` identifiers to `air` will come with the inevitable
air-memory-layout branch that I plan to start after the 0.8.0 release.
2021-05-22 14:29:16 -07:00
Andrew Kelley
a74632b50a C backend: fix emitting '$' in identifier names
This causes warnings from clang when compiled.
2021-05-11 14:51:21 -07:00
Andrew Kelley
bcf15e39e2 stage2: add owns_tv flag to Module.Decl
Decl objects need to know whether they are the owner of the Type/Value
associated with them, in order to decide whether to destroy the
associated Namespace, Fn, or Var when cleaning up.
2021-05-11 14:17:52 -07:00
Andrew Kelley
f86469bc5e stage2: semaDecl properly analyzes the decl block
Also flattened out Decl TypedValue fields into
ty, val, has_tv
and add relevant fields to Decl for alignment and link section.
2021-04-28 16:57:01 -07:00
Andrew Kelley
4630e3891c AstGen: implement inline asm output 2021-04-19 18:44:59 -07:00
Andrew Kelley
9f744f19e7
Merge pull request #8464 from gracefuu/grace/wasm-ops
stage2 wasm: Add division and bitwise/boolean ops &, |, ^, and, or
2021-04-08 13:41:49 -07:00
gracefu
4c71942f84
stage2: Add .div to ir.zig 2021-04-08 05:26:56 +08:00
Andrew Kelley
015599d1ef C backend: enumerate all the types in renderType
Now that we're close to supporting all the types, get rid of the `else`
prong and explicitly list out those types that are not yet implemented.

Thanks @g-w1
2021-04-07 13:17:23 -07:00
Andrew Kelley
19cf987198 C backend: implement Enum types and values
They are lowered directly as the integer tag type, with no typedef.
2021-04-06 23:19:46 -07:00
Andrew Kelley
97d7fddfb7 stage2: progress towards basic structs
Introduce `ResultLoc.none_or_ref` which is used by field access
expressions to avoid unnecessary loads when the field access itself
will do the load. This turns:

```zig
p.y - p.x - p.x
```

from

```zir
  %14 = load(%4) node_offset:8:12
  %15 = field_val(%14, "y") node_offset:8:13
  %16 = load(%4) node_offset:8:18
  %17 = field_val(%16, "x") node_offset:8:19
  %18 = sub(%15, %17) node_offset:8:16
  %19 = load(%4) node_offset:8:24
  %20 = field_val(%19, "x") node_offset:8:25
```

to

```zir
  %14 = field_val(%4, "y") node_offset:8:13
  %15 = field_val(%4, "x") node_offset:8:19
  %16 = sub(%14, %15) node_offset:8:16
  %17 = field_val(%4, "x") node_offset:8:25
```

Much more compact. This requires `Sema.zirFieldVal` to support both
pointers and non-pointers.

C backend: Implement typedefs for struct types, as well as the following
TZIR instructions:
 * mul
 * mulwrap
 * addwrap
 * subwrap
 * ref
 * struct_field_ptr

Note that add, addwrap, sub, subwrap, mul, mulwrap instructions are all
incorrect currently and need to be updated to properly handle wrapping
and non wrapping for signed and unsigned.

C backend: change indentation delta to 1, to make the output smaller and
to process fewer bytes.

I promise I will add a test case as soon as I fix those warnings that
are being printed for my test case.
2021-04-02 19:11:51 -07:00
jacob gw
0005b34637 stage2: implement sema for @errorToInt and @intToError 2021-03-28 18:22:01 -07:00
Andrew Kelley
bd2154da3d stage2: the code is compiling again
(with a lot of things commented out)
2021-03-18 22:48:28 -07:00
Andrew Kelley
b2682237db stage2: get Module and Sema compiling again
There are some `@panic("TODO")` in there but I'm trying to get the
branch to the point where collaborators can jump in.

Next is to repair the seam between LazySrcLoc and codegen's expected
absolute file offsets.
2021-03-18 22:19:28 -07:00
Veikka Tuominen
fc62ff77c3
stage2: error union payload must also be a valid variable type 2021-03-08 00:33:59 +02:00
jacob gw
30ffa052f2
stage2 cbe: add error union and error union operations 2021-03-08 00:33:59 +02:00
Veikka Tuominen
0a7be71bc2
stage2 cbe: non pointer optionals 2021-03-08 00:33:56 +02:00
Veikka Tuominen
cfc19eace7
stage2 cbe: errors 2021-03-08 00:33:07 +02:00
Veikka Tuominen
c22f010fdd
stage2 cbe: regular optional types 2021-03-08 00:33:07 +02:00
Veikka Tuominen
ca20d0ea26
stage2 cbe: pointer like optionals 2021-03-08 00:32:52 +02:00
Veikka Tuominen
8c6e7fb2c7
stage2: implement var args 2021-03-06 15:55:29 +02:00
Andrew Kelley
449f4de382 zig fmt src/ 2021-02-24 21:54:23 -07:00
Isaac Freund
070e548acf
std: remove io.AutoIndentingStream
This type is not widely applicable enough to be a public part of the
public interface of the std.

The current implementation in only fully utilized by the zig fmt
implementation, which could benefit by even tighter integration as
will be demonstrated in the next commit. Therefore, move the current
io.AutoIndentingStream to lib/std/zig/render.zig.

The C backend of the self hosted compiler also use this type currently,
but it does not require anywhere near its full complexity. Therefore,
implement a greatly simplified version of this interface in
src/codegen/c.zig.
2021-02-16 23:20:46 +01:00