| author | |
| committer | |
| log | 2fdf69bc4082c49a571c0ee7bb7441d910def795 |
| tree | 85777989a8f3976826612d50204aa655a2b4d8fd |
| parent | ac34841270d34fb2f47ada2960d7281328ec7b25 |
| parent | d669db76732a5137f9e37a22d08f5cba319a122d |
| signature |
Fixes c_ABI tests on windows5 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 | } |
| 6701 | 6701 | ||
| 6702 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) { | 6702 | static 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 | |||
| 6723 | static 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 | } |
| 6772 | 6790 | ||
| 6791 | X64CABIClass 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_64 | 6803 | // NOTE this does not depend on x86_64 |
| 6774 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { | 6804 | bool 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; |
| 374 | 374 | ||
| 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) { |
| 383 | 383 | 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); |
| 385 | 385 | 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 | } | ||
| 431 | 432 | ||
| 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(); |
| 567 | 574 | ||
| 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; |
| 570 | 578 | ||
| 571 | if (mod.mod_info.C13ByteSize == 0) | 579 | if (mod.mod_info.C13ByteSize == 0) |
| 572 | return error.MissingDebugInfo; | 580 | return; |
| 573 | 581 | ||
| 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; |
| 575 | 583 | ||
| ... | @@ -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; |
| 883 | 891 | ||
| 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 | } |
| 27 | 27 | ||
| 28 | if (!is_windows // TODO support compiling C files on windows with zig build system | 28 | 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); |
| 18 | void zig_i16(int16_t); | 18 | void zig_i16(int16_t); |
| 19 | void zig_i32(int32_t); | 19 | void zig_i32(int32_t); |
| 20 | void zig_i64(int64_t); | 20 | void zig_i64(int64_t); |
| 21 | void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t); | ||
| 21 | 22 | ||
| 22 | void zig_f32(float); | 23 | void zig_f32(float); |
| 23 | void zig_f64(double); | 24 | void zig_f64(double); |
| 25 | void zig_five_floats(float, float, float, float, float); | ||
| 24 | 26 | ||
| 25 | void zig_ptr(void *); | 27 | void zig_ptr(void *); |
| 26 | 28 | ||
| ... | @@ -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); | ||
| 74 | 77 | ||
| 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); | ||
| 77 | 81 | ||
| 78 | zig_ptr((void*)0xdeadbeefL); | 82 | zig_ptr((void*)0xdeadbeefL); |
| 79 | 83 | ||
| ... | @@ -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 | } |
| 158 | 162 | ||
| 163 | void 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 | |||
| 171 | void 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 | |||
| 159 | void c_array(uint8_t x[10]) { | 179 | void 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; |
| 20 | extern fn c_i32(i32) void; | 20 | extern fn c_i32(i32) void; |
| 21 | extern fn c_i64(i64) void; | 21 | extern fn c_i64(i64) void; |
| 22 | 22 | ||
| 23 | // On windows x64, the first 4 are passed via registers, others on the stack. | ||
| 24 | extern fn c_five_integers(i32, i32, i32, i32, i32) void; | ||
| 25 | |||
| 26 | export 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 | |||
| 23 | test "C ABI integers" { | 34 | test "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 | } |
| 34 | 46 | ||
| 35 | export fn zig_u8(x: u8) void { | 47 | export 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 { |
| 60 | extern fn c_f32(f32) void; | 72 | extern fn c_f32(f32) void; |
| 61 | extern fn c_f64(f64) void; | 73 | extern fn c_f64(f64) void; |
| 62 | 74 | ||
| 75 | // On windows x64, the first 4 are passed via registers, others on the stack. | ||
| 76 | extern fn c_five_floats(f32, f32, f32, f32, f32) void; | ||
| 77 | |||
| 78 | export 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 | |||
| 63 | test "C ABI floats" { | 86 | test "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 | } |
| 67 | 91 | ||
| 68 | export fn zig_f32(x: f32) void { | 92 | export fn zig_f32(x: f32) void { |