aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-22 15:12:22 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-22 15:35:35 -0700
commit069c83d58cebba88275ee76ba01fabcd8e964573 (patch)
treeab7e52f307bd23869e2461189383522dc64f42de /src
parent86b92809635607ff357ce96902e2aaf83c3fd029 (diff)
downloadzig-069c83d58cebba88275ee76ba01fabcd8e964573.tar.gz
zig-069c83d58cebba88275ee76ba01fabcd8e964573.zip
stage2: change `@bitCast` to always be by-value
After a discussion about language specs, this seems like the best way to go, because it's simpler to reason about both for humans and compilers. The `bitcast_result_ptr` ZIR instruction is no longer needed. This commit also implements writing enums, arrays, and vectors to virtual memory at compile-time. This unlocked some more of compiler-rt being able to build, which in turn unlocks saturating arithmetic behavior tests. There was also a memory leak in the comptime closure system which is now fixed.
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig57
-rw-r--r--src/Module.zig1
-rw-r--r--src/Sema.zig7
-rw-r--r--src/Zir.zig6
-rw-r--r--src/print_zir.zig1
-rw-r--r--src/value.zig21
6 files changed, 42 insertions, 51 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index e67ae6cddf..64cc60ecf5 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -276,17 +276,30 @@ fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zi
return expr(gz, scope, coerced_type_rl, type_node);
}
+fn reachableTypeExpr(
+ gz: *GenZir,
+ scope: *Scope,
+ type_node: Ast.Node.Index,
+ reachable_node: Ast.Node.Index,
+) InnerError!Zir.Inst.Ref {
+ const prev_force_comptime = gz.force_comptime;
+ gz.force_comptime = true;
+ defer gz.force_comptime = prev_force_comptime;
+
+ return reachableExpr(gz, scope, coerced_type_rl, type_node, reachable_node);
+}
+
/// Same as `expr` but fails with a compile error if the result type is `noreturn`.
fn reachableExpr(
gz: *GenZir,
scope: *Scope,
rl: ResultLoc,
node: Ast.Node.Index,
- src_node: Ast.Node.Index,
+ reachable_node: Ast.Node.Index,
) InnerError!Zir.Inst.Ref {
const result_inst = try expr(gz, scope, rl, node);
if (gz.refIsNoReturn(result_inst)) {
- return gz.astgen.failNodeNotes(src_node, "unreachable code", .{}, &[_]u32{
+ return gz.astgen.failNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{
try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}),
});
}
@@ -2040,7 +2053,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.as_node,
.bit_and,
.bitcast,
- .bitcast_result_ptr,
.bit_or,
.block,
.block_inline,
@@ -7160,42 +7172,13 @@ fn bitCast(
lhs: Ast.Node.Index,
rhs: Ast.Node.Index,
) InnerError!Zir.Inst.Ref {
- const astgen = gz.astgen;
- const dest_type = try typeExpr(gz, scope, lhs);
- switch (rl) {
- .none, .discard, .ty, .coerced_ty => {
- const operand = try expr(gz, scope, .none, rhs);
- const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
- .lhs = dest_type,
- .rhs = operand,
- });
- return rvalue(gz, rl, result, node);
- },
- .ref => {
- return astgen.failNode(node, "cannot take address of `@bitCast` result", .{});
- },
- .ptr, .inferred_ptr => |result_ptr| {
- return bitCastRlPtr(gz, scope, node, dest_type, result_ptr, rhs);
- },
- .block_ptr => |block| {
- return bitCastRlPtr(gz, scope, node, dest_type, block.rl_ptr, rhs);
- },
- }
-}
-
-fn bitCastRlPtr(
- gz: *GenZir,
- scope: *Scope,
- node: Ast.Node.Index,
- dest_type: Zir.Inst.Ref,
- result_ptr: Zir.Inst.Ref,
- rhs: Ast.Node.Index,
-) InnerError!Zir.Inst.Ref {
- const casted_result_ptr = try gz.addPlNode(.bitcast_result_ptr, node, Zir.Inst.Bin{
+ const dest_type = try reachableTypeExpr(gz, scope, lhs, node);
+ const operand = try reachableExpr(gz, scope, .none, rhs, node);
+ const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
.lhs = dest_type,
- .rhs = result_ptr,
+ .rhs = operand,
});
- return expr(gz, scope, .{ .ptr = casted_result_ptr }, rhs);
+ return rvalue(gz, rl, result, node);
}
fn typeOf(
diff --git a/src/Module.zig b/src/Module.zig
index 58a5a50698..8677be224f 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -317,6 +317,7 @@ pub const WipCaptureScope = struct {
assert(!self.finalized);
// use a temp to avoid unintentional aliasing due to RLS
const tmp = try self.scope.captures.clone(self.perm_arena);
+ self.scope.captures.deinit(self.gpa);
self.scope.captures = tmp;
self.finalized = true;
}
diff --git a/src/Sema.zig b/src/Sema.zig
index 1826d03559..166b668731 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -513,7 +513,6 @@ pub fn analyzeBody(
.bit_not => try sema.zirBitNot(block, inst),
.bit_or => try sema.zirBitwise(block, inst, .bit_or),
.bitcast => try sema.zirBitcast(block, inst),
- .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),
.suspend_block => try sema.zirSuspendBlock(block, inst),
.bool_not => try sema.zirBoolNot(block, inst),
.bool_br_and => try sema.zirBoolBr(block, inst, false),
@@ -1385,12 +1384,6 @@ pub fn resolveInstValue(
};
}
-fn zirBitcastResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
- const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
- const src = inst_data.src();
- return sema.fail(block, src, "TODO implement zir_sema.zirBitcastResultPtr", .{});
-}
-
fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const tracy = trace(@src());
defer tracy.end();
diff --git a/src/Zir.zig b/src/Zir.zig
index b21d12e33e..5b3da74f97 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -240,10 +240,6 @@ pub const Inst = struct {
/// Reinterpret the memory representation of a value as a different type.
/// Uses the pl_node field with payload `Bin`.
bitcast,
- /// A typed result location pointer is bitcasted to a new result location pointer.
- /// The new result location pointer has an inferred type.
- /// Uses the pl_node field with payload `Bin`.
- bitcast_result_ptr,
/// Bitwise NOT. `~`
/// Uses `un_node`.
bit_not,
@@ -977,7 +973,6 @@ pub const Inst = struct {
.as_node,
.bit_and,
.bitcast,
- .bitcast_result_ptr,
.bit_or,
.block,
.block_inline,
@@ -1235,7 +1230,6 @@ pub const Inst = struct {
.as_node = .pl_node,
.bit_and = .pl_node,
.bitcast = .pl_node,
- .bitcast_result_ptr = .pl_node,
.bit_not = .un_node,
.bit_or = .pl_node,
.block = .pl_node,
diff --git a/src/print_zir.zig b/src/print_zir.zig
index 0bbd7e1655..d7cb0a082d 100644
--- a/src/print_zir.zig
+++ b/src/print_zir.zig
@@ -349,7 +349,6 @@ const Writer = struct {
.reduce,
.atomic_load,
.bitcast,
- .bitcast_result_ptr,
.vector_type,
.maximum,
.minimum,
diff --git a/src/value.zig b/src/value.zig
index d4a5e6bbeb..3a4cdb1438 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1015,6 +1015,14 @@ pub const Value = extern union {
const bits = ty.intInfo(target).bits;
bigint.writeTwosComplement(buffer, bits, target.cpu.arch.endian());
},
+ .Enum => {
+ var enum_buffer: Payload.U64 = undefined;
+ const int_val = val.enumToInt(ty, &enum_buffer);
+ var bigint_buffer: BigIntSpace = undefined;
+ const bigint = int_val.toBigInt(&bigint_buffer);
+ const bits = ty.intInfo(target).bits;
+ bigint.writeTwosComplement(buffer, bits, target.cpu.arch.endian());
+ },
.Float => switch (ty.floatBits(target)) {
16 => return floatWriteToMemory(f16, val.toFloat(f16), target, buffer),
32 => return floatWriteToMemory(f32, val.toFloat(f32), target, buffer),
@@ -1022,6 +1030,19 @@ pub const Value = extern union {
128 => return floatWriteToMemory(f128, val.toFloat(f128), target, buffer),
else => unreachable,
},
+ .Array, .Vector => {
+ const len = ty.arrayLen();
+ const elem_ty = ty.childType();
+ const elem_size = elem_ty.abiSize(target);
+ var elem_i: usize = 0;
+ var elem_value_buf: ElemValueBuffer = undefined;
+ var buf_off: usize = 0;
+ while (elem_i < len) : (elem_i += 1) {
+ const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf);
+ writeToMemory(elem_val, elem_ty, target, buffer[buf_off..]);
+ buf_off += elem_size;
+ }
+ },
else => @panic("TODO implement writeToMemory for more types"),
}
}