authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-13 14:35:03-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-13 14:35:03-07:00
loga4316d5505d3af1e868a3506787f31a9ae90085a
tree197b3e2b3da083de2494c85a29fbf938f314fba9
parent1f34c03ac14ac352ec03267ca8592dadfbd5e4bc
parent4e9894cfc4c8e2e1d3e01aa2e3400b295b0ee2df

Merge remote-tracking branch 'origin/master' into llvm12


7 files changed, 174 insertions(+), 16 deletions(-)

CMakeLists.txt+6-1
...@@ -87,10 +87,15 @@ option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)...@@ -87,10 +87,15 @@ option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)
87set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")87set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")
88set(ZIG_TARGET_MCPU "baseline" CACHE STRING "-mcpu parameter to output binaries for")88set(ZIG_TARGET_MCPU "baseline" CACHE STRING "-mcpu parameter to output binaries for")
89set(ZIG_EXECUTABLE "" CACHE STRING "(when cross compiling) path to already-built zig binary")89set(ZIG_EXECUTABLE "" CACHE STRING "(when cross compiling) path to already-built zig binary")
90set(ZIG_PREFER_LLVM_CONFIG off CACHE BOOL "(when cross compiling) use llvm-config to find target llvm dependencies if needed")
91set(ZIG_SINGLE_THREADED off CACHE BOOL "limit the zig compiler to use only 1 thread")90set(ZIG_SINGLE_THREADED off CACHE BOOL "limit the zig compiler to use only 1 thread")
92set(ZIG_OMIT_STAGE2 off CACHE BOOL "omit the stage2 backend from stage1")91set(ZIG_OMIT_STAGE2 off CACHE BOOL "omit the stage2 backend from stage1")
9392
93if("${ZIG_TARGET_TRIPLE}" STREQUAL "native")
94 set(ZIG_USE_LLVM_CONFIG ON CACHE BOOL "use llvm-config to find LLVM libraries")
95else()
96 set(ZIG_USE_LLVM_CONFIG OFF CACHE BOOL "use llvm-config to find LLVM libraries")
97endif()
98
94find_package(llvm)99find_package(llvm)
95find_package(clang)100find_package(clang)
96find_package(lld)101find_package(lld)
cmake/Findllvm.cmake+1-1
...@@ -63,7 +63,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB)...@@ -63,7 +63,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB)
63 if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 13)63 if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 13)
64 message(FATAL_ERROR "expected LLVM 12.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")64 message(FATAL_ERROR "expected LLVM 12.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
65 endif()65 endif()
66elseif(("${ZIG_TARGET_TRIPLE}" STREQUAL "native") OR ZIG_PREFER_LLVM_CONFIG)66elseif(ZIG_USE_LLVM_CONFIG)
67 find_program(LLVM_CONFIG_EXE67 find_program(LLVM_CONFIG_EXE
68 NAMES llvm-config-12 llvm-config-12.0 llvm-config120 llvm-config12 llvm-config68 NAMES llvm-config-12 llvm-config-12.0 llvm-config120 llvm-config12 llvm-config
69 PATHS69 PATHS
doc/langref.html.in+12-13
...@@ -684,7 +684,7 @@ pub fn main() void {...@@ -684,7 +684,7 @@ pub fn main() void {
684 {#header_close#}684 {#header_close#}
685 {#header_open|String Literals and Unicode Code Point Literals#}685 {#header_open|String Literals and Unicode Code Point Literals#}
686 <p>686 <p>
687 String literals are single-item constant {#link|Pointers#} to null-terminated byte arrays.687 String literals are constant single-item {#link|Pointers#} to null-terminated byte arrays.
688 The type of string literals encodes both the length, and the fact that they are null-terminated,688 The type of string literals encodes both the length, and the fact that they are null-terminated,
689 and thus they can be {#link|coerced|Type Coercion#} to both {#link|Slices#} and689 and thus they can be {#link|coerced|Type Coercion#} to both {#link|Slices#} and
690 {#link|Null-Terminated Pointers|Sentinel-Terminated Pointers#}.690 {#link|Null-Terminated Pointers|Sentinel-Terminated Pointers#}.
...@@ -1783,7 +1783,7 @@ comptime {...@@ -1783,7 +1783,7 @@ comptime {
1783 expect(message.len == 5);1783 expect(message.len == 5);
1784}1784}
17851785
1786// A string literal is a pointer to an array literal.1786// A string literal is a single-item pointer to an array literal.
1787const same_message = "hello";1787const same_message = "hello";
17881788
1789comptime {1789comptime {
...@@ -1989,15 +1989,15 @@ test "null terminated array" {...@@ -1989,15 +1989,15 @@ test "null terminated array" {
19891989
1990 {#header_open|Pointers#}1990 {#header_open|Pointers#}
1991 <p>1991 <p>
1992 Zig has two kinds of pointers:1992 Zig has two kinds of pointers: single-item and many-item.
1993 </p>1993 </p>
1994 <ul>1994 <ul>
1995 <li>{#syntax#}*T{#endsyntax#} - pointer to exactly one item.1995 <li>{#syntax#}*T{#endsyntax#} - single-item pointer to exactly one item.
1996 <ul>1996 <ul>
1997 <li>Supports deref syntax: {#syntax#}ptr.*{#endsyntax#}</li>1997 <li>Supports deref syntax: {#syntax#}ptr.*{#endsyntax#}</li>
1998 </ul>1998 </ul>
1999 </li>1999 </li>
2000 <li>{#syntax#}[*]T{#endsyntax#} - pointer to unknown number of items.2000 <li>{#syntax#}[*]T{#endsyntax#} - many-item pointer to unknown number of items.
2001 <ul>2001 <ul>
2002 <li>Supports index syntax: {#syntax#}ptr[i]{#endsyntax#}</li>2002 <li>Supports index syntax: {#syntax#}ptr[i]{#endsyntax#}</li>
2003 <li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}</li>2003 <li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}</li>
...@@ -2009,7 +2009,7 @@ test "null terminated array" {...@@ -2009,7 +2009,7 @@ test "null terminated array" {
2009 </ul>2009 </ul>
2010 <p>These types are closely related to {#link|Arrays#} and {#link|Slices#}:</p>2010 <p>These types are closely related to {#link|Arrays#} and {#link|Slices#}:</p>
2011 <ul>2011 <ul>
2012 <li>{#syntax#}*[N]T{#endsyntax#} - pointer to N items, same as single-item pointer to array.2012 <li>{#syntax#}*[N]T{#endsyntax#} - pointer to N items, same as single-item pointer to an array.
2013 <ul>2013 <ul>
2014 <li>Supports index syntax: {#syntax#}array_ptr[i]{#endsyntax#}</li>2014 <li>Supports index syntax: {#syntax#}array_ptr[i]{#endsyntax#}</li>
2015 <li>Supports slice syntax: {#syntax#}array_ptr[start..end]{#endsyntax#}</li>2015 <li>Supports slice syntax: {#syntax#}array_ptr[start..end]{#endsyntax#}</li>
...@@ -2038,7 +2038,7 @@ test "address of syntax" {...@@ -2038,7 +2038,7 @@ test "address of syntax" {
2038 // Dereference a pointer:2038 // Dereference a pointer:
2039 expect(x_ptr.* == 1234);2039 expect(x_ptr.* == 1234);
20402040
2041 // When you get the address of a const variable, you get a const pointer to a single item.2041 // When you get the address of a const variable, you get a const single-item pointer.
2042 expect(@TypeOf(x_ptr) == *const i32);2042 expect(@TypeOf(x_ptr) == *const i32);
20432043
2044 // If you want to mutate the value, you'd need an address of a mutable variable:2044 // If you want to mutate the value, you'd need an address of a mutable variable:
...@@ -2051,7 +2051,7 @@ test "address of syntax" {...@@ -2051,7 +2051,7 @@ test "address of syntax" {
20512051
2052test "pointer array access" {2052test "pointer array access" {
2053 // Taking an address of an individual element gives a2053 // Taking an address of an individual element gives a
2054 // pointer to a single item. This kind of pointer2054 // single-item pointer. This kind of pointer
2055 // does not support pointer arithmetic.2055 // does not support pointer arithmetic.
2056 var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };2056 var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
2057 const ptr = &array[2];2057 const ptr = &array[2];
...@@ -2320,8 +2320,8 @@ test "basic slices" {...@@ -2320,8 +2320,8 @@ test "basic slices" {
2320 expect(&slice[0] == &array[0]);2320 expect(&slice[0] == &array[0]);
2321 expect(slice.len == array.len);2321 expect(slice.len == array.len);
23222322
2323 // Using the address-of operator on a slice gives a pointer to a single2323 // Using the address-of operator on a slice gives a single-item pointer,
2324 // item, while using the `ptr` field gives an unknown length pointer.2324 // while using the `ptr` field gives a many-item pointer.
2325 expect(@TypeOf(slice.ptr) == [*]i32);2325 expect(@TypeOf(slice.ptr) == [*]i32);
2326 expect(@TypeOf(&slice[0]) == *i32);2326 expect(@TypeOf(&slice[0]) == *i32);
2327 expect(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0]));2327 expect(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0]));
...@@ -5244,8 +5244,7 @@ test "*[N]T to []T" {...@@ -5244,8 +5244,7 @@ test "*[N]T to []T" {
5244 expect(std.mem.eql(f32, x2, &[2]f32{ 1.2, 3.4 }));5244 expect(std.mem.eql(f32, x2, &[2]f32{ 1.2, 3.4 }));
5245}5245}
52465246
5247// Single-item pointers to arrays can be coerced to5247// Single-item pointers to arrays can be coerced to many-item pointers.
5248// unknown length pointers.
5249test "*[N]T to [*]T" {5248test "*[N]T to [*]T" {
5250 var buf: [5]u8 = "hello".*;5249 var buf: [5]u8 = "hello".*;
5251 const x: [*]u8 = &buf;5250 const x: [*]u8 = &buf;
...@@ -9853,7 +9852,7 @@ const c = @cImport({...@@ -9853,7 +9852,7 @@ const c = @cImport({
9853 </p>9852 </p>
9854 <p>9853 <p>
9855 When importing C header files, it is ambiguous whether pointers should be translated as9854 When importing C header files, it is ambiguous whether pointers should be translated as
9856 single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}).9855 single-item pointers ({#syntax#}*T{#endsyntax#}) or many-item pointers ({#syntax#}[*]T{#endsyntax#}).
9857 C pointers are a compromise so that Zig code can utilize translated header files directly.9856 C pointers are a compromise so that Zig code can utilize translated header files directly.
9858 </p>9857 </p>
9859 <p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p>9858 <p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p>
src/link/MachO.zig+4-1
...@@ -835,7 +835,10 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -835,7 +835,10 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
835 std.process.exit(1);835 std.process.exit(1);
836 }836 }
837 },837 },
838 else => std.process.abort(),838 else => {
839 log.err("{s} terminated", .{ argv.items[0] });
840 return error.LLDCrashed;
841 },
839 }842 }
840 } else {843 } else {
841 child.stdin_behavior = .Ignore;844 child.stdin_behavior = .Ignore;
src/stage1/codegen.cpp+47
...@@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {...@@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
487 addLLVMFnAttr(llvm_fn, "noreturn");487 addLLVMFnAttr(llvm_fn, "noreturn");
488 }488 }
489489
490 if (!calling_convention_allows_zig_types(cc)) {
491 // A simplistic and desperate attempt at making the compiler respect the
492 // target ABI for return types.
493 // This is just enough to avoid miscompiling the test suite, it will be
494 // better in stage2.
495 ZigType *int_type = return_type->id == ZigTypeIdInt ? return_type :
496 return_type->id == ZigTypeIdEnum ? return_type->data.enumeration.tag_int_type :
497 nullptr;
498
499 if (int_type != nullptr) {
500 const bool is_signed = int_type->data.integral.is_signed;
501 const uint32_t bit_width = int_type->data.integral.bit_count;
502 bool should_extend = false;
503
504 // Rough equivalent of Clang's isPromotableIntegerType.
505 switch (bit_width) {
506 case 1: // bool
507 case 8: // {un,}signed char
508 case 16: // {un,}signed short
509 should_extend = true;
510 break;
511 default:
512 break;
513 }
514
515 switch (g->zig_target->arch) {
516 case ZigLLVM_sparcv9:
517 case ZigLLVM_riscv64:
518 case ZigLLVM_ppc64:
519 case ZigLLVM_ppc64le:
520 // Always extend to the register width.
521 should_extend = bit_width < 64;
522 break;
523 default:
524 break;
525 }
526
527 // {zero,sign}-extend the result.
528 if (should_extend) {
529 if (is_signed)
530 addLLVMAttr(llvm_fn, 0, "signext");
531 else
532 addLLVMAttr(llvm_fn, 0, "zeroext");
533 }
534 }
535 }
536
490 if (fn->body_node != nullptr) {537 if (fn->body_node != nullptr) {
491 maybe_export_dll(g, llvm_fn, linkage);538 maybe_export_dll(g, llvm_fn, linkage);
492539
test/stage1/c_abi/cfuncs.c+52
...@@ -24,6 +24,16 @@ void zig_f32(float);...@@ -24,6 +24,16 @@ void zig_f32(float);
24void zig_f64(double);24void zig_f64(double);
25void zig_five_floats(float, float, float, float, float);25void zig_five_floats(float, float, float, float, float);
2626
27bool zig_ret_bool();
28uint8_t zig_ret_u8();
29uint16_t zig_ret_u16();
30uint32_t zig_ret_u32();
31uint64_t zig_ret_u64();
32int8_t zig_ret_i8();
33int16_t zig_ret_i16();
34int32_t zig_ret_i32();
35int64_t zig_ret_i64();
36
27void zig_ptr(void *);37void zig_ptr(void *);
2838
29void zig_bool(bool);39void zig_bool(bool);
...@@ -119,6 +129,20 @@ void run_c_tests(void) {...@@ -119,6 +129,20 @@ void run_c_tests(void) {
119 assert_or_panic(res.d == 23);129 assert_or_panic(res.d == 23);
120 assert_or_panic(res.e == 24);130 assert_or_panic(res.e == 24);
121 }131 }
132
133 {
134 assert_or_panic(zig_ret_bool() == 1);
135
136 assert_or_panic(zig_ret_u8() == 0xff);
137 assert_or_panic(zig_ret_u16() == 0xffff);
138 assert_or_panic(zig_ret_u32() == 0xffffffff);
139 assert_or_panic(zig_ret_u64() == 0xffffffffffffffff);
140
141 assert_or_panic(zig_ret_i8() == -1);
142 assert_or_panic(zig_ret_i16() == -1);
143 assert_or_panic(zig_ret_i32() == -1);
144 assert_or_panic(zig_ret_i64() == -1);
145 }
122}146}
123147
124void c_u8(uint8_t x) {148void c_u8(uint8_t x) {
...@@ -236,3 +260,31 @@ void c_big_struct_floats(Vector5 vec) {...@@ -236,3 +260,31 @@ void c_big_struct_floats(Vector5 vec) {
236 assert_or_panic(vec.w == 69);260 assert_or_panic(vec.w == 69);
237 assert_or_panic(vec.q == 55);261 assert_or_panic(vec.q == 55);
238}262}
263
264bool c_ret_bool() {
265 return 1;
266}
267uint8_t c_ret_u8() {
268 return 0xff;
269}
270uint16_t c_ret_u16() {
271 return 0xffff;
272}
273uint32_t c_ret_u32() {
274 return 0xffffffff;
275}
276uint64_t c_ret_u64() {
277 return 0xffffffffffffffff;
278}
279int8_t c_ret_i8() {
280 return -1;
281}
282int16_t c_ret_i16() {
283 return -1;
284}
285int32_t c_ret_i32() {
286 return -1;
287}
288int64_t c_ret_i64() {
289 return -1;
290}
test/stage1/c_abi/main.zig+52
...@@ -284,3 +284,55 @@ test "C ABI structs of floats as parameter" {...@@ -284,3 +284,55 @@ test "C ABI structs of floats as parameter" {
284 };284 };
285 c_big_struct_floats(v5);285 c_big_struct_floats(v5);
286}286}
287
288export fn zig_ret_bool() bool {
289 return true;
290}
291export fn zig_ret_u8() u8 {
292 return 0xff;
293}
294export fn zig_ret_u16() u16 {
295 return 0xffff;
296}
297export fn zig_ret_u32() u32 {
298 return 0xffffffff;
299}
300export fn zig_ret_u64() u64 {
301 return 0xffffffffffffffff;
302}
303export fn zig_ret_i8() i8 {
304 return -1;
305}
306export fn zig_ret_i16() i16 {
307 return -1;
308}
309export fn zig_ret_i32() i32 {
310 return -1;
311}
312export fn zig_ret_i64() i64 {
313 return -1;
314}
315
316extern fn c_ret_bool() bool;
317extern fn c_ret_u8() u8;
318extern fn c_ret_u16() u16;
319extern fn c_ret_u32() u32;
320extern fn c_ret_u64() u64;
321extern fn c_ret_i8() i8;
322extern fn c_ret_i16() i16;
323extern fn c_ret_i32() i32;
324extern fn c_ret_i64() i64;
325
326test "C ABI integer return types" {
327 expect(c_ret_bool() == true);
328
329 expect(c_ret_u8() == 0xff);
330 expect(c_ret_u16() == 0xffff);
331 expect(c_ret_u32() == 0xffffffff);
332 expect(c_ret_u64() == 0xffffffffffffffff);
333
334 expect(c_ret_i8() == -1);
335 expect(c_ret_i16() == -1);
336 expect(c_ret_i32() == -1);
337 expect(c_ret_i64() == -1);
338}