aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-12 21:26:59 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-12 21:38:46 -0700
commita3104a4a78089f3260c0dd3f4a96012c6d73a63b (patch)
tree63d73840d9d48d09cd27c3fef5e52f051a2dc4bd /src/codegen/llvm.zig
parent7f006287ae89b97ff0ca977f64744ea344ec94fd (diff)
downloadzig-a3104a4a78089f3260c0dd3f4a96012c6d73a63b.tar.gz
zig-a3104a4a78089f3260c0dd3f4a96012c6d73a63b.zip
stage2: fix comptime stores and sentinel-terminated arrays
* ZIR: the `array_type_sentinel` now has a source node attached to it for proper error reporting. * Refactor: move `Module.arrayType` to `Type.array` * Value: the `bytes` and `array` tags now include the sentinel, if the type has one. This simplifies comptime evaluation logic. * Sema: fix `zirStructInitEmpty` to properly handle when the type is void or a sentinel-terminated array. This handles the syntax `void{}` and `[0:X]T{}`. * Sema: fix the logic for reporting "cannot store runtime value in compile time variable" as well as for emitting a runtime store when a pointer value is comptime known but it is a global variable. * Sema: implement elemVal for double pointer to array. This can happen with this code for example: `var a: *[1]u8 = undefined; _ = a[0];` * Sema: Rework the `storePtrVal` function to properly handle nested structs and arrays. - Also it now handles comptime stores through a bitcasted pointer. When the pointer element type and the type according to the Decl don't match, the element value is bitcasted before storage.
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig60
1 files changed, 33 insertions, 27 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 458ab093e4..5f461b1276 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1031,54 +1031,60 @@ pub const DeclGen = struct {
},
else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),
},
- .Array => {
- const gpa = self.gpa;
- if (tv.val.castTag(.bytes)) |payload| {
- const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: {
- if (sentinel.tag() == .zero) break :blk true;
- return self.todo("handle other sentinel values", .{});
- } else false;
-
+ .Array => switch (tv.val.tag()) {
+ .bytes => {
+ const bytes = tv.val.castTag(.bytes).?.data;
return self.context.constString(
- payload.data.ptr,
- @intCast(c_uint, payload.data.len),
- llvm.Bool.fromBool(!zero_sentinel),
+ bytes.ptr,
+ @intCast(c_uint, bytes.len),
+ .True, // don't null terminate. bytes has the sentinel, if any.
);
- }
- if (tv.val.castTag(.array)) |payload| {
+ },
+ .array => {
+ const elem_vals = tv.val.castTag(.array).?.data;
const elem_ty = tv.ty.elemType();
- const elem_vals = payload.data;
- const sento = tv.ty.sentinel();
- const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len + @boolToInt(sento != null));
+ const gpa = self.gpa;
+ const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len);
defer gpa.free(llvm_elems);
for (elem_vals) |elem_val, i| {
llvm_elems[i] = try self.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
}
- if (sento) |sent| llvm_elems[elem_vals.len] = try self.genTypedValue(.{ .ty = elem_ty, .val = sent });
const llvm_elem_ty = try self.llvmType(elem_ty);
return llvm_elem_ty.constArray(
llvm_elems.ptr,
@intCast(c_uint, llvm_elems.len),
);
- }
- if (tv.val.castTag(.repeated)) |payload| {
- const val = payload.data;
+ },
+ .repeated => {
+ const val = tv.val.castTag(.repeated).?.data;
const elem_ty = tv.ty.elemType();
+ const sentinel = tv.ty.sentinel();
const len = tv.ty.arrayLen();
-
- const llvm_elems = try gpa.alloc(*const llvm.Value, len);
+ const len_including_sent = len + @boolToInt(sentinel != null);
+ const gpa = self.gpa;
+ const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent);
defer gpa.free(llvm_elems);
- var i: u64 = 0;
- while (i < len) : (i += 1) {
- llvm_elems[i] = try self.genTypedValue(.{ .ty = elem_ty, .val = val });
+ for (llvm_elems[0..len]) |*elem| {
+ elem.* = try self.genTypedValue(.{ .ty = elem_ty, .val = val });
+ }
+ if (sentinel) |sent| {
+ llvm_elems[len] = try self.genTypedValue(.{ .ty = elem_ty, .val = sent });
}
const llvm_elem_ty = try self.llvmType(elem_ty);
return llvm_elem_ty.constArray(
llvm_elems.ptr,
@intCast(c_uint, llvm_elems.len),
);
- }
- return self.todo("handle more array values", .{});
+ },
+ .empty_array_sentinel => {
+ const elem_ty = tv.ty.elemType();
+ const sent_val = tv.ty.sentinel().?;
+ const sentinel = try self.genTypedValue(.{ .ty = elem_ty, .val = sent_val });
+ const llvm_elems: [1]*const llvm.Value = .{sentinel};
+ const llvm_elem_ty = try self.llvmType(elem_ty);
+ return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
+ },
+ else => unreachable,
},
.Optional => {
var buf: Type.Payload.ElemType = undefined;