aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-20 15:23:55 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-20 15:41:57 -0700
commit0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4 (patch)
treec3de2205e0bb525d61ee78800c118b13efbf1029 /src/value.zig
parent2f1abd919a8465e515875cd08816778df795aabe (diff)
downloadzig-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.zig30
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,