mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
CBE: implement big integer literals
This commit is contained in:
parent
e7f128c205
commit
874ae81f1b
@ -1674,6 +1674,7 @@ pub const Mutable = struct {
|
||||
|
||||
/// If a is positive, this passes through to truncate.
|
||||
/// If a is negative, then r is set to positive with the bit pattern ~(a - 1).
|
||||
/// r may alias a.
|
||||
///
|
||||
/// Asserts `r` has enough storage to store the result.
|
||||
/// The upper bound is `calcTwosCompLimbCount(a.len)`.
|
||||
|
||||
12
lib/zig.h
12
lib/zig.h
@ -1360,8 +1360,8 @@ typedef signed __int128 zig_i128;
|
||||
|
||||
#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
|
||||
#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
|
||||
#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
|
||||
#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
|
||||
#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
|
||||
#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
|
||||
#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
|
||||
#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
|
||||
#define zig_hi_i128(val) (( int64_t)((val) >> 64))
|
||||
@ -1391,11 +1391,11 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
|
||||
#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
|
||||
|
||||
#if _MSC_VER /* MSVC doesn't allow struct literals in constant expressions */
|
||||
#define zig_make_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
|
||||
#define zig_make_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
|
||||
#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
|
||||
#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
|
||||
#else /* But non-MSVC doesn't like the unprotected commas */
|
||||
#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
|
||||
#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
|
||||
#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
|
||||
#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
|
||||
#endif
|
||||
#define zig_hi_u128(val) ((val).hi)
|
||||
#define zig_lo_u128(val) ((val).lo)
|
||||
|
||||
@ -449,7 +449,7 @@ pub const Function = struct {
|
||||
}
|
||||
|
||||
fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
|
||||
return f.object.dg.fmtIntLiteral(ty, val);
|
||||
return f.object.dg.fmtIntLiteral(ty, val, .Other);
|
||||
}
|
||||
|
||||
fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 {
|
||||
@ -574,9 +574,9 @@ pub const DeclGen = struct {
|
||||
const len_val = Value.initPayload(&len_pl.base);
|
||||
|
||||
if (location == .StaticInitializer) {
|
||||
return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
|
||||
return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
|
||||
} else {
|
||||
return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
|
||||
return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,7 +606,7 @@ pub const DeclGen = struct {
|
||||
try writer.writeByte(')');
|
||||
}
|
||||
switch (ptr_val.tag()) {
|
||||
.int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val)}),
|
||||
.int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val, .Other)}),
|
||||
.decl_ref_mut, .decl_ref, .variable => {
|
||||
const decl_index = switch (ptr_val.tag()) {
|
||||
.decl_ref => ptr_val.castTag(.decl_ref).?.data,
|
||||
@ -670,7 +670,9 @@ pub const DeclGen = struct {
|
||||
container_ptr_ty,
|
||||
location,
|
||||
);
|
||||
try writer.print(" + {})", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)});
|
||||
try writer.print(" + {})", .{
|
||||
try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),
|
||||
});
|
||||
},
|
||||
.end => {
|
||||
try writer.writeAll("((");
|
||||
@ -680,7 +682,9 @@ pub const DeclGen = struct {
|
||||
container_ptr_ty,
|
||||
location,
|
||||
);
|
||||
try writer.print(") + {})", .{try dg.fmtIntLiteral(Type.usize, Value.one)});
|
||||
try writer.print(") + {})", .{
|
||||
try dg.fmtIntLiteral(Type.usize, Value.one, .Other),
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -746,7 +750,7 @@ pub const DeclGen = struct {
|
||||
return writer.writeAll("false");
|
||||
}
|
||||
},
|
||||
.Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),
|
||||
.Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}),
|
||||
.Float => {
|
||||
const bits = ty.floatBits(target);
|
||||
var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits };
|
||||
@ -780,11 +784,11 @@ pub const DeclGen = struct {
|
||||
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
|
||||
const ptr_ty = ty.slicePtrFieldType(&buf);
|
||||
try dg.renderType(writer, ptr_ty);
|
||||
return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)});
|
||||
return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
|
||||
} else {
|
||||
try writer.writeAll("((");
|
||||
try dg.renderType(writer, ty);
|
||||
return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)});
|
||||
return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
|
||||
},
|
||||
.Optional => {
|
||||
var opt_buf: Type.Payload.ElemType = undefined;
|
||||
@ -831,7 +835,7 @@ pub const DeclGen = struct {
|
||||
|
||||
return writer.writeByte('}');
|
||||
},
|
||||
.Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}),
|
||||
.Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef, .Other)}),
|
||||
},
|
||||
.Union => {
|
||||
if (!location.isInitializer()) {
|
||||
@ -854,7 +858,7 @@ pub const DeclGen = struct {
|
||||
if (!field.ty.hasRuntimeBits()) continue;
|
||||
try dg.renderValue(writer, field.ty, val, initializer_type);
|
||||
break;
|
||||
} else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
|
||||
} else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef, .Other)});
|
||||
if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
|
||||
return writer.writeByte('}');
|
||||
},
|
||||
@ -868,7 +872,7 @@ pub const DeclGen = struct {
|
||||
try writer.writeAll("{ .payload = ");
|
||||
try dg.renderValue(writer, ty.errorUnionPayload(), val, initializer_type);
|
||||
return writer.print(", .error = {x} }}", .{
|
||||
try dg.fmtIntLiteral(ty.errorUnionSet(), val),
|
||||
try dg.fmtIntLiteral(ty.errorUnionSet(), val, .Other),
|
||||
});
|
||||
},
|
||||
.Array, .Vector => {
|
||||
@ -927,7 +931,7 @@ pub const DeclGen = struct {
|
||||
.decl_ref_mut,
|
||||
.decl_ref,
|
||||
=> try dg.renderParentPtr(writer, val, ty, location),
|
||||
else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),
|
||||
else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
|
||||
},
|
||||
.Float => {
|
||||
const bits = ty.floatBits(target);
|
||||
@ -1020,7 +1024,7 @@ pub const DeclGen = struct {
|
||||
try writer.writeAll(", ");
|
||||
empty = false;
|
||||
}
|
||||
try writer.print("{x}", .{try dg.fmtIntLiteralLoc(int_ty, int_val, location)});
|
||||
try writer.print("{x}", .{try dg.fmtIntLiteral(int_ty, int_val, location)});
|
||||
if (!empty) try writer.writeByte(')');
|
||||
return;
|
||||
},
|
||||
@ -1069,7 +1073,7 @@ pub const DeclGen = struct {
|
||||
.int_u64, .one => {
|
||||
try writer.writeAll("((");
|
||||
try dg.renderType(writer, ty);
|
||||
return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)});
|
||||
return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
|
||||
},
|
||||
.field_ptr,
|
||||
.elem_ptr,
|
||||
@ -1889,11 +1893,11 @@ pub const DeclGen = struct {
|
||||
const int_info = ty.intInfo(target);
|
||||
if (int_info.signedness == .signed) {
|
||||
const min_val = try ty.minInt(stack.get(), target);
|
||||
try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val)});
|
||||
try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val, .Other)});
|
||||
}
|
||||
|
||||
const max_val = try ty.maxInt(stack.get(), target);
|
||||
try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val)});
|
||||
try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val, .Other)});
|
||||
},
|
||||
.Bits => {
|
||||
var bits_pl = Value.Payload.U64{
|
||||
@ -1901,7 +1905,7 @@ pub const DeclGen = struct {
|
||||
.data = ty.bitSize(target),
|
||||
};
|
||||
const bits_val = Value.initPayload(&bits_pl.base);
|
||||
try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val)});
|
||||
try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val, .Other)});
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1910,30 +1914,21 @@ pub const DeclGen = struct {
|
||||
dg: *DeclGen,
|
||||
ty: Type,
|
||||
val: Value,
|
||||
loc: ValueRenderLocation,
|
||||
) !std.fmt.Formatter(formatIntLiteral) {
|
||||
const int_info = ty.intInfo(dg.module.getTarget());
|
||||
const c_bits = toCIntBits(int_info.bits);
|
||||
if (c_bits == null or c_bits.? > 128)
|
||||
return dg.fail("TODO implement integer constants larger than 128 bits", .{});
|
||||
const kind: CType.Kind = switch (loc) {
|
||||
.FunctionArgument => .parameter,
|
||||
.Initializer, .Other => .complete,
|
||||
.StaticInitializer => .global,
|
||||
};
|
||||
return std.fmt.Formatter(formatIntLiteral){ .data = .{
|
||||
.ty = ty,
|
||||
.dg = dg,
|
||||
.int_info = ty.intInfo(dg.module.getTarget()),
|
||||
.kind = kind,
|
||||
.cty = try dg.typeToCType(ty, kind),
|
||||
.val = val,
|
||||
.mod = dg.module,
|
||||
} };
|
||||
}
|
||||
|
||||
fn fmtIntLiteralLoc(
|
||||
dg: *DeclGen,
|
||||
ty: Type,
|
||||
val: Value,
|
||||
location: ValueRenderLocation, // TODO: Instead add this as optional arg to fmtIntLiteral
|
||||
) !std.fmt.Formatter(formatIntLiteral) {
|
||||
const int_info = ty.intInfo(dg.module.getTarget());
|
||||
const c_bits = toCIntBits(int_info.bits);
|
||||
if (c_bits == null or c_bits.? > 128)
|
||||
return dg.fail("TODO implement integer constants larger than 128 bits", .{});
|
||||
return std.fmt.Formatter(formatIntLiteral){ .data = .{ .ty = ty, .val = val, .mod = dg.module, .location = location } };
|
||||
}
|
||||
};
|
||||
|
||||
const CTypeFix = enum { prefix, suffix };
|
||||
@ -2450,7 +2445,7 @@ pub fn genErrDecls(o: *Object) !void {
|
||||
const len_val = Value.initPayload(&len_pl.base);
|
||||
|
||||
try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
|
||||
fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val),
|
||||
fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other),
|
||||
});
|
||||
}
|
||||
try writer.writeAll("};\n");
|
||||
@ -2501,7 +2496,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
|
||||
var int_pl: Value.Payload.U64 = undefined;
|
||||
const int_val = tag_val.enumToInt(enum_ty, &int_pl);
|
||||
|
||||
var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
|
||||
var name_ty_pl = Type.Payload.Len{
|
||||
.base = .{ .tag = .array_u8_sentinel_0 },
|
||||
.data = name.len,
|
||||
};
|
||||
const name_ty = Type.initPayload(&name_ty_pl.base);
|
||||
|
||||
var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name };
|
||||
@ -2510,14 +2508,16 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
|
||||
var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
|
||||
const len_val = Value.initPayload(&len_pl.base);
|
||||
|
||||
try w.print(" case {}: {{\n static ", .{try o.dg.fmtIntLiteral(enum_ty, int_val)});
|
||||
try w.print(" case {}: {{\n static ", .{
|
||||
try o.dg.fmtIntLiteral(enum_ty, int_val, .Other),
|
||||
});
|
||||
try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete);
|
||||
try w.writeAll(" = ");
|
||||
try o.dg.renderValue(w, name_ty, name_val, .Initializer);
|
||||
try w.writeAll(";\n return (");
|
||||
try o.dg.renderType(w, name_slice_ty);
|
||||
try w.print("){{{}, {}}};\n", .{
|
||||
fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val),
|
||||
fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other),
|
||||
});
|
||||
|
||||
try w.writeAll(" }\n");
|
||||
@ -2535,7 +2535,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
|
||||
|
||||
const fwd_decl_writer = o.dg.fwd_decl.writer();
|
||||
try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)});
|
||||
try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{ .string = fn_name });
|
||||
try o.dg.renderFunctionSignature(
|
||||
fwd_decl_writer,
|
||||
fn_decl_index,
|
||||
.forward,
|
||||
.{ .string = fn_name },
|
||||
);
|
||||
try fwd_decl_writer.writeAll(";\n");
|
||||
|
||||
try w.print("static zig_{s} ", .{@tagName(key)});
|
||||
@ -7177,30 +7182,33 @@ fn undefPattern(comptime IntType: type) IntType {
|
||||
return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3));
|
||||
}
|
||||
|
||||
const FormatIntLiteralContext = struct { ty: Type, val: Value, mod: *Module, location: ?ValueRenderLocation = null };
|
||||
const FormatIntLiteralContext = struct {
|
||||
dg: *DeclGen,
|
||||
int_info: std.builtin.Type.Int,
|
||||
kind: CType.Kind,
|
||||
cty: CType,
|
||||
val: Value,
|
||||
};
|
||||
fn formatIntLiteral(
|
||||
data: FormatIntLiteralContext,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
const target = data.mod.getTarget();
|
||||
const int_info = data.ty.intInfo(target);
|
||||
const target = data.dg.module.getTarget();
|
||||
|
||||
const ExpectedContents = struct {
|
||||
const base = 10;
|
||||
const limbs_count_128 = BigInt.calcTwosCompLimbCount(128);
|
||||
const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base);
|
||||
const worst_case_int = BigInt.Const{
|
||||
.limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count),
|
||||
.positive = false,
|
||||
};
|
||||
const bits = 128;
|
||||
const limbs_count = BigInt.calcTwosCompLimbCount(bits);
|
||||
|
||||
undef_limbs: [limbs_count_128]BigIntLimb,
|
||||
wrap_limbs: [limbs_count_128]BigIntLimb,
|
||||
undef_limbs: [limbs_count]BigIntLimb,
|
||||
wrap_limbs: [limbs_count]BigIntLimb,
|
||||
to_string_buf: [bits]u8,
|
||||
to_string_limbs: [BigInt.calcToStringLimbsBufferLen(limbs_count, base)]BigIntLimb,
|
||||
};
|
||||
var stack align(@alignOf(ExpectedContents)) =
|
||||
std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa);
|
||||
std.heap.stackFallback(@sizeOf(ExpectedContents), data.dg.gpa);
|
||||
const allocator = stack.get();
|
||||
|
||||
var undef_limbs: []BigIntLimb = &.{};
|
||||
@ -7208,7 +7216,7 @@ fn formatIntLiteral(
|
||||
|
||||
var int_buf: Value.BigIntSpace = undefined;
|
||||
const int = if (data.val.isUndefDeep()) blk: {
|
||||
undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(int_info.bits));
|
||||
undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
|
||||
std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb));
|
||||
|
||||
var undef_int = BigInt.Mutable{
|
||||
@ -7216,163 +7224,150 @@ fn formatIntLiteral(
|
||||
.len = undef_limbs.len,
|
||||
.positive = true,
|
||||
};
|
||||
undef_int.truncate(undef_int.toConst(), int_info.signedness, int_info.bits);
|
||||
undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits);
|
||||
break :blk undef_int.toConst();
|
||||
} else data.val.toBigInt(&int_buf, target);
|
||||
assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));
|
||||
assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));
|
||||
|
||||
const c_bits = toCIntBits(int_info.bits) orelse unreachable;
|
||||
const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8);
|
||||
var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
|
||||
const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
|
||||
|
||||
const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits));
|
||||
defer allocator.free(wrap_limbs);
|
||||
var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined };
|
||||
if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
|
||||
int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits))
|
||||
{
|
||||
const abbrev = switch (data.ty.tag()) {
|
||||
.c_short, .c_ushort => "SHRT",
|
||||
.c_int, .c_uint => "INT",
|
||||
.c_long, .c_ulong => "LONG",
|
||||
.c_longlong, .c_ulonglong => "LLONG",
|
||||
.isize, .usize => "INTPTR",
|
||||
else => return writer.print("zig_{s}Int_{c}{d}", .{
|
||||
if (int.positive) "max" else "min", signAbbrev(int_info.signedness), c_bits,
|
||||
var wrap = BigInt.Mutable{
|
||||
.limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)),
|
||||
.len = undefined,
|
||||
.positive = undefined,
|
||||
};
|
||||
defer allocator.free(wrap.limbs);
|
||||
if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or
|
||||
data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits))
|
||||
return writer.print("{s}_{s}", .{
|
||||
data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{
|
||||
if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits,
|
||||
}),
|
||||
};
|
||||
if (int_info.signedness == .unsigned) try writer.writeByte('U');
|
||||
return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" });
|
||||
}
|
||||
if (int.positive) "MAX" else "MIN",
|
||||
});
|
||||
|
||||
var use_twos_comp = false;
|
||||
if (!int.positive) {
|
||||
if (c_bits > 64) {
|
||||
// TODO: Can this be done for decimal literals as well?
|
||||
if (fmt.len == 1 and fmt[0] != 'd') {
|
||||
use_twos_comp = true;
|
||||
} else {
|
||||
// TODO: Use fmtIntLiteral for 0?
|
||||
try writer.print("zig_sub_{c}{d}(zig_make_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits });
|
||||
}
|
||||
} else {
|
||||
try writer.writeByte('-');
|
||||
}
|
||||
}
|
||||
|
||||
switch (data.ty.tag()) {
|
||||
.c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
|
||||
else => {
|
||||
if (int_info.bits <= 64) {
|
||||
try writer.print("{s}INT{d}_C(", .{ switch (int_info.signedness) {
|
||||
.signed => "",
|
||||
.unsigned => "U",
|
||||
}, c_bits });
|
||||
} else if (data.location != null and data.location.? == .StaticInitializer) {
|
||||
// MSVC treats casting the struct initializer as not constant (C2099), so an alternate form is used in global initializers
|
||||
try writer.print("zig_make_constant_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
|
||||
} else {
|
||||
try writer.print("zig_make_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
|
||||
}
|
||||
const c_limb_info: struct {
|
||||
cty: CType,
|
||||
count: usize,
|
||||
endian: std.builtin.Endian,
|
||||
homogeneous: bool,
|
||||
} = switch (data.cty.tag()) {
|
||||
else => .{
|
||||
.cty = CType.initTag(.void),
|
||||
.count = 1,
|
||||
.endian = .Little,
|
||||
.homogeneous = true,
|
||||
},
|
||||
}
|
||||
.zig_u128, .zig_i128 => .{
|
||||
.cty = CType.initTag(.uint64_t),
|
||||
.count = 2,
|
||||
.endian = .Big,
|
||||
.homogeneous = false,
|
||||
},
|
||||
.array => info: {
|
||||
const array_data = data.cty.castTag(.array).?.data;
|
||||
break :info .{
|
||||
.cty = data.dg.indexToCType(array_data.elem_type),
|
||||
.count = @intCast(usize, array_data.len),
|
||||
.endian = target.cpu.arch.endian(),
|
||||
.homogeneous = true,
|
||||
};
|
||||
},
|
||||
};
|
||||
if (c_limb_info.count == 1) {
|
||||
if (!int.positive) try writer.writeByte('-');
|
||||
try data.cty.renderLiteralPrefix(writer, data.kind);
|
||||
|
||||
const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb));
|
||||
if (c_bits <= 64) {
|
||||
var base: u8 = undefined;
|
||||
var case: std.fmt.Case = undefined;
|
||||
switch (fmt.len) {
|
||||
0 => base = 10,
|
||||
const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) {
|
||||
0 => .{ .base = 10 },
|
||||
1 => switch (fmt[0]) {
|
||||
'b' => {
|
||||
base = 2;
|
||||
'b' => style: {
|
||||
try writer.writeAll("0b");
|
||||
break :style .{ .base = 2 };
|
||||
},
|
||||
'o' => {
|
||||
base = 8;
|
||||
'o' => style: {
|
||||
try writer.writeByte('0');
|
||||
break :style .{ .base = 8 };
|
||||
},
|
||||
'd' => base = 10,
|
||||
'x' => {
|
||||
base = 16;
|
||||
case = .lower;
|
||||
try writer.writeAll("0x");
|
||||
},
|
||||
'X' => {
|
||||
base = 16;
|
||||
case = .upper;
|
||||
'd' => .{ .base = 10 },
|
||||
'x', 'X' => |base| style: {
|
||||
try writer.writeAll("0x");
|
||||
break :style .{ .base = 16, .case = switch (base) {
|
||||
'x' => .lower,
|
||||
'X' => .upper,
|
||||
else => unreachable,
|
||||
} };
|
||||
},
|
||||
else => @compileError("Invalid fmt: " ++ fmt),
|
||||
},
|
||||
else => @compileError("Invalid fmt: " ++ fmt),
|
||||
}
|
||||
};
|
||||
|
||||
var str: [64]u8 = undefined;
|
||||
var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]BigIntLimb = undefined;
|
||||
try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]);
|
||||
const string = try int.abs().toStringAlloc(allocator, style.base, style.case);
|
||||
defer allocator.free(string);
|
||||
try writer.writeAll(string);
|
||||
} else {
|
||||
assert(c_bits == 128);
|
||||
const split = std.math.min(int.limbs.len, limbs_count_64);
|
||||
var twos_comp_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
|
||||
try data.cty.renderLiteralPrefix(writer, data.kind);
|
||||
wrap.convertToTwosComplement(int, .unsigned, data.int_info.bits);
|
||||
std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0);
|
||||
wrap.len = wrap.limbs.len;
|
||||
const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count);
|
||||
|
||||
// Adding a negation in the C code before the doesn't work in all cases:
|
||||
// - struct versions would require an extra zig_sub_ call to negate, which wouldn't work in constant expressions
|
||||
// - negating the f80 int representation (i128) doesn't make sense
|
||||
// Instead we write out the literal as a negative number in twos complement
|
||||
var limbs = int.limbs;
|
||||
var c_limb_int_info = std.builtin.Type.Int{
|
||||
.signedness = undefined,
|
||||
.bits = @intCast(u16, @divExact(c_bits, c_limb_info.count)),
|
||||
};
|
||||
var c_limb_cty: CType = undefined;
|
||||
|
||||
if (use_twos_comp) {
|
||||
var twos_comp = BigInt.Mutable{
|
||||
.limbs = &twos_comp_limbs,
|
||||
.positive = undefined,
|
||||
var limb_offset: usize = 0;
|
||||
const most_significant_limb_i = wrap.len - limbs_per_c_limb;
|
||||
while (limb_offset < wrap.len) : (limb_offset += limbs_per_c_limb) {
|
||||
const limb_i = switch (c_limb_info.endian) {
|
||||
.Little => limb_offset,
|
||||
.Big => most_significant_limb_i - limb_offset,
|
||||
};
|
||||
var c_limb_mut = BigInt.Mutable{
|
||||
.limbs = wrap.limbs[limb_i..][0..limbs_per_c_limb],
|
||||
.len = undefined,
|
||||
.positive = true,
|
||||
};
|
||||
c_limb_mut.normalize(limbs_per_c_limb);
|
||||
|
||||
if (limb_i == most_significant_limb_i and
|
||||
!c_limb_info.homogeneous and data.int_info.signedness == .signed)
|
||||
{
|
||||
// most significant limb is actually signed
|
||||
c_limb_int_info.signedness = .signed;
|
||||
c_limb_cty = c_limb_info.cty.toSigned();
|
||||
|
||||
c_limb_mut.positive = wrap.positive;
|
||||
c_limb_mut.convertToTwosComplement(
|
||||
c_limb_mut.toConst(),
|
||||
.signed,
|
||||
data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb),
|
||||
);
|
||||
} else {
|
||||
c_limb_int_info.signedness = .unsigned;
|
||||
c_limb_cty = c_limb_info.cty;
|
||||
}
|
||||
var c_limb_val_pl = Value.Payload.BigInt{
|
||||
.base = .{ .tag = if (c_limb_mut.positive) .int_big_positive else .int_big_negative },
|
||||
.data = c_limb_mut.limbs[0..c_limb_mut.len],
|
||||
};
|
||||
|
||||
twos_comp.convertToTwosComplement(int, .signed, int_info.bits);
|
||||
limbs = twos_comp.limbs;
|
||||
if (limb_offset > 0) try writer.writeAll(", ");
|
||||
try formatIntLiteral(.{
|
||||
.dg = data.dg,
|
||||
.int_info = c_limb_int_info,
|
||||
.kind = data.kind,
|
||||
.cty = c_limb_cty,
|
||||
.val = Value.initPayload(&c_limb_val_pl.base),
|
||||
}, fmt, options, writer);
|
||||
}
|
||||
|
||||
var upper_pl = Value.Payload.BigInt{
|
||||
.base = .{ .tag = .int_big_positive },
|
||||
.data = limbs[split..],
|
||||
};
|
||||
const upper_val = Value.initPayload(&upper_pl.base);
|
||||
try formatIntLiteral(.{
|
||||
.ty = switch (int_info.signedness) {
|
||||
.unsigned => Type.u64,
|
||||
.signed => if (use_twos_comp) Type.u64 else Type.i64,
|
||||
},
|
||||
.val = upper_val,
|
||||
.mod = data.mod,
|
||||
}, fmt, options, writer);
|
||||
|
||||
try writer.writeAll(", ");
|
||||
|
||||
var lower_pl = Value.Payload.BigInt{
|
||||
.base = .{ .tag = .int_big_positive },
|
||||
.data = limbs[0..split],
|
||||
};
|
||||
const lower_val = Value.initPayload(&lower_pl.base);
|
||||
try formatIntLiteral(.{
|
||||
.ty = Type.u64,
|
||||
.val = lower_val,
|
||||
.mod = data.mod,
|
||||
}, fmt, options, writer);
|
||||
|
||||
if (!int.positive and c_bits > 64 and !use_twos_comp) try writer.writeByte(')');
|
||||
return writer.writeByte(')');
|
||||
}
|
||||
|
||||
switch (data.ty.tag()) {
|
||||
.c_short, .c_ushort, .c_int => {},
|
||||
.c_uint => try writer.writeAll("u"),
|
||||
.c_long => try writer.writeAll("l"),
|
||||
.c_ulong => try writer.writeAll("ul"),
|
||||
.c_longlong => try writer.writeAll("ll"),
|
||||
.c_ulonglong => try writer.writeAll("ull"),
|
||||
else => try writer.writeByte(')'),
|
||||
}
|
||||
try data.cty.renderLiteralSuffix(writer);
|
||||
}
|
||||
|
||||
fn isByRef(ty: Type) bool {
|
||||
|
||||
@ -496,6 +496,296 @@ pub const CType = extern union {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn toSigned(self: CType) CType {
|
||||
return CType.initTag(switch (self.tag()) {
|
||||
.char, .@"signed char", .@"unsigned char" => .@"signed char",
|
||||
.short, .@"unsigned short" => .short,
|
||||
.int, .@"unsigned int" => .int,
|
||||
.long, .@"unsigned long" => .long,
|
||||
.@"long long", .@"unsigned long long" => .@"long long",
|
||||
.size_t, .ptrdiff_t => .ptrdiff_t,
|
||||
.uint8_t, .int8_t => .int8_t,
|
||||
.uint16_t, .int16_t => .int16_t,
|
||||
.uint32_t, .int32_t => .int32_t,
|
||||
.uint64_t, .int64_t => .int64_t,
|
||||
.uintptr_t, .intptr_t => .intptr_t,
|
||||
.zig_u128, .zig_i128 => .zig_i128,
|
||||
.float,
|
||||
.double,
|
||||
.@"long double",
|
||||
.zig_f16,
|
||||
.zig_f32,
|
||||
.zig_f80,
|
||||
.zig_f128,
|
||||
.zig_c_longdouble,
|
||||
=> |t| t,
|
||||
else => unreachable,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn toUnsigned(self: CType) CType {
|
||||
return CType.initTag(switch (self.tag()) {
|
||||
.char, .@"signed char", .@"unsigned char" => .@"unsigned char",
|
||||
.short, .@"unsigned short" => .@"unsigned short",
|
||||
.int, .@"unsigned int" => .@"unsigned int",
|
||||
.long, .@"unsigned long" => .@"unsigned long",
|
||||
.@"long long", .@"unsigned long long" => .@"unsigned long long",
|
||||
.size_t, .ptrdiff_t => .size_t,
|
||||
.uint8_t, .int8_t => .uint8_t,
|
||||
.uint16_t, .int16_t => .uint16_t,
|
||||
.uint32_t, .int32_t => .uint32_t,
|
||||
.uint64_t, .int64_t => .uint64_t,
|
||||
.uintptr_t, .intptr_t => .uintptr_t,
|
||||
.zig_u128, .zig_i128 => .zig_u128,
|
||||
else => unreachable,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn getStandardDefineAbbrev(self: CType) ?[]const u8 {
|
||||
return switch (self.tag()) {
|
||||
.char => "CHAR",
|
||||
.@"signed char" => "SCHAR",
|
||||
.short => "SHRT",
|
||||
.int => "INT",
|
||||
.long => "LONG",
|
||||
.@"long long" => "LLONG",
|
||||
.@"unsigned char" => "UCHAR",
|
||||
.@"unsigned short" => "USHRT",
|
||||
.@"unsigned int" => "UINT",
|
||||
.@"unsigned long" => "ULONG",
|
||||
.@"unsigned long long" => "ULLONG",
|
||||
.float => "FLT",
|
||||
.double => "DBL",
|
||||
.@"long double" => "LDBL",
|
||||
.size_t => "SIZE",
|
||||
.ptrdiff_t => "PTRDIFF",
|
||||
.uint8_t => "UINT8",
|
||||
.int8_t => "INT8",
|
||||
.uint16_t => "UINT16",
|
||||
.int16_t => "INT16",
|
||||
.uint32_t => "UINT32",
|
||||
.int32_t => "INT32",
|
||||
.uint64_t => "UINT64",
|
||||
.int64_t => "INT64",
|
||||
.uintptr_t => "UINTPTR",
|
||||
.intptr_t => "INTPTR",
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn renderLiteralPrefix(self: CType, writer: anytype, kind: Kind) @TypeOf(writer).Error!void {
|
||||
switch (self.tag()) {
|
||||
.void => unreachable,
|
||||
._Bool,
|
||||
.char,
|
||||
.@"signed char",
|
||||
.short,
|
||||
.@"unsigned short",
|
||||
.bool,
|
||||
.size_t,
|
||||
.ptrdiff_t,
|
||||
.uintptr_t,
|
||||
.intptr_t,
|
||||
=> |t| switch (kind) {
|
||||
else => try writer.print("({s})", .{@tagName(t)}),
|
||||
.global => {},
|
||||
},
|
||||
.int,
|
||||
.long,
|
||||
.@"long long",
|
||||
.@"unsigned char",
|
||||
.@"unsigned int",
|
||||
.@"unsigned long",
|
||||
.@"unsigned long long",
|
||||
.float,
|
||||
.double,
|
||||
.@"long double",
|
||||
=> {},
|
||||
.uint8_t,
|
||||
.int8_t,
|
||||
.uint16_t,
|
||||
.int16_t,
|
||||
.uint32_t,
|
||||
.int32_t,
|
||||
.uint64_t,
|
||||
.int64_t,
|
||||
=> try writer.print("{s}_C(", .{self.getStandardDefineAbbrev().?}),
|
||||
.zig_u128,
|
||||
.zig_i128,
|
||||
.zig_f16,
|
||||
.zig_f32,
|
||||
.zig_f64,
|
||||
.zig_f80,
|
||||
.zig_f128,
|
||||
.zig_c_longdouble,
|
||||
=> |t| try writer.print("zig_{s}_{s}(", .{
|
||||
switch (kind) {
|
||||
else => "make",
|
||||
.global => "init",
|
||||
},
|
||||
@tagName(t)["zig_".len..],
|
||||
}),
|
||||
.pointer,
|
||||
.pointer_const,
|
||||
.pointer_volatile,
|
||||
.pointer_const_volatile,
|
||||
=> unreachable,
|
||||
.array,
|
||||
.vector,
|
||||
=> try writer.writeByte('{'),
|
||||
.fwd_anon_struct,
|
||||
.fwd_anon_union,
|
||||
.fwd_struct,
|
||||
.fwd_union,
|
||||
.unnamed_struct,
|
||||
.unnamed_union,
|
||||
.packed_unnamed_struct,
|
||||
.packed_unnamed_union,
|
||||
.anon_struct,
|
||||
.anon_union,
|
||||
.@"struct",
|
||||
.@"union",
|
||||
.packed_struct,
|
||||
.packed_union,
|
||||
.function,
|
||||
.varargs_function,
|
||||
=> unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn renderLiteralSuffix(self: CType, writer: anytype) @TypeOf(writer).Error!void {
|
||||
switch (self.tag()) {
|
||||
.void => unreachable,
|
||||
._Bool => {},
|
||||
.char,
|
||||
.@"signed char",
|
||||
.short,
|
||||
.int,
|
||||
=> {},
|
||||
.long => try writer.writeByte('l'),
|
||||
.@"long long" => try writer.writeAll("ll"),
|
||||
.@"unsigned char",
|
||||
.@"unsigned short",
|
||||
.@"unsigned int",
|
||||
=> try writer.writeByte('u'),
|
||||
.@"unsigned long",
|
||||
.size_t,
|
||||
.uintptr_t,
|
||||
=> try writer.writeAll("ul"),
|
||||
.@"unsigned long long" => try writer.writeAll("ull"),
|
||||
.float => try writer.writeByte('f'),
|
||||
.double => {},
|
||||
.@"long double" => try writer.writeByte('l'),
|
||||
.bool,
|
||||
.ptrdiff_t,
|
||||
.intptr_t,
|
||||
=> {},
|
||||
.uint8_t,
|
||||
.int8_t,
|
||||
.uint16_t,
|
||||
.int16_t,
|
||||
.uint32_t,
|
||||
.int32_t,
|
||||
.uint64_t,
|
||||
.int64_t,
|
||||
.zig_u128,
|
||||
.zig_i128,
|
||||
.zig_f16,
|
||||
.zig_f32,
|
||||
.zig_f64,
|
||||
.zig_f80,
|
||||
.zig_f128,
|
||||
.zig_c_longdouble,
|
||||
=> try writer.writeByte(')'),
|
||||
.pointer,
|
||||
.pointer_const,
|
||||
.pointer_volatile,
|
||||
.pointer_const_volatile,
|
||||
=> unreachable,
|
||||
.array,
|
||||
.vector,
|
||||
=> try writer.writeByte('}'),
|
||||
.fwd_anon_struct,
|
||||
.fwd_anon_union,
|
||||
.fwd_struct,
|
||||
.fwd_union,
|
||||
.unnamed_struct,
|
||||
.unnamed_union,
|
||||
.packed_unnamed_struct,
|
||||
.packed_unnamed_union,
|
||||
.anon_struct,
|
||||
.anon_union,
|
||||
.@"struct",
|
||||
.@"union",
|
||||
.packed_struct,
|
||||
.packed_union,
|
||||
.function,
|
||||
.varargs_function,
|
||||
=> unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 {
|
||||
return switch (self.tag()) {
|
||||
.void => 0,
|
||||
.char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1,
|
||||
.short => target.c_type_byte_size(.short),
|
||||
.int => target.c_type_byte_size(.int),
|
||||
.long => target.c_type_byte_size(.long),
|
||||
.@"long long" => target.c_type_byte_size(.longlong),
|
||||
.@"unsigned short" => target.c_type_byte_size(.ushort),
|
||||
.@"unsigned int" => target.c_type_byte_size(.uint),
|
||||
.@"unsigned long" => target.c_type_byte_size(.ulong),
|
||||
.@"unsigned long long" => target.c_type_byte_size(.ulonglong),
|
||||
.float => target.c_type_byte_size(.float),
|
||||
.double => target.c_type_byte_size(.double),
|
||||
.@"long double" => target.c_type_byte_size(.longdouble),
|
||||
.size_t,
|
||||
.ptrdiff_t,
|
||||
.uintptr_t,
|
||||
.intptr_t,
|
||||
.pointer,
|
||||
.pointer_const,
|
||||
.pointer_volatile,
|
||||
.pointer_const_volatile,
|
||||
=> @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
.uint16_t, .int16_t, .zig_f16 => 2,
|
||||
.uint32_t, .int32_t, .zig_f32 => 4,
|
||||
.uint64_t, .int64_t, .zig_f64 => 8,
|
||||
.zig_u128, .zig_i128, .zig_f128 => 16,
|
||||
.zig_f80 => if (target.c_type_bit_size(.longdouble) == 80)
|
||||
target.c_type_byte_size(.longdouble)
|
||||
else
|
||||
16,
|
||||
.zig_c_longdouble => target.c_type_byte_size(.longdouble),
|
||||
|
||||
.array,
|
||||
.vector,
|
||||
=> {
|
||||
const data = self.cast(Payload.Sequence).?.data;
|
||||
return data.len * store.indexToCType(data.elem_type).byteSize(store, target);
|
||||
},
|
||||
|
||||
.fwd_anon_struct,
|
||||
.fwd_anon_union,
|
||||
.fwd_struct,
|
||||
.fwd_union,
|
||||
.unnamed_struct,
|
||||
.unnamed_union,
|
||||
.packed_unnamed_struct,
|
||||
.packed_unnamed_union,
|
||||
.anon_struct,
|
||||
.anon_union,
|
||||
.@"struct",
|
||||
.@"union",
|
||||
.packed_struct,
|
||||
.packed_union,
|
||||
.function,
|
||||
.varargs_function,
|
||||
=> unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isPacked(self: CType) bool {
|
||||
return switch (self.tag()) {
|
||||
else => false,
|
||||
@ -787,26 +1077,26 @@ pub const CType = extern union {
|
||||
};
|
||||
}
|
||||
|
||||
fn tagFromIntInfo(signedness: std.builtin.Signedness, bits: u16) Tag {
|
||||
return switch (bits) {
|
||||
fn tagFromIntInfo(int_info: std.builtin.Type.Int) Tag {
|
||||
return switch (int_info.bits) {
|
||||
0 => .void,
|
||||
1...8 => switch (signedness) {
|
||||
1...8 => switch (int_info.signedness) {
|
||||
.unsigned => .uint8_t,
|
||||
.signed => .int8_t,
|
||||
},
|
||||
9...16 => switch (signedness) {
|
||||
9...16 => switch (int_info.signedness) {
|
||||
.unsigned => .uint16_t,
|
||||
.signed => .int16_t,
|
||||
},
|
||||
17...32 => switch (signedness) {
|
||||
17...32 => switch (int_info.signedness) {
|
||||
.unsigned => .uint32_t,
|
||||
.signed => .int32_t,
|
||||
},
|
||||
33...64 => switch (signedness) {
|
||||
33...64 => switch (int_info.signedness) {
|
||||
.unsigned => .uint64_t,
|
||||
.signed => .int64_t,
|
||||
},
|
||||
65...128 => switch (signedness) {
|
||||
65...128 => switch (int_info.signedness) {
|
||||
.unsigned => .zig_u128,
|
||||
.signed => .zig_i128,
|
||||
},
|
||||
@ -945,31 +1235,27 @@ pub const CType = extern union {
|
||||
.c_ulong => self.init(.@"unsigned long"),
|
||||
.c_longlong => self.init(.@"long long"),
|
||||
.c_ulonglong => self.init(.@"unsigned long long"),
|
||||
else => {
|
||||
const info = ty.intInfo(target);
|
||||
const t = tagFromIntInfo(info.signedness, info.bits);
|
||||
switch (t) {
|
||||
.void => unreachable,
|
||||
else => self.init(t),
|
||||
.array => switch (kind) {
|
||||
.forward, .complete, .global => {
|
||||
const abi_size = ty.abiSize(target);
|
||||
const abi_align = ty.abiAlignment(target);
|
||||
self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
|
||||
.len = @divExact(abi_size, abi_align),
|
||||
.elem_type = tagFromIntInfo(
|
||||
.unsigned,
|
||||
@intCast(u16, abi_align * 8),
|
||||
).toIndex(),
|
||||
} } };
|
||||
self.value = .{ .cty = initPayload(&self.storage.seq) };
|
||||
},
|
||||
.forward_parameter,
|
||||
.parameter,
|
||||
=> try self.initArrayParameter(ty, kind, lookup),
|
||||
.payload => unreachable,
|
||||
else => switch (tagFromIntInfo(ty.intInfo(target))) {
|
||||
.void => unreachable,
|
||||
else => |t| self.init(t),
|
||||
.array => switch (kind) {
|
||||
.forward, .complete, .global => {
|
||||
const abi_size = ty.abiSize(target);
|
||||
const abi_align = ty.abiAlignment(target);
|
||||
self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
|
||||
.len = @divExact(abi_size, abi_align),
|
||||
.elem_type = tagFromIntInfo(.{
|
||||
.signedness = .unsigned,
|
||||
.bits = @intCast(u16, abi_align * 8),
|
||||
}).toIndex(),
|
||||
} } };
|
||||
self.value = .{ .cty = initPayload(&self.storage.seq) };
|
||||
},
|
||||
}
|
||||
.forward_parameter,
|
||||
.parameter,
|
||||
=> try self.initArrayParameter(ty, kind, lookup),
|
||||
.payload => unreachable,
|
||||
},
|
||||
},
|
||||
} else switch (ty.zigTypeTag()) {
|
||||
.Frame => unreachable,
|
||||
|
||||
@ -368,7 +368,6 @@ test "comptime @bitCast packed struct to int and back" {
|
||||
}
|
||||
|
||||
test "comptime bitcast with fields following f80" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user