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) {...@@ -1465,6 +1465,11 @@ static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1465static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs); // TODO1465static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs); // TODO
1466#endif1466#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
1468static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {1473static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1469 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);1474 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
1470}1475}
src/codegen/c.zig+60-23
...@@ -320,7 +320,7 @@ pub const Function = struct {...@@ -320,7 +320,7 @@ pub const Function = struct {
320 try writer.writeAll("static ");320 try writer.writeAll("static ");
321 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, alignment, .Complete);321 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, alignment, .Complete);
322 try writer.writeAll(" = ");322 try writer.writeAll(" = ");
323 try f.object.dg.renderValue(writer, ty, val, .Initializer);323 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
324 try writer.writeAll(";\n ");324 try writer.writeAll(";\n ");
325 break :result decl_c_value;325 break :result decl_c_value;
326 } else CValue{ .constant = inst };326 } else CValue{ .constant = inst };
...@@ -514,6 +514,7 @@ pub const DeclGen = struct {...@@ -514,6 +514,7 @@ pub const DeclGen = struct {
514 ty: Type,514 ty: Type,
515 val: Value,515 val: Value,
516 decl_index: Decl.Index,516 decl_index: Decl.Index,
517 location: ValueRenderLocation,
517 ) error{ OutOfMemory, AnalysisFail }!void {518 ) error{ OutOfMemory, AnalysisFail }!void {
518 const decl = dg.module.declPtr(decl_index);519 const decl = dg.module.declPtr(decl_index);
519 assert(decl.has_tv);520 assert(decl.has_tv);
...@@ -527,12 +528,16 @@ pub const DeclGen = struct {...@@ -527,12 +528,16 @@ pub const DeclGen = struct {
527 inline for (.{ .function, .extern_fn }) |tag|528 inline for (.{ .function, .extern_fn }) |tag|
528 if (decl.val.castTag(tag)) |func|529 if (decl.val.castTag(tag)) |func|
529 if (func.data.owner_decl != decl_index)530 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
532 if (ty.isSlice()) {533 if (ty.isSlice()) {
533 try writer.writeByte('(');534 if (location == .StaticInitializer) {
534 try dg.renderTypecast(writer, ty);535 try writer.writeByte('{');
535 try writer.writeAll("){ .ptr = ");536 } else {
537 try writer.writeByte('(');
538 try dg.renderTypecast(writer, ty);
539 try writer.writeAll("){ .ptr = ");
540 }
536541
537 var buf: Type.SlicePtrFieldTypeBuffer = undefined;542 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
538 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer);543 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer);
...@@ -542,7 +547,12 @@ pub const DeclGen = struct {...@@ -542,7 +547,12 @@ pub const DeclGen = struct {
542 .data = val.sliceLen(dg.module),547 .data = val.sliceLen(dg.module),
543 };548 };
544 const len_val = Value.initPayload(&len_pl.base);549 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 }
546 }556 }
547557
548 // We shouldn't cast C function pointers as this is UB (when you call558 // We shouldn't cast C function pointers as this is UB (when you call
...@@ -564,7 +574,7 @@ pub const DeclGen = struct {...@@ -564,7 +574,7 @@ pub const DeclGen = struct {
564 // that its contents are defined with respect to.574 // that its contents are defined with respect to.
565 //575 //
566 // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr576 // 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 {
568 if (!ptr_ty.isSlice()) {578 if (!ptr_ty.isSlice()) {
569 try writer.writeByte('(');579 try writer.writeByte('(');
570 try dg.renderTypecast(writer, ptr_ty);580 try dg.renderTypecast(writer, ptr_ty);
...@@ -579,7 +589,7 @@ pub const DeclGen = struct {...@@ -579,7 +589,7 @@ pub const DeclGen = struct {
579 .variable => ptr_val.castTag(.variable).?.data.owner_decl,589 .variable => ptr_val.castTag(.variable).?.data.owner_decl,
580 else => unreachable,590 else => unreachable,
581 };591 };
582 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index);592 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location);
583 },593 },
584 .field_ptr => {594 .field_ptr => {
585 const ptr_info = ptr_ty.ptrInfo();595 const ptr_info = ptr_ty.ptrInfo();
...@@ -617,7 +627,7 @@ pub const DeclGen = struct {...@@ -617,7 +627,7 @@ pub const DeclGen = struct {
617 try writer.writeAll("&((");627 try writer.writeAll("&((");
618 try dg.renderTypecast(writer, u8_ptr_ty);628 try dg.renderTypecast(writer, u8_ptr_ty);
619 try writer.writeByte(')');629 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);
621 return writer.print(")[{}]", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)});631 return writer.print(")[{}]", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)});
622 } else {632 } else {
623 var host_pl = Type.Payload.Bits{633 var host_pl = Type.Payload.Bits{
...@@ -629,7 +639,7 @@ pub const DeclGen = struct {...@@ -629,7 +639,7 @@ pub const DeclGen = struct {
629 try writer.writeByte('(');639 try writer.writeByte('(');
630 try dg.renderTypecast(writer, ptr_ty);640 try dg.renderTypecast(writer, ptr_ty);
631 try writer.writeByte(')');641 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);
633 },643 },
634 },644 },
635 .Union => switch (container_ty.containerLayout()) {645 .Union => switch (container_ty.containerLayout()) {
...@@ -638,7 +648,7 @@ pub const DeclGen = struct {...@@ -638,7 +648,7 @@ pub const DeclGen = struct {
638 .ty = container_ty.unionFields().values()[index].ty,648 .ty = container_ty.unionFields().values()[index].ty,
639 },649 },
640 .Packed => {650 .Packed => {
641 return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty);651 return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty, location);
642 },652 },
643 },653 },
644 .Pointer => field_info: {654 .Pointer => field_info: {
...@@ -657,7 +667,7 @@ pub const DeclGen = struct {...@@ -657,7 +667,7 @@ pub const DeclGen = struct {
657 try dg.renderType(std.io.null_writer, field_ptr.container_ty, .Complete);667 try dg.renderType(std.io.null_writer, field_ptr.container_ty, .Complete);
658668
659 try writer.writeAll("&(");669 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);
661 try writer.writeAll(")->");671 try writer.writeAll(")->");
662 switch (field_ptr.container_ty.tag()) {672 switch (field_ptr.container_ty.tag()) {
663 .union_tagged, .union_safety_tagged => try writer.writeAll("payload."),673 .union_tagged, .union_safety_tagged => try writer.writeAll("payload."),
...@@ -665,7 +675,7 @@ pub const DeclGen = struct {...@@ -665,7 +675,7 @@ pub const DeclGen = struct {
665 }675 }
666 try writer.print("{ }", .{fmtIdent(field_info.name)});676 try writer.print("{ }", .{fmtIdent(field_info.name)});
667 } else {677 } 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);
669 }679 }
670 },680 },
671 .elem_ptr => {681 .elem_ptr => {
...@@ -677,7 +687,7 @@ pub const DeclGen = struct {...@@ -677,7 +687,7 @@ pub const DeclGen = struct {
677 const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);687 const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);
678688
679 try writer.writeAll("&(");689 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);
681 try writer.print(")[{d}]", .{elem_ptr.index});691 try writer.print(")[{d}]", .{elem_ptr.index});
682 },692 },
683 .opt_payload_ptr, .eu_payload_ptr => {693 .opt_payload_ptr, .eu_payload_ptr => {
...@@ -692,7 +702,7 @@ pub const DeclGen = struct {...@@ -692,7 +702,7 @@ pub const DeclGen = struct {
692 try dg.renderType(std.io.null_writer, payload_ptr.container_ty, .Complete);702 try dg.renderType(std.io.null_writer, payload_ptr.container_ty, .Complete);
693703
694 try writer.writeAll("&(");704 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);
696 try writer.writeAll(")->payload");706 try writer.writeAll(")->payload");
697 },707 },
698 else => unreachable,708 else => unreachable,
...@@ -910,7 +920,7 @@ pub const DeclGen = struct {...@@ -910,7 +920,7 @@ pub const DeclGen = struct {
910 .eu_payload_ptr,920 .eu_payload_ptr,
911 .decl_ref_mut,921 .decl_ref_mut,
912 .decl_ref,922 .decl_ref,
913 => try dg.renderParentPtr(writer, val, ty),923 => try dg.renderParentPtr(writer, val, ty, location),
914 else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),924 else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),
915 },925 },
916 .Float => {926 .Float => {
...@@ -1024,7 +1034,7 @@ pub const DeclGen = struct {...@@ -1024,7 +1034,7 @@ pub const DeclGen = struct {
1024 },1034 },
1025 .variable => {1035 .variable => {
1026 const decl = val.castTag(.variable).?.data.owner_decl;1036 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);
1028 },1038 },
1029 .slice => {1039 .slice => {
1030 if (!location.isInitializer()) {1040 if (!location.isInitializer()) {
...@@ -1061,7 +1071,7 @@ pub const DeclGen = struct {...@@ -1061,7 +1071,7 @@ pub const DeclGen = struct {
1061 .eu_payload_ptr,1071 .eu_payload_ptr,
1062 .decl_ref_mut,1072 .decl_ref_mut,
1063 .decl_ref,1073 .decl_ref,
1064 => try dg.renderParentPtr(writer, val, ty),1074 => try dg.renderParentPtr(writer, val, ty, location),
1065 else => unreachable,1075 else => unreachable,
1066 },1076 },
1067 .Array, .Vector => {1077 .Array, .Vector => {
...@@ -1255,11 +1265,11 @@ pub const DeclGen = struct {...@@ -1255,11 +1265,11 @@ pub const DeclGen = struct {
1255 .Fn => switch (val.tag()) {1265 .Fn => switch (val.tag()) {
1256 .function => {1266 .function => {
1257 const decl = val.castTag(.function).?.data.owner_decl;1267 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);
1259 },1269 },
1260 .extern_fn => {1270 .extern_fn => {
1261 const decl = val.castTag(.extern_fn).?.data.owner_decl;1271 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);
1263 },1273 },
1264 else => unreachable,1274 else => unreachable,
1265 },1275 },
...@@ -2512,6 +2522,9 @@ pub const DeclGen = struct {...@@ -2512,6 +2522,9 @@ pub const DeclGen = struct {
2512 try dg.writeCValue(writer, member);2522 try dg.writeCValue(writer, member);
2513 }2523 }
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
2515 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {2528 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
2516 const decl = dg.module.declPtr(decl_index);2529 const decl = dg.module.declPtr(decl_index);
2517 dg.module.markDeclAlive(decl);2530 dg.module.markDeclAlive(decl);
...@@ -2529,7 +2542,18 @@ pub const DeclGen = struct {...@@ -2529,7 +2542,18 @@ pub const DeclGen = struct {
2529 const gpa = dg.gpa;2542 const gpa = dg.gpa;
2530 const name = try decl.getFullyQualifiedName(dg.module);2543 const name = try decl.getFullyQualifiedName(dg.module);
2531 defer gpa.free(name);2544 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 }
2533 }2557 }
2534 }2558 }
25352559
...@@ -4648,7 +4672,15 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4648,7 +4672,15 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4648 try f.writeCValue(writer, cond, .Other);4672 try f.writeCValue(writer, cond, .Other);
4649 try writer.writeAll(") ");4673 try writer.writeAll(") ");
4650 try genBody(f, then_body);4674 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
4652 f.value_map.deinit();4684 f.value_map.deinit();
4653 f.value_map = cloned_map.move();4685 f.value_map = cloned_map.move();
4654 const free_locals = f.getFreeLocals();4686 const free_locals = f.getFreeLocals();
...@@ -4661,7 +4693,12 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4661,7 +4693,12 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
46614693
4662 try noticeBranchFrees(f, pre_locals_len, inst);4694 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
4665 try f.object.indent_writer.insertNewline();4702 try f.object.indent_writer.insertNewline();
46664703
4667 return CValue.none;4704 return CValue.none;
test/behavior/math.zig+19-4
...@@ -632,10 +632,25 @@ test "128-bit multiplication" {...@@ -632,10 +632,25 @@ test "128-bit multiplication" {
632 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO632 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
633 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO633 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
634634
635 var a: i128 = 3;635 {
636 var b: i128 = 2;636 var a: i128 = 3;
637 var c = a * b;637 var b: i128 = 2;
638 try expect(c == 6);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
639}654}
640655
641test "@addWithOverflow" {656test "@addWithOverflow" {