authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-20 00:11:11-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-03-20 00:11:11-04:00
log2fdf69bc4082c49a571c0ee7bb7441d910def795
tree85777989a8f3976826612d50204aa655a2b4d8fd
parentac34841270d34fb2f47ada2960d7281328ec7b25
parentd669db76732a5137f9e37a22d08f5cba319a122d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #2079 from Sahnvour/issue-2050

Fixes c_ABI tests on windows

5 files changed, 108 insertions(+), 27 deletions(-)

src/analyze.cpp+34-4
...@@ -6699,10 +6699,28 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {...@@ -6699,10 +6699,28 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {
6699 }6699 }
6700}6700}
67016701
6702X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {6702static X64CABIClass type_windows_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
6703 size_t ty_size = type_size(g, ty);6703 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
6704 if (get_codegen_ptr_type(ty) != nullptr)6704 switch (ty->id) {
6705 return X64CABIClass_INTEGER;6705 case ZigTypeIdEnum:
6706 case ZigTypeIdInt:
6707 case ZigTypeIdBool:
6708 return X64CABIClass_INTEGER;
6709 case ZigTypeIdFloat:
6710 case ZigTypeIdVector:
6711 return X64CABIClass_SSE;
6712 case ZigTypeIdStruct:
6713 case ZigTypeIdUnion: {
6714 if (ty_size <= 8)
6715 return X64CABIClass_INTEGER;
6716 return X64CABIClass_MEMORY;
6717 }
6718 default:
6719 return X64CABIClass_Unknown;
6720 }
6721}
6722
6723static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
6706 switch (ty->id) {6724 switch (ty->id) {
6707 case ZigTypeIdEnum:6725 case ZigTypeIdEnum:
6708 case ZigTypeIdInt:6726 case ZigTypeIdInt:
...@@ -6770,6 +6788,18 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {...@@ -6770,6 +6788,18 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
6770 }6788 }
6771}6789}
67726790
6791X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
6792 const size_t ty_size = type_size(g, ty);
6793 if (get_codegen_ptr_type(ty) != nullptr)
6794 return X64CABIClass_INTEGER;
6795
6796 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
6797 return type_windows_abi_x86_64_class(g, ty, ty_size);
6798 } else {
6799 return type_system_V_abi_x86_64_class(g, ty, ty_size);
6800 }
6801}
6802
6773// NOTE this does not depend on x86_646803// NOTE this does not depend on x86_64
6774bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {6804bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
6775 return (ty->id == ZigTypeIdInt ||6805 return (ty->id == ZigTypeIdInt ||
std/debug.zig+29-20
...@@ -372,18 +372,20 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -372,18 +372,20 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
372 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;372 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
373 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;373 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
374374
375 // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)375 if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {
376 // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,376 // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)
377 // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.377 // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,
378 const subsection_end_index = sect_offset + subsect_hdr.Length;378 // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.
379 while (line_index < subsection_end_index) {379
380 const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);380 const subsection_end_index = sect_offset + subsect_hdr.Length;
381 line_index += @sizeOf(pdb.LineBlockFragmentHeader);381
382 const start_line_index = line_index;382 while (line_index < subsection_end_index) {
383383 const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);
384 const has_column = line_hdr.Flags.LF_HaveColumns;384 line_index += @sizeOf(pdb.LineBlockFragmentHeader);
385385 const start_line_index = line_index;
386 if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {386
387 const has_column = line_hdr.Flags.LF_HaveColumns;
388
387 // All line entries are stored inside their line block by ascending start address.389 // All line entries are stored inside their line block by ascending start address.
388 // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address.390 // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address.
389 // This is done with a simple linear search.391 // This is done with a simple linear search.
...@@ -427,11 +429,11 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -427,11 +429,11 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
427 };429 };
428 }430 }
429 }431 }
430 }
431432
432 // Checking that we are not reading garbage after the (possibly) multiple block fragments.433 // Checking that we are not reading garbage after the (possibly) multiple block fragments.
433 if (line_index != subsection_end_index) {434 if (line_index != subsection_end_index) {
434 return error.InvalidDebugInfo;435 return error.InvalidDebugInfo;
436 }
435 }437 }
436 },438 },
437 else => {},439 else => {},
...@@ -476,6 +478,11 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -476,6 +478,11 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
476 }478 }
477 } else |err| switch (err) {479 } else |err| switch (err) {
478 error.EndOfFile => {},480 error.EndOfFile => {},
481 error.FileNotFound => {
482 setTtyColor(TtyColor.Dim);
483 try out_stream.write("file not found\n\n");
484 setTtyColor(TtyColor.White);
485 },
479 else => return err,486 else => return err,
480 }487 }
481 } else {488 } else {
...@@ -565,11 +572,12 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {...@@ -565,11 +572,12 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
565 return;572 return;
566 const allocator = getDebugInfoAllocator();573 const allocator = getDebugInfoAllocator();
567574
568 if (mod.mod_info.C11ByteSize != 0)575 // At most one can be non-zero.
576 if (mod.mod_info.C11ByteSize != 0 and mod.mod_info.C13ByteSize != 0)
569 return error.InvalidDebugInfo;577 return error.InvalidDebugInfo;
570578
571 if (mod.mod_info.C13ByteSize == 0)579 if (mod.mod_info.C13ByteSize == 0)
572 return error.MissingDebugInfo;580 return;
573581
574 const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;582 const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
575583
...@@ -881,8 +889,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -881,8 +889,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
881 const obj_file_name = try dbi.readNullTermString(allocator);889 const obj_file_name = try dbi.readNullTermString(allocator);
882 this_record_len += obj_file_name.len + 1;890 this_record_len += obj_file_name.len + 1;
883891
884 const march_forward_bytes = this_record_len % 4;892 if (this_record_len % 4 != 0) {
885 if (march_forward_bytes != 0) {893 const round_to_next_4 = (this_record_len | 0x3) + 1;
894 const march_forward_bytes = round_to_next_4 - this_record_len;
886 try dbi.seekForward(march_forward_bytes);895 try dbi.seekForward(march_forward_bytes);
887 this_record_len += march_forward_bytes;896 this_record_len += march_forward_bytes;
888 }897 }
test/build_examples.zig+1-3
...@@ -25,9 +25,7 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {...@@ -25,9 +25,7 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
25 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");25 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
26 }26 }
2727
28 if (!is_windows // TODO support compiling C files on windows with zig build system28 if (builtin.arch == builtin.Arch.x86_64) { // TODO add C ABI support for other architectures
29 and builtin.arch == builtin.Arch.x86_64 // TODO add C ABI support for other architectures
30 ) {
31 cases.addBuildFile("test/stage1/c_abi/build.zig");29 cases.addBuildFile("test/stage1/c_abi/build.zig");
32 }30 }
33}31}
test/stage1/c_abi/cfuncs.c+20
...@@ -18,9 +18,11 @@ void zig_i8(int8_t);...@@ -18,9 +18,11 @@ void zig_i8(int8_t);
18void zig_i16(int16_t);18void zig_i16(int16_t);
19void zig_i32(int32_t);19void zig_i32(int32_t);
20void zig_i64(int64_t);20void zig_i64(int64_t);
21void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);
2122
22void zig_f32(float);23void zig_f32(float);
23void zig_f64(double);24void zig_f64(double);
25void zig_five_floats(float, float, float, float, float);
2426
25void zig_ptr(void *);27void zig_ptr(void *);
2628
...@@ -71,9 +73,11 @@ void run_c_tests(void) {...@@ -71,9 +73,11 @@ void run_c_tests(void) {
71 zig_i16(-2);73 zig_i16(-2);
72 zig_i32(-3);74 zig_i32(-3);
73 zig_i64(-4);75 zig_i64(-4);
76 zig_five_integers(12, 34, 56, 78, 90);
7477
75 zig_f32(12.34f);78 zig_f32(12.34f);
76 zig_f64(56.78);79 zig_f64(56.78);
80 zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f);
7781
78 zig_ptr((void*)0xdeadbeefL);82 zig_ptr((void*)0xdeadbeefL);
7983
...@@ -156,6 +160,22 @@ void c_bool(bool x) {...@@ -156,6 +160,22 @@ void c_bool(bool x) {
156 assert_or_panic(x);160 assert_or_panic(x);
157}161}
158162
163void c_five_integers(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e) {
164 assert_or_panic(a == 12);
165 assert_or_panic(b == 34);
166 assert_or_panic(c == 56);
167 assert_or_panic(d == 78);
168 assert_or_panic(e == 90);
169}
170
171void c_five_floats(float a, float b, float c, float d, float e) {
172 assert_or_panic(a == 1.0);
173 assert_or_panic(b == 2.0);
174 assert_or_panic(c == 3.0);
175 assert_or_panic(d == 4.0);
176 assert_or_panic(e == 5.0);
177}
178
159void c_array(uint8_t x[10]) {179void c_array(uint8_t x[10]) {
160 assert_or_panic(x[0] == '1');180 assert_or_panic(x[0] == '1');
161 assert_or_panic(x[1] == '2');181 assert_or_panic(x[1] == '2');
test/stage1/c_abi/main.zig+24
...@@ -20,6 +20,17 @@ extern fn c_i16(i16) void;...@@ -20,6 +20,17 @@ extern fn c_i16(i16) void;
20extern fn c_i32(i32) void;20extern fn c_i32(i32) void;
21extern fn c_i64(i64) void;21extern fn c_i64(i64) void;
2222
23// On windows x64, the first 4 are passed via registers, others on the stack.
24extern fn c_five_integers(i32, i32, i32, i32, i32) void;
25
26export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {
27 expect(a == 12);
28 expect(b == 34);
29 expect(c == 56);
30 expect(d == 78);
31 expect(e == 90);
32}
33
23test "C ABI integers" {34test "C ABI integers" {
24 c_u8(0xff);35 c_u8(0xff);
25 c_u16(0xfffe);36 c_u16(0xfffe);
...@@ -30,6 +41,7 @@ test "C ABI integers" {...@@ -30,6 +41,7 @@ test "C ABI integers" {
30 c_i16(-2);41 c_i16(-2);
31 c_i32(-3);42 c_i32(-3);
32 c_i64(-4);43 c_i64(-4);
44 c_five_integers(12, 34, 56, 78, 90);
33}45}
3446
35export fn zig_u8(x: u8) void {47export fn zig_u8(x: u8) void {
...@@ -60,9 +72,21 @@ export fn zig_i64(x: i64) void {...@@ -60,9 +72,21 @@ export fn zig_i64(x: i64) void {
60extern fn c_f32(f32) void;72extern fn c_f32(f32) void;
61extern fn c_f64(f64) void;73extern fn c_f64(f64) void;
6274
75// On windows x64, the first 4 are passed via registers, others on the stack.
76extern fn c_five_floats(f32, f32, f32, f32, f32) void;
77
78export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void {
79 expect(a == 1.0);
80 expect(b == 2.0);
81 expect(c == 3.0);
82 expect(d == 4.0);
83 expect(e == 5.0);
84}
85
63test "C ABI floats" {86test "C ABI floats" {
64 c_f32(12.34);87 c_f32(12.34);
65 c_f64(56.78);88 c_f64(56.78);
89 c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0);
66}90}
6791
68export fn zig_f32(x: f32) void {92export fn zig_f32(x: f32) void {