128 Commits

Author SHA1 Message Date
gracefu
1e63e8d8b6
stage2 x86_64: fix codegen ensureCapacity bug for function calls
Co-authored-by: joachimschmidt557 <joachim.schmidt557@outlook.com>
2021-04-16 15:21:17 +08:00
gracefu
62e755623f
stage2 x86_64: bugfix abi_size == 64 should be abi_size == 8 2021-04-16 15:21:17 +08:00
gracefu
b004c3da15
stage2 x86_64: try to fix RIP-relative offset to GOT for macho 2021-04-16 15:21:17 +08:00
gracefu
0409f9e024
stage2 x86_64: simplify inst encoder to a set of dumb helper fns 2021-04-16 15:21:17 +08:00
gracefu
c4b83ea021
stage2 x86_64: implement integer mul
This was also an experiment to see if it were easier to implement a new
feature when using the instruction encoder.

Verdict: It's not that much easier, but I think it's certainly much more
readable, because the description of the Instruction annotates what each
field means. Right now, precise knowledge of x86_64 instructions is
still required because things like when to set the 64-bit flag, how to
read x86_64 instruction references, etc. are still not automatically
done for you.

In the future, this interface might make it sligtly easier to write an
assembler for x86_64, by abstracting the bit-fiddling aspects of
instruction encoding.
2021-04-16 15:21:17 +08:00
gracefu
5bd464e386
stage2 x86_64: use abi size to determine 64-bit operation
From my very cursory reading, it seems that the register manager doesn't
distinguish between registers that are physically the same but have
different sizes.

In that case, this means that during codegen, we can't rely on
`reg.size()` when determining the width of the operations we have to
perform. Instead, we must use some form of `ty.abiSize(self.target.*)`
to determine the size of the type we're operating with. If this size is
64 bits, then we should enable 64-bit operation.

This fixed a bug in the codegen for spilling instructions, which was
overwriting the previous stack entry with zeroes. See the modified test
case in this commit.
2021-04-16 15:21:17 +08:00
gracefu
36df1526da
stage2 x86_64: refactor codegen to use inst encoder
There are parts of it that I didn't modify because the byte
representation was important (e.g. we need to know what the exact
byte position where we store the address into the offset table is)
2021-04-16 15:21:17 +08:00
joachimschmidt557
4fe575f47b
stage2 ARM: Add fibonacci test 2021-04-11 10:19:36 +02:00
joachimschmidt557
a6ddc12b33
stage2 codegen: Set MCValue of register arguments to their stack copy 2021-04-11 10:19:35 +02:00
Andrew Kelley
f75cdd1acd
Merge pull request #8470 from ziglang/stage2-start
stage2: blaze the trail for std lib integration
2021-04-09 10:15:46 -07:00
Andrew Kelley
61b868f9a5 stage2: simplify Decl src_node field
Also fix "previous definition here" error notes to be correct.
2021-04-08 20:37:19 -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
joachimschmidt557
4ff5a3cd94
stage2 regalloc: Add unit test for getReg 2021-04-07 15:15:14 +02:00
joachimschmidt557
ac2211118f
stage2 regalloc: Add getReg and getRegWithoutTracking 2021-04-06 21:14:00 +02:00
joachimschmidt557
43d364afef stage2 AArch64: Add ldrh and ldrb instructions 2021-04-02 14:46:30 -07:00
joachimschmidt557
228a1ce3e8 stage2 register_manager: Add unit tests for tryAllocReg and allocReg 2021-04-02 12:01:52 -07:00
joachimschmidt557
4efbcad26d stage2 codegen: Extract register management code into separate file 2021-04-02 12:01:52 -07:00
Andrew Kelley
8ebfdc14f6 stage2: implement structs in the frontend
New ZIR instructions:
 * struct_decl_packed
 * struct_decl_extern

New TZIR instruction: struct_field_ptr

Introduce `Module.Struct`. It uses `Value` to store default values and
abi alignments.

Implemented Sema.analyzeStructFieldPtr and zirStructDecl.

