| 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 | 6699 | } |
| 6700 | 6700 | } |
| 6701 | 6701 | |
| 6702 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) { | |
| 6703 | size_t ty_size = type_size(g, ty); | |
| 6704 | if (get_codegen_ptr_type(ty) != nullptr) | |
| 6705 | return X64CABIClass_INTEGER; | |
| 6702 | static X64CABIClass type_windows_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) { | |
| 6703 | // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 | |
| 6704 | switch (ty->id) { | |
| 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 | 6724 | switch (ty->id) { |
| 6707 | 6725 | case ZigTypeIdEnum: |
| 6708 | 6726 | case ZigTypeIdInt: |
| ... | ... | @@ -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 | 6803 | // NOTE this does not depend on x86_64 |
| 6774 | 6804 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { |
| 6775 | 6805 | return (ty->id == ZigTypeIdInt || |
std/debug.zig+29-20| ... | ... | @@ -372,18 +372,20 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 372 | 372 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; |
| 373 | 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) | |
| 376 | // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, | |
| 377 | // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. | |
| 378 | const subsection_end_index = sect_offset + subsect_hdr.Length; | |
| 379 | while (line_index < subsection_end_index) { | |
| 380 | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); | |
| 381 | line_index += @sizeOf(pdb.LineBlockFragmentHeader); | |
| 382 | const start_line_index = line_index; | |
| 383 | ||
| 384 | const has_column = line_hdr.Flags.LF_HaveColumns; | |
| 385 | ||
| 386 | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { | |
| 375 | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { | |
| 376 | // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) | |
| 377 | // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, | |
| 378 | // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. | |
| 379 | ||
| 380 | const subsection_end_index = sect_offset + subsect_hdr.Length; | |
| 381 | ||
| 382 | while (line_index < subsection_end_index) { | |
| 383 | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); | |
| 384 | line_index += @sizeOf(pdb.LineBlockFragmentHeader); | |
| 385 | const start_line_index = line_index; | |
| 386 | ||
| 387 | const has_column = line_hdr.Flags.LF_HaveColumns; | |
| 388 | ||
| 387 | 389 | // All line entries are stored inside their line block by ascending start address. |
| 388 | 390 | // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address. |
| 389 | 391 | // This is done with a simple linear search. |
| ... | ... | @@ -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 | if (line_index != subsection_end_index) { | |
| 434 | return error.InvalidDebugInfo; | |
| 433 | // Checking that we are not reading garbage after the (possibly) multiple block fragments. | |
| 434 | if (line_index != subsection_end_index) { | |
| 435 | return error.InvalidDebugInfo; | |
| 436 | } | |
| 435 | 437 | } |
| 436 | 438 | }, |
| 437 | 439 | else => {}, |
| ... | ... | @@ -476,6 +478,11 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 476 | 478 | } |
| 477 | 479 | } else |err| switch (err) { |
| 478 | 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 | 486 | else => return err, |
| 480 | 487 | } |
| 481 | 488 | } else { |
| ... | ... | @@ -565,11 +572,12 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { |
| 565 | 572 | return; |
| 566 | 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 | 577 | return error.InvalidDebugInfo; |
| 570 | 578 | |
| 571 | 579 | if (mod.mod_info.C13ByteSize == 0) |
| 572 | return error.MissingDebugInfo; | |
| 580 | return; | |
| 573 | 581 | |
| 574 | 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 | 889 | const obj_file_name = try dbi.readNullTermString(allocator); |
| 882 | 890 | this_record_len += obj_file_name.len + 1; |
| 883 | 891 | |
| 884 | const march_forward_bytes = this_record_len % 4; | |
| 885 | if (march_forward_bytes != 0) { | |
| 892 | if (this_record_len % 4 != 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 | 895 | try dbi.seekForward(march_forward_bytes); |
| 887 | 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 | 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 | |
| 29 | and builtin.arch == builtin.Arch.x86_64 // TODO add C ABI support for other architectures | |
| 30 | ) { | |
| 28 | if (builtin.arch == builtin.Arch.x86_64) { // TODO add C ABI support for other architectures | |
| 31 | 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 | 18 | void zig_i16(int16_t); |
| 19 | 19 | void zig_i32(int32_t); |
| 20 | 20 | void zig_i64(int64_t); |
| 21 | void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t); | |
| 21 | 22 | |
| 22 | 23 | void zig_f32(float); |
| 23 | 24 | void zig_f64(double); |
| 25 | void zig_five_floats(float, float, float, float, float); | |
| 24 | 26 | |
| 25 | 27 | void zig_ptr(void *); |
| 26 | 28 | |
| ... | ... | @@ -71,9 +73,11 @@ void run_c_tests(void) { |
| 71 | 73 | zig_i16(-2); |
| 72 | 74 | zig_i32(-3); |
| 73 | 75 | zig_i64(-4); |
| 76 | zig_five_integers(12, 34, 56, 78, 90); | |
| 74 | 77 | |
| 75 | 78 | zig_f32(12.34f); |
| 76 | 79 | zig_f64(56.78); |
| 80 | zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f); | |
| 77 | 81 | |
| 78 | 82 | zig_ptr((void*)0xdeadbeefL); |
| 79 | 83 | |
| ... | ... | @@ -156,6 +160,22 @@ void c_bool(bool x) { |
| 156 | 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 | 179 | void c_array(uint8_t x[10]) { |
| 160 | 180 | assert_or_panic(x[0] == '1'); |
| 161 | 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 | 20 | extern fn c_i32(i32) void; |
| 21 | 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 | 34 | test "C ABI integers" { |
| 24 | 35 | c_u8(0xff); |
| 25 | 36 | c_u16(0xfffe); |
| ... | ... | @@ -30,6 +41,7 @@ test "C ABI integers" { |
| 30 | 41 | c_i16(-2); |
| 31 | 42 | c_i32(-3); |
| 32 | 43 | c_i64(-4); |
| 44 | c_five_integers(12, 34, 56, 78, 90); | |
| 33 | 45 | } |
| 34 | 46 | |
| 35 | 47 | export fn zig_u8(x: u8) void { |
| ... | ... | @@ -60,9 +72,21 @@ export fn zig_i64(x: i64) void { |
| 60 | 72 | extern fn c_f32(f32) void; |
| 61 | 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 | 86 | test "C ABI floats" { |
| 64 | 87 | c_f32(12.34); |
| 65 | 88 | c_f64(56.78); |
| 89 | c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0); | |
| 66 | 90 | } |
| 67 | 91 | |
| 68 | 92 | export fn zig_f32(x: f32) void { |