feature. See also
. The project being documented here (as the example) is the Zig library itself.
ubsan_rt.Value
const Value = extern struct
File
Code
const Value = extern struct {
td: *const TypeDescriptor,
handle: ValueHandle,
fn getUnsignedInteger(value: Value) u128 {
assert(!value.td.isSigned());
const size = value.td.getIntegerSize();
const max_inline_size = @bitSizeOf(ValueHandle);
if (size <= max_inline_size) {
return @intFromPtr(value.handle);
}
return switch (size) {
64 => @as(*const u64, @ptrCast(@alignCast(value.handle))).*,
128 => @as(*const u128, @ptrCast(@alignCast(value.handle))).*,
else => @trap(),
};
}
fn getSignedInteger(value: Value) i128 {
assert(value.td.isSigned());
const size = value.td.getIntegerSize();
const max_inline_size = @bitSizeOf(ValueHandle);
if (size <= max_inline_size) {
const extra_bits: std.math.Log2Int(usize) = @intCast(max_inline_size - size);
const handle: isize = @bitCast(@intFromPtr(value.handle));
return (handle << extra_bits) >> extra_bits;
}
return switch (size) {
64 => @as(*const i64, @ptrCast(@alignCast(value.handle))).*,
128 => @as(*const i128, @ptrCast(@alignCast(value.handle))).*,
else => @trap(),
};
}
fn getFloat(value: Value) f128 {
assert(value.td.kind == .float);
const size = value.td.info.float;
const max_inline_size = @bitSizeOf(ValueHandle);
if (size <= max_inline_size) {
return @as(switch (@bitSizeOf(usize)) {
32 => f32,
64 => f64,
else => @compileError("unsupported target"),
}, @bitCast(@intFromPtr(value.handle)));
}
return @floatCast(switch (size) {
64 => @as(*const f64, @ptrCast(@alignCast(value.handle))).*,
80 => @as(*const f80, @ptrCast(@alignCast(value.handle))).*,
128 => @as(*const f128, @ptrCast(@alignCast(value.handle))).*,
else => @trap(),
});
}
fn isMinusOne(value: Value) bool {
return value.td.isSigned() and
value.getSignedInteger() == -1;
}
fn isNegative(value: Value) bool {
return value.td.isSigned() and
value.getSignedInteger() < 0;
}
fn getPositiveInteger(value: Value) u128 {
if (value.td.isSigned()) {
const signed = value.getSignedInteger();
assert(signed >= 0);
return @intCast(signed);
} else {
return value.getUnsignedInteger();
}
}
pub fn format(value: Value, writer: *std.Io.Writer) std.Io.Writer.Error!void {
switch (value.td.kind) {
.integer => {
if (value.td.isSigned()) {
try writer.print("{d}", .{value.getSignedInteger()});
} else {
try writer.print("{d}", .{value.getUnsignedInteger()});
}
},
.float => try writer.print("{d}", .{value.getFloat()}),
.unknown => try writer.writeAll("(unknown)"),
}
}
}