Some stuff I changed from `@panic("TODO")` to `log.warn("TODO")`.
It's becoming more clear that we need the lazy value mechanism soon;
Type is becoming unruly, and some of these functions have too much logic
given that they don't have any context for memory management or error
reporting.
2021-04-01 22:39:09 -07:00
Andrew Kelley
070a28e493
Merge pull request #8266 from ziglang/zir-memory-layout
rework ZIR memory layout; overhaul source locations
2021-03-31 23:11:15 -07:00
Andrew Kelley
e272c29c16 Sema: implement switch validation for ranges 2021-03-31 15:06:03 -07:00
joachimschmidt557
1b657e6e41 stage2 codegen: Make sure function return value is in a callee
preserved register
2021-03-31 23:27:50 +02:00
joachimschmidt557
e088a17f56 stage2 AArch64: implement strb and strh 2021-03-31 23:26:49 +02:00
jacob gw
0005b34637 stage2: implement sema for @errorToInt and @intToError 2021-03-28 18:22:01 -07:00
Andrew Kelley
abdbc11c7e stage2: codegen: update asm IR to new names 2021-03-18 22:54:59 -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
Andrew Kelley
f5aca4a6a1 Merge remote-tracking branch 'origin/master' into zir-memory-layout
I need the enum arrays that were just merged into master.
2021-03-18 15:52:12 -07:00
Andrew Kelley
66245ac834 stage2: Module and Sema are compiling again
Next up is reworking the seam between the LazySrcLoc emitted by Sema
and the byte offsets currently expected by codegen.

And then the big one: updating astgen.zig to use the new memory layout.
2021-03-17 22:54:56 -07:00
Jakub Konka
e5234c0e9e macho: offset table part of GOT 2021-03-17 12:16:36 +01:00
Jakub Konka
3019676440 macho: apply some renames to bring closer to zld 2021-03-17 12:10:39 +01:00
Andrew Kelley
e9a038c33b
Merge pull request #7934 from Vexu/stage2-cbe
Stage2 cbe: optionals and errors
2021-03-11 22:02:35 -05:00
joachimschmidt557
bdb917006c stage2 tzir: Add wrapping integer arithmetic instructions 2021-03-11 14:31:21 -05:00
jacob gw
6467ef6d3b
cbe: add error comparison support 2021-03-08 00:33:59 +02:00
joachimschmidt557
345ac53836
stage2 ARM: Implement basic integer multiplication 2021-03-02 00:14:56 +01:00
g-w1
153c97ac9e improve stage2 to allow catch at comptime:
* add error_union value tag.
* add analyzeIsErr
* add Value.isError
* add TZIR wrap_errunion_payload and wrap_errunion_err for
  wrapping from T -> E!T and E -> E!T
* add anlyzeInstUnwrapErrCode and analyzeInstUnwrapErr
* add analyzeInstEnsureErrPayloadVoid:
* add wrapErrorUnion
* add comptime error comparison for tests
* tests!
2021-02-25 16:41:16 -08:00
joachimschmidt557
297eabd4ac stage2 ARM: Save callee-saved registers
Add a new allocated_registers bitmap to keep track of all callee-saved
registers allocated during generation of this function.

