diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-08-20 15:23:55 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-08-20 15:41:57 -0700 |
| commit | 0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4 (patch) | |
| tree | c3de2205e0bb525d61ee78800c118b13efbf1029 /src/value.zig | |
| parent | 2f1abd919a8465e515875cd08816778df795aabe (diff) | |
| download | zig-0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4.tar.gz zig-0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4.zip | |
stage2: field type expressions support referencing locals
The big change in this commit is making `semaDecl` resolve the fields if
the Decl ends up being a struct or union. It needs to do this while
the `Sema` is still in scope, because it will have the resolved AIR
instructions that the field type expressions possibly reference. We do
this after the decl is populated and set to `complete` so that a `Decl`
may reference itself.
Everything else is fixes and improvements to make the test suite pass
again after making this change.
* New AIR instruction: `ptr_elem_ptr`
- Implemented for LLVM backend
* New Type tag: `type_info` which represents `std.builtin.TypeInfo`. It
is used by AstGen for the operand type of `@Type`.
* ZIR instruction `set_float_mode` uses `coerced_ty` to avoid
superfluous `as` instruction on operand.
* ZIR instruction `Type` uses `coerced_ty` to properly handle result
location type of operand.
* Fix two instances of `enum_nonexhaustive` Value Tag not handled
properly - it should generally be handled the same as `enum_full`.
* Fix struct and union field resolution not copying Type and Value
objects into its Decl arena.
* Fix enum tag value resolution discarding the ZIR=>AIR instruction map
for the child Sema, when they still needed to be accessed.
* Fix `zirResolveInferredAlloc` use-after-free in the AIR instructions
data array.
* Fix `elemPtrArray` not respecting const/mutable attribute of pointer
in the result type.
* Fix LLVM backend crashing when `updateDeclExports` is called before
`updateDecl`/`updateFunc` (which is, according to the API, perfectly
legal for the frontend to do).
* Fix LLVM backend handling element pointer of pointer-to-array. It
needed another index in the GEP otherwise LLVM saw the wrong type.
* Fix LLVM test cases not returning 0 from main, causing test failures.
Fixes a regression introduced in
6a5094872f10acc629543cc7f10533b438d0283a.
* Implement comptime shift-right.
* Implement `@Type` for integers and `@TypeInfo` for integers.
* Implement union initialization syntax.
* Implement `zirFieldType` for unions.
* Implement `elemPtrArray` for a runtime-known operand.
* Make `zirLog2IntType` support RHS of shift being `comptime_int`. In
this case it returns `comptime_int`.
The motivating test case for this commit was originally:
```zig
test "example" {
var l: List(10) = undefined;
l.array[1] = 1;
}
fn List(comptime L: usize) type {
var T = u8;
return struct {
array: [L]T,
};
}
```
However I changed it to:
```zig
test "example" {
var l: List = undefined;
l.array[1] = 1;
}
const List = blk: {
const T = [10]u8;
break :blk struct {
array: T,
};
};
```
Which ended up being a similar, smaller problem. The former test case
will require a similar solution in the implementation of comptime
function calls - checking if the result of the function call is a struct
or union, and using the child `Sema` before it is destroyed to resolve
the fields.
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/value.zig b/src/value.zig index 562d7171e8..7b3056bfcf 100644 --- a/src/value.zig +++ b/src/value.zig @@ -68,6 +68,7 @@ pub const Value = extern union { call_options_type, export_options_type, extern_options_type, + type_info_type, manyptr_u8_type, manyptr_const_u8_type, fn_noreturn_no_args_type, @@ -221,6 +222,7 @@ pub const Value = extern union { .call_options_type, .export_options_type, .extern_options_type, + .type_info_type, .generic_poison, => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"), @@ -402,6 +404,7 @@ pub const Value = extern union { .call_options_type, .export_options_type, .extern_options_type, + .type_info_type, .generic_poison, => unreachable, @@ -585,6 +588,7 @@ pub const Value = extern union { .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"), .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"), .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"), + .type_info_type => return out_stream.writeAll("std.builtin.TypeInfo"), .abi_align_default => return out_stream.writeAll("(default ABI alignment)"), .empty_struct_value => return out_stream.writeAll("struct {}{}"), @@ -743,6 +747,7 @@ pub const Value = extern union { .call_options_type => Type.initTag(.call_options), .export_options_type => Type.initTag(.export_options), .extern_options_type => Type.initTag(.extern_options), + .type_info_type => Type.initTag(.type_info), .int_type => { const payload = self.castTag(.int_type).?.data; @@ -1514,6 +1519,31 @@ pub const Value = extern union { return Tag.int_u64.create(arena, truncated); } + pub fn shr(lhs: Value, rhs: Value, allocator: *Allocator) !Value { + // TODO is this a performance issue? maybe we should try the operation without + // resorting to BigInt first. + var lhs_space: Value.BigIntSpace = undefined; + const lhs_bigint = lhs.toBigInt(&lhs_space); + const shift = rhs.toUnsignedInt(); + const limbs = try allocator.alloc( + std.math.big.Limb, + lhs_bigint.limbs.len - (shift / (@sizeOf(std.math.big.Limb) * 8)), + ); + var result_bigint = BigIntMutable{ + .limbs = limbs, + .positive = undefined, + .len = undefined, + }; + result_bigint.shiftRight(lhs_bigint, shift); + const result_limbs = result_bigint.limbs[0..result_bigint.len]; + + if (result_bigint.positive) { + return Value.Tag.int_big_positive.create(allocator, result_limbs); + } else { + return Value.Tag.int_big_negative.create(allocator, result_limbs); + } + } + pub fn floatAdd( lhs: Value, rhs: Value, |
