aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-04-12 21:46:20 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-04-15 19:06:39 -0700
commit6dba9bc6fc6741e51af86f71e3057cffed7406a6 (patch)
tree14f01a271c9e633769804f8b86f7687f838c5aca /src/type.zig
parentdf983b30d2b890e21fba214145ccc4f4a263359d (diff)
downloadzig-6dba9bc6fc6741e51af86f71e3057cffed7406a6.tar.gz
zig-6dba9bc6fc6741e51af86f71e3057cffed7406a6.zip
stage2: implement `@bitSizeOf`
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/type.zig b/src/type.zig
index d05fa0f5e3..0429fd876a 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1377,6 +1377,151 @@ pub const Type = extern union {
};
}
+ /// Asserts the type has the bit size already resolved.
+ pub fn bitSize(self: Type, target: Target) u64 {
+ return switch (self.tag()) {
+ .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer
+ .fn_void_no_args => unreachable, // represents machine code; not a pointer
+ .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer
+ .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer
+ .function => unreachable, // represents machine code; not a pointer
+ .c_void => unreachable,
+ .void => unreachable,
+ .type => unreachable,
+ .comptime_int => unreachable,
+ .comptime_float => unreachable,
+ .noreturn => unreachable,
+ .@"null" => unreachable,
+ .@"undefined" => unreachable,
+ .enum_literal => unreachable,
+ .single_const_pointer_to_comptime_int => unreachable,
+ .empty_struct => unreachable,
+ .empty_struct_literal => unreachable,
+ .inferred_alloc_const => unreachable,
+ .inferred_alloc_mut => unreachable,
+ .@"opaque" => unreachable,
+ .var_args_param => unreachable,
+
+ .@"struct" => {
+ @panic("TODO bitSize struct");
+ },
+ .enum_simple, .enum_full, .enum_nonexhaustive => {
+ var buffer: Payload.Bits = undefined;
+ const int_tag_ty = self.intTagType(&buffer);
+ return int_tag_ty.bitSize(target);
+ },
+
+ .u8, .i8 => 8,
+
+ .bool => 1,
+
+ .array_u8 => 8 * self.castTag(.array_u8).?.data,
+ .array_u8_sentinel_0 => 8 * (self.castTag(.array_u8_sentinel_0).?.data + 1),
+ .array => {
+ const payload = self.castTag(.array).?.data;
+ const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
+ if (elem_size == 0 or payload.len == 0)
+ return 0;
+ return (payload.len - 1) * 8 * elem_size + payload.elem_type.bitSize(target);
+ },
+ .array_sentinel => {
+ const payload = self.castTag(.array_sentinel).?.data;
+ const elem_size = std.math.max(
+ payload.elem_type.abiAlignment(target),
+ payload.elem_type.abiSize(target),
+ );
+ return payload.len * 8 * elem_size + payload.elem_type.bitSize(target);
+ },
+ .i16, .u16, .f16 => 16,
+ .i32, .u32, .f32 => 32,
+ .i64, .u64, .f64 => 64,
+ .u128, .i128, .f128 => 128,
+
+ .isize, .usize => target.cpu.arch.ptrBitWidth(),
+
+ .const_slice,
+ .mut_slice,
+ => {
+ if (self.elemType().hasCodeGenBits()) {
+ return target.cpu.arch.ptrBitWidth() * 2;
+ } else {
+ return target.cpu.arch.ptrBitWidth();
+ }
+ },
+ .const_slice_u8 => target.cpu.arch.ptrBitWidth() * 2,
+
+ .optional_single_const_pointer,
+ .optional_single_mut_pointer,
+ => {
+ if (self.elemType().hasCodeGenBits()) {
+ return target.cpu.arch.ptrBitWidth();
+ } else {
+ return 1;
+ }
+ },
+
+ .single_const_pointer,
+ .single_mut_pointer,
+ .many_const_pointer,
+ .many_mut_pointer,
+ .c_const_pointer,
+ .c_mut_pointer,
+ .pointer,
+ => {
+ if (self.elemType().hasCodeGenBits()) {
+ return target.cpu.arch.ptrBitWidth();
+ } else {
+ return 0;
+ }
+ },
+
+ .c_short => return CType.short.sizeInBits(target),
+ .c_ushort => return CType.ushort.sizeInBits(target),
+ .c_int => return CType.int.sizeInBits(target),
+ .c_uint => return CType.uint.sizeInBits(target),
+ .c_long => return CType.long.sizeInBits(target),
+ .c_ulong => return CType.ulong.sizeInBits(target),
+ .c_longlong => return CType.longlong.sizeInBits(target),
+ .c_ulonglong => return CType.ulonglong.sizeInBits(target),
+ .c_longdouble => 128,
+
+ .error_set,
+ .error_set_single,
+ .anyerror_void_error_union,
+ .anyerror,
+ => return 16, // TODO revisit this when we have the concept of the error tag type
+
+ .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data,
+
+ .optional => {
+ var buf: Payload.ElemType = undefined;
+ const child_type = self.optionalChild(&buf);
+ if (!child_type.hasCodeGenBits()) return 8;
+
+ if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr())
+ return target.cpu.arch.ptrBitWidth();
+
+ // Optional types are represented as a struct with the child type as the first
+ // field and a boolean as the second. Since the child type's abi alignment is
+ // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
+ // to the child type's ABI alignment.
+ return child_type.bitSize(target) + 1;
+ },
+
+ .error_union => {
+ const payload = self.castTag(.error_union).?.data;
+ if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) {
+ return 0;
+ } else if (!payload.error_set.hasCodeGenBits()) {
+ return payload.payload.bitSize(target);
+ } else if (!payload.payload.hasCodeGenBits()) {
+ return payload.error_set.bitSize(target);
+ }
+ @panic("TODO abiSize error union");
+ },
+ };
+ }
+
/// Asserts the type is an enum.
pub fn intTagType(self: Type, buffer: *Payload.Bits) Type {
switch (self.tag()) {