Function(.arm).gen uses this data to generate instructions in the
function prologue and epilogue to push and pop these registers
respectively.
2021-02-25 22:27:19 +02:00
Andrew Kelley
449f4de382 zig fmt src/ 2021-02-24 21:54:23 -07:00
Andrew Kelley
8e6c2b7a47 Merge remote-tracking branch 'origin/master' into ast-memory-layout 2021-02-24 15:08:23 -07:00
joachimschmidt557
9712e89265 stage2 codegen: Add Type argument to genSetReg 2021-02-21 12:23:36 +02:00
Andrew Kelley
7630a5c566 stage2: more progress towards Module/astgen building with new mem layout 2021-02-12 23:47:17 -07:00
Tadeo Kondrak
9270aae071
stage2: fix zero-sized function parameters (#7998) 2021-02-12 15:40:44 -05:00
Jonathan Marler
1480c42806 require specifier for arrayish types 2021-02-09 22:25:52 -08:00
joachimschmidt557
6a5a6386c6 stage2 ARM: fix register allocation in genArmBinOp
Previously, this would reuse an operand even if reuseOperand returned
false for both operands.

genArmBinOpCode was also changed to be more Three-address code oriented
in the process.
2021-02-09 23:58:41 +01:00
joachimschmidt557
446ebddb93 stage2 ARM: save function arguments to stack for debugging
This changes genArg to copy registers to the stack for better
debugging. Thus, it requires genSetStack to be implemented in order for
genArg to work.
2021-02-01 12:17:24 -08:00
Andrew Kelley
6c8985fcee astgen: rework labeled blocks 2021-01-31 21:09:22 -07:00
Andrew Kelley
588171c30b sema: after block gets peer type resolved, insert type coercions
on the break instruction operands. This involves a new TZIR instruction,
br_block_flat, which represents a break instruction where the operand is
the result of a flat block. See the doc comments on the instructions for
more details.

How it works: when adding break instructions in semantic analysis, the
underlying allocation is slightly padded so that it is the size of a
br_block_flat instruction, which allows the break instruction to later
be converted without removing instructions inside the parent body. The
extra type coercion instructions go into the body of the br_block_flat,
and backends are responsible for dispatching the instruction correctly
(it should map to the same function calls for related instructions).
2021-01-31 21:09:22 -07:00
Andrew Kelley
b7452fe35f stage2: rework astgen result locations
Motivating test case:

```zig
export fn _start() noreturn {
    var x: u64 = 1;
    var y: u32 = 2;
    var thing: u32 = 1;
    const result = if (thing == 1) x else y;
    exit();
}
```

The main idea here is for astgen to output ideal ZIR depending on
whether or not the sub-expressions of a block consume the result
location. Here, neither `x` nor `y` consume the result location of the
conditional expression block, and so the ZIR should communicate the
result of the condbr using break instructions, not with the result
location pointer.

With this commit, this is accomplished:

```
  %22 = alloc_inferred()
  %23 = block({
    %24 = const(TypedValue{ .ty = type, .val = bool})
    %25 = deref(%18)
    %26 = const(TypedValue{ .ty = comptime_int, .val = 1})
    %27 = cmp_eq(%25, %26)
    %28 = as(%24, %27)
    %29 = condbr(%28, {
      %30 = deref(%4)
      < there is no longer a store instruction here >
      %31 = break("label_23", %30)
    }, {
      %32 = deref(%11)
      < there is no longer a store instruction here >
      %33 = break("label_23", %32)
    })
  })
  %34 = store_to_inferred_ptr(%22, %23) <-- the store is only here
  %35 = resolve_inferred_alloc(%22)
```

However if the result location gets consumed, the break instructions
change to break_void, and the result value is communicated only by the
stores, not by the break instructions.

Implementation:

 * The GenZIR scope that conditional branches uses now has an optional
   result location pointer field and a count of how many times the
   result location ended up being an rvalue (not consumed).
 * When rvalue() is called on a result location for a block, it
   increments this counter. After generating the branches of a block,
   astgen for the conditional branch checks this count and if it is 2
   then the store_to_block_ptr instructions are elided and it calls
   rvalue() using the block result (which will account for peer type
   resolution on the break operands).

astgen has many functions disabled until they can be reworked with these
new semantics. That will be done before merging the branch.

There are some new rules for astgen to follow regarding result locations
and what you are allowed/required to do depending on which one is passed
to expr(). See the updated doc comments of ResultLoc for details.

I also changed naming conventions of stuff in this commit, sorry about
that.
2021-01-31 21:09:22 -07:00
Andrew Kelley
ecc246efa2 stage2: rework ZIR/TZIR for optionals and error unions
* fix wrong pointer const-ness when unwrapping optionals
 * allow grouped expressions and orelse as lvalues
 * ZIR for unwrapping optionals: no redundant deref
   - add notes to please don't use rlWrapPtr, this function should be
     deleted
 * catch and orelse: better ZIR for non-lvalue: no redundant deref;
   operate entirely on values. lvalue case still works properly.
   - properly propagate the result location into the target expression
 * Test harness: better output when tests fail due to compile errors.
 * TZIR: add instruction variants. These allow fewer TZIR instructions to
   be emitted from zir_sema. See the commit diff for per-instruction
   documentation.
   - is_null
   - is_non_null
   - is_null_ptr
   - is_non_null_ptr
   - is_err
   - is_err_ptr
   - optional_payload
   - optional_payload_ptr
 * TZIR: removed old naming convention instructions:
   - isnonnull
   - isnull
   - iserr
   - unwrap_optional
 * ZIR: add instruction variants. These allow fewer ZIR instructions to
   be emitted from astgen. See the commit diff for per-instruction
   documentation.
   - is_non_null
   - is_null
   - is_non_null_ptr
   - is_null_ptr
   - is_err
   - is_err_ptr
   - optional_payload_safe
   - optional_payload_unsafe
   - optional_payload_safe_ptr
   - optional_payload_unsafe_ptr
   - err_union_payload_safe
   - err_union_payload_unsafe
   - err_union_payload_safe_ptr
   - err_union_payload_unsafe_ptr
   - err_union_code
   - err_union_code_ptr
 * ZIR: removed old naming convention instructions:
   - isnonnull
   - isnull
   - iserr
   - unwrap_optional_safe
   - unwrap_optional_unsafe
   - unwrap_err_safe
   - unwrap_err_unsafe
   - unwrap_err_code
2021-01-18 19:29:18 -07:00
joachimschmidt557
6c7e66613d stage2 AArch64: implement jump 2021-01-18 22:22:53 +01:00