authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2022-12-23 23:48:44-05:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-01-01 16:44:29-05:00
logf07d33f54b3448019f5e7c74c1f9063a5079b961
tree786540e287a1e01af2a01b98f61153416c3da01c
parent55c3551bef9eb2ae882e8b2c811672ee64b60a70

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

3 files changed, 84 insertions(+), 27 deletions(-)

lib/zig.h+5
......@@ -1465,6 +1465,11 @@ static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
14651465static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs); // TODO
14661466#endif
14671467
1468zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
1469static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1470 return __multi3(lhs, rhs);
1471}
1472
14681473static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
14691474 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
14701475}
src/codegen/c.zig+60-23
......@@ -320,7 +320,7 @@ pub const Function = struct {
320320 try writer.writeAll("static ");
321321 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, alignment, .Complete);
322322 try writer.writeAll(" = ");
323 try f.object.dg.renderValue(writer, ty, val, .Initializer);
323 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
324324 try writer.writeAll(";\n ");
325325 break :result decl_c_value;
326326 } else CValue{ .constant = inst };
......@@ -514,6 +514,7 @@ pub const DeclGen = struct {
514514 ty: Type,
515515 val: Value,
516516 decl_index: Decl.Index,
517 location: ValueRenderLocation,
517518 ) error{ OutOfMemory, AnalysisFail }!void {
518519 const decl = dg.module.declPtr(decl_index);
519520 assert(decl.has_tv);
......@@ -527,12 +528,16 @@ pub const DeclGen = struct {
527528 inline for (.{ .function, .extern_fn }) |tag|
528529 if (decl.val.castTag(tag)) |func|
529530 if (func.data.owner_decl != decl_index)
530 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl);
531 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location);
531532
532533 if (ty.isSlice()) {
533 try writer.writeByte('(');
534 try dg.renderTypecast(writer, ty);
535 try writer.writeAll("){ .ptr = ");
534 if (location == .StaticInitializer) {
535 try writer.writeByte('{');
536 } else {
537 try writer.writeByte('(');
538 try dg.renderTypecast(writer, ty);
539 try writer.writeAll("){ .ptr = ");
540 }
536541
537542 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
538543 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer);
......@@ -542,7 +547,12 @@ pub const DeclGen = struct {
542547 .data = val.sliceLen(dg.module),
543548 };
544549 const len_val = Value.initPayload(&len_pl.base);
545 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
550
551 if (location == .StaticInitializer) {
552 return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
553 } else {
554 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
555 }
546556 }
547557
548558 // We shouldn't cast C function pointers as this is UB (when you call
......@@ -564,7 +574,7 @@ pub const DeclGen = struct {
564574 // that its contents are defined with respect to.
565575 //
566576 // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
567 fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type) error{ OutOfMemory, AnalysisFail }!void {
577 fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void {
568578 if (!ptr_ty.isSlice()) {
569579 try writer.writeByte('(');
570580 try dg.renderTypecast(writer, ptr_ty);
......@@ -579,7 +589,7 @@ pub const DeclGen = struct {
579589 .variable => ptr_val.castTag(.variable).?.data.owner_decl,
580590 else => unreachable,
581591 };
582 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index);
592 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location);
583593 },
584594 .field_ptr => {
585595 const ptr_info = ptr_ty.ptrInfo();
......@@ -617,7 +627,7 @@ pub const DeclGen = struct {
617627 try writer.writeAll("&((");
618628 try dg.renderTypecast(writer, u8_ptr_ty);
619629 try writer.writeByte(')');
620 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
630 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location);
621631 return writer.print(")[{}]", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)});
622632 } else {
623633 var host_pl = Type.Payload.Bits{
......@@ -629,7 +639,7 @@ pub const DeclGen = struct {
629639 try writer.writeByte('(');
630640 try dg.renderTypecast(writer, ptr_ty);
631641 try writer.writeByte(')');
632 return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty);
642 return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty, location);
633643 },
634644 },
635645 .Union => switch (container_ty.containerLayout()) {
......@@ -638,7 +648,7 @@ pub const DeclGen = struct {
638648 .ty = container_ty.unionFields().values()[index].ty,
639649 },
640650 .Packed => {
641 return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty);
651 return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty, location);
642652 },
643653 },
644654 .Pointer => field_info: {
......@@ -657,7 +667,7 @@ pub const DeclGen = struct {
657667 try dg.renderType(std.io.null_writer, field_ptr.container_ty, .Complete);
658668
659669 try writer.writeAll("&(");
660 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
670 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location);
661671 try writer.writeAll(")->");
662672 switch (field_ptr.container_ty.tag()) {
663673 .union_tagged, .union_safety_tagged => try writer.writeAll("payload."),
......@@ -665,7 +675,7 @@ pub const DeclGen = struct {
665675 }
666676 try writer.print("{ }", .{fmtIdent(field_info.name)});
667677 } else {
668 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
678 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location);
669679 }
670680 },
671681 .elem_ptr => {
......@@ -677,7 +687,7 @@ pub const DeclGen = struct {
677687 const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);
678688
679689 try writer.writeAll("&(");
680 try dg.renderParentPtr(writer, elem_ptr.array_ptr, elem_ptr_ty);
690 try dg.renderParentPtr(writer, elem_ptr.array_ptr, elem_ptr_ty, location);
681691 try writer.print(")[{d}]", .{elem_ptr.index});
682692 },
683693 .opt_payload_ptr, .eu_payload_ptr => {
......@@ -692,7 +702,7 @@ pub const DeclGen = struct {
692702 try dg.renderType(std.io.null_writer, payload_ptr.container_ty, .Complete);
693703
694704 try writer.writeAll("&(");
695 try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty);
705 try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty, location);
696706 try writer.writeAll(")->payload");
697707 },
698708 else => unreachable,
......@@ -910,7 +920,7 @@ pub const DeclGen = struct {
910920 .eu_payload_ptr,
911921 .decl_ref_mut,
912922 .decl_ref,
913 => try dg.renderParentPtr(writer, val, ty),
923 => try dg.renderParentPtr(writer, val, ty, location),
914924 else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),
915925 },
916926 .Float => {
......@@ -1024,7 +1034,7 @@ pub const DeclGen = struct {
10241034 },
10251035 .variable => {
10261036 const decl = val.castTag(.variable).?.data.owner_decl;
1027 return dg.renderDeclValue(writer, ty, val, decl);
1037 return dg.renderDeclValue(writer, ty, val, decl, location);
10281038 },
10291039 .slice => {
10301040 if (!location.isInitializer()) {
......@@ -1061,7 +1071,7 @@ pub const DeclGen = struct {
10611071 .eu_payload_ptr,
10621072 .decl_ref_mut,
10631073 .decl_ref,
1064 => try dg.renderParentPtr(writer, val, ty),
1074 => try dg.renderParentPtr(writer, val, ty, location),
10651075 else => unreachable,
10661076 },
10671077 .Array, .Vector => {
......@@ -1255,11 +1265,11 @@ pub const DeclGen = struct {
12551265 .Fn => switch (val.tag()) {
12561266 .function => {
12571267 const decl = val.castTag(.function).?.data.owner_decl;
1258 return dg.renderDeclValue(writer, ty, val, decl);
1268 return dg.renderDeclValue(writer, ty, val, decl, location);
12591269 },
12601270 .extern_fn => {
12611271 const decl = val.castTag(.extern_fn).?.data.owner_decl;
1262 return dg.renderDeclValue(writer, ty, val, decl);
1272 return dg.renderDeclValue(writer, ty, val, decl, location);
12631273 },
12641274 else => unreachable,
12651275 },
......@@ -2512,6 +2522,9 @@ pub const DeclGen = struct {
25122522 try dg.writeCValue(writer, member);
25132523 }
25142524
2525 const IdentHasher = std.crypto.auth.siphash.SipHash128(1, 3);
2526 const ident_hasher_init: IdentHasher = IdentHasher.init(&[_]u8{0} ** IdentHasher.key_length);
2527
25152528 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
25162529 const decl = dg.module.declPtr(decl_index);
25172530 dg.module.markDeclAlive(decl);
......@@ -2529,7 +2542,18 @@ pub const DeclGen = struct {
25292542 const gpa = dg.gpa;
25302543 const name = try decl.getFullyQualifiedName(dg.module);
25312544 defer gpa.free(name);
2532 return writer.print("{}", .{fmtIdent(name)});
2545
2546 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), expand
2547 // to 3x the length of its input
2548 if (name.len > 1365) {
2549 var hash = ident_hasher_init;
2550 hash.update(name);
2551 const ident_hash = hash.finalInt();
2552 try writer.writeAll("zig_D_");
2553 return std.fmt.formatIntValue(ident_hash, "x", .{}, writer);
2554 } else {
2555 return writer.print("{}", .{fmtIdent(name)});
2556 }
25332557 }
25342558 }
25352559
......@@ -4648,7 +4672,15 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
46484672 try f.writeCValue(writer, cond, .Other);
46494673 try writer.writeAll(") ");
46504674 try genBody(f, then_body);
4651 try writer.writeAll(" else ");
4675
4676 // TODO: If body ends in goto, elide the else block?
4677 const needs_else = then_body.len <= 0 or f.air.instructions.items(.tag)[then_body[then_body.len - 1]] != .br;
4678 if (needs_else) {
4679 try writer.writeAll(" else ");
4680 } else {
4681 try writer.writeByte('\n');
4682 }
4683
46524684 f.value_map.deinit();
46534685 f.value_map = cloned_map.move();
46544686 const free_locals = f.getFreeLocals();
......@@ -4661,7 +4693,12 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
46614693
46624694 try noticeBranchFrees(f, pre_locals_len, inst);
46634695
4664 try genBody(f, else_body);
4696 if (needs_else) {
4697 try genBody(f, else_body);
4698 } else {
4699 try genBodyInner(f, else_body);
4700 }
4701
46654702 try f.object.indent_writer.insertNewline();
46664703
46674704 return CValue.none;
test/behavior/math.zig+19-4
......@@ -632,10 +632,25 @@ test "128-bit multiplication" {
632632 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
633633 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
634634
635 var a: i128 = 3;
636 var b: i128 = 2;
637 var c = a * b;
638 try expect(c == 6);
635 {
636 var a: i128 = 3;
637 var b: i128 = 2;
638 var c = a * b;
639 try expect(c == 6);
640
641 a = -3;
642 b = 2;
643 c = a * b;
644 try expect(c == -6);
645 }
646
647 {
648 var a: u128 = 0xffffffffffffffff;
649 var b: u128 = 100;
650 var c = a * b;
651 try expect(c == 0x63ffffffffffffff9c);
652 }
653
639654}
640655
641656test "@addWithOverflow" {