mirror of
https://github.com/ziglang/zig.git
synced 2025-12-31 18:43:18 +00:00
stage2: implement runtime @intToEnum
* Update AIR instruction `intcast` to allow the dest type to be an enum. * LLVM backend: update `intcast` to support when the bit counts of operand and dest type are the same. This was already a requirement of the instruction previously. * Type: `intInfo` supports the case when the type is an enum, and retrieves the info for the integer tag type. This makes it pretty easy for backends to implement `intcast` without having to care explicitly that the new type is an enum. As a bonus, simple enums never have to go through the type system; their signedness and bit count are computed directly. The "int to enum" behavior test case is now passing for stage2 in the LLVM backend.
This commit is contained in:
parent
941b2f0d5e
commit
cb616cb797
@ -272,8 +272,11 @@ pub const Inst = struct {
|
||||
/// Uses the `ty_op` field.
|
||||
fpext,
|
||||
/// Returns an integer with a different type than the operand. The new type may have
|
||||
/// fewer, the same, or more bits than the operand type. However, the instruction
|
||||
/// fewer, the same, or more bits than the operand type. The new type may also
|
||||
/// differ in signedness from the operand type. However, the instruction
|
||||
/// guarantees that the same integer value fits in both types.
|
||||
/// The new type may also be an enum type, in which case the integer cast operates on
|
||||
/// the integer tag type of the enum.
|
||||
/// See `trunc` for integer truncation.
|
||||
/// Uses the `ty_op` field.
|
||||
intcast,
|
||||
|
||||
@ -4312,7 +4312,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
return block.addTyOp(.bitcast, dest_ty, operand);
|
||||
// TODO insert safety check to make sure the value matches an enum value
|
||||
return block.addTyOp(.intcast, dest_ty, operand);
|
||||
}
|
||||
|
||||
/// Pointer in, pointer out.
|
||||
@ -5050,6 +5051,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, operand_src);
|
||||
// TODO insert safety check to make sure the value fits in the dest type
|
||||
return block.addTyOp(.intcast, dest_type, operand);
|
||||
}
|
||||
|
||||
|
||||
@ -2381,8 +2381,11 @@ pub const FuncGen = struct {
|
||||
.signed => return self.builder.buildSExt(operand, dest_llvm_ty, ""),
|
||||
.unsigned => return self.builder.buildZExt(operand, dest_llvm_ty, ""),
|
||||
}
|
||||
} else if (operand_info.bits > dest_info.bits) {
|
||||
return self.builder.buildTrunc(operand, dest_llvm_ty, "");
|
||||
} else {
|
||||
return operand;
|
||||
}
|
||||
return self.builder.buildTrunc(operand, dest_llvm_ty, "");
|
||||
}
|
||||
|
||||
fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
||||
|
||||
83
src/type.zig
83
src/type.zig
@ -2657,38 +2657,49 @@ pub const Type = extern union {
|
||||
};
|
||||
}
|
||||
|
||||
/// Asserts the type is an integer.
|
||||
/// Asserts the type is an integer or enum.
|
||||
pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } {
|
||||
return switch (self.tag()) {
|
||||
.int_unsigned => .{
|
||||
var ty = self;
|
||||
while (true) switch (ty.tag()) {
|
||||
.int_unsigned => return .{
|
||||
.signedness = .unsigned,
|
||||
.bits = self.castTag(.int_unsigned).?.data,
|
||||
.bits = ty.castTag(.int_unsigned).?.data,
|
||||
},
|
||||
.int_signed => .{
|
||||
.int_signed => return .{
|
||||
.signedness = .signed,
|
||||
.bits = self.castTag(.int_signed).?.data,
|
||||
.bits = ty.castTag(.int_signed).?.data,
|
||||
},
|
||||
.u1 => return .{ .signedness = .unsigned, .bits = 1 },
|
||||
.u8 => return .{ .signedness = .unsigned, .bits = 8 },
|
||||
.i8 => return .{ .signedness = .signed, .bits = 8 },
|
||||
.u16 => return .{ .signedness = .unsigned, .bits = 16 },
|
||||
.i16 => return .{ .signedness = .signed, .bits = 16 },
|
||||
.u32 => return .{ .signedness = .unsigned, .bits = 32 },
|
||||
.i32 => return .{ .signedness = .signed, .bits = 32 },
|
||||
.u64 => return .{ .signedness = .unsigned, .bits = 64 },
|
||||
.i64 => return .{ .signedness = .signed, .bits = 64 },
|
||||
.u128 => return .{ .signedness = .unsigned, .bits = 128 },
|
||||
.i128 => return .{ .signedness = .signed, .bits = 128 },
|
||||
.usize => return .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.isize => return .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.c_short => return .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },
|
||||
.c_ushort => return .{ .signedness = .unsigned, .bits = CType.ushort.sizeInBits(target) },
|
||||
.c_int => return .{ .signedness = .signed, .bits = CType.int.sizeInBits(target) },
|
||||
.c_uint => return .{ .signedness = .unsigned, .bits = CType.uint.sizeInBits(target) },
|
||||
.c_long => return .{ .signedness = .signed, .bits = CType.long.sizeInBits(target) },
|
||||
.c_ulong => return .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },
|
||||
.c_longlong => return .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },
|
||||
.c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
|
||||
|
||||
.enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,
|
||||
.enum_numbered => ty = self.castTag(.enum_numbered).?.data.tag_ty,
|
||||
.enum_simple => {
|
||||
const enum_obj = self.castTag(.enum_simple).?.data;
|
||||
return .{
|
||||
.signedness = .unsigned,
|
||||
.bits = smallestUnsignedBits(enum_obj.fields.count()),
|
||||
};
|
||||
},
|
||||
.u1 => .{ .signedness = .unsigned, .bits = 1 },
|
||||
.u8 => .{ .signedness = .unsigned, .bits = 8 },
|
||||
.i8 => .{ .signedness = .signed, .bits = 8 },
|
||||
.u16 => .{ .signedness = .unsigned, .bits = 16 },
|
||||
.i16 => .{ .signedness = .signed, .bits = 16 },
|
||||
.u32 => .{ .signedness = .unsigned, .bits = 32 },
|
||||
.i32 => .{ .signedness = .signed, .bits = 32 },
|
||||
.u64 => .{ .signedness = .unsigned, .bits = 64 },
|
||||
.i64 => .{ .signedness = .signed, .bits = 64 },
|
||||
.u128 => .{ .signedness = .unsigned, .bits = 128 },
|
||||
.i128 => .{ .signedness = .signed, .bits = 128 },
|
||||
.usize => .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.isize => .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.c_short => .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },
|
||||
.c_ushort => .{ .signedness = .unsigned, .bits = CType.ushort.sizeInBits(target) },
|
||||
.c_int => .{ .signedness = .signed, .bits = CType.int.sizeInBits(target) },
|
||||
.c_uint => .{ .signedness = .unsigned, .bits = CType.uint.sizeInBits(target) },
|
||||
.c_long => .{ .signedness = .signed, .bits = CType.long.sizeInBits(target) },
|
||||
.c_ulong => .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },
|
||||
.c_longlong => .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },
|
||||
.c_ulonglong => .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
@ -3905,20 +3916,22 @@ pub const Type = extern union {
|
||||
return Type.initPayload(&type_payload.base);
|
||||
}
|
||||
|
||||
pub fn smallestUnsignedBits(max: u64) u16 {
|
||||
if (max == 0) return 0;
|
||||
const base = std.math.log2(max);
|
||||
const upper = (@as(u64, 1) << @intCast(u6, base)) - 1;
|
||||
return @intCast(u16, base + @boolToInt(upper < max));
|
||||
}
|
||||
|
||||
pub fn smallestUnsignedInt(arena: *Allocator, max: u64) !Type {
|
||||
const bits = bits: {
|
||||
if (max == 0) break :bits 0;
|
||||
const base = std.math.log2(max);
|
||||
const upper = (@as(u64, 1) << @intCast(u6, base)) - 1;
|
||||
break :bits base + @boolToInt(upper < max);
|
||||
};
|
||||
return switch (@intCast(u16, bits)) {
|
||||
const bits = smallestUnsignedBits(max);
|
||||
return switch (bits) {
|
||||
1 => initTag(.u1),
|
||||
8 => initTag(.u8),
|
||||
16 => initTag(.u16),
|
||||
32 => initTag(.u32),
|
||||
64 => initTag(.u64),
|
||||
else => |b| return Tag.int_unsigned.create(arena, b),
|
||||
else => return Tag.int_unsigned.create(arena, bits),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -17,6 +17,15 @@ test "enum to int" {
|
||||
try shouldEqual(Number.Four, 4);
|
||||
}
|
||||
|
||||
fn testIntToEnumEval(x: i32) !void {
|
||||
try expect(@intToEnum(IntToEnumNumber, x) == IntToEnumNumber.Three);
|
||||
}
|
||||
const IntToEnumNumber = enum { Zero, One, Two, Three, Four };
|
||||
|
||||
test "int to enum" {
|
||||
try testIntToEnumEval(3);
|
||||
}
|
||||
|
||||
const ValueCount1 = enum {
|
||||
I0,
|
||||
};
|
||||
|
||||
@ -104,18 +104,6 @@ const Bar = enum { A, B, C, D };
|
||||
|
||||
const Number = enum { Zero, One, Two, Three, Four };
|
||||
|
||||
fn shouldEqual(n: Number, expected: u3) !void {
|
||||
try expect(@enumToInt(n) == expected);
|
||||
}
|
||||
|
||||
test "int to enum" {
|
||||
try testIntToEnumEval(3);
|
||||
}
|
||||
fn testIntToEnumEval(x: i32) !void {
|
||||
try expect(@intToEnum(IntToEnumNumber, x) == IntToEnumNumber.Three);
|
||||
}
|
||||
const IntToEnumNumber = enum { Zero, One, Two, Three, Four };
|
||||
|
||||
test "@tagName" {
|
||||
try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
comptime try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
@ -131,544 +119,9 @@ fn testEnumTagNameBare(n: anytype) []const u8 {
|
||||
}
|
||||
|
||||
const BareNumber = enum { One, Two, Three };
|
||||
|
||||
const NonExhaustive = enum(u8) { A, B, _ };
|
||||
|
||||
const ValueCount1 = enum {
|
||||
I0,
|
||||
};
|
||||
const ValueCount2 = enum {
|
||||
I0,
|
||||
I1,
|
||||
};
|
||||
const ValueCount256 = enum {
|
||||
I0,
|
||||
I1,
|
||||
I2,
|
||||
I3,
|
||||
I4,
|
||||
I5,
|
||||
I6,
|
||||
I7,
|
||||
I8,
|
||||
I9,
|
||||
I10,
|
||||
I11,
|
||||
I12,
|
||||
I13,
|
||||
I14,
|
||||
I15,
|
||||
I16,
|
||||
I17,
|
||||
I18,
|
||||
I19,
|
||||
I20,
|
||||
I21,
|
||||
I22,
|
||||
I23,
|
||||
I24,
|
||||
I25,
|
||||
I26,
|
||||
I27,
|
||||
I28,
|
||||
I29,
|
||||
I30,
|
||||
I31,
|
||||
I32,
|
||||
I33,
|
||||
I34,
|
||||
I35,
|
||||
I36,
|
||||
I37,
|
||||
I38,
|
||||
I39,
|
||||
I40,
|
||||
I41,
|
||||
I42,
|
||||
I43,
|
||||
I44,
|
||||
I45,
|
||||
I46,
|
||||
I47,
|
||||
I48,
|
||||
I49,
|
||||
I50,
|
||||
I51,
|
||||
I52,
|
||||
I53,
|
||||
I54,
|
||||
I55,
|
||||
I56,
|
||||
I57,
|
||||
I58,
|
||||
I59,
|
||||
I60,
|
||||
I61,
|
||||
I62,
|
||||
I63,
|
||||
I64,
|
||||
I65,
|
||||
I66,
|
||||
I67,
|
||||
I68,
|
||||
I69,
|
||||
I70,
|
||||
I71,
|
||||
I72,
|
||||
I73,
|
||||
I74,
|
||||
I75,
|
||||
I76,
|
||||
I77,
|
||||
I78,
|
||||
I79,
|
||||
I80,
|
||||
I81,
|
||||
I82,
|
||||
I83,
|
||||
I84,
|
||||
I85,
|
||||
I86,
|
||||
I87,
|
||||
I88,
|
||||
I89,
|
||||
I90,
|
||||
I91,
|
||||
I92,
|
||||
I93,
|
||||
I94,
|
||||
I95,
|
||||
I96,
|
||||
I97,
|
||||
I98,
|
||||
I99,
|
||||
I100,
|
||||
I101,
|
||||
I102,
|
||||
I103,
|
||||
I104,
|
||||
I105,
|
||||
I106,
|
||||
I107,
|
||||
I108,
|
||||
I109,
|
||||
I110,
|
||||
I111,
|
||||
I112,
|
||||
I113,
|
||||
I114,
|
||||
I115,
|
||||
I116,
|
||||
I117,
|
||||
I118,
|
||||
I119,
|
||||
I120,
|
||||
I121,
|
||||
I122,
|
||||
I123,
|
||||
I124,
|
||||
I125,
|
||||
I126,
|
||||
I127,
|
||||
I128,
|
||||
I129,
|
||||
I130,
|
||||
I131,
|
||||
I132,
|
||||
I133,
|
||||
I134,
|
||||
I135,
|
||||
I136,
|
||||
I137,
|
||||
I138,
|
||||
I139,
|
||||
I140,
|
||||
I141,
|
||||
I142,
|
||||
I143,
|
||||
I144,
|
||||
I145,
|
||||
I146,
|
||||
I147,
|
||||
I148,
|
||||
I149,
|
||||
I150,
|
||||
I151,
|
||||
I152,
|
||||
I153,
|
||||
I154,
|
||||
I155,
|
||||
I156,
|
||||
I157,
|
||||
I158,
|
||||
I159,
|
||||
I160,
|
||||
I161,
|
||||
I162,
|
||||
I163,
|
||||
I164,
|
||||
I165,
|
||||
I166,
|
||||
I167,
|
||||
I168,
|
||||
I169,
|
||||
I170,
|
||||
I171,
|
||||
I172,
|
||||
I173,
|
||||
I174,
|
||||
I175,
|
||||
I176,
|
||||
I177,
|
||||
I178,
|
||||
I179,
|
||||
I180,
|
||||
I181,
|
||||
I182,
|
||||
I183,
|
||||
I184,
|
||||
I185,
|
||||
I186,
|
||||
I187,
|
||||
I188,
|
||||
I189,
|
||||
I190,
|
||||
I191,
|
||||
I192,
|
||||
I193,
|
||||
I194,
|
||||
I195,
|
||||
I196,
|
||||
I197,
|
||||
I198,
|
||||
I199,
|
||||
I200,
|
||||
I201,
|
||||
I202,
|
||||
I203,
|
||||
I204,
|
||||
I205,
|
||||
I206,
|
||||
I207,
|
||||
I208,
|
||||
I209,
|
||||
I210,
|
||||
I211,
|
||||
I212,
|
||||
I213,
|
||||
I214,
|
||||
I215,
|
||||
I216,
|
||||
I217,
|
||||
I218,
|
||||
I219,
|
||||
I220,
|
||||
I221,
|
||||
I222,
|
||||
I223,
|
||||
I224,
|
||||
I225,
|
||||
I226,
|
||||
I227,
|
||||
I228,
|
||||
I229,
|
||||
I230,
|
||||
I231,
|
||||
I232,
|
||||
I233,
|
||||
I234,
|
||||
I235,
|
||||
I236,
|
||||
I237,
|
||||
I238,
|
||||
I239,
|
||||
I240,
|
||||
I241,
|
||||
I242,
|
||||
I243,
|
||||
I244,
|
||||
I245,
|
||||
I246,
|
||||
I247,
|
||||
I248,
|
||||
I249,
|
||||
I250,
|
||||
I251,
|
||||
I252,
|
||||
I253,
|
||||
I254,
|
||||
I255,
|
||||
};
|
||||
const ValueCount257 = enum {
|
||||
I0,
|
||||
I1,
|
||||
I2,
|
||||
I3,
|
||||
I4,
|
||||
I5,
|
||||
I6,
|
||||
I7,
|
||||
I8,
|
||||
I9,
|
||||
I10,
|
||||
I11,
|
||||
I12,
|
||||
I13,
|
||||
I14,
|
||||
I15,
|
||||
I16,
|
||||
I17,
|
||||
I18,
|
||||
I19,
|
||||
I20,
|
||||
I21,
|
||||
I22,
|
||||
I23,
|
||||
I24,
|
||||
I25,
|
||||
I26,
|
||||
I27,
|
||||
I28,
|
||||
I29,
|
||||
I30,
|
||||
I31,
|
||||
I32,
|
||||
I33,
|
||||
I34,
|
||||
I35,
|
||||
I36,
|
||||
I37,
|
||||
I38,
|
||||
I39,
|
||||
I40,
|
||||
I41,
|
||||
I42,
|
||||
I43,
|
||||
I44,
|
||||
I45,
|
||||
I46,
|
||||
I47,
|
||||
I48,
|
||||
I49,
|
||||
I50,
|
||||
I51,
|
||||
I52,
|
||||
I53,
|
||||
I54,
|
||||
I55,
|
||||
I56,
|
||||
I57,
|
||||
I58,
|
||||
I59,
|
||||
I60,
|
||||
I61,
|
||||
I62,
|
||||
I63,
|
||||
I64,
|
||||
I65,
|
||||
I66,
|
||||
I67,
|
||||
I68,
|
||||
I69,
|
||||
I70,
|
||||
I71,
|
||||
I72,
|
||||
I73,
|
||||
I74,
|
||||
I75,
|
||||
I76,
|
||||
I77,
|
||||
I78,
|
||||
I79,
|
||||
I80,
|
||||
I81,
|
||||
I82,
|
||||
I83,
|
||||
I84,
|
||||
I85,
|
||||
I86,
|
||||
I87,
|
||||
I88,
|
||||
I89,
|
||||
I90,
|
||||
I91,
|
||||
I92,
|
||||
I93,
|
||||
I94,
|
||||
I95,
|
||||
I96,
|
||||
I97,
|
||||
I98,
|
||||
I99,
|
||||
I100,
|
||||
I101,
|
||||
I102,
|
||||
I103,
|
||||
I104,
|
||||
I105,
|
||||
I106,
|
||||
I107,
|
||||
I108,
|
||||
I109,
|
||||
I110,
|
||||
I111,
|
||||
I112,
|
||||
I113,
|
||||
I114,
|
||||
I115,
|
||||
I116,
|
||||
I117,
|
||||
I118,
|
||||
I119,
|
||||
I120,
|
||||
I121,
|
||||
I122,
|
||||
I123,
|
||||
I124,
|
||||
I125,
|
||||
I126,
|
||||
I127,
|
||||
I128,
|
||||
I129,
|
||||
I130,
|
||||
I131,
|
||||
I132,
|
||||
I133,
|
||||
I134,
|
||||
I135,
|
||||
I136,
|
||||
I137,
|
||||
I138,
|
||||
I139,
|
||||
I140,
|
||||
I141,
|
||||
I142,
|
||||
I143,
|
||||
I144,
|
||||
I145,
|
||||
I146,
|
||||
I147,
|
||||
I148,
|
||||
I149,
|
||||
I150,
|
||||
I151,
|
||||
I152,
|
||||
I153,
|
||||
I154,
|
||||
I155,
|
||||
I156,
|
||||
I157,
|
||||
I158,
|
||||
I159,
|
||||
I160,
|
||||
I161,
|
||||
I162,
|
||||
I163,
|
||||
I164,
|
||||
I165,
|
||||
I166,
|
||||
I167,
|
||||
I168,
|
||||
I169,
|
||||
I170,
|
||||
I171,
|
||||
I172,
|
||||
I173,
|
||||
I174,
|
||||
I175,
|
||||
I176,
|
||||
I177,
|
||||
I178,
|
||||
I179,
|
||||
I180,
|
||||
I181,
|
||||
I182,
|
||||
I183,
|
||||
I184,
|
||||
I185,
|
||||
I186,
|
||||
I187,
|
||||
I188,
|
||||
I189,
|
||||
I190,
|
||||
I191,
|
||||
I192,
|
||||
I193,
|
||||
I194,
|
||||
I195,
|
||||
I196,
|
||||
I197,
|
||||
I198,
|
||||
I199,
|
||||
I200,
|
||||
I201,
|
||||
I202,
|
||||
I203,
|
||||
I204,
|
||||
I205,
|
||||
I206,
|
||||
I207,
|
||||
I208,
|
||||
I209,
|
||||
I210,
|
||||
I211,
|
||||
I212,
|
||||
I213,
|
||||
I214,
|
||||
I215,
|
||||
I216,
|
||||
I217,
|
||||
I218,
|
||||
I219,
|
||||
I220,
|
||||
I221,
|
||||
I222,
|
||||
I223,
|
||||
I224,
|
||||
I225,
|
||||
I226,
|
||||
I227,
|
||||
I228,
|
||||
I229,
|
||||
I230,
|
||||
I231,
|
||||
I232,
|
||||
I233,
|
||||
I234,
|
||||
I235,
|
||||
I236,
|
||||
I237,
|
||||
I238,
|
||||
I239,
|
||||
I240,
|
||||
I241,
|
||||
I242,
|
||||
I243,
|
||||
I244,
|
||||
I245,
|
||||
I246,
|
||||
I247,
|
||||
I248,
|
||||
I249,
|
||||
I250,
|
||||
I251,
|
||||
I252,
|
||||
I253,
|
||||
I254,
|
||||
I255,
|
||||
I256,
|
||||
};
|
||||
|
||||
const Small2 = enum(u2) {
|
||||
One,
|
||||
Two,
|
||||
};
|
||||
const Small = enum(u2) {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
};
|
||||
const Small2 = enum(u2) { One, Two };
|
||||
const Small = enum(u2) { One, Two, Three, Four };
|
||||
|
||||
test "set enum tag type" {
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user