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;...@@ -25,11 +25,15 @@ typedef char bool;
25#endif25#endif
26#endif26#endif
2727
28#define zig_concat(lhs, rhs) lhs##rhs
29#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
30
28#if defined(__has_builtin)31#if defined(__has_builtin)
29#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)32#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)
30#else33#else
31#define zig_has_builtin(builtin) 034#define zig_has_builtin(builtin) 0
32#endif35#endif
36#define zig_expand_has_builtin(b) zig_has_builtin(b)
3337
34#if defined(__has_attribute)38#if defined(__has_attribute)
35#define zig_has_attribute(attribute) __has_attribute(attribute)39#define zig_has_attribute(attribute) __has_attribute(attribute)
...@@ -180,49 +184,51 @@ typedef char bool;...@@ -180,49 +184,51 @@ typedef char bool;
180#define zig_extern extern184#define zig_extern extern
181#endif185#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
193#if _MSC_VER187#if _MSC_VER
194#if _M_X64188#if _M_X64
195#define zig_export(sig, symbol, name) zig_extern sig;\189#define zig_mangle_c(symbol) symbol
196 __pragma(comment(linker, "/alternatename:" name "=" #symbol ))
197#else /*_M_X64 */190#else /*_M_X64 */
198#define zig_export(sig, symbol, name) zig_extern sig;\191#define zig_mangle_c(symbol) "_" symbol
199 __pragma(comment(linker, "/alternatename:" name "=" #symbol ))
200#endif /*_M_X64 */192#endif /*_M_X64 */
201#else /* _MSC_VER */193#else /* _MSC_VER */
202#if __APPLE__194#if __APPLE__
203#define zig_export(sig, symbol, name) zig_extern sig;\195#define zig_mangle_c(symbol) "_" symbol
204 __asm("_" name " = _" #symbol)
205#else /* __APPLE__ */196#else /* __APPLE__ */
206#define zig_export(sig, symbol, name) zig_extern sig;\197#define zig_mangle_c(symbol) symbol
207 __asm(name " = " #symbol)
208#endif /* __APPLE__ */198#endif /* __APPLE__ */
209#endif /* _MSC_VER */199#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
211#if _MSC_VER226#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 */
216#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args;\227#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 ));228 __pragma(comment(linker, "/alternatename:" zig_mangle_c(#fn_name) "=" zig_mangle_c(#libc_name)));
218#endif /*_M_X64 */
219#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, sig_args, call_args)229#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, sig_args, call_args)
220#else /* _MSC_VER */230#else /* _MSC_VER */
221#if __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));
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__ */
226#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type libc_name sig_args; \232#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type libc_name sig_args; \
227 static inline Type fn_name sig_args { return libc_name call_args; }233 static inline Type fn_name sig_args { return libc_name call_args; }
228#endif234#endif
...@@ -303,9 +309,6 @@ typedef char bool;...@@ -303,9 +309,6 @@ typedef char bool;
303#define zig_wasm_memory_grow(index, delta) zig_unimplemented()309#define zig_wasm_memory_grow(index, delta) zig_unimplemented()
304#endif310#endif
305311
306#define zig_concat(lhs, rhs) lhs##rhs
307#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
308
309#if __STDC_VERSION__ >= 201112L312#if __STDC_VERSION__ >= 201112L
310#define zig_noreturn _Noreturn313#define zig_noreturn _Noreturn
311#elif zig_has_attribute(noreturn) || defined(zig_gnuc)314#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...@@ -2199,7 +2202,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
2199 const uint8_t *rhs_bytes = rhs;2202 const uint8_t *rhs_bytes = rhs;
2200 uint16_t byte_offset = 0;2203 uint16_t byte_offset = 0;
2201 uint16_t remaining_bytes = zig_int_bytes(bits);2204 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);
2203 bool overflow = false;2206 bool overflow = false;
22042207
2205#if zig_big_endian2208#if zig_big_endian
...@@ -2207,7 +2210,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2207,7 +2210,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
2207#endif2210#endif
22082211
2209 while (remaining_bytes >= 128 / CHAR_BIT) {2212 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
2212#if zig_big_endian2215#if zig_big_endian
2213 byte_offset -= 128 / CHAR_BIT;2216 byte_offset -= 128 / CHAR_BIT;
...@@ -2247,7 +2250,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2247,7 +2250,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
2247 }2250 }
22482251
2249 while (remaining_bytes >= 64 / CHAR_BIT) {2252 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
2252#if zig_big_endian2255#if zig_big_endian
2253 byte_offset -= 64 / CHAR_BIT;2256 byte_offset -= 64 / CHAR_BIT;
...@@ -2287,7 +2290,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2287,7 +2290,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
2287 }2290 }
22882291
2289 while (remaining_bytes >= 32 / CHAR_BIT) {2292 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
2292#if zig_big_endian2295#if zig_big_endian
2293 byte_offset -= 32 / CHAR_BIT;2296 byte_offset -= 32 / CHAR_BIT;
...@@ -2327,7 +2330,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2327,7 +2330,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
2327 }2330 }
23282331
2329 while (remaining_bytes >= 16 / CHAR_BIT) {2332 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
2332#if zig_big_endian2335#if zig_big_endian
2333 byte_offset -= 16 / CHAR_BIT;2336 byte_offset -= 16 / CHAR_BIT;
...@@ -2367,7 +2370,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2367,7 +2370,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
2367 }2370 }
23682371
2369 while (remaining_bytes >= 8 / CHAR_BIT) {2372 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
2372#if zig_big_endian2375#if zig_big_endian
2373 byte_offset -= 8 / CHAR_BIT;2376 byte_offset -= 8 / CHAR_BIT;
...@@ -2415,7 +2418,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2415,7 +2418,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
2415 const uint8_t *rhs_bytes = rhs;2418 const uint8_t *rhs_bytes = rhs;
2416 uint16_t byte_offset = 0;2419 uint16_t byte_offset = 0;
2417 uint16_t remaining_bytes = zig_int_bytes(bits);2420 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);
2419 bool overflow = false;2422 bool overflow = false;
24202423
2421#if zig_big_endian2424#if zig_big_endian
...@@ -2423,7 +2426,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2423,7 +2426,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
2423#endif2426#endif
24242427
2425 while (remaining_bytes >= 128 / CHAR_BIT) {2428 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
2428#if zig_big_endian2431#if zig_big_endian
2429 byte_offset -= 128 / CHAR_BIT;2432 byte_offset -= 128 / CHAR_BIT;
...@@ -2463,7 +2466,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2463,7 +2466,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
2463 }2466 }
24642467
2465 while (remaining_bytes >= 64 / CHAR_BIT) {2468 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
2468#if zig_big_endian2471#if zig_big_endian
2469 byte_offset -= 64 / CHAR_BIT;2472 byte_offset -= 64 / CHAR_BIT;
...@@ -2503,7 +2506,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2503,7 +2506,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
2503 }2506 }
25042507
2505 while (remaining_bytes >= 32 / CHAR_BIT) {2508 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
2508#if zig_big_endian2511#if zig_big_endian
2509 byte_offset -= 32 / CHAR_BIT;2512 byte_offset -= 32 / CHAR_BIT;
...@@ -2543,7 +2546,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2543,7 +2546,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
2543 }2546 }
25442547
2545 while (remaining_bytes >= 16 / CHAR_BIT) {2548 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
2548#if zig_big_endian2551#if zig_big_endian
2549 byte_offset -= 16 / CHAR_BIT;2552 byte_offset -= 16 / CHAR_BIT;
...@@ -2583,7 +2586,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -2583,7 +2586,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
2583 }2586 }
25842587
2585 while (remaining_bytes >= 8 / CHAR_BIT) {2588 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
2588#if zig_big_endian2591#if zig_big_endian
2589 byte_offset -= 8 / CHAR_BIT;2592 byte_offset -= 8 / CHAR_BIT;
...@@ -3355,7 +3358,6 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))...@@ -3355,7 +3358,6 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
3355 return lhs operator rhs; \3358 return lhs operator rhs; \
3356 }3359 }
33573360
3358#define zig_expand_has_builtin(b) zig_has_builtin(b)
3359#define zig_common_float_builtins(w) \3361#define zig_common_float_builtins(w) \
3360 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \3362 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
3361 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \3363 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
...@@ -3475,129 +3477,134 @@ zig_float_builtins(64)...@@ -3475,129 +3477,134 @@ zig_float_builtins(64)
3475/* Note that zig_atomicrmw_expected is needed to handle aliasing between res and arg. */3477/* Note that zig_atomicrmw_expected is needed to handle aliasing between res and arg. */
3476#define zig_atomicrmw_xchg_float(res, obj, arg, order, Type, ReprType) do { \3478#define zig_atomicrmw_xchg_float(res, obj, arg, order, Type, ReprType) do { \
3477 zig_##Type zig_atomicrmw_expected; \3479 zig_##Type zig_atomicrmw_expected; \
3478 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \3480 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
3479 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, memory_order_relaxed, Type, ReprType)); \3481 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
3480 res = zig_atomicrmw_expected; \3482 res = zig_atomicrmw_expected; \
3481} while (0)3483} while (0)
3482#define zig_atomicrmw_add_float(res, obj, arg, order, Type, ReprType) do { \3484#define zig_atomicrmw_add_float(res, obj, arg, order, Type, ReprType) do { \
3483 zig_##Type zig_atomicrmw_expected; \3485 zig_##Type zig_atomicrmw_expected; \
3484 zig_##Type zig_atomicrmw_desired; \3486 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); \
3486 do { \3488 do { \
3487 zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \3489 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)); \
3489 res = zig_atomicrmw_expected; \3491 res = zig_atomicrmw_expected; \
3490} while (0)3492} while (0)
3491#define zig_atomicrmw_sub_float(res, obj, arg, order, Type, ReprType) do { \3493#define zig_atomicrmw_sub_float(res, obj, arg, order, Type, ReprType) do { \
3492 zig_##Type zig_atomicrmw_expected; \3494 zig_##Type zig_atomicrmw_expected; \
3493 zig_##Type zig_atomicrmw_desired; \3495 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); \
3495 do { \3497 do { \
3496 zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \3498 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)); \
3498 res = zig_atomicrmw_expected; \3500 res = zig_atomicrmw_expected; \
3499} while (0)3501} while (0)
3500#define zig_atomicrmw_min_float(res, obj, arg, order, Type, ReprType) do { \3502#define zig_atomicrmw_min_float(res, obj, arg, order, Type, ReprType) do { \
3501 zig_##Type zig_atomicrmw_expected; \3503 zig_##Type zig_atomicrmw_expected; \
3502 zig_##Type zig_atomicrmw_desired; \3504 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); \
3504 do { \3506 do { \
3505 zig_atomicrmw_desired = zig_float_fn_##Type##_fmin(zig_atomicrmw_expected, arg); \3507 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)); \
3507 res = zig_atomicrmw_expected; \3509 res = zig_atomicrmw_expected; \
3508} while (0)3510} while (0)
3509#define zig_atomicrmw_max_float(res, obj, arg, order, Type, ReprType) do { \3511#define zig_atomicrmw_max_float(res, obj, arg, order, Type, ReprType) do { \
3510 zig_##Type zig_atomicrmw_expected; \3512 zig_##Type zig_atomicrmw_expected; \
3511 zig_##Type zig_atomicrmw_desired; \3513 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); \
3513 do { \3515 do { \
3514 zig_atomicrmw_desired = zig_float_fn_##Type##_fmax(zig_atomicrmw_expected, arg); \3516 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)); \
3516 res = zig_atomicrmw_expected; \3518 res = zig_atomicrmw_expected; \
3517} while (0)3519} while (0)
35183520
3519#define zig_atomicrmw_xchg_int128(res, obj, arg, order, Type, ReprType) do { \3521#define zig_atomicrmw_xchg_int128(res, obj, arg, order, Type, ReprType) do { \
3520 zig_##Type zig_atomicrmw_expected; \3522 zig_##Type zig_atomicrmw_expected; \
3521 zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \3523 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
3522 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, memory_order_relaxed, Type, ReprType)); \3524 while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
3523 res = zig_atomicrmw_expected; \3525 res = zig_atomicrmw_expected; \
3524} while (0)3526} while (0)
3525#define zig_atomicrmw_add_int128(res, obj, arg, order, Type, ReprType) do { \3527#define zig_atomicrmw_add_int128(res, obj, arg, order, Type, ReprType) do { \
3526 zig_##Type zig_atomicrmw_expected; \3528 zig_##Type zig_atomicrmw_expected; \
3527 zig_##Type zig_atomicrmw_desired; \3529 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); \
3529 do { \3531 do { \
3530 zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \3532 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)); \
3532 res = zig_atomicrmw_expected; \3534 res = zig_atomicrmw_expected; \
3533} while (0)3535} while (0)
3534#define zig_atomicrmw_sub_int128(res, obj, arg, order, Type, ReprType) do { \3536#define zig_atomicrmw_sub_int128(res, obj, arg, order, Type, ReprType) do { \
3535 zig_##Type zig_atomicrmw_expected; \3537 zig_##Type zig_atomicrmw_expected; \
3536 zig_##Type zig_atomicrmw_desired; \3538 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); \
3538 do { \3540 do { \
3539 zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \3541 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)); \
3541 res = zig_atomicrmw_expected; \3543 res = zig_atomicrmw_expected; \
3542} while (0)3544} while (0)
3543#define zig_atomicrmw_and_int128(res, obj, arg, order, Type, ReprType) do { \3545#define zig_atomicrmw_and_int128(res, obj, arg, order, Type, ReprType) do { \
3544 zig_##Type zig_atomicrmw_expected; \3546 zig_##Type zig_atomicrmw_expected; \
3545 zig_##Type zig_atomicrmw_desired; \3547 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); \
3547 do { \3549 do { \
3548 zig_atomicrmw_desired = zig_and_##Type(zig_atomicrmw_expected, arg); \3550 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)); \
3550 res = zig_atomicrmw_expected; \3552 res = zig_atomicrmw_expected; \
3551} while (0)3553} while (0)
3552#define zig_atomicrmw_nand_int128(res, obj, arg, order, Type, ReprType) do { \3554#define zig_atomicrmw_nand_int128(res, obj, arg, order, Type, ReprType) do { \
3553 zig_##Type zig_atomicrmw_expected; \3555 zig_##Type zig_atomicrmw_expected; \
3554 zig_##Type zig_atomicrmw_desired; \3556 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); \
3556 do { \3558 do { \
3557 zig_atomicrmw_desired = zig_not_##Type(zig_and_##Type(zig_atomicrmw_expected, arg), 128); \3559 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)); \
3559 res = zig_atomicrmw_expected; \3561 res = zig_atomicrmw_expected; \
3560} while (0)3562} while (0)
3561#define zig_atomicrmw_or_int128(res, obj, arg, order, Type, ReprType) do { \3563#define zig_atomicrmw_or_int128(res, obj, arg, order, Type, ReprType) do { \
3562 zig_##Type zig_atomicrmw_expected; \3564 zig_##Type zig_atomicrmw_expected; \
3563 zig_##Type zig_atomicrmw_desired; \3565 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); \
3565 do { \3567 do { \
3566 zig_atomicrmw_desired = zig_or_##Type(zig_atomicrmw_expected, arg); \3568 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)); \
3568 res = zig_atomicrmw_expected; \3570 res = zig_atomicrmw_expected; \
3569} while (0)3571} while (0)
3570#define zig_atomicrmw_xor_int128(res, obj, arg, order, Type, ReprType) do { \3572#define zig_atomicrmw_xor_int128(res, obj, arg, order, Type, ReprType) do { \
3571 zig_##Type zig_atomicrmw_expected; \3573 zig_##Type zig_atomicrmw_expected; \
3572 zig_##Type zig_atomicrmw_desired; \3574 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); \
3574 do { \3576 do { \
3575 zig_atomicrmw_desired = zig_xor_##Type(zig_atomicrmw_expected, arg); \3577 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)); \
3577 res = zig_atomicrmw_expected; \3579 res = zig_atomicrmw_expected; \
3578} while (0)3580} while (0)
3579#define zig_atomicrmw_min_int128(res, obj, arg, order, Type, ReprType) do { \3581#define zig_atomicrmw_min_int128(res, obj, arg, order, Type, ReprType) do { \
3580 zig_##Type zig_atomicrmw_expected; \3582 zig_##Type zig_atomicrmw_expected; \
3581 zig_##Type zig_atomicrmw_desired; \3583 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); \
3583 do { \3585 do { \
3584 zig_atomicrmw_desired = zig_min_##Type(zig_atomicrmw_expected, arg); \3586 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)); \
3586 res = zig_atomicrmw_expected; \3588 res = zig_atomicrmw_expected; \
3587} while (0)3589} while (0)
3588#define zig_atomicrmw_max_int128(res, obj, arg, order, Type, ReprType) do { \3590#define zig_atomicrmw_max_int128(res, obj, arg, order, Type, ReprType) do { \
3589 zig_##Type zig_atomicrmw_expected; \3591 zig_##Type zig_atomicrmw_expected; \
3590 zig_##Type zig_atomicrmw_desired; \3592 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); \
3592 do { \3594 do { \
3593 zig_atomicrmw_desired = zig_max_##Type(zig_atomicrmw_expected, arg); \3595 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)); \
3595 res = zig_atomicrmw_expected; \3597 res = zig_atomicrmw_expected; \
3596} while (0)3598} while (0)
35973599
3598#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)3600#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
3599#include <stdatomic.h>3601#include <stdatomic.h>
3600typedef enum memory_order zig_memory_order;3602typedef 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
3601#define zig_atomic(Type) _Atomic(Type)3608#define zig_atomic(Type) _Atomic(Type)
3602#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)3609#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
3603#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)3610#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;...@@ -3621,12 +3628,11 @@ typedef enum memory_order zig_memory_order;
3621#define zig_fence(order) atomic_thread_fence(order)3628#define zig_fence(order) atomic_thread_fence(order)
3622#elif defined(__GNUC__)3629#elif defined(__GNUC__)
3623typedef int zig_memory_order;3630typedef int zig_memory_order;
3624#define memory_order_relaxed __ATOMIC_RELAXED3631#define zig_memory_order_relaxed __ATOMIC_RELAXED
3625#define memory_order_consume __ATOMIC_CONSUME3632#define zig_memory_order_acquire __ATOMIC_ACQUIRE
3626#define memory_order_acquire __ATOMIC_ACQUIRE3633#define zig_memory_order_release __ATOMIC_RELEASE
3627#define memory_order_release __ATOMIC_RELEASE3634#define zig_memory_order_acq_rel __ATOMIC_ACQ_REL
3628#define memory_order_acq_rel __ATOMIC_ACQ_REL3635#define zig_memory_order_seq_cst __ATOMIC_SEQ_CST
3629#define memory_order_seq_cst __ATOMIC_SEQ_CST
3630#define zig_atomic(Type) Type3636#define zig_atomic(Type) Type
3631#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), false, succ, fail)3637#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), false, succ, fail)
3632#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), true, succ, fail)3638#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;...@@ -3645,12 +3651,11 @@ typedef int zig_memory_order;
3645#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg3651#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg
3646#define zig_fence(order) __atomic_thread_fence(order)3652#define zig_fence(order) __atomic_thread_fence(order)
3647#elif _MSC_VER && (_M_IX86 || _M_X64)3653#elif _MSC_VER && (_M_IX86 || _M_X64)
3648#define memory_order_relaxed 03654#define zig_memory_order_relaxed 0
3649#define memory_order_consume 13655#define zig_memory_order_acquire 2
3650#define memory_order_acquire 23656#define zig_memory_order_release 3
3651#define memory_order_release 33657#define zig_memory_order_acq_rel 4
3652#define memory_order_acq_rel 43658#define zig_memory_order_seq_cst 5
3653#define memory_order_seq_cst 5
3654#define zig_atomic(Type) Type3659#define zig_atomic(Type) Type
3655#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_msvc_cmpxchg_##Type(obj, &(expected), desired)3660#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_msvc_cmpxchg_##Type(obj, &(expected), desired)
3656#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_cmpxchg_strong(obj, expected, desired, succ, fail, Type, ReprType)3661#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;...@@ -3672,12 +3677,11 @@ typedef int zig_memory_order;
3672#endif3677#endif
3673/* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */3678/* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */
3674#else3679#else
3675#define memory_order_relaxed 03680#define zig_memory_order_relaxed 0
3676#define memory_order_consume 13681#define zig_memory_order_acquire 2
3677#define memory_order_acquire 23682#define zig_memory_order_release 3
3678#define memory_order_release 33683#define zig_memory_order_acq_rel 4
3679#define memory_order_acq_rel 43684#define zig_memory_order_seq_cst 5
3680#define memory_order_seq_cst 5
3681#define zig_atomic(Type) Type3685#define zig_atomic(Type) Type
3682#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable3686#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable
3683#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable3687#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...@@ -3868,9 +3872,32 @@ static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expec
3868 return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_u128(desired), (__int64)zig_lo_u128(desired), (__int64*)expected);3872 return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_u128(desired), (__int64)zig_lo_u128(desired), (__int64*)expected);
3869}3873}
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
3871static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {3886static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {
3872 return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_i128(desired), (__int64)zig_lo_i128(desired), (__int64*)expected);3887 return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_i128(desired), (__int64)zig_lo_i128(desired), (__int64*)expected);
3873}3888}
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
3874#endif /* _M_IX86 */3901#endif /* _M_IX86 */
38753902
3876#endif /* _MSC_VER && (_M_IX86 || _M_X64) */3903#endif /* _MSC_VER && (_M_IX86 || _M_X64) */
src/AstGen.zig+4
...@@ -4456,6 +4456,7 @@ fn globalVarDecl(...@@ -4456,6 +4456,7 @@ fn globalVarDecl(
4456 .align_inst = .none, // passed via the decls data4456 .align_inst = .none, // passed via the decls data
4457 .init = init_inst,4457 .init = init_inst,
4458 .is_extern = false,4458 .is_extern = false,
4459 .is_const = !is_mutable,
4459 .is_threadlocal = is_threadlocal,4460 .is_threadlocal = is_threadlocal,
4460 });4461 });
4461 break :vi var_inst;4462 break :vi var_inst;
...@@ -4474,6 +4475,7 @@ fn globalVarDecl(...@@ -4474,6 +4475,7 @@ fn globalVarDecl(
4474 .align_inst = .none, // passed via the decls data4475 .align_inst = .none, // passed via the decls data
4475 .init = .none,4476 .init = .none,
4476 .is_extern = true,4477 .is_extern = true,
4478 .is_const = !is_mutable,
4477 .is_threadlocal = is_threadlocal,4479 .is_threadlocal = is_threadlocal,
4478 });4480 });
4479 break :vi var_inst;4481 break :vi var_inst;
...@@ -11495,6 +11497,7 @@ const GenZir = struct {...@@ -11495,6 +11497,7 @@ const GenZir = struct {
11495 var_type: Zir.Inst.Ref,11497 var_type: Zir.Inst.Ref,
11496 init: Zir.Inst.Ref,11498 init: Zir.Inst.Ref,
11497 is_extern: bool,11499 is_extern: bool,
11500 is_const: bool,
11498 is_threadlocal: bool,11501 is_threadlocal: bool,
11499 }) !Zir.Inst.Ref {11502 }) !Zir.Inst.Ref {
11500 const astgen = gz.astgen;11503 const astgen = gz.astgen;
...@@ -11533,6 +11536,7 @@ const GenZir = struct {...@@ -11533,6 +11536,7 @@ const GenZir = struct {
11533 .has_align = args.align_inst != .none,11536 .has_align = args.align_inst != .none,
11534 .has_init = args.init != .none,11537 .has_init = args.init != .none,
11535 .is_extern = args.is_extern,11538 .is_extern = args.is_extern,
11539 .is_const = args.is_const,
11536 .is_threadlocal = args.is_threadlocal,11540 .is_threadlocal = args.is_threadlocal,
11537 }),11541 }),
11538 .operand = payload_index,11542 .operand = payload_index,
src/InternPool.zig+5-5
...@@ -1005,11 +1005,11 @@ pub const Key = union(enum) {...@@ -1005,11 +1005,11 @@ pub const Key = union(enum) {
1005 ty: Index,1005 ty: Index,
1006 init: Index,1006 init: Index,
1007 decl: DeclIndex,1007 decl: DeclIndex,
1008 lib_name: OptionalNullTerminatedString = .none,1008 lib_name: OptionalNullTerminatedString,
1009 is_extern: bool = false,1009 is_extern: bool,
1010 is_const: bool = false,1010 is_const: bool,
1011 is_threadlocal: bool = false,1011 is_threadlocal: bool,
1012 is_weak_linkage: bool = false,1012 is_weak_linkage: bool,
1013 };1013 };
10141014
1015 pub const ExternFunc = struct {1015 pub const ExternFunc = struct {
src/Sema.zig+7-3
...@@ -24758,7 +24758,9 @@ fn zirVarExtended(...@@ -24758,7 +24758,9 @@ fn zirVarExtended(
24758 .decl = sema.owner_decl_index,24758 .decl = sema.owner_decl_index,
24759 .lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, lib_name),24759 .lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, lib_name),
24760 .is_extern = small.is_extern,24760 .is_extern = small.is_extern,
24761 .is_const = small.is_const,
24761 .is_threadlocal = small.is_threadlocal,24762 .is_threadlocal = small.is_threadlocal,
24763 .is_weak_linkage = false,
24762 } })));24764 } })));
24763}24765}
2476424766
...@@ -25262,6 +25264,7 @@ fn zirBuiltinExtern(...@@ -25262,6 +25264,7 @@ fn zirBuiltinExtern(
25262 if (options.linkage == .Weak and !ty.ptrAllowsZero(mod)) {25264 if (options.linkage == .Weak and !ty.ptrAllowsZero(mod)) {
25263 ty = try mod.optionalType(ty.toIntern());25265 ty = try mod.optionalType(ty.toIntern());
25264 }25266 }
25267 const ptr_info = ty.ptrInfo(mod);
2526525268
25266 // TODO check duplicate extern25269 // TODO check duplicate extern
2526725270
...@@ -25272,11 +25275,12 @@ fn zirBuiltinExtern(...@@ -25272,11 +25275,12 @@ fn zirBuiltinExtern(
2527225275
25273 {25276 {
25274 const new_var = try mod.intern(.{ .variable = .{25277 const new_var = try mod.intern(.{ .variable = .{
25275 .ty = ty.toIntern(),25278 .ty = ptr_info.child,
25276 .init = .none,25279 .init = .none,
25277 .decl = sema.owner_decl_index,25280 .decl = sema.owner_decl_index,
25281 .lib_name = options.library_name,
25278 .is_extern = true,25282 .is_extern = true,
25279 .is_const = true,25283 .is_const = ptr_info.flags.is_const,
25280 .is_threadlocal = options.is_thread_local,25284 .is_threadlocal = options.is_thread_local,
25281 .is_weak_linkage = options.linkage == .Weak,25285 .is_weak_linkage = options.linkage == .Weak,
25282 } });25286 } });
...@@ -25284,7 +25288,7 @@ fn zirBuiltinExtern(...@@ -25284,7 +25288,7 @@ fn zirBuiltinExtern(
25284 new_decl.src_line = sema.owner_decl.src_line;25288 new_decl.src_line = sema.owner_decl.src_line;
25285 // We only access this decl through the decl_ref with the correct type created25289 // We only access this decl through the decl_ref with the correct type created
25286 // below, so this type doesn't matter25290 // below, so this type doesn't matter
25287 new_decl.ty = ty;25291 new_decl.ty = Type.fromInterned(ptr_info.child);
25288 new_decl.val = Value.fromInterned(new_var);25292 new_decl.val = Value.fromInterned(new_var);
25289 new_decl.alignment = .none;25293 new_decl.alignment = .none;
25290 new_decl.@"linksection" = .none;25294 new_decl.@"linksection" = .none;
src/Zir.zig+2-1
...@@ -2610,8 +2610,9 @@ pub const Inst = struct {...@@ -2610,8 +2610,9 @@ pub const Inst = struct {
2610 has_align: bool,2610 has_align: bool,
2611 has_init: bool,2611 has_init: bool,
2612 is_extern: bool,2612 is_extern: bool,
2613 is_const: bool,
2613 is_threadlocal: bool,2614 is_threadlocal: bool,
2614 _: u11 = undefined,2615 _: u10 = undefined,
2615 };2616 };
2616 };2617 };
26172618
src/codegen/c.zig+173-128
...@@ -272,28 +272,6 @@ pub fn isMangledIdent(ident: []const u8, solo: bool) bool {...@@ -272,28 +272,6 @@ pub fn isMangledIdent(ident: []const u8, solo: bool) bool {
272 return false;272 return false;
273}273}
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
297/// This data is available when outputting .c code for a `InternPool.Index`275/// This data is available when outputting .c code for a `InternPool.Index`
298/// that corresponds to `func`.276/// that corresponds to `func`.
299/// It is not available when generating .h file.277/// It is not available when generating .h file.
...@@ -566,7 +544,6 @@ pub const DeclGen = struct {...@@ -566,7 +544,6 @@ pub const DeclGen = struct {
566 is_naked_fn: bool,544 is_naked_fn: bool,
567 /// This is a borrowed reference from `link.C`.545 /// This is a borrowed reference from `link.C`.
568 fwd_decl: std.ArrayList(u8),546 fwd_decl: std.ArrayList(u8),
569
570 error_msg: ?*Module.ErrorMsg,547 error_msg: ?*Module.ErrorMsg,
571 ctypes: CType.Store,548 ctypes: CType.Store,
572 /// Keeps track of anonymous decls that need to be rendered before this549 /// Keeps track of anonymous decls that need to be rendered before this
...@@ -683,7 +660,7 @@ pub const DeclGen = struct {...@@ -683,7 +660,7 @@ pub const DeclGen = struct {
683 if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)660 if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
684 return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);661 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
688 // We shouldn't cast C function pointers as this is UB (when you call665 // We shouldn't cast C function pointers as this is UB (when you call
689 // them). The analysis until now should ensure that the C function666 // them). The analysis until now should ensure that the C function
...@@ -1630,7 +1607,7 @@ pub const DeclGen = struct {...@@ -1630,7 +1607,7 @@ pub const DeclGen = struct {
1630 kind: CType.Kind,1607 kind: CType.Kind,
1631 name: union(enum) {1608 name: union(enum) {
1632 export_index: u32,1609 export_index: u32,
1633 string: []const u8,1610 ident: []const u8,
1634 },1611 },
1635 ) !void {1612 ) !void {
1636 const store = &dg.ctypes.set;1613 const store = &dg.ctypes.set;
...@@ -1652,23 +1629,28 @@ pub const DeclGen = struct {...@@ -1652,23 +1629,28 @@ pub const DeclGen = struct {
1652 try w.writeAll("zig_cold ");1629 try w.writeAll("zig_cold ");
1653 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");1630 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, .{});1632 var trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{});
1656 try w.print("{}", .{trailing});
16571633
1658 if (toCallingConvention(fn_info.cc)) |call_conv| {1634 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;
1660 }1637 }
16611638
1662 switch (kind) {1639 switch (kind) {
1663 .forward => {},1640 .forward => {},
1664 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a|1641 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a| {
1665 try w.print(" zig_align_fn({})", .{a}),1642 try w.print("{}zig_align_fn({})", .{ trailing, a });
1643 trailing = .maybe_space;
1644 },
1666 else => unreachable,1645 else => unreachable,
1667 }1646 }
16681647
1669 switch (name) {1648 switch (name) {
1670 .export_index => |export_index| try dg.renderDeclName(w, fn_decl_index, export_index),1649 .export_index => |export_index| {
1671 .string => |string| try w.print("{ }", .{fmtIdent(string)}),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) }),
1672 }1654 }
16731655
1674 try renderTypeSuffix(1656 try renderTypeSuffix(
...@@ -1686,8 +1668,49 @@ pub const DeclGen = struct {...@@ -1686,8 +1668,49 @@ pub const DeclGen = struct {
1686 );1668 );
16871669
1688 switch (kind) {1670 switch (kind) {
1689 .forward => if (fn_info.alignment.toByteUnitsOptional()) |a|1671 .forward => {
1690 try w.print(" zig_align_fn({})", .{a}),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 },
1691 .complete => {},1714 .complete => {},
1692 else => unreachable,1715 else => unreachable,
1693 }1716 }
...@@ -1880,26 +1903,12 @@ pub const DeclGen = struct {...@@ -1880,26 +1903,12 @@ pub const DeclGen = struct {
1880 try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});1903 try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});
1881 }1904 }
18821905
1883 fn declVisibility(dg: *DeclGen, tv: TypedValue) DeclVisibility {1906 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
1884 const mod = dg.module;1907 const mod = dg.module;
1885 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {1908 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1886 .variable => |variable| {1909 .variable => |variable| mod.decl_exports.contains(variable.decl),
1887 if (mod.decl_exports.get(variable.decl)) |exports| {1910 .extern_func => true,
1888 return if (isMangledIdent(dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true))1911 .func => |func| mod.decl_exports.contains(func.owner_decl),
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 },
1903 else => unreachable,1912 else => unreachable,
1904 };1913 };
1905 }1914 }
...@@ -1981,12 +1990,18 @@ pub const DeclGen = struct {...@@ -1981,12 +1990,18 @@ pub const DeclGen = struct {
1981 try dg.writeCValue(writer, member);1990 try dg.writeCValue(writer, member);
1982 }1991 }
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 {
1985 const decl = dg.module.declPtr(decl_index);1999 const decl = dg.module.declPtr(decl_index);
1986 const fwd = dg.fwd_decl.writer();2000 const fwd = dg.fwd_decl.writer();
1987 const visibility = if (variable.is_extern) .global else dg.declVisibility(.{ .ty = decl.ty, .val = decl.val });2001 const is_global = variable.is_extern or dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val });
1988 try visibility.renderFwd(fwd);2002 try fwd.writeAll(if (is_global) "zig_extern " else "static ");
1989 const export_weak_linkage = if (dg.module.decl_exports.get(decl_index)) |exports|2003 const maybe_exports = dg.module.decl_exports.get(decl_index);
2004 const export_weak_linkage = if (maybe_exports) |exports|
1990 exports.items[0].opts.linkage == .Weak2005 exports.items[0].opts.linkage == .Weak
1991 else2006 else
1992 false;2007 false;
...@@ -2000,6 +2015,21 @@ pub const DeclGen = struct {...@@ -2000,6 +2015,21 @@ pub const DeclGen = struct {
2000 decl.alignment,2015 decl.alignment,
2001 .complete,2016 .complete,
2002 );2017 );
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 }
2003 try fwd.writeAll(";\n");2033 try fwd.writeAll(";\n");
2004 }2034 }
20052035
...@@ -2009,9 +2039,13 @@ pub const DeclGen = struct {...@@ -2009,9 +2039,13 @@ pub const DeclGen = struct {
2009 try mod.markDeclAlive(decl);2039 try mod.markDeclAlive(decl);
20102040
2011 if (mod.decl_exports.get(decl_index)) |exports| {2041 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 });
2013 } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| {2045 } 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 });
2015 } else {2049 } else {
2016 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),2050 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
2017 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.2051 // 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 {...@@ -2643,54 +2677,61 @@ fn genExports(o: *Object) !void {
26432677
2644 const mod = o.dg.module;2678 const mod = o.dg.module;
2645 const ip = &mod.intern_pool;2679 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 };
2647 const decl = mod.declPtr(decl_index);2684 const decl = mod.declPtr(decl_index);
2648 const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) };2685 const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) };
2649 const fwd = o.dg.fwd_decl.writer();2686 const fwd = o.dg.fwd_decl.writer();
26502687
2651 const exports = mod.decl_exports.get(decl_index) orelse return;2688 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);2691 const is_variable_const = switch (ip.indexToKey(tv.val.toIntern())) {
2654 if (exports.items.len < 2 and !is_mangled) return;2692 .func => return for (exports.items[1..], 1..) |@"export", i| {
26552693 try fwd.writeAll("zig_extern ");
2656 switch (ip.indexToKey(tv.val.toIntern())) {2694 if (@"export".opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn ");
2657 .func => {2695 try o.dg.renderFunctionSignature(
2658 const start_i = 1 - @intFromBool(is_mangled);2696 fwd,
2659 for (exports.items[start_i..], start_i..) |@"export", i| {2697 decl_index,
2660 try fwd.writeAll("zig_export(");2698 .forward,
2661 if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn ");2699 .{ .export_index = @intCast(i) },
2662 try o.dg.renderFunctionSignature(fwd, decl_index, .forward, .{ .export_index = @as(u32, @intCast(i)) });2700 );
2663 try fwd.print(", { }, {s});\n", .{2701 try fwd.writeAll(";\n");
2664 fmtIdent(ip.stringToSlice(exports.items[0].opts.name)),
2665 fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null),
2666 });
2667 }
2668 },2702 },
2669 .extern_func => {2703 .extern_func => {
2670 // TODO: when sema allows re-exporting extern decls2704 // TODO: when sema allows re-exporting extern decls
2671 unreachable;2705 unreachable;
2672 },2706 },
2673 .variable => |variable| {2707 .variable => |variable| variable.is_const,
2674 const start_i = 1 - @intFromBool(is_mangled);2708 else => true,
2675 for (exports.items[start_i..], start_i..) |@"export", i| {2709 };
2676 try fwd.writeAll("zig_export(");2710 for (exports.items[1..]) |@"export"| {
2677 if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage ");2711 try fwd.writeAll("zig_extern ");
2678 const alias = ip.stringToSlice(@"export".opts.name);2712 if (@"export".opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage ");
2679 try o.dg.renderTypeAndName(2713 const export_name = ip.stringToSlice(@"export".opts.name);
2680 fwd,2714 try o.dg.renderTypeAndName(
2681 decl.ty,2715 fwd,
2682 .{ .identifier = alias },2716 decl.ty,
2683 CQualifiers.init(.{ .@"const" = variable.is_const }),2717 .{ .identifier = export_name },
2684 decl.alignment,2718 CQualifiers.init(.{ .@"const" = is_variable_const }),
2685 .complete,2719 decl.alignment,
2686 );2720 .complete,
2687 try fwd.print(", { }, {s});\n", .{2721 );
2688 fmtIdent(ip.stringToSlice(exports.items[0].opts.name)),2722 if (isMangledIdent(export_name, true)) {
2689 fmtStringLiteral(alias, null),2723 try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
2690 });2724 fmtIdent(export_name),
2691 }2725 fmtStringLiteral(export_name, null),
2692 },2726 fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
2693 else => {},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");
2694 }2735 }
2695}2736}
26962737
...@@ -2762,12 +2803,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {...@@ -2762,12 +2803,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2762 fwd_decl_writer,2803 fwd_decl_writer,
2763 fn_decl_index,2804 fn_decl_index,
2764 .forward,2805 .forward,
2765 .{ .string = fn_name },2806 .{ .ident = fn_name },
2766 );2807 );
2767 try fwd_decl_writer.writeAll(";\n");2808 try fwd_decl_writer.writeAll(";\n");
27682809
2769 try w.print("static zig_{s} ", .{@tagName(key)});2810 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 });
2771 try w.writeAll(" {\n return ");2812 try w.writeAll(" {\n return ");
2772 try o.dg.renderDeclName(w, fn_decl_index, 0);2813 try o.dg.renderDeclName(w, fn_decl_index, 0);
2773 try w.writeByte('(');2814 try w.writeByte('(');
...@@ -2797,9 +2838,9 @@ pub fn genFunc(f: *Function) !void {...@@ -2797,9 +2838,9 @@ pub fn genFunc(f: *Function) !void {
2797 o.code_header = std.ArrayList(u8).init(gpa);2838 o.code_header = std.ArrayList(u8).init(gpa);
2798 defer o.code_header.deinit();2839 defer o.code_header.deinit();
27992840
2800 const visibility = o.dg.declVisibility(tv);2841 const is_global = o.dg.declIsGlobal(tv);
2801 const fwd_decl_writer = o.dg.fwd_decl.writer();2842 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
2804 if (mod.decl_exports.get(decl_index)) |exports|2845 if (mod.decl_exports.get(decl_index)) |exports|
2805 if (exports.items[0].opts.linkage == .Weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");2846 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 {...@@ -2808,7 +2849,7 @@ pub fn genFunc(f: *Function) !void {
2808 try genExports(o);2849 try genExports(o);
28092850
2810 try o.indent_writer.insertNewline();2851 try o.indent_writer.insertNewline();
2811 try visibility.renderDef(o.writer());2852 if (!is_global) try o.writer().writeAll("static ");
2812 try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });2853 try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });
2813 try o.writer().writeByte(' ');2854 try o.writer().writeByte(' ');
28142855
...@@ -2887,14 +2928,14 @@ pub fn genDecl(o: *Object) !void {...@@ -2887,14 +2928,14 @@ pub fn genDecl(o: *Object) !void {
2887 try fwd_decl_writer.writeAll(";\n");2928 try fwd_decl_writer.writeAll(";\n");
2888 try genExports(o);2929 try genExports(o);
2889 } else if (tv.val.getVariable(mod)) |variable| {2930 } else if (tv.val.getVariable(mod)) |variable| {
2890 try o.dg.renderFwdDecl(decl_index, variable);2931 try o.dg.renderFwdDecl(decl_index, variable, .final);
2891 try genExports(o);2932 try genExports(o);
28922933
2893 if (variable.is_extern) return;2934 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);
2896 const w = o.writer();2937 const w = o.writer();
2897 try visibility.renderDef(w);2938 if (!is_global) try w.writeAll("static ");
2898 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");2939 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
2899 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");2940 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
2900 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|2941 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
...@@ -2907,21 +2948,16 @@ pub fn genDecl(o: *Object) !void {...@@ -2907,21 +2948,16 @@ pub fn genDecl(o: *Object) !void {
2907 try w.writeByte(';');2948 try w.writeByte(';');
2908 try o.indent_writer.insertNewline();2949 try o.indent_writer.insertNewline();
2909 } else {2950 } else {
2910 const visibility: DeclVisibility = if (o.dg.module.decl_exports.get(decl_index)) |exports| b: {2951 const is_global = o.dg.module.decl_exports.contains(decl_index);
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;
2916 const decl_c_value = .{ .decl = decl_index };2952 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");
2918 }2954 }
2919}2955}
29202956
2921pub fn genDeclValue(2957pub fn genDeclValue(
2922 o: *Object,2958 o: *Object,
2923 tv: TypedValue,2959 tv: TypedValue,
2924 visibility: DeclVisibility,2960 is_global: bool,
2925 decl_c_value: CValue,2961 decl_c_value: CValue,
2926 alignment: Alignment,2962 alignment: Alignment,
2927 link_section: InternPool.OptionalNullTerminatedString,2963 link_section: InternPool.OptionalNullTerminatedString,
...@@ -2929,12 +2965,27 @@ pub fn genDeclValue(...@@ -2929,12 +2965,27 @@ pub fn genDeclValue(
2929 const mod = o.dg.module;2965 const mod = o.dg.module;
2930 const fwd_decl_writer = o.dg.fwd_decl.writer();2966 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 ");
2933 try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete);2969 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 }
2934 try fwd_decl_writer.writeAll(";\n");2984 try fwd_decl_writer.writeAll(";\n");
2985 try genExports(o);
29352986
2936 const w = o.writer();2987 const w = o.writer();
2937 try visibility.renderDef(w);2988 if (!is_global) try w.writeAll("static ");
29382989
2939 if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|2990 if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|
2940 try w.print("zig_linksection(\"{s}\", ", .{s});2991 try w.print("zig_linksection(\"{s}\", ", .{s});
...@@ -2959,16 +3010,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -2959,16 +3010,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
2959 const writer = dg.fwd_decl.writer();3010 const writer = dg.fwd_decl.writer();
29603011
2961 switch (tv.ty.zigTypeTag(mod)) {3012 switch (tv.ty.zigTypeTag(mod)) {
2962 .Fn => {3013 .Fn => if (dg.declIsGlobal(tv)) {
2963 const visibility = dg.declVisibility(tv);3014 try writer.writeAll("zig_extern ");
2964 switch (visibility) {3015 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
2965 .global, .global_mangled => {3016 try dg.fwd_decl.appendSlice(";\n");
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 }
2972 },3017 },
2973 else => {},3018 else => {},
2974 }3019 }
...@@ -7451,11 +7496,11 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7451,11 +7496,11 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
7451fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {7496fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
7452 return switch (order) {7497 return switch (order) {
7453 // Note: unordered is actually even less atomic than relaxed7498 // Note: unordered is actually even less atomic than relaxed
7454 .Unordered, .Monotonic => "memory_order_relaxed",7499 .Unordered, .Monotonic => "zig_memory_order_relaxed",
7455 .Acquire => "memory_order_acquire",7500 .Acquire => "zig_memory_order_acquire",
7456 .Release => "memory_order_release",7501 .Release => "zig_memory_order_release",
7457 .AcqRel => "memory_order_acq_rel",7502 .AcqRel => "zig_memory_order_acq_rel",
7458 .SeqCst => "memory_order_seq_cst",7503 .SeqCst => "zig_memory_order_seq_cst",
7459 };7504 };
7460}7505}
74617506
src/link/C.zig+1-1
...@@ -291,7 +291,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {...@@ -291,7 +291,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
291 };291 };
292 const c_value: codegen.CValue = .{ .constant = anon_decl };292 const c_value: codegen.CValue = .{ .constant = anon_decl };
293 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;293 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) {
295 error.AnalysisFail => {295 error.AnalysisFail => {
296 @panic("TODO: C backend AnalysisFail on anonymous decl");296 @panic("TODO: C backend AnalysisFail on anonymous decl");
297 //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);297 //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
test/behavior.zig+1-3
...@@ -110,7 +110,6 @@ test {...@@ -110,7 +110,6 @@ test {
110 _ = @import("behavior/bugs/12551.zig");110 _ = @import("behavior/bugs/12551.zig");
111 _ = @import("behavior/bugs/12571.zig");111 _ = @import("behavior/bugs/12571.zig");
112 _ = @import("behavior/bugs/12644.zig");112 _ = @import("behavior/bugs/12644.zig");
113 _ = @import("behavior/bugs/12680.zig");
114 _ = @import("behavior/bugs/12723.zig");113 _ = @import("behavior/bugs/12723.zig");
115 _ = @import("behavior/bugs/12776.zig");114 _ = @import("behavior/bugs/12776.zig");
116 _ = @import("behavior/bugs/12786.zig");115 _ = @import("behavior/bugs/12786.zig");
...@@ -175,6 +174,7 @@ test {...@@ -175,6 +174,7 @@ test {
175 _ = @import("behavior/hasfield.zig");174 _ = @import("behavior/hasfield.zig");
176 _ = @import("behavior/if.zig");175 _ = @import("behavior/if.zig");
177 _ = @import("behavior/import.zig");176 _ = @import("behavior/import.zig");
177 _ = @import("behavior/import_c_keywords.zig");
178 _ = @import("behavior/incomplete_struct_param_tld.zig");178 _ = @import("behavior/incomplete_struct_param_tld.zig");
179 _ = @import("behavior/inline_switch.zig");179 _ = @import("behavior/inline_switch.zig");
180 _ = @import("behavior/int128.zig");180 _ = @import("behavior/int128.zig");
...@@ -251,9 +251,7 @@ test {...@@ -251,9 +251,7 @@ test {
251 }251 }
252252
253 if (builtin.zig_backend != .stage2_arm and253 if (builtin.zig_backend != .stage2_arm and
254 builtin.zig_backend != .stage2_x86_64 and
255 builtin.zig_backend != .stage2_aarch64 and254 builtin.zig_backend != .stage2_aarch64 and
256 builtin.zig_backend != .stage2_c and
257 builtin.zig_backend != .stage2_spirv64)255 builtin.zig_backend != .stage2_spirv64)
258 {256 {
259 _ = @import("behavior/export_keyword.zig");257 _ = @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}