aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorkcbanner <kcbanner@gmail.com>2022-12-23 23:48:44 -0500
committerkcbanner <kcbanner@gmail.com>2023-01-01 16:44:29 -0500
commitf07d33f54b3448019f5e7c74c1f9063a5079b961 (patch)
tree786540e287a1e01af2a01b98f61153416c3da01c /src/codegen/c.zig
parent55c3551bef9eb2ae882e8b2c811672ee64b60a70 (diff)
downloadzig-f07d33f54b3448019f5e7c74c1f9063a5079b961.tar.gz
zig-f07d33f54b3448019f5e7c74c1f9063a5079b961.zip
cbe: fixes for compiling zig2.c under msvc
- add zig_mul_i128 - render slice structs in static initializers without casts / c99 style init - add negative numbers and u128 to 128-bit multiply test
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig83
1 files changed, 60 insertions, 23 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 23d9e1093f..216366e576 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -320,7 +320,7 @@ pub const Function = struct {
try writer.writeAll("static ");
try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, alignment, .Complete);
try writer.writeAll(" = ");
- try f.object.dg.renderValue(writer, ty, val, .Initializer);
+ try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
try writer.writeAll(";\n ");
break :result decl_c_value;
} else CValue{ .constant = inst };
@@ -514,6 +514,7 @@ pub const DeclGen = struct {
ty: Type,
val: Value,
decl_index: Decl.Index,
+ location: ValueRenderLocation,
) error{ OutOfMemory, AnalysisFail }!void {
const decl = dg.module.declPtr(decl_index);
assert(decl.has_tv);
@@ -527,12 +528,16 @@ pub const DeclGen = struct {
inline for (.{ .function, .extern_fn }) |tag|
if (decl.val.castTag(tag)) |func|
if (func.data.owner_decl != decl_index)
- return dg.renderDeclValue(writer, ty, val, func.data.owner_decl);
+ return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location);
if (ty.isSlice()) {
- try writer.writeByte('(');
- try dg.renderTypecast(writer, ty);
- try writer.writeAll("){ .ptr = ");
+ if (location == .StaticInitializer) {
+ try writer.writeByte('{');
+ } else {
+ try writer.writeByte('(');
+ try dg.renderTypecast(writer, ty);
+ try writer.writeAll("){ .ptr = ");
+ }
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer);
@@ -542,7 +547,12 @@ pub const DeclGen = struct {
.data = val.sliceLen(dg.module),
};
const len_val = Value.initPayload(&len_pl.base);
- return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
+
+ if (location == .StaticInitializer) {
+ return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
+ } else {
+ return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
+ }
}
// We shouldn't cast C function pointers as this is UB (when you call
@@ -564,7 +574,7 @@ pub const DeclGen = struct {
// that its contents are defined with respect to.
//
// Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
- fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type) error{ OutOfMemory, AnalysisFail }!void {
+ fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void {
if (!ptr_ty.isSlice()) {
try writer.writeByte('(');
try dg.renderTypecast(writer, ptr_ty);
@@ -579,7 +589,7 @@ pub const DeclGen = struct {
.variable => ptr_val.castTag(.variable).?.data.owner_decl,
else => unreachable,
};
- try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index);
+ try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location);
},
.field_ptr => {
const ptr_info = ptr_ty.ptrInfo();
@@ -617,7 +627,7 @@ pub const DeclGen = struct {
try writer.writeAll("&((");
try dg.renderTypecast(writer, u8_ptr_ty);
try writer.writeByte(')');
- try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
+ try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location);
return writer.print(")[{}]", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)});
} else {
var host_pl = Type.Payload.Bits{
@@ -629,7 +639,7 @@ pub const DeclGen = struct {
try writer.writeByte('(');
try dg.renderTypecast(writer, ptr_ty);
try writer.writeByte(')');
- return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty);
+ return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty, location);
},
},
.Union => switch (container_ty.containerLayout()) {
@@ -638,7 +648,7 @@ pub const DeclGen = struct {
.ty = container_ty.unionFields().values()[index].ty,
},
.Packed => {
- return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty);
+ return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty, location);
},
},
.Pointer => field_info: {
@@ -657,7 +667,7 @@ pub const DeclGen = struct {
try dg.renderType(std.io.null_writer, field_ptr.container_ty, .Complete);
try writer.writeAll("&(");
- try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
+ try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location);
try writer.writeAll(")->");
switch (field_ptr.container_ty.tag()) {
.union_tagged, .union_safety_tagged => try writer.writeAll("payload."),
@@ -665,7 +675,7 @@ pub const DeclGen = struct {
}
try writer.print("{ }", .{fmtIdent(field_info.name)});
} else {
- try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
+ try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location);
}
},
.elem_ptr => {
@@ -677,7 +687,7 @@ pub const DeclGen = struct {
const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);
try writer.writeAll("&(");
- try dg.renderParentPtr(writer, elem_ptr.array_ptr, elem_ptr_ty);
+ try dg.renderParentPtr(writer, elem_ptr.array_ptr, elem_ptr_ty, location);
try writer.print(")[{d}]", .{elem_ptr.index});
},
.opt_payload_ptr, .eu_payload_ptr => {
@@ -692,7 +702,7 @@ pub const DeclGen = struct {
try dg.renderType(std.io.null_writer, payload_ptr.container_ty, .Complete);
try writer.writeAll("&(");
- try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty);
+ try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty, location);
try writer.writeAll(")->payload");
},
else => unreachable,
@@ -910,7 +920,7 @@ pub const DeclGen = struct {
.eu_payload_ptr,
.decl_ref_mut,
.decl_ref,
- => try dg.renderParentPtr(writer, val, ty),
+ => try dg.renderParentPtr(writer, val, ty, location),
else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),
},
.Float => {
@@ -1024,7 +1034,7 @@ pub const DeclGen = struct {
},
.variable => {
const decl = val.castTag(.variable).?.data.owner_decl;
- return dg.renderDeclValue(writer, ty, val, decl);
+ return dg.renderDeclValue(writer, ty, val, decl, location);
},
.slice => {
if (!location.isInitializer()) {
@@ -1061,7 +1071,7 @@ pub const DeclGen = struct {
.eu_payload_ptr,
.decl_ref_mut,
.decl_ref,
- => try dg.renderParentPtr(writer, val, ty),
+ => try dg.renderParentPtr(writer, val, ty, location),
else => unreachable,
},
.Array, .Vector => {
@@ -1255,11 +1265,11 @@ pub const DeclGen = struct {
.Fn => switch (val.tag()) {
.function => {
const decl = val.castTag(.function).?.data.owner_decl;
- return dg.renderDeclValue(writer, ty, val, decl);
+ return dg.renderDeclValue(writer, ty, val, decl, location);
},
.extern_fn => {
const decl = val.castTag(.extern_fn).?.data.owner_decl;
- return dg.renderDeclValue(writer, ty, val, decl);
+ return dg.renderDeclValue(writer, ty, val, decl, location);
},
else => unreachable,
},
@@ -2512,6 +2522,9 @@ pub const DeclGen = struct {
try dg.writeCValue(writer, member);
}
+ const IdentHasher = std.crypto.auth.siphash.SipHash128(1, 3);
+ const ident_hasher_init: IdentHasher = IdentHasher.init(&[_]u8{0} ** IdentHasher.key_length);
+
fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
const decl = dg.module.declPtr(decl_index);
dg.module.markDeclAlive(decl);
@@ -2529,7 +2542,18 @@ pub const DeclGen = struct {
const gpa = dg.gpa;
const name = try decl.getFullyQualifiedName(dg.module);
defer gpa.free(name);
- return writer.print("{}", .{fmtIdent(name)});
+
+ // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), expand
+ // to 3x the length of its input
+ if (name.len > 1365) {
+ var hash = ident_hasher_init;
+ hash.update(name);
+ const ident_hash = hash.finalInt();
+ try writer.writeAll("zig_D_");
+ return std.fmt.formatIntValue(ident_hash, "x", .{}, writer);
+ } else {
+ return writer.print("{}", .{fmtIdent(name)});
+ }
}
}
@@ -4648,7 +4672,15 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
try f.writeCValue(writer, cond, .Other);
try writer.writeAll(") ");
try genBody(f, then_body);
- try writer.writeAll(" else ");
+
+ // TODO: If body ends in goto, elide the else block?
+ const needs_else = then_body.len <= 0 or f.air.instructions.items(.tag)[then_body[then_body.len - 1]] != .br;
+ if (needs_else) {
+ try writer.writeAll(" else ");
+ } else {
+ try writer.writeByte('\n');
+ }
+
f.value_map.deinit();
f.value_map = cloned_map.move();
const free_locals = f.getFreeLocals();
@@ -4661,7 +4693,12 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
try noticeBranchFrees(f, pre_locals_len, inst);
- try genBody(f, else_body);
+ if (needs_else) {
+ try genBody(f, else_body);
+ } else {
+ try genBodyInner(f, else_body);
+ }
+
try f.object.indent_writer.insertNewline();
return CValue.none;