authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-01-02 07:59:22-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-01-03 02:52:25-05:00
log047d6d996e540eaa50ec24b0751d147bfe2cacdb
tree80455773be42b35cd7f12b1b75df017d7f3e361a
parent98b633ff176f0ec5cc4d86c24ad4bece26cab421

cbe: fix non-msvc externs and exports

Closes #17817

12 files changed, 447 insertions(+), 257 deletions(-)

lib/zig.h+118-91
......@@ -25,11 +25,15 @@ typedef char bool;
2525#endif
2626#endif
2727
28#define zig_concat(lhs, rhs) lhs##rhs
29#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
30
2831#if defined(__has_builtin)
2932#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)
3033#else
3134#define zig_has_builtin(builtin) 0
3235#endif
36#define zig_expand_has_builtin(b) zig_has_builtin(b)
3337
3438#if defined(__has_attribute)
3539#define zig_has_attribute(attribute) __has_attribute(attribute)
......@@ -180,49 +184,51 @@ typedef char bool;
180184#define zig_extern extern
181185#endif
182186
183#if _MSC_VER
184#define zig_extern_mangled zig_extern
185#else
186#if zig_has_attribute(visibility)
187#define zig_extern_mangled zig_extern __attribute__((visibility("hidden")))
188#else
189#define zig_extern_mangled zig_extern
190#endif
191#endif
192
193187#if _MSC_VER
194188#if _M_X64
195#define zig_export(sig, symbol, name) zig_extern sig;\
196 __pragma(comment(linker, "/alternatename:" name "=" #symbol ))
189#define zig_mangle_c(symbol) symbol
197190#else /*_M_X64 */
198#define zig_export(sig, symbol, name) zig_extern sig;\
199 __pragma(comment(linker, "/alternatename:" name "=" #symbol ))
191#define zig_mangle_c(symbol) "_" symbol
200192#endif /*_M_X64 */
201193#else /* _MSC_VER */
202194#if __APPLE__
203#define zig_export(sig, symbol, name) zig_extern sig;\
204 __asm("_" name " = _" #symbol)
195#define zig_mangle_c(symbol) "_" symbol
205196#else /* __APPLE__ */
206#define zig_export(sig, symbol, name) zig_extern sig;\
207 __asm(name " = " #symbol)
197#define zig_mangle_c(symbol) symbol
208198#endif /* __APPLE__ */
209199#endif /* _MSC_VER */
210200
201#if zig_has_attribute(alias) && !__APPLE__
202#define zig_export(symbol, name) __attribute__((alias(symbol)))
203#elif _MSC_VER
204#define zig_export(symbol, name) ; \
205 __pragma(comment(linker, "/alternatename:" zig_mangle_c(name) "=" zig_mangle_c(symbol)))
206#else
207#define zig_export(symbol, name) ; \
208 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
209#endif
210
211#if _MSC_VER
212#define zig_mangled_tentative(mangled, unmangled)
213#define zig_mangled_final(mangled, unmangled) ; \
214 zig_export(#mangled, unmangled)
215#define zig_mangled_export(mangled, unmangled, symbol) \
216 zig_export(unmangled, #mangled) \
217 zig_export(symbol, unmangled)
218#else /* _MSC_VER */
219#define zig_mangled_tentative(mangled, unmangled) __asm(zig_mangle_c(unmangled))
220#define zig_mangled_final(mangled, unmangled) zig_mangled_tentative(mangled, unmangled)
221#define zig_mangled_export(mangled, unmangled, symbol) \
222 zig_mangled_final(mangled, unmangled) \
223 zig_export(symbol, unmangled)
224#endif /* _MSC_VER */
225
211226#if _MSC_VER
212#if _M_X64
213#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args;\
214 __pragma(comment(linker, "/alternatename:" #fn_name "=" #libc_name ));
215#else /*_M_X64 */
216227#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args;\
217 __pragma(comment(linker, "/alternatename:_" #fn_name "=_" #libc_name ));
218#endif /*_M_X64 */
228 __pragma(comment(linker, "/alternatename:" zig_mangle_c(#fn_name) "=" zig_mangle_c(#libc_name)));
219229#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, sig_args, call_args)
220230#else /* _MSC_VER */
221#if __APPLE__
222#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args __asm("_" #libc_name);
223#else /* __APPLE__ */
224#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args __asm(#libc_name);
225#endif /* __APPLE__ */
231#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args __asm(zig_mangle_c(#libc_name));
226232#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type libc_name sig_args; \
227233 static inline Type fn_name sig_args { return libc_name call_args; }
228234#endif
......@@ -303,9 +309,6 @@ typedef char bool;
303309#define zig_wasm_memory_grow(index, delta) zig_unimplemented()
304310#endif
305311
306#define zig_concat(lhs, rhs) lhs##rhs
307#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
308
309312#if __STDC_VERSION__ >= 201112L
310313#define zig_noreturn _Noreturn
311314#elif zig_has_attribute(noreturn) || defined(zig_gnuc)
......@@ -2199,7 +2202,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
21992202 const uint8_t *rhs_bytes = rhs;
22002203 uint16_t byte_offset = 0;
22012204 uint16_t remaining_bytes = zig_int_bytes(bits);
2202 uint16_t top_bits = remaining_bytes * 8 - bits;
2205 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
22032206 bool overflow = false;
22042207
22052208#if zig_big_endian
......@@ -2207,7 +2210,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
22072210#endif
22082211
22092212 while (remaining_bytes >= 128 / CHAR_BIT) {
2210 uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
2213 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
22112214
22122215#if zig_big_endian
22132216 byte_offset -= 128 / CHAR_BIT;
......@@ -2247,7 +2250,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
22472250 }
22482251
22492252 while (remaining_bytes >= 64 / CHAR_BIT) {
2250 uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2253 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
22512254
22522255#if zig_big_endian
22532256 byte_offset -= 64 / CHAR_BIT;
......@@ -2287,7 +2290,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
22872290 }
22882291
22892292 while (remaining_bytes >= 32 / CHAR_BIT) {
2290 uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2293 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
22912294
22922295#if zig_big_endian
22932296 byte_offset -= 32 / CHAR_BIT;
......@@ -2327,7 +2330,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
23272330 }
23282331
23292332 while (remaining_bytes >= 16 / CHAR_BIT) {
2330 uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2333 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
23312334
23322335#if zig_big_endian
23332336 byte_offset -= 16 / CHAR_BIT;
......@@ -2367,7 +2370,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
23672370 }
23682371
23692372 while (remaining_bytes >= 8 / CHAR_BIT) {
2370 uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
2373 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
23712374
23722375#if zig_big_endian
23732376 byte_offset -= 8 / CHAR_BIT;
......@@ -2415,7 +2418,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
24152418 const uint8_t *rhs_bytes = rhs;
24162419 uint16_t byte_offset = 0;
24172420 uint16_t remaining_bytes = zig_int_bytes(bits);
2418 uint16_t top_bits = remaining_bytes * 8 - bits;
2421 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
24192422 bool overflow = false;
24202423
24212424#if zig_big_endian
......@@ -2423,7 +2426,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
24232426#endif
24242427
24252428 while (remaining_bytes >= 128 / CHAR_BIT) {
2426 uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
2429 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
24272430
24282431#if zig_big_endian
24292432 byte_offset -= 128 / CHAR_BIT;
......@@ -2463,7 +2466,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
24632466 }
24642467
24652468 while (remaining_bytes >= 64 / CHAR_BIT) {
2466 uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2469 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
24672470
24682471#if zig_big_endian
24692472 byte_offset -= 64 / CHAR_BIT;
......@@ -2503,7 +2506,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
25032506 }
25042507
25052508 while (remaining_bytes >= 32 / CHAR_BIT) {
2506 uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2509 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
25072510
25082511#if zig_big_endian
25092512 byte_offset -= 32 / CHAR_BIT;
......@@ -2543,7 +2546,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
25432546 }
25442547
25452548 while (remaining_bytes >= 16 / CHAR_BIT) {
2546 uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2549 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
25472550
25482551#if zig_big_endian
25492552 byte_offset -= 16 / CHAR_BIT;
......@@ -2583,7 +2586,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
25832586 }
25842587
25852588 while (remaining_bytes >= 8 / CHAR_BIT) {
2586 uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
2589 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
25872590
25882591#if zig_big_endian
25892592 byte_offset -= 8 / CHAR_BIT;
......@@ -3355,7 +3358,6 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
33553358 return lhs operator rhs; \
33563359 }
33573360
3358#define zig_expand_has_builtin(b) zig_has_builtin(b)
33593361#define zig_common_float_builtins(w) \
33603362 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
33613363 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
......@@ -3475,129 +3477,134 @@ zig_float_builtins(64)
34753477/* Note that zig_atomicrmw_expected is needed to handle aliasing between res and arg. */
34763478#define zig_atomicrmw_xchg_float(res, obj, arg, order, Type, ReprType) do { \
34773479 zig_##Type zig_atomicrmw_expected; \
3478 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3479 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, memory_order_relaxed, Type, ReprType)); \
3480 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
3481 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
34803482 res = zig_atomicrmw_expected; \
34813483} while (0)
34823484#define zig_atomicrmw_add_float(res, obj, arg, order, Type, ReprType) do { \
34833485 zig_##Type zig_atomicrmw_expected; \
34843486 zig_##Type zig_atomicrmw_desired; \
3485 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3487 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
34863488 do { \
34873489 zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \
3488 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3490 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
34893491 res = zig_atomicrmw_expected; \
34903492} while (0)
34913493#define zig_atomicrmw_sub_float(res, obj, arg, order, Type, ReprType) do { \
34923494 zig_##Type zig_atomicrmw_expected; \
34933495 zig_##Type zig_atomicrmw_desired; \
3494 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3496 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
34953497 do { \
34963498 zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \
3497 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3499 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
34983500 res = zig_atomicrmw_expected; \
34993501} while (0)
35003502#define zig_atomicrmw_min_float(res, obj, arg, order, Type, ReprType) do { \
35013503 zig_##Type zig_atomicrmw_expected; \
35023504 zig_##Type zig_atomicrmw_desired; \
3503 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3505 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35043506 do { \
35053507 zig_atomicrmw_desired = zig_float_fn_##Type##_fmin(zig_atomicrmw_expected, arg); \
3506 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3508 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35073509 res = zig_atomicrmw_expected; \
35083510} while (0)
35093511#define zig_atomicrmw_max_float(res, obj, arg, order, Type, ReprType) do { \
35103512 zig_##Type zig_atomicrmw_expected; \
35113513 zig_##Type zig_atomicrmw_desired; \
3512 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3514 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35133515 do { \
35143516 zig_atomicrmw_desired = zig_float_fn_##Type##_fmax(zig_atomicrmw_expected, arg); \
3515 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3517 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35163518 res = zig_atomicrmw_expected; \
35173519} while (0)
35183520
35193521#define zig_atomicrmw_xchg_int128(res, obj, arg, order, Type, ReprType) do { \
35203522 zig_##Type zig_atomicrmw_expected; \
3521 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3522 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, memory_order_relaxed, Type, ReprType)); \
3523 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
3524 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
35233525 res = zig_atomicrmw_expected; \
35243526} while (0)
35253527#define zig_atomicrmw_add_int128(res, obj, arg, order, Type, ReprType) do { \
35263528 zig_##Type zig_atomicrmw_expected; \
35273529 zig_##Type zig_atomicrmw_desired; \
3528 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3530 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35293531 do { \
35303532 zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \
3531 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3533 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35323534 res = zig_atomicrmw_expected; \
35333535} while (0)
35343536#define zig_atomicrmw_sub_int128(res, obj, arg, order, Type, ReprType) do { \
35353537 zig_##Type zig_atomicrmw_expected; \
35363538 zig_##Type zig_atomicrmw_desired; \
3537 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3539 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35383540 do { \
35393541 zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \
3540 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3542 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35413543 res = zig_atomicrmw_expected; \
35423544} while (0)
35433545#define zig_atomicrmw_and_int128(res, obj, arg, order, Type, ReprType) do { \
35443546 zig_##Type zig_atomicrmw_expected; \
35453547 zig_##Type zig_atomicrmw_desired; \
3546 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3548 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35473549 do { \
35483550 zig_atomicrmw_desired = zig_and_##Type(zig_atomicrmw_expected, arg); \
3549 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3551 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35503552 res = zig_atomicrmw_expected; \
35513553} while (0)
35523554#define zig_atomicrmw_nand_int128(res, obj, arg, order, Type, ReprType) do { \
35533555 zig_##Type zig_atomicrmw_expected; \
35543556 zig_##Type zig_atomicrmw_desired; \
3555 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3557 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35563558 do { \
35573559 zig_atomicrmw_desired = zig_not_##Type(zig_and_##Type(zig_atomicrmw_expected, arg), 128); \
3558 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3560 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35593561 res = zig_atomicrmw_expected; \
35603562} while (0)
35613563#define zig_atomicrmw_or_int128(res, obj, arg, order, Type, ReprType) do { \
35623564 zig_##Type zig_atomicrmw_expected; \
35633565 zig_##Type zig_atomicrmw_desired; \
3564 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3566 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35653567 do { \
35663568 zig_atomicrmw_desired = zig_or_##Type(zig_atomicrmw_expected, arg); \
3567 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3569 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35683570 res = zig_atomicrmw_expected; \
35693571} while (0)
35703572#define zig_atomicrmw_xor_int128(res, obj, arg, order, Type, ReprType) do { \
35713573 zig_##Type zig_atomicrmw_expected; \
35723574 zig_##Type zig_atomicrmw_desired; \
3573 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3575 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35743576 do { \
35753577 zig_atomicrmw_desired = zig_xor_##Type(zig_atomicrmw_expected, arg); \
3576 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3578 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35773579 res = zig_atomicrmw_expected; \
35783580} while (0)
35793581#define zig_atomicrmw_min_int128(res, obj, arg, order, Type, ReprType) do { \
35803582 zig_##Type zig_atomicrmw_expected; \
35813583 zig_##Type zig_atomicrmw_desired; \
3582 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3584 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35833585 do { \
35843586 zig_atomicrmw_desired = zig_min_##Type(zig_atomicrmw_expected, arg); \
3585 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3587 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35863588 res = zig_atomicrmw_expected; \
35873589} while (0)
35883590#define zig_atomicrmw_max_int128(res, obj, arg, order, Type, ReprType) do { \
35893591 zig_##Type zig_atomicrmw_expected; \
35903592 zig_##Type zig_atomicrmw_desired; \
3591 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
3593 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
35923594 do { \
35933595 zig_atomicrmw_desired = zig_max_##Type(zig_atomicrmw_expected, arg); \
3594 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
3596 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
35953597 res = zig_atomicrmw_expected; \
35963598} while (0)
35973599
35983600#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
35993601#include <stdatomic.h>
36003602typedef enum memory_order zig_memory_order;
3603#define zig_memory_order_relaxed memory_order_relaxed
3604#define zig_memory_order_acquire memory_order_acquire
3605#define zig_memory_order_release memory_order_release
3606#define zig_memory_order_acq_rel memory_order_acq_rel
3607#define zig_memory_order_seq_cst memory_order_seq_cst
36013608#define zig_atomic(Type) _Atomic(Type)
36023609#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
36033610#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
......@@ -3621,12 +3628,11 @@ typedef enum memory_order zig_memory_order;
36213628#define zig_fence(order) atomic_thread_fence(order)
36223629#elif defined(__GNUC__)
36233630typedef int zig_memory_order;
3624#define memory_order_relaxed __ATOMIC_RELAXED
3625#define memory_order_consume __ATOMIC_CONSUME
3626#define memory_order_acquire __ATOMIC_ACQUIRE
3627#define memory_order_release __ATOMIC_RELEASE
3628#define memory_order_acq_rel __ATOMIC_ACQ_REL
3629#define memory_order_seq_cst __ATOMIC_SEQ_CST
3631#define zig_memory_order_relaxed __ATOMIC_RELAXED
3632#define zig_memory_order_acquire __ATOMIC_ACQUIRE
3633#define zig_memory_order_release __ATOMIC_RELEASE
3634#define zig_memory_order_acq_rel __ATOMIC_ACQ_REL
3635#define zig_memory_order_seq_cst __ATOMIC_SEQ_CST
36303636#define zig_atomic(Type) Type
36313637#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), false, succ, fail)
36323638#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), true, succ, fail)
......@@ -3645,12 +3651,11 @@ typedef int zig_memory_order;
36453651#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg
36463652#define zig_fence(order) __atomic_thread_fence(order)
36473653#elif _MSC_VER && (_M_IX86 || _M_X64)
3648#define memory_order_relaxed 0
3649#define memory_order_consume 1
3650#define memory_order_acquire 2
3651#define memory_order_release 3
3652#define memory_order_acq_rel 4
3653#define memory_order_seq_cst 5
3654#define zig_memory_order_relaxed 0
3655#define zig_memory_order_acquire 2
3656#define zig_memory_order_release 3
3657#define zig_memory_order_acq_rel 4
3658#define zig_memory_order_seq_cst 5
36543659#define zig_atomic(Type) Type
36553660#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_msvc_cmpxchg_##Type(obj, &(expected), desired)
36563661#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_cmpxchg_strong(obj, expected, desired, succ, fail, Type, ReprType)
......@@ -3672,12 +3677,11 @@ typedef int zig_memory_order;
36723677#endif
36733678/* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */
36743679#else
3675#define memory_order_relaxed 0
3676#define memory_order_consume 1
3677#define memory_order_acquire 2
3678#define memory_order_release 3
3679#define memory_order_acq_rel 4
3680#define memory_order_seq_cst 5
3680#define zig_memory_order_relaxed 0
3681#define zig_memory_order_acquire 2
3682#define zig_memory_order_release 3
3683#define zig_memory_order_acq_rel 4
3684#define zig_memory_order_seq_cst 5
36813685#define zig_atomic(Type) Type
36823686#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable
36833687#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable
......@@ -3868,9 +3872,32 @@ static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expec
38683872 return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_u128(desired), (__int64)zig_lo_u128(desired), (__int64*)expected);
38693873}
38703874
3875static inline zig_u128 zig_msvc_atomic_load_u128(zig_u128 volatile* obj) {
3876 zig_u128 expected = zig_make_u128(UINT64_C(0), UINT64_C(0));
3877 (void)zig_cmpxchg_strong(obj, expected, expected, zig_memory_order_seq_cst, zig_memory_order_seq_cst, u128, zig_u128);
3878 return expected;
3879}
3880
3881static inline void zig_msvc_atomic_store_u128(zig_u128 volatile* obj, zig_u128 arg) {
3882 zig_u128 expected = zig_make_u128(UINT64_C(0), UINT64_C(0));
3883 while (!zig_cmpxchg_weak(obj, expected, arg, zig_memory_order_seq_cst, zig_memory_order_seq_cst, u128, zig_u128));
3884}
3885
38713886static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {
38723887 return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_i128(desired), (__int64)zig_lo_i128(desired), (__int64*)expected);
38733888}
3889
3890static inline zig_i128 zig_msvc_atomic_load_i128(zig_i128 volatile* obj) {
3891 zig_i128 expected = zig_make_i128(INT64_C(0), UINT64_C(0));
3892 (void)zig_cmpxchg_strong(obj, expected, expected, zig_memory_order_seq_cst, zig_memory_order_seq_cst, i128, zig_i128);
3893 return expected;
3894}
3895
3896static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 arg) {
3897 zig_i128 expected = zig_make_i128(INT64_C(0), UINT64_C(0));
3898 while (!zig_cmpxchg_weak(obj, expected, arg, zig_memory_order_seq_cst, zig_memory_order_seq_cst, i128, zig_i128));
3899}
3900
38743901#endif /* _M_IX86 */
38753902
38763903#endif /* _MSC_VER && (_M_IX86 || _M_X64) */
src/AstGen.zig+4
......@@ -4456,6 +4456,7 @@ fn globalVarDecl(
44564456 .align_inst = .none, // passed via the decls data
44574457 .init = init_inst,
44584458 .is_extern = false,
4459 .is_const = !is_mutable,
44594460 .is_threadlocal = is_threadlocal,
44604461 });
44614462 break :vi var_inst;
......@@ -4474,6 +4475,7 @@ fn globalVarDecl(
44744475 .align_inst = .none, // passed via the decls data
44754476 .init = .none,
44764477 .is_extern = true,
4478 .is_const = !is_mutable,
44774479 .is_threadlocal = is_threadlocal,
44784480 });
44794481 break :vi var_inst;
......@@ -11495,6 +11497,7 @@ const GenZir = struct {
1149511497 var_type: Zir.Inst.Ref,
1149611498 init: Zir.Inst.Ref,
1149711499 is_extern: bool,
11500 is_const: bool,
1149811501 is_threadlocal: bool,
1149911502 }) !Zir.Inst.Ref {
1150011503 const astgen = gz.astgen;
......@@ -11533,6 +11536,7 @@ const GenZir = struct {
1153311536 .has_align = args.align_inst != .none,
1153411537 .has_init = args.init != .none,
1153511538 .is_extern = args.is_extern,
11539 .is_const = args.is_const,
1153611540 .is_threadlocal = args.is_threadlocal,
1153711541 }),
1153811542 .operand = payload_index,
src/InternPool.zig+5-5
......@@ -1005,11 +1005,11 @@ pub const Key = union(enum) {
10051005 ty: Index,
10061006 init: Index,
10071007 decl: DeclIndex,
1008 lib_name: OptionalNullTerminatedString = .none,
1009 is_extern: bool = false,
1010 is_const: bool = false,
1011 is_threadlocal: bool = false,
1012 is_weak_linkage: bool = false,
1008 lib_name: OptionalNullTerminatedString,
1009 is_extern: bool,
1010 is_const: bool,
1011 is_threadlocal: bool,
1012 is_weak_linkage: bool,
10131013 };
10141014
10151015 pub const ExternFunc = struct {
src/Sema.zig+7-3
......@@ -24758,7 +24758,9 @@ fn zirVarExtended(
2475824758 .decl = sema.owner_decl_index,
2475924759 .lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, lib_name),
2476024760 .is_extern = small.is_extern,
24761 .is_const = small.is_const,
2476124762 .is_threadlocal = small.is_threadlocal,
24763 .is_weak_linkage = false,
2476224764 } })));
2476324765}
2476424766
......@@ -25262,6 +25264,7 @@ fn zirBuiltinExtern(
2526225264 if (options.linkage == .Weak and !ty.ptrAllowsZero(mod)) {
2526325265 ty = try mod.optionalType(ty.toIntern());
2526425266 }
25267 const ptr_info = ty.ptrInfo(mod);
2526525268
2526625269 // TODO check duplicate extern
2526725270
......@@ -25272,11 +25275,12 @@ fn zirBuiltinExtern(
2527225275
2527325276 {
2527425277 const new_var = try mod.intern(.{ .variable = .{
25275 .ty = ty.toIntern(),
25278 .ty = ptr_info.child,
2527625279 .init = .none,
2527725280 .decl = sema.owner_decl_index,
25281 .lib_name = options.library_name,
2527825282 .is_extern = true,
25279 .is_const = true,
25283 .is_const = ptr_info.flags.is_const,
2528025284 .is_threadlocal = options.is_thread_local,
2528125285 .is_weak_linkage = options.linkage == .Weak,
2528225286 } });
......@@ -25284,7 +25288,7 @@ fn zirBuiltinExtern(
2528425288 new_decl.src_line = sema.owner_decl.src_line;
2528525289 // We only access this decl through the decl_ref with the correct type created
2528625290 // below, so this type doesn't matter
25287 new_decl.ty = ty;
25291 new_decl.ty = Type.fromInterned(ptr_info.child);
2528825292 new_decl.val = Value.fromInterned(new_var);
2528925293 new_decl.alignment = .none;
2529025294 new_decl.@"linksection" = .none;
src/Zir.zig+2-1
......@@ -2610,8 +2610,9 @@ pub const Inst = struct {
26102610 has_align: bool,
26112611 has_init: bool,
26122612 is_extern: bool,
2613 is_const: bool,
26132614 is_threadlocal: bool,
2614 _: u11 = undefined,
2615 _: u10 = undefined,
26152616 };
26162617 };
26172618
src/codegen/c.zig+173-128
......@@ -272,28 +272,6 @@ pub fn isMangledIdent(ident: []const u8, solo: bool) bool {
272272 return false;
273273}
274274
275const DeclVisibility = enum {
276 global,
277 global_mangled,
278 local,
279
280 fn renderFwd(visibility: DeclVisibility, w: anytype) !void {
281 try w.writeAll(switch (visibility) {
282 .global => "zig_extern ",
283 // MSVC doesn't support exporting `static` functions, so they need special treatment
284 .global_mangled => "zig_extern_mangled ",
285 .local => "static ",
286 });
287 }
288
289 fn renderDef(visibility: DeclVisibility, w: anytype) !void {
290 return switch (visibility) {
291 .global => {},
292 else => visibility.renderFwd(w),
293 };
294 }
295};
296
297275/// This data is available when outputting .c code for a `InternPool.Index`
298276/// that corresponds to `func`.
299277/// It is not available when generating .h file.
......@@ -566,7 +544,6 @@ pub const DeclGen = struct {
566544 is_naked_fn: bool,
567545 /// This is a borrowed reference from `link.C`.
568546 fwd_decl: std.ArrayList(u8),
569
570547 error_msg: ?*Module.ErrorMsg,
571548 ctypes: CType.Store,
572549 /// Keeps track of anonymous decls that need to be rendered before this
......@@ -683,7 +660,7 @@ pub const DeclGen = struct {
683660 if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
684661 return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);
685662
686 if (decl.val.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable);
663 if (decl.val.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative);
687664
688665 // We shouldn't cast C function pointers as this is UB (when you call
689666 // them). The analysis until now should ensure that the C function
......@@ -1630,7 +1607,7 @@ pub const DeclGen = struct {
16301607 kind: CType.Kind,
16311608 name: union(enum) {
16321609 export_index: u32,
1633 string: []const u8,
1610 ident: []const u8,
16341611 },
16351612 ) !void {
16361613 const store = &dg.ctypes.set;
......@@ -1652,23 +1629,28 @@ pub const DeclGen = struct {
16521629 try w.writeAll("zig_cold ");
16531630 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
16541631
1655 const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{});
1656 try w.print("{}", .{trailing});
1632 var trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{});
16571633
16581634 if (toCallingConvention(fn_info.cc)) |call_conv| {
1659 try w.print("zig_callconv({s}) ", .{call_conv});
1635 try w.print("{}zig_callconv({s})", .{ trailing, call_conv });
1636 trailing = .maybe_space;
16601637 }
16611638
16621639 switch (kind) {
16631640 .forward => {},
1664 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a|
1665 try w.print(" zig_align_fn({})", .{a}),
1641 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a| {
1642 try w.print("{}zig_align_fn({})", .{ trailing, a });
1643 trailing = .maybe_space;
1644 },
16661645 else => unreachable,
16671646 }
16681647
16691648 switch (name) {
1670 .export_index => |export_index| try dg.renderDeclName(w, fn_decl_index, export_index),
1671 .string => |string| try w.print("{ }", .{fmtIdent(string)}),
1649 .export_index => |export_index| {
1650 try w.print("{}", .{trailing});
1651 try dg.renderDeclName(w, fn_decl_index, export_index);
1652 },
1653 .ident => |ident| try w.print("{}{ }", .{ trailing, fmtIdent(ident) }),
16721654 }
16731655
16741656 try renderTypeSuffix(
......@@ -1686,8 +1668,49 @@ pub const DeclGen = struct {
16861668 );
16871669
16881670 switch (kind) {
1689 .forward => if (fn_info.alignment.toByteUnitsOptional()) |a|
1690 try w.print(" zig_align_fn({})", .{a}),
1671 .forward => {
1672 if (fn_info.alignment.toByteUnitsOptional()) |a| {
1673 try w.print(" zig_align_fn({})", .{a});
1674 }
1675 switch (name) {
1676 .export_index => |export_index| mangled: {
1677 const maybe_exports = mod.decl_exports.get(fn_decl_index);
1678 const external_name = ip.stringToSlice(
1679 if (maybe_exports) |exports|
1680 exports.items[export_index].opts.name
1681 else if (fn_decl.isExtern(mod))
1682 fn_decl.name
1683 else
1684 break :mangled,
1685 );
1686 const is_mangled = isMangledIdent(external_name, true);
1687 const is_export = export_index > 0;
1688 if (is_mangled and is_export) {
1689 try w.print(" zig_mangled_export({ }, {s}, {s})", .{
1690 fmtIdent(external_name),
1691 fmtStringLiteral(external_name, null),
1692 fmtStringLiteral(
1693 ip.stringToSlice(maybe_exports.?.items[0].opts.name),
1694 null,
1695 ),
1696 });
1697 } else if (is_mangled) {
1698 try w.print(" zig_mangled_final({ }, {s})", .{
1699 fmtIdent(external_name), fmtStringLiteral(external_name, null),
1700 });
1701 } else if (is_export) {
1702 try w.print(" zig_export({s}, {s})", .{
1703 fmtStringLiteral(
1704 ip.stringToSlice(maybe_exports.?.items[0].opts.name),
1705 null,
1706 ),
1707 fmtStringLiteral(external_name, null),
1708 });
1709 }
1710 },
1711 .ident => {},
1712 }
1713 },
16911714 .complete => {},
16921715 else => unreachable,
16931716 }
......@@ -1880,26 +1903,12 @@ pub const DeclGen = struct {
18801903 try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});
18811904 }
18821905
1883 fn declVisibility(dg: *DeclGen, tv: TypedValue) DeclVisibility {
1906 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
18841907 const mod = dg.module;
18851908 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1886 .variable => |variable| {
1887 if (mod.decl_exports.get(variable.decl)) |exports| {
1888 return if (isMangledIdent(dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true))
1889 .global_mangled
1890 else
1891 .global;
1892 } else return .local;
1893 },
1894 .extern_func => .global,
1895 .func => |func| {
1896 if (mod.decl_exports.get(func.owner_decl)) |exports| {
1897 return if (isMangledIdent(dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true))
1898 .global_mangled
1899 else
1900 .global;
1901 } else return .local;
1902 },
1909 .variable => |variable| mod.decl_exports.contains(variable.decl),
1910 .extern_func => true,
1911 .func => |func| mod.decl_exports.contains(func.owner_decl),
19031912 else => unreachable,
19041913 };
19051914 }
......@@ -1981,12 +1990,18 @@ pub const DeclGen = struct {
19811990 try dg.writeCValue(writer, member);
19821991 }
19831992
1984 fn renderFwdDecl(dg: *DeclGen, decl_index: InternPool.DeclIndex, variable: InternPool.Key.Variable) !void {
1993 fn renderFwdDecl(
1994 dg: *DeclGen,
1995 decl_index: InternPool.DeclIndex,
1996 variable: InternPool.Key.Variable,
1997 fwd_kind: enum { tentative, final },
1998 ) !void {
19851999 const decl = dg.module.declPtr(decl_index);
19862000 const fwd = dg.fwd_decl.writer();
1987 const visibility = if (variable.is_extern) .global else dg.declVisibility(.{ .ty = decl.ty, .val = decl.val });
1988 try visibility.renderFwd(fwd);
1989 const export_weak_linkage = if (dg.module.decl_exports.get(decl_index)) |exports|
2001 const is_global = variable.is_extern or dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val });
2002 try fwd.writeAll(if (is_global) "zig_extern " else "static ");
2003 const maybe_exports = dg.module.decl_exports.get(decl_index);
2004 const export_weak_linkage = if (maybe_exports) |exports|
19902005 exports.items[0].opts.linkage == .Weak
19912006 else
19922007 false;
......@@ -2000,6 +2015,21 @@ pub const DeclGen = struct {
20002015 decl.alignment,
20012016 .complete,
20022017 );
2018 mangled: {
2019 const external_name = dg.module.intern_pool.stringToSlice(if (maybe_exports) |exports|
2020 exports.items[0].opts.name
2021 else if (variable.is_extern)
2022 decl.name
2023 else
2024 break :mangled);
2025 if (isMangledIdent(external_name, true)) {
2026 try fwd.print(" zig_mangled_{s}({ }, {s})", .{
2027 @tagName(fwd_kind),
2028 fmtIdent(external_name),
2029 fmtStringLiteral(external_name, null),
2030 });
2031 }
2032 }
20032033 try fwd.writeAll(";\n");
20042034 }
20052035
......@@ -2009,9 +2039,13 @@ pub const DeclGen = struct {
20092039 try mod.markDeclAlive(decl);
20102040
20112041 if (mod.decl_exports.get(decl_index)) |exports| {
2012 try writer.print("{ }", .{fmtIdent(mod.intern_pool.stringToSlice(exports.items[export_index].opts.name))});
2042 try writer.print("{ }", .{
2043 fmtIdent(mod.intern_pool.stringToSlice(exports.items[export_index].opts.name)),
2044 });
20132045 } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| {
2014 try writer.print("{}", .{mod.declPtr(extern_decl_index).name.fmt(&mod.intern_pool)});
2046 try writer.print("{ }", .{
2047 fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(extern_decl_index).name)),
2048 });
20152049 } else {
20162050 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
20172051 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
......@@ -2643,54 +2677,61 @@ fn genExports(o: *Object) !void {
26432677
26442678 const mod = o.dg.module;
26452679 const ip = &mod.intern_pool;
2646 const decl_index = o.dg.pass.decl;
2680 const decl_index = switch (o.dg.pass) {
2681 .decl => |decl| decl,
2682 .anon, .flush => return,
2683 };
26472684 const decl = mod.declPtr(decl_index);
26482685 const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) };
26492686 const fwd = o.dg.fwd_decl.writer();
26502687
26512688 const exports = mod.decl_exports.get(decl_index) orelse return;
2689 if (exports.items.len < 2) return;
26522690
2653 const is_mangled = isMangledIdent(ip.stringToSlice(exports.items[0].opts.name), true);
2654 if (exports.items.len < 2 and !is_mangled) return;
2655
2656 switch (ip.indexToKey(tv.val.toIntern())) {
2657 .func => {
2658 const start_i = 1 - @intFromBool(is_mangled);
2659 for (exports.items[start_i..], start_i..) |@"export", i| {
2660 try fwd.writeAll("zig_export(");
2661 if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn ");
2662 try o.dg.renderFunctionSignature(fwd, decl_index, .forward, .{ .export_index = @as(u32, @intCast(i)) });
2663 try fwd.print(", { }, {s});\n", .{
2664 fmtIdent(ip.stringToSlice(exports.items[0].opts.name)),
2665 fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null),
2666 });
2667 }
2691 const is_variable_const = switch (ip.indexToKey(tv.val.toIntern())) {
2692 .func => return for (exports.items[1..], 1..) |@"export", i| {
2693 try fwd.writeAll("zig_extern ");
2694 if (@"export".opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn ");
2695 try o.dg.renderFunctionSignature(
2696 fwd,
2697 decl_index,
2698 .forward,
2699 .{ .export_index = @intCast(i) },
2700 );
2701 try fwd.writeAll(";\n");
26682702 },
26692703 .extern_func => {
26702704 // TODO: when sema allows re-exporting extern decls
26712705 unreachable;
26722706 },
2673 .variable => |variable| {
2674 const start_i = 1 - @intFromBool(is_mangled);
2675 for (exports.items[start_i..], start_i..) |@"export", i| {
2676 try fwd.writeAll("zig_export(");
2677 if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage ");
2678 const alias = ip.stringToSlice(@"export".opts.name);
2679 try o.dg.renderTypeAndName(
2680 fwd,
2681 decl.ty,
2682 .{ .identifier = alias },
2683 CQualifiers.init(.{ .@"const" = variable.is_const }),
2684 decl.alignment,
2685 .complete,
2686 );
2687 try fwd.print(", { }, {s});\n", .{
2688 fmtIdent(ip.stringToSlice(exports.items[0].opts.name)),
2689 fmtStringLiteral(alias, null),
2690 });
2691 }
2692 },
2693 else => {},
2707 .variable => |variable| variable.is_const,
2708 else => true,
2709 };
2710 for (exports.items[1..]) |@"export"| {
2711 try fwd.writeAll("zig_extern ");
2712 if (@"export".opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage ");
2713 const export_name = ip.stringToSlice(@"export".opts.name);
2714 try o.dg.renderTypeAndName(
2715 fwd,
2716 decl.ty,
2717 .{ .identifier = export_name },
2718 CQualifiers.init(.{ .@"const" = is_variable_const }),
2719 decl.alignment,
2720 .complete,
2721 );
2722 if (isMangledIdent(export_name, true)) {
2723 try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
2724 fmtIdent(export_name),
2725 fmtStringLiteral(export_name, null),
2726 fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
2727 });
2728 } else {
2729 try fwd.print(" zig_export({s}, {s})", .{
2730 fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
2731 fmtStringLiteral(export_name, null),
2732 });
2733 }
2734 try fwd.writeAll(";\n");
26942735 }
26952736}
26962737
......@@ -2762,12 +2803,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
27622803 fwd_decl_writer,
27632804 fn_decl_index,
27642805 .forward,
2765 .{ .string = fn_name },
2806 .{ .ident = fn_name },
27662807 );
27672808 try fwd_decl_writer.writeAll(";\n");
27682809
27692810 try w.print("static zig_{s} ", .{@tagName(key)});
2770 try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ .string = fn_name });
2811 try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ .ident = fn_name });
27712812 try w.writeAll(" {\n return ");
27722813 try o.dg.renderDeclName(w, fn_decl_index, 0);
27732814 try w.writeByte('(');
......@@ -2797,9 +2838,9 @@ pub fn genFunc(f: *Function) !void {
27972838 o.code_header = std.ArrayList(u8).init(gpa);
27982839 defer o.code_header.deinit();
27992840
2800 const visibility = o.dg.declVisibility(tv);
2841 const is_global = o.dg.declIsGlobal(tv);
28012842 const fwd_decl_writer = o.dg.fwd_decl.writer();
2802 try visibility.renderFwd(fwd_decl_writer);
2843 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
28032844
28042845 if (mod.decl_exports.get(decl_index)) |exports|
28052846 if (exports.items[0].opts.linkage == .Weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");
......@@ -2808,7 +2849,7 @@ pub fn genFunc(f: *Function) !void {
28082849 try genExports(o);
28092850
28102851 try o.indent_writer.insertNewline();
2811 try visibility.renderDef(o.writer());
2852 if (!is_global) try o.writer().writeAll("static ");
28122853 try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });
28132854 try o.writer().writeByte(' ');
28142855
......@@ -2887,14 +2928,14 @@ pub fn genDecl(o: *Object) !void {
28872928 try fwd_decl_writer.writeAll(";\n");
28882929 try genExports(o);
28892930 } else if (tv.val.getVariable(mod)) |variable| {
2890 try o.dg.renderFwdDecl(decl_index, variable);
2931 try o.dg.renderFwdDecl(decl_index, variable, .final);
28912932 try genExports(o);
28922933
28932934 if (variable.is_extern) return;
28942935
2895 const visibility = if (variable.is_extern) .global else o.dg.declVisibility(tv);
2936 const is_global = variable.is_extern or o.dg.declIsGlobal(tv);
28962937 const w = o.writer();
2897 try visibility.renderDef(w);
2938 if (!is_global) try w.writeAll("static ");
28982939 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
28992940 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
29002941 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
......@@ -2907,21 +2948,16 @@ pub fn genDecl(o: *Object) !void {
29072948 try w.writeByte(';');
29082949 try o.indent_writer.insertNewline();
29092950 } else {
2910 const visibility: DeclVisibility = if (o.dg.module.decl_exports.get(decl_index)) |exports| b: {
2911 break :b if (isMangledIdent(o.dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true))
2912 .global_mangled
2913 else
2914 .global;
2915 } else .local;
2951 const is_global = o.dg.module.decl_exports.contains(decl_index);
29162952 const decl_c_value = .{ .decl = decl_index };
2917 return genDeclValue(o, tv, visibility, decl_c_value, decl.alignment, decl.@"linksection");
2953 try genDeclValue(o, tv, is_global, decl_c_value, decl.alignment, decl.@"linksection");
29182954 }
29192955}
29202956
29212957pub fn genDeclValue(
29222958 o: *Object,
29232959 tv: TypedValue,
2924 visibility: DeclVisibility,
2960 is_global: bool,
29252961 decl_c_value: CValue,
29262962 alignment: Alignment,
29272963 link_section: InternPool.OptionalNullTerminatedString,
......@@ -2929,12 +2965,27 @@ pub fn genDeclValue(
29292965 const mod = o.dg.module;
29302966 const fwd_decl_writer = o.dg.fwd_decl.writer();
29312967
2932 try visibility.renderFwd(fwd_decl_writer);
2968 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
29332969 try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete);
2970 switch (o.dg.pass) {
2971 .decl => |decl_index| {
2972 if (mod.decl_exports.get(decl_index)) |exports| {
2973 const export_name = mod.intern_pool.stringToSlice(exports.items[0].opts.name);
2974 if (isMangledIdent(export_name, true)) {
2975 try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{
2976 fmtIdent(export_name), fmtStringLiteral(export_name, null),
2977 });
2978 }
2979 }
2980 },
2981 .anon => {},
2982 .flush => unreachable,
2983 }
29342984 try fwd_decl_writer.writeAll(";\n");
2985 try genExports(o);
29352986
29362987 const w = o.writer();
2937 try visibility.renderDef(w);
2988 if (!is_global) try w.writeAll("static ");
29382989
29392990 if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|
29402991 try w.print("zig_linksection(\"{s}\", ", .{s});
......@@ -2959,16 +3010,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
29593010 const writer = dg.fwd_decl.writer();
29603011
29613012 switch (tv.ty.zigTypeTag(mod)) {
2962 .Fn => {
2963 const visibility = dg.declVisibility(tv);
2964 switch (visibility) {
2965 .global, .global_mangled => {
2966 try visibility.renderFwd(writer);
2967 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
2968 try dg.fwd_decl.appendSlice(";\n");
2969 },
2970 .local => {},
2971 }
3013 .Fn => if (dg.declIsGlobal(tv)) {
3014 try writer.writeAll("zig_extern ");
3015 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
3016 try dg.fwd_decl.appendSlice(";\n");
29723017 },
29733018 else => {},
29743019 }
......@@ -7451,11 +7496,11 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
74517496fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
74527497 return switch (order) {
74537498 // Note: unordered is actually even less atomic than relaxed
7454 .Unordered, .Monotonic => "memory_order_relaxed",
7455 .Acquire => "memory_order_acquire",
7456 .Release => "memory_order_release",
7457 .AcqRel => "memory_order_acq_rel",
7458 .SeqCst => "memory_order_seq_cst",
7499 .Unordered, .Monotonic => "zig_memory_order_relaxed",
7500 .Acquire => "zig_memory_order_acquire",
7501 .Release => "zig_memory_order_release",
7502 .AcqRel => "zig_memory_order_acq_rel",
7503 .SeqCst => "zig_memory_order_seq_cst",
74597504 };
74607505}
74617506
src/link/C.zig+1-1
......@@ -291,7 +291,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
291291 };
292292 const c_value: codegen.CValue = .{ .constant = anon_decl };
293293 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;
294 codegen.genDeclValue(&object, tv, .local, c_value, alignment, .none) catch |err| switch (err) {
294 codegen.genDeclValue(&object, tv, false, c_value, alignment, .none) catch |err| switch (err) {
295295 error.AnalysisFail => {
296296 @panic("TODO: C backend AnalysisFail on anonymous decl");
297297 //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
test/behavior.zig+1-3
......@@ -110,7 +110,6 @@ test {
110110 _ = @import("behavior/bugs/12551.zig");
111111 _ = @import("behavior/bugs/12571.zig");
112112 _ = @import("behavior/bugs/12644.zig");
113 _ = @import("behavior/bugs/12680.zig");
114113 _ = @import("behavior/bugs/12723.zig");
115114 _ = @import("behavior/bugs/12776.zig");
116115 _ = @import("behavior/bugs/12786.zig");
......@@ -175,6 +174,7 @@ test {
175174 _ = @import("behavior/hasfield.zig");
176175 _ = @import("behavior/if.zig");
177176 _ = @import("behavior/import.zig");
177 _ = @import("behavior/import_c_keywords.zig");
178178 _ = @import("behavior/incomplete_struct_param_tld.zig");
179179 _ = @import("behavior/inline_switch.zig");
180180 _ = @import("behavior/int128.zig");
......@@ -251,9 +251,7 @@ test {
251251 }
252252
253253 if (builtin.zig_backend != .stage2_arm and
254 builtin.zig_backend != .stage2_x86_64 and
255254 builtin.zig_backend != .stage2_aarch64 and
256 builtin.zig_backend != .stage2_c and
257255 builtin.zig_backend != .stage2_spirv64)
258256 {
259257 _ = @import("behavior/export_keyword.zig");
test/behavior/bugs/12680.zig deleted-17
......@@ -1,17 +0,0 @@
1const std = @import("std");
2const expectEqual = std.testing.expectEqual;
3const other_file = @import("12680_other_file.zig");
4const builtin = @import("builtin");
5
6extern fn test_func() callconv(.C) usize;
7
8test "export a function twice" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
14
15 // If it exports the function correctly, `test_func` and `testFunc` will points to the same address.
16 try expectEqual(test_func(), other_file.testFunc());
17}
test/behavior/bugs/12680_other_file.zig deleted-8
......@@ -1,8 +0,0 @@
1// export this function twice
2pub export fn testFunc() callconv(.C) usize {
3 return @intFromPtr(&testFunc);
4}
5
6comptime {
7 @export(testFunc, .{ .name = "test_func", .linkage = .Strong });
8}
test/behavior/export_c_keywords.zig created+44
......@@ -0,0 +1,44 @@
1pub const Id = enum(c_int) {
2 c_keyword_variable = 12,
3 non_c_keyword_variable = 34,
4 c_keyword_constant = 56,
5 non_c_keyword_constant = 78,
6 c_keyword_function = 910,
7 non_c_keyword_function = 1112,
8};
9
10export var int: Id = .c_keyword_variable;
11
12export var some_non_c_keyword_variable: Id = .non_c_keyword_variable;
13
14export const @"if": Id = .c_keyword_constant;
15
16export const some_non_c_keyword_constant: Id = .non_c_keyword_constant;
17
18export fn float() Id {
19 return .c_keyword_function;
20}
21
22export fn some_non_c_keyword_function() Id {
23 return .non_c_keyword_function;
24}
25
26comptime {
27 @export(int, .{ .name = "long" });
28 @export(int, .{ .name = "an_alias_of_int" });
29
30 @export(some_non_c_keyword_variable, .{ .name = "void" });
31 @export(some_non_c_keyword_variable, .{ .name = "an_alias_of_some_non_c_keyword_variable" });
32
33 @export(@"if", .{ .name = "else" });
34 @export(@"if", .{ .name = "an_alias_of_if" });
35
36 @export(some_non_c_keyword_constant, .{ .name = "switch" });
37 @export(some_non_c_keyword_constant, .{ .name = "an_alias_of_some_non_c_keyword_constant" });
38
39 @export(float, .{ .name = "double" });
40 @export(float, .{ .name = "an_alias_of_float" });
41
42 @export(some_non_c_keyword_function, .{ .name = "break" });
43 @export(some_non_c_keyword_function, .{ .name = "an_alias_of_some_non_c_keyword_function" });
44}
test/behavior/import_c_keywords.zig created+92
......@@ -0,0 +1,92 @@
1const builtin = @import("builtin");
2const Id = @import("export_c_keywords.zig").Id;
3const std = @import("std");
4
5extern var int: Id;
6extern var long: Id;
7extern var an_alias_of_int: Id;
8
9extern var some_non_c_keyword_variable: Id;
10extern var @"void": Id;
11extern var an_alias_of_some_non_c_keyword_variable: Id;
12
13extern const @"if": Id;
14extern const @"else": Id;
15extern const an_alias_of_if: Id;
16
17extern const some_non_c_keyword_constant: Id;
18extern const @"switch": Id;
19extern const an_alias_of_some_non_c_keyword_constant: Id;
20
21extern fn float() Id;
22extern fn double() Id;
23extern fn an_alias_of_float() Id;
24
25extern fn some_non_c_keyword_function() Id;
26extern fn @"break"() Id;
27extern fn an_alias_of_some_non_c_keyword_function() Id;
28
29test "import c keywords" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
35 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
36
37 try std.testing.expect(int == .c_keyword_variable);
38 try std.testing.expect(long == .c_keyword_variable);
39 try std.testing.expect(an_alias_of_int == .c_keyword_variable);
40
41 try std.testing.expect(some_non_c_keyword_variable == .non_c_keyword_variable);
42 try std.testing.expect(@"void" == .non_c_keyword_variable);
43 try std.testing.expect(an_alias_of_some_non_c_keyword_variable == .non_c_keyword_variable);
44
45 try std.testing.expect(@"if" == .c_keyword_constant);
46 try std.testing.expect(@"else" == .c_keyword_constant);
47 try std.testing.expect(an_alias_of_if == .c_keyword_constant);
48
49 try std.testing.expect(some_non_c_keyword_constant == .non_c_keyword_constant);
50 try std.testing.expect(@"switch" == .non_c_keyword_constant);
51 try std.testing.expect(an_alias_of_some_non_c_keyword_constant == .non_c_keyword_constant);
52
53 try std.testing.expect(float() == .c_keyword_function);
54 try std.testing.expect(double() == .c_keyword_function);
55 try std.testing.expect(an_alias_of_float() == .c_keyword_function);
56
57 try std.testing.expect(some_non_c_keyword_function() == .non_c_keyword_function);
58 try std.testing.expect(@"break"() == .non_c_keyword_function);
59 try std.testing.expect(an_alias_of_some_non_c_keyword_function() == .non_c_keyword_function);
60
61 var ptr_id: *const Id = &long;
62 try std.testing.expect(ptr_id == &int);
63 ptr_id = &an_alias_of_int;
64 try std.testing.expect(ptr_id == &int);
65
66 ptr_id = &@"void";
67 try std.testing.expect(ptr_id == &some_non_c_keyword_variable);
68 ptr_id = &an_alias_of_some_non_c_keyword_variable;
69 try std.testing.expect(ptr_id == &some_non_c_keyword_variable);
70
71 ptr_id = &@"else";
72 try std.testing.expect(ptr_id == &@"if");
73 ptr_id = &an_alias_of_if;
74 try std.testing.expect(ptr_id == &@"if");
75
76 ptr_id = &@"switch";
77 try std.testing.expect(ptr_id == &some_non_c_keyword_constant);
78 ptr_id = &an_alias_of_some_non_c_keyword_constant;
79 try std.testing.expect(ptr_id == &some_non_c_keyword_constant);
80
81 if (builtin.target.ofmt != .coff and builtin.target.os.tag != .windows) {
82 var ptr_fn: *const fn () callconv(.C) Id = &double;
83 try std.testing.expect(ptr_fn == &float);
84 ptr_fn = &an_alias_of_float;
85 try std.testing.expect(ptr_fn == &float);
86
87 ptr_fn = &@"break";
88 try std.testing.expect(ptr_fn == &some_non_c_keyword_function);
89 ptr_fn = &an_alias_of_some_non_c_keyword_function;
90 try std.testing.expect(ptr_fn == &some_non_c_keyword_function);
91 }
92}