cbe: first set of changes for msvc compatibility
- Forward declare int builtins, so the definitions aren't assumed incorrectly - Add define to handle MSVC not support static const in function parameter array lengths - Fixup several spots where int128 support was assumed. - Support zig_align - Support zig_export - Stub out some missing non-builtin functions - Added StringLiteral to automatically split string literals when they get to 16380 in size, which is the maxmimum pre-concatenation string literal size on MSVC.
This commit is contained in:
56
lib/zig.h
56
lib/zig.h
@@ -38,6 +38,12 @@ typedef char bool;
|
||||
#define zig_threadlocal zig_threadlocal_unavailable
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
#define zig_const_arr
|
||||
#else
|
||||
#define zig_const_arr static const
|
||||
#endif
|
||||
|
||||
#if zig_has_attribute(naked) || defined(__GNUC__)
|
||||
#define zig_naked __attribute__((naked))
|
||||
#elif defined(_MSC_VER)
|
||||
@@ -65,7 +71,7 @@ typedef char bool;
|
||||
#elif zig_has_attribute(aligned)
|
||||
#define zig_align(alignment) __attribute__((aligned(alignment)))
|
||||
#elif _MSC_VER
|
||||
#define zig_align zig_align_unavailable
|
||||
#define zig_align(alignment) __declspec(align(alignment))
|
||||
#else
|
||||
#define zig_align zig_align_unavailable
|
||||
#endif
|
||||
@@ -73,7 +79,8 @@ typedef char bool;
|
||||
#if zig_has_attribute(aligned)
|
||||
#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
|
||||
#elif _MSC_VER
|
||||
#define zig_align_fn zig_align_fn_unavailable
|
||||
// TODO: Figure out how to do this under MSVC
|
||||
#define zig_align_fn(alignment)
|
||||
#else
|
||||
#define zig_align_fn zig_align_fn_unavailable
|
||||
#endif
|
||||
@@ -92,6 +99,9 @@ typedef char bool;
|
||||
|
||||
#if zig_has_attribute(alias)
|
||||
#define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(symbol)))
|
||||
#elif _MSC_VER
|
||||
#define zig_export(sig, symbol, name) sig;\
|
||||
__pragma(comment(linker, "/alternatename:" name "=" symbol ))
|
||||
#else
|
||||
#define zig_export(sig, symbol, name) __asm(name " = " symbol)
|
||||
#endif
|
||||
@@ -1327,13 +1337,15 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
|
||||
return zig_sub_i128(zig_div_trunc_i128(lhs, rhs), (((lhs.hi ^ rhs.hi) & zig_rem_i128(lhs, rhs).hi) < zig_as_i64(0)) ? zig_as_i128(0, 1) : zig_as_i128(0, 0));
|
||||
}
|
||||
// TODO: Implement
|
||||
static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs);
|
||||
|
||||
// TODO: Implement
|
||||
static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs);
|
||||
|
||||
static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
|
||||
zig_i128 rem = zig_rem_i128(lhs, rhs);
|
||||
return rem + (((lhs.hi ^ rhs.hi) & rem.hi) < zig_as_i64(0) ? rhs : zig_as_i128(0, 0));
|
||||
return zig_add_i128(rem, (((lhs.hi ^ rhs.hi) & rem.hi) < zig_as_i64(0) ? rhs : zig_as_i128(0, 0)));
|
||||
}
|
||||
|
||||
#endif /* zig_has_int128 */
|
||||
@@ -1358,7 +1370,7 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
|
||||
}
|
||||
|
||||
static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
|
||||
zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i32(0) ? -zig_as_i128(0, 1) : zig_as_i128(0, 0);
|
||||
zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_sub_i128(zig_as_i128(0, 0), zig_as_i128(0, 1)) : zig_as_i128(0, 0);
|
||||
return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
|
||||
}
|
||||
|
||||
@@ -1375,7 +1387,7 @@ static inline zig_u128 zig_shlw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
|
||||
}
|
||||
|
||||
static inline zig_i128 zig_shlw_i128(zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
|
||||
return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
|
||||
return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), rhs)), bits);
|
||||
}
|
||||
|
||||
static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
|
||||
@@ -1394,6 +1406,9 @@ static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
|
||||
return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs);
|
||||
|
||||
static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
|
||||
return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
|
||||
}
|
||||
@@ -1496,15 +1511,15 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_
|
||||
|
||||
#else /* zig_has_int128 */
|
||||
|
||||
static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
|
||||
return zig_addo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
|
||||
zig_addo_u64(&res->hi, res->hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
|
||||
}
|
||||
/* static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) { */
|
||||
/* return zig_addo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) | */
|
||||
/* zig_addo_u64(&res->hi, res->hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX)); */
|
||||
/* } */
|
||||
|
||||
static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
|
||||
return zig_subo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
|
||||
zig_subo_u64(&res->hi, res->hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
|
||||
}
|
||||
/* static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) { */
|
||||
/* return zig_subo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) | */
|
||||
/* zig_subo_u64(&res->hi, res->hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX)); */
|
||||
/* } */
|
||||
|
||||
#endif /* zig_has_int128 */
|
||||
|
||||
@@ -1512,7 +1527,12 @@ static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
|
||||
zig_u128 res;
|
||||
if (zig_cmp_u128(rhs, zig_as_u128(0, bits)) >= zig_as_i32(0))
|
||||
return zig_cmp_u128(lhs, zig_as_u128(0, 0)) != zig_as_i32(0) ? zig_maxInt(u128, bits) : lhs;
|
||||
|
||||
#if zig_has_int128
|
||||
return zig_shlo_u128(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u128, bits) : res;
|
||||
#else
|
||||
return zig_shlo_u128(&res, lhs, (zig_u8)rhs.lo, bits) ? zig_maxInt(u128, bits) : res;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
|
||||
@@ -1593,7 +1613,7 @@ static inline zig_u128 zig_byte_swap_u128(zig_u128 val, zig_u8 bits) {
|
||||
}
|
||||
|
||||
static inline zig_i128 zig_byte_swap_i128(zig_i128 val, zig_u8 bits) {
|
||||
return zig_byte_swap_u128(zig_bitcast_u128(val), bits);
|
||||
return zig_bitcast_i128(zig_byte_swap_u128(zig_bitcast_u128(val), bits));
|
||||
}
|
||||
|
||||
static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {
|
||||
@@ -1603,7 +1623,7 @@ static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {
|
||||
}
|
||||
|
||||
static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
|
||||
return zig_bit_reverse_u128(zig_bitcast_u128(val), bits);
|
||||
return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits));
|
||||
}
|
||||
|
||||
/* ========================= Floating Point Support ========================= */
|
||||
|
||||
@@ -848,12 +848,13 @@ pub const DeclGen = struct {
|
||||
|
||||
const ai = ty.arrayInfo();
|
||||
if (ai.elem_type.eql(Type.u8, dg.module)) {
|
||||
try writer.writeByte('"');
|
||||
var literal = stringLiteral(writer);
|
||||
try literal.start();
|
||||
const c_len = ty.arrayLenIncludingSentinel();
|
||||
var index: usize = 0;
|
||||
while (index < c_len) : (index += 1)
|
||||
try writeStringLiteralChar(writer, 0xaa);
|
||||
return writer.writeByte('"');
|
||||
try literal.writeChar(0xaa);
|
||||
return literal.end();
|
||||
} else {
|
||||
try writer.writeByte('{');
|
||||
const c_len = ty.arrayLenIncludingSentinel();
|
||||
@@ -1060,23 +1061,40 @@ pub const DeclGen = struct {
|
||||
defer arena.deinit();
|
||||
const arena_allocator = arena.allocator();
|
||||
|
||||
// MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal
|
||||
const max_string_initializer_len = 65535;
|
||||
|
||||
const ai = ty.arrayInfo();
|
||||
if (ai.elem_type.eql(Type.u8, dg.module)) {
|
||||
try writer.writeByte('"');
|
||||
var index: usize = 0;
|
||||
while (index < ai.len) : (index += 1) {
|
||||
const elem_val = try val.elemValue(dg.module, arena_allocator, index);
|
||||
const elem_val_u8 = if (elem_val.isUndef())
|
||||
undefPattern(u8)
|
||||
else
|
||||
@intCast(u8, elem_val.toUnsignedInt(target));
|
||||
try writeStringLiteralChar(writer, elem_val_u8);
|
||||
if (ai.len <= max_string_initializer_len) {
|
||||
var literal = stringLiteral(writer);
|
||||
try literal.start();
|
||||
var index: usize = 0;
|
||||
while (index < ai.len) : (index += 1) {
|
||||
const elem_val = try val.elemValue(dg.module, arena_allocator, index);
|
||||
const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target));
|
||||
try literal.writeChar(elem_val_u8);
|
||||
}
|
||||
if (ai.sentinel) |s| {
|
||||
const s_u8 = @intCast(u8, s.toUnsignedInt(target));
|
||||
try literal.writeChar(s_u8);
|
||||
}
|
||||
try literal.end();
|
||||
} else {
|
||||
try writer.writeByte('{');
|
||||
var index: usize = 0;
|
||||
while (index < ai.len) : (index += 1) {
|
||||
if (index != 0) try writer.writeByte(',');
|
||||
const elem_val = try val.elemValue(dg.module, arena_allocator, index);
|
||||
const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target));
|
||||
try writer.print("'\\x{x}'", .{ elem_val_u8 });
|
||||
}
|
||||
if (ai.sentinel) |s| {
|
||||
if (index != 0) try writer.writeByte(',');
|
||||
try dg.renderValue(writer, ai.elem_type, s, .Initializer);
|
||||
}
|
||||
try writer.writeByte('}');
|
||||
}
|
||||
if (ai.sentinel) |s| {
|
||||
const s_u8 = @intCast(u8, s.toUnsignedInt(target));
|
||||
try writeStringLiteralChar(writer, s_u8);
|
||||
}
|
||||
try writer.writeByte('"');
|
||||
} else {
|
||||
try writer.writeByte('{');
|
||||
var index: usize = 0;
|
||||
@@ -2134,7 +2152,7 @@ pub const DeclGen = struct {
|
||||
const c_len_val = Value.initPayload(&c_len_pl.base);
|
||||
|
||||
try suffix_writer.writeByte('[');
|
||||
if (mutability == .ConstArgument and depth == 0) try suffix_writer.writeAll("static const ");
|
||||
if (mutability == .ConstArgument and depth == 0) try suffix_writer.writeAll("zig_const_arr ");
|
||||
try suffix.writer().print("{}]", .{try dg.fmtIntLiteral(Type.usize, c_len_val)});
|
||||
render_ty = array_info.elem_type;
|
||||
depth += 1;
|
||||
@@ -6793,6 +6811,68 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 {
|
||||
} else unreachable;
|
||||
}
|
||||
|
||||
fn StringLiteral(comptime WriterType: type) type {
|
||||
// msvc has a length limit of 16380 per string literal (before concatenation)
|
||||
const max_char_len = 4;
|
||||
const max_len = 16380 - max_char_len;
|
||||
|
||||
return struct {
|
||||
cur_len: usize = 0,
|
||||
counting_writer: std.io.CountingWriter(WriterType),
|
||||
|
||||
pub const Error = WriterType.Error;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn start(self: *Self) Error!void {
|
||||
const writer = self.counting_writer.writer();
|
||||
try writer.writeByte('\"');
|
||||
}
|
||||
|
||||
pub fn end(self: *Self) Error!void {
|
||||
const writer = self.counting_writer.writer();
|
||||
try writer.writeByte('\"');
|
||||
}
|
||||
|
||||
fn writeStringLiteralChar(writer: anytype, c: u8) !void {
|
||||
switch (c) {
|
||||
7 => try writer.writeAll("\\a"),
|
||||
8 => try writer.writeAll("\\b"),
|
||||
'\t' => try writer.writeAll("\\t"),
|
||||
'\n' => try writer.writeAll("\\n"),
|
||||
11 => try writer.writeAll("\\v"),
|
||||
12 => try writer.writeAll("\\f"),
|
||||
'\r' => try writer.writeAll("\\r"),
|
||||
'"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}),
|
||||
else => switch (c) {
|
||||
' '...'~' => try writer.writeByte(c),
|
||||
else => try writer.print("\\{o:0>3}", .{c}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeChar(self: *Self, c: u8) Error!void {
|
||||
const writer = self.counting_writer.writer();
|
||||
|
||||
if (self.cur_len == 0 and self.counting_writer.bytes_written > 1)
|
||||
try writer.writeAll("\"\"");
|
||||
|
||||
const len = self.counting_writer.bytes_written;
|
||||
try writeStringLiteralChar(writer, c);
|
||||
|
||||
const char_length = self.counting_writer.bytes_written - len;
|
||||
assert(char_length <= max_char_len);
|
||||
self.cur_len += char_length;
|
||||
|
||||
if (self.cur_len >= max_len) self.cur_len = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn stringLiteral(child_stream: anytype) StringLiteral(@TypeOf(child_stream)) {
|
||||
return .{ .counting_writer = std.io.countingWriter(child_stream) };
|
||||
}
|
||||
|
||||
fn formatStringLiteral(
|
||||
str: []const u8,
|
||||
comptime fmt: []const u8,
|
||||
@@ -6800,33 +6880,18 @@ fn formatStringLiteral(
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt);
|
||||
try writer.writeByte('\"');
|
||||
|
||||
var literal = stringLiteral(writer);
|
||||
try literal.start();
|
||||
for (str) |c|
|
||||
try writeStringLiteralChar(writer, c);
|
||||
try writer.writeByte('\"');
|
||||
try literal.writeChar(c);
|
||||
try literal.end();
|
||||
}
|
||||
|
||||
fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) {
|
||||
return .{ .data = str };
|
||||
}
|
||||
|
||||
fn writeStringLiteralChar(writer: anytype, c: u8) !void {
|
||||
switch (c) {
|
||||
7 => try writer.writeAll("\\a"),
|
||||
8 => try writer.writeAll("\\b"),
|
||||
'\t' => try writer.writeAll("\\t"),
|
||||
'\n' => try writer.writeAll("\\n"),
|
||||
11 => try writer.writeAll("\\v"),
|
||||
12 => try writer.writeAll("\\f"),
|
||||
'\r' => try writer.writeAll("\\r"),
|
||||
'"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}),
|
||||
else => switch (c) {
|
||||
' '...'~' => try writer.writeByte(c),
|
||||
else => try writer.print("\\{o:0>3}", .{c}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn undefPattern(comptime IntType: type) IntType {
|
||||
const int_info = @typeInfo(IntType).Int;
|
||||
const UnsignedType = std.meta.Int(.unsigned, int_info.bits);
|
||||
@@ -6905,7 +6970,15 @@ fn formatIntLiteral(
|
||||
return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" });
|
||||
}
|
||||
|
||||
if (!int.positive) try writer.writeByte('-');
|
||||
// TODO: If > 64 bit, need to use a subtract from zero fn here instead of negate
|
||||
if (!int.positive) {
|
||||
if (c_bits > 64) {
|
||||
try writer.print("zig_sub_{c}{d}(zig_as_{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 => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }),
|
||||
@@ -6976,6 +7049,7 @@ fn formatIntLiteral(
|
||||
.mod = data.mod,
|
||||
}, fmt, options, writer);
|
||||
|
||||
if (!int.positive and c_bits > 64) try writer.writeByte(')');
|
||||
return writer.writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user