diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-11 11:00:32 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-11 11:39:12 -0700 |
| commit | 6d6cf598475ab8d2c3259002655ba04f1d056b2e (patch) | |
| tree | daf38d2c3c68de0411d9106668bde92cc7e0651b /src/codegen.zig | |
| parent | f42725c39bbbe5db13c1a1706db3f31aa0549307 (diff) | |
| download | zig-6d6cf598475ab8d2c3259002655ba04f1d056b2e.tar.gz zig-6d6cf598475ab8d2c3259002655ba04f1d056b2e.zip | |
stage2: support nested structs and arrays and sret
* Add AIR instructions: ret_ptr, ret_load
- This allows Sema to be blissfully unaware of the backend's decision
to implement by-val/by-ref semantics for struct/union/array types.
Backends can lower these simply as alloc, load, ret instructions,
or they can take advantage of them to use a result pointer.
* Add AIR instruction: array_elem_val
- Allows for better codegen for `Sema.elemVal`.
* Implement calculation of ABI alignment and ABI size for unions.
* Before appending the following AIR instructions to a block,
resolveTypeLayout is called on the type:
- call - return type
- ret - return type
- store_ptr - elem type
* Sema: fix memory leak in `zirArrayInit` and other cleanups to this
function.
* x86_64: implement the full x86_64 C ABI according to the spec
* Type: implement `intInfo` for error sets.
* Type: implement `intTagType` for tagged unions.
The Zig type tag `Fn` is now used exclusively for function bodies.
Function pointers are modeled as `*const T` where `T` is a `Fn` type.
* The `call` AIR instruction now allows a function pointer operand as
well as a function operand.
* Sema now has a coercion from function body to function pointer.
* Function type syntax, e.g. `fn()void`, now returns zig tag type of
Pointer with child Fn, rather than Fn directly.
- I think this should probably be reverted. Will discuss the lang
specs before doing this. Idea being that function pointers would
need to be specified as `*const fn()void` rather than `fn() void`.
LLVM backend:
* Enable calling the panic handler (previously this just
emitted `@breakpoint()` since the backend could not handle the panic
function).
* Implement sret
* Introduce `isByRef` and implement it for structs and arrays. Types
that are `isByRef` are now passed as pointers to functions, and e.g.
`elem_val` will return a pointer instead of doing a load.
* Move the function type creating code from `resolveLlvmFunction` to
`llvmType` where it belongs; now there is only 1 instance of this
logic instead of two.
* Add the `nonnull` attribute to non-optional pointer parameters.
* Fix `resolveGlobalDecl` not using fully-qualified names and not using
the `decl_map`.
* Implement `genTypedValue` for pointer-like optionals.
* Fix memory leak when lowering `block` instruction and OOM occurs.
* Implement volatile checks where relevant.
Diffstat (limited to 'src/codegen.zig')
| -rw-r--r-- | src/codegen.zig | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index b25e361f76..2a33cca702 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -855,6 +855,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .shr => try self.airShr(inst), .alloc => try self.airAlloc(inst), + .ret_ptr => try self.airRetPtr(inst), .arg => try self.airArg(inst), .assembly => try self.airAsm(inst), .bitcast => try self.airBitCast(inst), @@ -883,6 +884,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .not => try self.airNot(inst), .ptrtoint => try self.airPtrToInt(inst), .ret => try self.airRet(inst), + .ret_load => try self.airRetLoad(inst), .store => try self.airStore(inst), .struct_field_ptr=> try self.airStructFieldPtr(inst), .struct_field_val=> try self.airStructFieldVal(inst), @@ -914,6 +916,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .slice_ptr => try self.airSlicePtr(inst), .slice_len => try self.airSliceLen(inst), + .array_elem_val => try self.airArrayElemVal(inst), .slice_elem_val => try self.airSliceElemVal(inst), .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst), .ptr_elem_val => try self.airPtrElemVal(inst), @@ -1185,6 +1188,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); } + fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void { + const stack_offset = try self.allocMemPtr(inst); + return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); + } + fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { @@ -1557,6 +1565,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); } + fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { + else => return self.fail("TODO implement array_elem_val for {}", .{self.target.cpu.arch}), + }; + return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); + } + fn airPtrSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { const is_volatile = false; // TODO const bin_op = self.air.instructions.items(.data)[inst].bin_op; @@ -3213,6 +3229,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { return self.finishAir(inst, .dead, .{ un_op, .none, .none }); } + fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { + const un_op = self.air.instructions.items(.data)[inst].un_op; + const ptr = try self.resolveInst(un_op); + _ = ptr; + return self.fail("TODO implement airRetLoad for {}", .{self.target.cpu.arch}); + //return self.finishAir(inst, .dead, .{ un_op, .none, .none }); + } + fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { const bin_op = self.air.instructions.items(.data)[inst].bin_op; if (self.liveness.isUnused(inst)) |
