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)
8787set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")
8888set(ZIG_TARGET_MCPU "baseline" CACHE STRING "-mcpu parameter to output binaries for")
8989set(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")
9190set(ZIG_SINGLE_THREADED off CACHE BOOL "limit the zig compiler to use only 1 thread")
9291set(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
9499find_package(llvm)
95100find_package(clang)
96101find_package(lld)
cmake/Findllvm.cmake+1-1
......@@ -63,7 +63,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB)
6363 if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 13)
6464 message(FATAL_ERROR "expected LLVM 12.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
6565 endif()
66elseif(("${ZIG_TARGET_TRIPLE}" STREQUAL "native") OR ZIG_PREFER_LLVM_CONFIG)
66elseif(ZIG_USE_LLVM_CONFIG)
6767 find_program(LLVM_CONFIG_EXE
6868 NAMES llvm-config-12 llvm-config-12.0 llvm-config120 llvm-config12 llvm-config
6969 PATHS
doc/langref.html.in+12-13
......@@ -684,7 +684,7 @@ pub fn main() void {
684684 {#header_close#}
685685 {#header_open|String Literals and Unicode Code Point Literals#}
686686 <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.
688688 The type of string literals encodes both the length, and the fact that they are null-terminated,
689689 and thus they can be {#link|coerced|Type Coercion#} to both {#link|Slices#} and
690690 {#link|Null-Terminated Pointers|Sentinel-Terminated Pointers#}.
......@@ -1783,7 +1783,7 @@ comptime {
17831783 expect(message.len == 5);
17841784}
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.
17871787const same_message = "hello";
17881788
17891789comptime {
......@@ -1989,15 +1989,15 @@ test "null terminated array" {
19891989
19901990 {#header_open|Pointers#}
19911991 <p>
1992 Zig has two kinds of pointers:
1992 Zig has two kinds of pointers: single-item and many-item.
19931993 </p>
19941994 <ul>
1995 <li>{#syntax#}*T{#endsyntax#} - pointer to exactly one item.
1995 <li>{#syntax#}*T{#endsyntax#} - single-item pointer to exactly one item.
19961996 <ul>
19971997 <li>Supports deref syntax: {#syntax#}ptr.*{#endsyntax#}</li>
19981998 </ul>
19991999 </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.
20012001 <ul>
20022002 <li>Supports index syntax: {#syntax#}ptr[i]{#endsyntax#}</li>
20032003 <li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}</li>
......@@ -2009,7 +2009,7 @@ test "null terminated array" {
20092009 </ul>
20102010 <p>These types are closely related to {#link|Arrays#} and {#link|Slices#}:</p>
20112011 <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.
20132013 <ul>
20142014 <li>Supports index syntax: {#syntax#}array_ptr[i]{#endsyntax#}</li>
20152015 <li>Supports slice syntax: {#syntax#}array_ptr[start..end]{#endsyntax#}</li>
......@@ -2038,7 +2038,7 @@ test "address of syntax" {
20382038 // Dereference a pointer:
20392039 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.
20422042 expect(@TypeOf(x_ptr) == *const i32);
20432043
20442044 // If you want to mutate the value, you'd need an address of a mutable variable:
......@@ -2051,7 +2051,7 @@ test "address of syntax" {
20512051
20522052test "pointer array access" {
20532053 // Taking an address of an individual element gives a
2054 // pointer to a single item. This kind of pointer
2054 // single-item pointer. This kind of pointer
20552055 // does not support pointer arithmetic.
20562056 var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
20572057 const ptr = &array[2];
......@@ -2320,8 +2320,8 @@ test "basic slices" {
23202320 expect(&slice[0] == &array[0]);
23212321 expect(slice.len == array.len);
23222322
2323 // Using the address-of operator on a slice gives a pointer to a single
2324 // item, while using the `ptr` field gives an unknown length pointer.
2323 // Using the address-of operator on a slice gives a single-item pointer,
2324 // while using the `ptr` field gives a many-item pointer.
23252325 expect(@TypeOf(slice.ptr) == [*]i32);
23262326 expect(@TypeOf(&slice[0]) == *i32);
23272327 expect(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0]));
......@@ -5244,8 +5244,7 @@ test "*[N]T to []T" {
52445244 expect(std.mem.eql(f32, x2, &[2]f32{ 1.2, 3.4 }));
52455245}
52465246
5247// Single-item pointers to arrays can be coerced to
5248// unknown length pointers.
5247// Single-item pointers to arrays can be coerced to many-item pointers.
52495248test "*[N]T to [*]T" {
52505249 var buf: [5]u8 = "hello".*;
52515250 const x: [*]u8 = &buf;
......@@ -9853,7 +9852,7 @@ const c = @cImport({
98539852 </p>
98549853 <p>
98559854 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#}).
98579856 C pointers are a compromise so that Zig code can utilize translated header files directly.
98589857 </p>
98599858 <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 {
835835 std.process.exit(1);
836836 }
837837 },
838 else => std.process.abort(),
838 else => {
839 log.err("{s} terminated", .{ argv.items[0] });
840 return error.LLDCrashed;
841 },
839842 }
840843 } else {
841844 child.stdin_behavior = .Ignore;
src/stage1/codegen.cpp+47
......@@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
487487 addLLVMFnAttr(llvm_fn, "noreturn");
488488 }
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
490537 if (fn->body_node != nullptr) {
491538 maybe_export_dll(g, llvm_fn, linkage);
492539
test/stage1/c_abi/cfuncs.c+52
......@@ -24,6 +24,16 @@ void zig_f32(float);
2424void zig_f64(double);
2525void 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
2737void zig_ptr(void *);
2838
2939void zig_bool(bool);
......@@ -119,6 +129,20 @@ void run_c_tests(void) {
119129 assert_or_panic(res.d == 23);
120130 assert_or_panic(res.e == 24);
121131 }
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 }
122146}
123147
124148void c_u8(uint8_t x) {
......@@ -236,3 +260,31 @@ void c_big_struct_floats(Vector5 vec) {
236260 assert_or_panic(vec.w == 69);
237261 assert_or_panic(vec.q == 55);
238262}
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" {
284284 };
285285 c_big_struct_floats(v5);
286286}
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}