authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-29 07:32:01+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-29 14:25:51+01:00
loga7119d4269f0c31281cd472aab6228593378b294
tree409a3b7035331c76fdfaf0ca34a926378f9ee26d
parent6568f0f75b900d2ee27363b2ba81bedf206a13e7

remove all IBM AIX and z/OS support

As with Solaris (dba1bf935390ddb0184a4dc72245454de6c06fd2), we have no way to actually audit contributions for these OSs. IBM also makes it even harder than Oracle to actually obtain these OSs. closes #23695 closes #23694 closes #3655 closes #23693

38 files changed, 47 insertions(+), 1910 deletions(-)

CMakeLists.txt-2
......@@ -581,7 +581,6 @@ set(ZIG_STAGE2_SOURCES
581581 src/link/Elf/relocation.zig
582582 src/link/Elf/synthetic_sections.zig
583583 src/link/Elf2.zig
584 src/link/Goff.zig
585584 src/link/LdScript.zig
586585 src/link/Lld.zig
587586 src/link/MachO.zig
......@@ -617,7 +616,6 @@ set(ZIG_STAGE2_SOURCES
617616 src/link/Wasm/Archive.zig
618617 src/link/Wasm/Flush.zig
619618 src/link/Wasm/Object.zig
620 src/link/Xcoff.zig
621619 src/link/aarch64.zig
622620 src/link/riscv.zig
623621 src/link/table_section.zig
lib/compiler/aro/aro/Compilation.zig-8
......@@ -362,7 +362,6 @@ fn generateSystemDefines(comp: *Compilation, w: *std.Io.Writer) !void {
362362 .haiku,
363363 .hurd,
364364 .illumos,
365 .aix,
366365 .emscripten,
367366 .ps4,
368367 .ps5,
......@@ -1006,13 +1005,6 @@ fn writeBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefinesMode
10061005 \\
10071006 );
10081007 },
1009 .aix => {
1010 try w.writeAll(
1011 \\#define __STDC_NO_THREADS__ 1
1012 \\#define __STDC_NO_ATOMICS__ 1
1013 \\
1014 );
1015 },
10161008 else => {},
10171009 };
10181010 if (comp.langopts.standard.StdCVersionMacro()) |stdc_version| {
lib/compiler/aro/aro/Driver.zig+1-1
......@@ -810,7 +810,7 @@ pub fn parseArgs(
810810 if (strip) break :debug .strip;
811811 if (debug) |explicit| break :debug explicit;
812812 break :debug switch (d.comp.target.ofmt) {
813 .elf, .goff, .macho, .wasm, .xcoff => .{ .dwarf = .@"32" },
813 .elf, .macho, .wasm => .{ .dwarf = .@"32" },
814814 .coff => .code_view,
815815 .c => switch (d.comp.target.os.tag) {
816816 .windows, .uefi => .code_view,
lib/compiler/aro/aro/Toolchain.zig+3-7
......@@ -369,7 +369,7 @@ fn getUnwindLibKind(tc: *const Toolchain) !UnwindLibKind {
369369 switch (tc.getRuntimeLibKind()) {
370370 .compiler_rt => {
371371 const target = tc.getTarget();
372 if (target.abi.isAndroid() or target.os.tag == .aix) {
372 if (target.abi.isAndroid()) {
373373 return .compiler_rt;
374374 } else {
375375 return .none;
......@@ -408,7 +408,7 @@ fn addUnwindLibrary(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !voi
408408 unw == .none) return;
409409
410410 const lgk = tc.getLibGCCKind();
411 const as_needed = lgk == .unspecified and !target.abi.isAndroid() and !target_util.isCygwinMinGW(target) and target.os.tag != .aix;
411 const as_needed = lgk == .unspecified and !target.abi.isAndroid() and !target_util.isCygwinMinGW(target);
412412
413413 try argv.ensureUnusedCapacity(tc.driver.comp.gpa, 3);
414414 if (as_needed) {
......@@ -417,11 +417,7 @@ fn addUnwindLibrary(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !voi
417417 switch (unw) {
418418 .none => return,
419419 .libgcc => argv.appendAssumeCapacity(if (lgk == .static) "-lgcc_eh" else "-lgcc_s"),
420 .compiler_rt => if (target.os.tag == .aix) {
421 if (lgk != .static) {
422 argv.appendAssumeCapacity("-lunwind");
423 }
424 } else if (lgk == .static) {
420 .compiler_rt => if (lgk == .static) {
425421 argv.appendAssumeCapacity("-l:libunwind.a");
426422 } else if (lgk == .shared) {
427423 if (target_util.isCygwinMinGW(target)) {
lib/compiler/aro/aro/TypeStore.zig+1-4
......@@ -2099,10 +2099,7 @@ fn generateVaListType(ts: *TypeStore, comp: *Compilation) !QualType {
20992099 .hexagon_va_list
21002100 else
21012101 return .char_pointer,
2102 .powerpc, .powerpcle => switch (comp.target.os.tag) {
2103 .aix => return .char_pointer,
2104 else => .powerpc_va_list,
2105 },
2102 .powerpc, .powerpcle => .powerpc_va_list,
21062103 .s390x => .s390x_va_list,
21072104 .x86_64 => switch (comp.target.os.tag) {
21082105 .uefi, .windows => return .char_pointer,
lib/compiler/aro/aro/target.zig+1-9
......@@ -403,7 +403,6 @@ pub fn builtinEnabled(target: std.Target, enabled_for: TargetSet) bool {
403403}
404404
405405pub fn defaultFpEvalMethod(target: std.Target) LangOpts.FPEvalMethod {
406 if (target.os.tag == .aix) return .double;
407406 switch (target.cpu.arch) {
408407 .x86, .x86_64 => {
409408 if (target.ptrBitWidth() == 32 and target.os.tag == .netbsd) {
......@@ -656,10 +655,8 @@ pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 {
656655 .openbsd => "openbsd",
657656 .illumos => "solaris",
658657 .windows => "windows",
659 .zos => "zos",
660658 .haiku => "haiku",
661659 .rtems => "rtems",
662 .aix => "aix",
663660 .cuda => "cuda",
664661 .nvcl => "nvcl",
665662 .amdhsa => "amdhsa",
......@@ -741,7 +738,6 @@ pub const DefaultPIStatus = enum { yes, no, depends_on_linker };
741738
742739pub fn isPIEDefault(target: std.Target) DefaultPIStatus {
743740 return switch (target.os.tag) {
744 .aix,
745741 .haiku,
746742
747743 .macos,
......@@ -765,7 +761,6 @@ pub fn isPIEDefault(target: std.Target) DefaultPIStatus {
765761 .ps5,
766762
767763 .hurd,
768 .zos,
769764 => .no,
770765
771766 .openbsd,
......@@ -810,7 +805,6 @@ pub fn isPIEDefault(target: std.Target) DefaultPIStatus {
810805
811806pub fn isPICdefault(target: std.Target) DefaultPIStatus {
812807 return switch (target.os.tag) {
813 .aix,
814808 .haiku,
815809
816810 .macos,
......@@ -830,7 +824,6 @@ pub fn isPICdefault(target: std.Target) DefaultPIStatus {
830824
831825 .fuchsia,
832826 .cuda,
833 .zos,
834827 => .no,
835828
836829 .dragonfly,
......@@ -889,7 +882,7 @@ pub fn isPICdefault(target: std.Target) DefaultPIStatus {
889882
890883pub fn isPICDefaultForced(target: std.Target) DefaultPIStatus {
891884 return switch (target.os.tag) {
892 .aix, .amdhsa, .amdpal, .mesa3d => .yes,
885 .amdhsa, .amdpal, .mesa3d => .yes,
893886
894887 .haiku,
895888 .dragonfly,
......@@ -903,7 +896,6 @@ pub fn isPICDefaultForced(target: std.Target) DefaultPIStatus {
903896 .hurd,
904897 .linux,
905898 .fuchsia,
906 .zos,
907899 => .no,
908900
909901 .windows => {
lib/include/zos_wrappers/builtins.h deleted-18
......@@ -1,18 +0,0 @@
1/*===---- builtins.h - z/Architecture Builtin Functions --------------------===
2 *
3 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 * See https://llvm.org/LICENSE.txt for license information.
5 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 *
7 *===-----------------------------------------------------------------------===
8 */
9
10#ifndef __ZOS_WRAPPERS_BUILTINS_H
11#define __ZOS_WRAPPERS_BUILTINS_H
12#if defined(__MVS__)
13#include_next <builtins.h>
14#if defined(__VEC__)
15#include <vecintrin.h>
16#endif
17#endif /* defined(__MVS__) */
18#endif /* __ZOS_WRAPPERS_BUILTINS_H */
lib/libcxx/include/__locale_dir/locale_base_api/ibm.h deleted-108
......@@ -1,108 +0,0 @@
1// -*- C++ -*-
2//===-----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_IBM_H
11#define _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_IBM_H
12
13#if defined(__MVS__)
14# include <__support/ibm/locale_mgmt_zos.h>
15#endif // defined(__MVS__)
16
17#include <locale.h>
18#include <stdarg.h>
19#include <stdio.h>
20
21#include "cstdlib"
22
23#if defined(__MVS__)
24# include <wctype.h>
25// POSIX routines
26# include <__support/xlocale/__posix_l_fallback.h>
27#endif // defined(__MVS__)
28
29namespace {
30
31struct __setAndRestore {
32 explicit __setAndRestore(locale_t locale) {
33 if (locale == (locale_t)0) {
34 __cloc = newlocale(LC_ALL_MASK, "C", /* base */ (locale_t)0);
35 __stored = uselocale(__cloc);
36 } else {
37 __stored = uselocale(locale);
38 }
39 }
40
41 ~__setAndRestore() {
42 uselocale(__stored);
43 if (__cloc)
44 freelocale(__cloc);
45 }
46
47private:
48 locale_t __stored = (locale_t)0;
49 locale_t __cloc = (locale_t)0;
50};
51
52} // namespace
53
54// The following are not POSIX routines. These are quick-and-dirty hacks
55// to make things pretend to work
56inline _LIBCPP_HIDE_FROM_ABI long long strtoll_l(const char* __nptr, char** __endptr, int __base, locale_t locale) {
57 __setAndRestore __newloc(locale);
58 return ::strtoll(__nptr, __endptr, __base);
59}
60
61inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr, locale_t locale) {
62 __setAndRestore __newloc(locale);
63 return ::strtod(__nptr, __endptr);
64}
65
66inline _LIBCPP_HIDE_FROM_ABI float strtof_l(const char* __nptr, char** __endptr, locale_t locale) {
67 __setAndRestore __newloc(locale);
68 return ::strtof(__nptr, __endptr);
69}
70
71inline _LIBCPP_HIDE_FROM_ABI long double strtold_l(const char* __nptr, char** __endptr, locale_t locale) {
72 __setAndRestore __newloc(locale);
73 return ::strtold(__nptr, __endptr);
74}
75
76inline _LIBCPP_HIDE_FROM_ABI unsigned long long
77strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t locale) {
78 __setAndRestore __newloc(locale);
79 return ::strtoull(__nptr, __endptr, __base);
80}
81
82inline _LIBCPP_HIDE_FROM_ABI
83_LIBCPP_ATTRIBUTE_FORMAT(__printf__, 2, 0) int vasprintf(char** strp, const char* fmt, va_list ap) {
84 const size_t buff_size = 256;
85 if ((*strp = (char*)malloc(buff_size)) == nullptr) {
86 return -1;
87 }
88
89 va_list ap_copy;
90 // va_copy may not be provided by the C library in C++03 mode.
91#if defined(_LIBCPP_CXX03_LANG) && __has_builtin(__builtin_va_copy)
92 __builtin_va_copy(ap_copy, ap);
93#else
94 va_copy(ap_copy, ap);
95#endif
96 int str_size = vsnprintf(*strp, buff_size, fmt, ap_copy);
97 va_end(ap_copy);
98
99 if ((size_t)str_size >= buff_size) {
100 if ((*strp = (char*)realloc(*strp, str_size + 1)) == nullptr) {
101 return -1;
102 }
103 str_size = vsnprintf(*strp, str_size + 1, fmt, ap);
104 }
105 return str_size;
106}
107
108#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_IBM_H
lib/libcxx/include/__support/ibm/gettod_zos.h deleted-52
......@@ -1,52 +0,0 @@
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___SUPPORT_IBM_GETTOD_ZOS_H
11#define _LIBCPP___SUPPORT_IBM_GETTOD_ZOS_H
12
13#include <time.h>
14
15inline _LIBCPP_HIDE_FROM_ABI int gettimeofdayMonotonic(struct timespec64* Output) {
16 // The POSIX gettimeofday() function is not available on z/OS. Therefore,
17 // we will call stcke and other hardware instructions in implement equivalent.
18 // Note that nanoseconds alone will overflow when reaching new epoch in 2042.
19
20 struct _t {
21 uint64_t Hi;
22 uint64_t Lo;
23 };
24 struct _t Value = {0, 0};
25 uint64_t CC = 0;
26 asm(" stcke %0\n"
27 " ipm %1\n"
28 " srlg %1,%1,28\n"
29 : "=m"(Value), "+r"(CC)::);
30
31 if (CC != 0) {
32 errno = EMVSTODNOTSET;
33 return CC;
34 }
35 uint64_t us = (Value.Hi >> 4);
36 uint64_t ns = ((Value.Hi & 0x0F) << 8) + (Value.Lo >> 56);
37 ns = (ns * 1000) >> 12;
38 us = us - 2208988800000000;
39
40 register uint64_t DivPair0 asm("r0"); // dividend (upper half), remainder
41 DivPair0 = 0;
42 register uint64_t DivPair1 asm("r1"); // dividend (lower half), quotient
43 DivPair1 = us;
44 uint64_t Divisor = 1000000;
45 asm(" dlgr %0,%2" : "+r"(DivPair0), "+r"(DivPair1) : "r"(Divisor) :);
46
47 Output->tv_sec = DivPair1;
48 Output->tv_nsec = DivPair0 * 1000 + ns;
49 return 0;
50}
51
52#endif // _LIBCPP___SUPPORT_IBM_GETTOD_ZOS_H
lib/libcxx/include/__support/ibm/locale_mgmt_zos.h deleted-53
......@@ -1,53 +0,0 @@
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___SUPPORT_IBM_LOCALE_MGMT_ZOS_H
11#define _LIBCPP___SUPPORT_IBM_LOCALE_MGMT_ZOS_H
12
13#if defined(__MVS__)
14# include <locale.h>
15# include <string>
16
17# ifdef __cplusplus
18extern "C" {
19# endif
20
21# define _LC_MAX LC_MESSAGES /* highest real category */
22# define _NCAT (_LC_MAX + 1) /* maximum + 1 */
23
24# define _CATMASK(n) (1 << (n))
25# define LC_COLLATE_MASK _CATMASK(LC_COLLATE)
26# define LC_CTYPE_MASK _CATMASK(LC_CTYPE)
27# define LC_MONETARY_MASK _CATMASK(LC_MONETARY)
28# define LC_NUMERIC_MASK _CATMASK(LC_NUMERIC)
29# define LC_TIME_MASK _CATMASK(LC_TIME)
30# define LC_MESSAGES_MASK _CATMASK(LC_MESSAGES)
31# define LC_ALL_MASK (_CATMASK(_NCAT) - 1)
32
33typedef struct locale_struct {
34 int category_mask;
35 std::string lc_collate;
36 std::string lc_ctype;
37 std::string lc_monetary;
38 std::string lc_numeric;
39 std::string lc_time;
40 std::string lc_messages;
41}* locale_t;
42
43// z/OS does not have newlocale, freelocale and uselocale.
44// The functions below are workarounds in single thread mode.
45locale_t newlocale(int category_mask, const char* locale, locale_t base);
46void freelocale(locale_t locobj);
47locale_t uselocale(locale_t newloc);
48
49# ifdef __cplusplus
50}
51# endif
52#endif // defined(__MVS__)
53#endif // _LIBCPP___SUPPORT_IBM_LOCALE_MGMT_ZOS_H
lib/libcxx/include/__support/ibm/nanosleep.h deleted-55
......@@ -1,55 +0,0 @@
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___SUPPORT_IBM_NANOSLEEP_H
11#define _LIBCPP___SUPPORT_IBM_NANOSLEEP_H
12
13#include <unistd.h>
14
15inline int nanosleep(const struct timespec* __req, struct timespec* __rem) {
16 // The nanosleep() function is not available on z/OS. Therefore, we will call
17 // sleep() to sleep for whole seconds and usleep() to sleep for any remaining
18 // fraction of a second. Any remaining nanoseconds will round up to the next
19 // microsecond.
20 if (__req->tv_sec < 0 || __req->tv_nsec < 0 || __req->tv_nsec > 999999999) {
21 errno = EINVAL;
22 return -1;
23 }
24 long __micro_sec = (__req->tv_nsec + 999) / 1000;
25 time_t __sec = __req->tv_sec;
26 if (__micro_sec > 999999) {
27 ++__sec;
28 __micro_sec -= 1000000;
29 }
30 __sec = static_cast<time_t>(sleep(static_cast<unsigned int>(__sec)));
31 if (__sec) {
32 if (__rem) {
33 // Updating the remaining time to sleep in case of unsuccessful call to sleep().
34 __rem->tv_sec = __sec;
35 __rem->tv_nsec = __micro_sec * 1000;
36 }
37 errno = EINTR;
38 return -1;
39 }
40 if (__micro_sec) {
41 int __rt = usleep(static_cast<unsigned int>(__micro_sec));
42 if (__rt != 0 && __rem) {
43 // The usleep() does not provide the amount of remaining time upon its failure,
44 // so the time slept will be ignored.
45 __rem->tv_sec = 0;
46 __rem->tv_nsec = __micro_sec * 1000;
47 // The errno is already set.
48 return -1;
49 }
50 return __rt;
51 }
52 return 0;
53}
54
55#endif // _LIBCPP___SUPPORT_IBM_NANOSLEEP_H
lib/libcxx/src/support/ibm/mbsnrtowcs.cpp deleted-97
......@@ -1,97 +0,0 @@
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <cstddef> // size_t
10#include <cwchar> // mbstate_t
11#include <limits.h> // MB_LEN_MAX
12#include <string.h> // wmemcpy
13
14// Returns the number of wide characters found in the multi byte sequence `src`
15// (of `src_size_bytes`), that fit in the buffer `dst` (of `max_dest_chars`
16// elements size). The count returned excludes the null terminator.
17// When `dst` is NULL, no characters are copied to `dst`.
18// Returns (size_t) -1 when an invalid sequence is encountered.
19// Leaves *`src` pointing to the next character to convert or NULL
20// if a null character was converted from *`src`.
21_LIBCPP_EXPORTED_FROM_ABI size_t mbsnrtowcs(
22 wchar_t* __restrict dst,
23 const char** __restrict src,
24 size_t src_size_bytes,
25 size_t max_dest_chars,
26 mbstate_t* __restrict ps) {
27 const size_t terminated_sequence = static_cast<size_t>(0);
28 const size_t invalid_sequence = static_cast<size_t>(-1);
29 const size_t incomplete_sequence = static_cast<size_t>(-2);
30
31 size_t source_converted;
32 size_t dest_converted;
33 size_t result = 0;
34
35 // If `dst` is null then `max_dest_chars` should be ignored according to the
36 // standard. Setting `max_dest_chars` to a large value has this effect.
37 if (dst == nullptr)
38 max_dest_chars = static_cast<size_t>(-1);
39
40 for (dest_converted = source_converted = 0;
41 source_converted < src_size_bytes && (!dst || dest_converted < max_dest_chars);
42 ++dest_converted, source_converted += result) {
43 // Converts one multi byte character.
44 // If result (char_size) is greater than 0, it's the size in bytes of that character.
45 // If result (char_size) is zero, it indicates that the null character has been found.
46 // Otherwise, it's an error and errno may be set.
47 size_t source_remaining = src_size_bytes - source_converted;
48 size_t dest_remaining = max_dest_chars - dest_converted;
49
50 if (dst == nullptr) {
51 result = mbrtowc(nullptr, *src + source_converted, source_remaining, ps);
52 } else if (dest_remaining >= source_remaining) {
53 // dst has enough space to translate in-place.
54 result = mbrtowc(dst + dest_converted, *src + source_converted, source_remaining, ps);
55 } else {
56 /*
57 * dst may not have enough space, so use a temporary buffer.
58 *
59 * We need to save a copy of the conversion state
60 * here so we can restore it if the multibyte
61 * character is too long for the buffer.
62 */
63 wchar_t buff[MB_LEN_MAX];
64 mbstate_t mbstate_tmp;
65
66 if (ps != nullptr)
67 mbstate_tmp = *ps;
68 result = mbrtowc(buff, *src + source_converted, source_remaining, ps);
69
70 if (result > dest_remaining) {
71 // Multi-byte sequence for character won't fit.
72 if (ps != nullptr)
73 *ps = mbstate_tmp;
74 break;
75 } else {
76 // The buffer was used, so we need copy the translation to dst.
77 wmemcpy(dst, buff, result);
78 }
79 }
80
81 // Don't do anything to change errno from here on.
82 if (result == invalid_sequence || result == terminated_sequence || result == incomplete_sequence) {
83 break;
84 }
85 }
86
87 if (dst) {
88 if (result == terminated_sequence)
89 *src = nullptr;
90 else
91 *src += source_converted;
92 }
93 if (result == invalid_sequence)
94 return invalid_sequence;
95
96 return dest_converted;
97}
lib/libcxx/src/support/ibm/wcsnrtombs.cpp deleted-94
......@@ -1,94 +0,0 @@
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <cwchar> // mbstate_t
10#include <limits.h> // MB_LEN_MAX
11#include <stdlib.h> // MB_CUR_MAX, size_t
12#include <string.h> // memcpy
13
14// Converts `max_source_chars` from the wide character buffer pointer to by *`src`,
15// into the multi byte character sequence buffer stored at `dst`, which must be
16// `dst_size_bytes` bytes in size. Returns the number of bytes in the sequence
17// converted from *src, excluding the null terminator.
18// Returns (size_t) -1 if an error occurs and sets errno.
19// If `dst` is NULL, `dst_size_bytes` is ignored and no bytes are copied to `dst`.
20_LIBCPP_EXPORTED_FROM_ABI size_t wcsnrtombs(
21 char* __restrict dst,
22 const wchar_t** __restrict src,
23 size_t max_source_chars,
24 size_t dst_size_bytes,
25 mbstate_t* __restrict ps) {
26 const size_t invalid_wchar = static_cast<size_t>(-1);
27
28 size_t source_converted;
29 size_t dest_converted;
30 size_t result = 0;
31
32 // If `dst` is null then `dst_size_bytes` should be ignored according to the
33 // standard. Setting dst_size_bytes to a large value has this effect.
34 if (dst == nullptr)
35 dst_size_bytes = static_cast<size_t>(-1);
36
37 for (dest_converted = source_converted = 0;
38 source_converted < max_source_chars && (!dst || dest_converted < dst_size_bytes);
39 ++source_converted, dest_converted += result) {
40 wchar_t c = (*src)[source_converted];
41 size_t dest_remaining = dst_size_bytes - dest_converted;
42
43 if (dst == nullptr) {
44 result = wcrtomb(nullptr, c, ps);
45 } else if (dest_remaining >= static_cast<size_t>(MB_CUR_MAX)) {
46 // dst has enough space to translate in-place.
47 result = wcrtomb(dst + dest_converted, c, ps);
48 } else {
49 /*
50 * dst may not have enough space, so use a temporary buffer.
51 *
52 * We need to save a copy of the conversion state
53 * here so we can restore it if the multibyte
54 * character is too long for the buffer.
55 */
56 char buff[MB_LEN_MAX];
57 mbstate_t mbstate_tmp;
58
59 if (ps != nullptr)
60 mbstate_tmp = *ps;
61 result = wcrtomb(buff, c, ps);
62
63 if (result > dest_remaining) {
64 // Multi-byte sequence for character won't fit.
65 if (ps != nullptr)
66 *ps = mbstate_tmp;
67 if (result != invalid_wchar)
68 break;
69 } else {
70 // The buffer was used, so we need copy the translation to dst.
71 memcpy(dst, buff, result);
72 }
73 }
74
75 // result (char_size) contains the size of the multi-byte-sequence converted.
76 // Otherwise, result (char_size) is (size_t) -1 and wcrtomb() sets the errno.
77 if (result == invalid_wchar) {
78 if (dst)
79 *src = *src + source_converted;
80 return invalid_wchar;
81 }
82
83 if (c == L'\0') {
84 if (dst)
85 *src = nullptr;
86 return dest_converted;
87 }
88 }
89
90 if (dst)
91 *src = *src + source_converted;
92
93 return dest_converted;
94}
lib/libcxx/src/support/ibm/xlocale_zos.cpp deleted-130
......@@ -1,130 +0,0 @@
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <__assert>
10#include <__support/ibm/xlocale.h>
11#include <sstream>
12#include <vector>
13
14#ifdef __cplusplus
15extern "C" {
16#endif // __cplusplus
17
18locale_t newlocale(int category_mask, const char* locale, locale_t base) {
19 // Maintain current locale name(s) to restore later.
20 std::string current_loc_name(setlocale(LC_ALL, 0));
21
22 // Check for errors.
23 if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == nullptr) {
24 errno = EINVAL;
25 return (locale_t)0;
26 } else {
27 for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) {
28 if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == nullptr) {
29 setlocale(LC_ALL, current_loc_name.c_str());
30 errno = EINVAL;
31 return (locale_t)0;
32 }
33 }
34 }
35
36 // Create new locale.
37 locale_t newloc = new locale_struct();
38
39 if (base) {
40 if (category_mask != LC_ALL_MASK) {
41 // Copy base when it will not be overwritten.
42 memcpy(newloc, base, sizeof(locale_struct));
43 newloc->category_mask = category_mask | base->category_mask;
44 }
45 delete base;
46 } else {
47 newloc->category_mask = category_mask;
48 }
49
50 if (category_mask & LC_COLLATE_MASK)
51 newloc->lc_collate = locale;
52 if (category_mask & LC_CTYPE_MASK)
53 newloc->lc_ctype = locale;
54 if (category_mask & LC_MONETARY_MASK)
55 newloc->lc_monetary = locale;
56 if (category_mask & LC_NUMERIC_MASK)
57 newloc->lc_numeric = locale;
58 if (category_mask & LC_TIME_MASK)
59 newloc->lc_time = locale;
60 if (category_mask & LC_MESSAGES_MASK)
61 newloc->lc_messages = locale;
62
63 // Restore current locale.
64 setlocale(LC_ALL, current_loc_name.c_str());
65 return (locale_t)newloc;
66}
67
68void freelocale(locale_t locobj) { delete locobj; }
69
70locale_t uselocale(locale_t newloc) {
71 // Maintain current locale name(s).
72 std::string current_loc_name(setlocale(LC_ALL, 0));
73
74 if (newloc) {
75 // Set locales and check for errors.
76 bool is_error =
77 (newloc->category_mask & LC_COLLATE_MASK && setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == nullptr) ||
78 (newloc->category_mask & LC_CTYPE_MASK && setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == nullptr) ||
79 (newloc->category_mask & LC_MONETARY_MASK && setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == nullptr) ||
80 (newloc->category_mask & LC_NUMERIC_MASK && setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == nullptr) ||
81 (newloc->category_mask & LC_TIME_MASK && setlocale(LC_TIME, newloc->lc_time.c_str()) == nullptr) ||
82 (newloc->category_mask & LC_MESSAGES_MASK && setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == nullptr);
83
84 if (is_error) {
85 setlocale(LC_ALL, current_loc_name.c_str());
86 errno = EINVAL;
87 return (locale_t)0;
88 }
89 }
90
91 // Construct and return previous locale.
92 locale_t previous_loc = new locale_struct();
93
94 // current_loc_name might be a comma-separated locale name list.
95 if (current_loc_name.find(',') != std::string::npos) {
96 // Tokenize locale name list.
97 const char delimiter = ',';
98 std::vector<std::string> tokenized;
99 std::stringstream ss(current_loc_name);
100 std::string s;
101
102 while (std::getline(ss, s, delimiter)) {
103 tokenized.push_back(s);
104 }
105
106 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(tokenized.size() >= _NCAT, "locale-name list is too short");
107
108 previous_loc->lc_collate = tokenized[LC_COLLATE];
109 previous_loc->lc_ctype = tokenized[LC_CTYPE];
110 previous_loc->lc_monetary = tokenized[LC_MONETARY];
111 previous_loc->lc_numeric = tokenized[LC_NUMERIC];
112 previous_loc->lc_time = tokenized[LC_TIME];
113 // Skip LC_TOD.
114 previous_loc->lc_messages = tokenized[LC_MESSAGES];
115 } else {
116 previous_loc->lc_collate = current_loc_name;
117 previous_loc->lc_ctype = current_loc_name;
118 previous_loc->lc_monetary = current_loc_name;
119 previous_loc->lc_numeric = current_loc_name;
120 previous_loc->lc_time = current_loc_name;
121 previous_loc->lc_messages = current_loc_name;
122 }
123
124 previous_loc->category_mask = LC_ALL_MASK;
125 return previous_loc;
126}
127
128#ifdef __cplusplus
129}
130#endif // __cplusplus
lib/libcxxabi/src/aix_state_tab_eh.inc deleted-745
......@@ -1,745 +0,0 @@
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8// This file implements the personality and helper functions for the state
9// table based EH used by IBM legacy compilers xlC and xlclang++ on AIX.
10//
11//===----------------------------------------------------------------------===//
12
13#include <new>
14#include <stdio.h>
15#include <sys/debug.h>
16
17/*
18 The legacy IBM xlC and xlclang++ compilers use the state table for EH
19 instead of the range table. Destructors, or addresses of the possible catch
20 sites or cleanup code are specified in the state table which is a finite
21 state machine (FSM). Each function that has a state table also has an
22 autolocal state variable. The state variable represents the current state
23 of the function for EH and is found through the traceback table of the
24 function during unwinding, which is located at the end of each function.
25 The FSM is an array of state entries. Each state entry has the following
26 fields:
27
28 * offset/address/pointer - the offset used to locate the object, or the
29 address of a global object, or the address of the next state if it is an
30 old conditional state change entry;
31 * dtor/landing pad - address of the destructor function to invoke,
32 or address of the catch block or cleanup code in the user code to branch to;
33 * element count/action flag - the number of elements or the flag for actions;
34 * element size - if the object is an array this is the size of one element
35 of the array;
36 * flags - flags used to control how fields in the entry are interpreted;
37 * next state - the state to execute next after the action for this state is
38 performed. The value of zero indicates the end of the state for this
39 function.
40
41 The following is the description of 'element count/action flag' field.
42+-----------------------------------------------------------------------------+
43| value | description | action |
44+-------+------------------------+--------------------------------------------+
45| > 1 | object is an array | calls __cxa_vec_cleanup to run dtor for |
46| | | each member of the array |
47+-------+------------------------+--------------------------------------------+
48| 1, 0 | object is a scalar | calls dtor for the object |
49+-------+------------------------+--------------------------------------------+
50| -1 | begin catch | branches to the handler which performes |
51| | | catch-match. If there is no catch that |
52| | | matches the exception it will be rethrown |
53+-------+------------------------+--------------------------------------------+
54| -2 | end catch | ends current catch block and continues |
55| | | attempting to catch the exception |
56+-------+------------------------+--------------------------------------------+
57| -3 | delete the object | calls the delete function of the object |
58+-------+------------------------+--------------------------------------------+
59| -4 | cleanup label | branches to the user code for cleaning up |
60+-------+------------------------+--------------------------------------------+
61*/
62
63namespace __cxxabiv1 {
64
65extern "C" {
66
67// Macros for debugging the state table parsing.
68#ifdef NDEBUG
69# define _LIBCXXABI_TRACE_STATETAB(msg, ...)
70# define _LIBCXXABI_TRACE_STATETAB0(msg)
71# define _LIBCXXABI_TRACE_STATETAB1(msg)
72# define _LIBCXXABI_TRACING_STATETAB 0
73#else
74static bool state_tab_dbg() {
75 static bool checked = false;
76 static bool log = false;
77 if (!checked) {
78 log = (getenv("LIBCXXABI_PRINT_STATTAB") != NULL);
79 checked = true;
80 }
81 return log;
82}
83
84# define _LIBCXXABI_TRACE_STATETAB(msg, ...) \
85 do { \
86 if (state_tab_dbg()) \
87 fprintf(stderr, "libcxxabi: " msg, __VA_ARGS__); \
88 } while (0)
89# define _LIBCXXABI_TRACE_STATETAB0(msg) \
90 do { \
91 if (state_tab_dbg()) \
92 fprintf(stderr, "libcxxabi: " msg); \
93 } while (0)
94# define _LIBCXXABI_TRACE_STATETAB1(msg) \
95 do { \
96 if (state_tab_dbg()) \
97 fprintf(stderr, msg); \
98 } while (0)
99
100# define _LIBCXXABI_TRACING_STATETAB state_tab_dbg()
101#endif // NDEBUG
102
103namespace __state_table_eh {
104
105// Definition of flags for the state table entry field 'action flag'.
106enum FSMEntryCount : intptr_t { beginCatch = -1, endCatch = -2, deleteObject = -3, cleanupLabel = -4, terminate = -5 };
107
108// Definition of flags for the state table entry field 'flags'.
109enum FSMEntryFlag : int16_t {
110 indirect = 0x100, // Object was thrown from a function where
111 // the return value optimization was used.
112 oldConditionalStateChange = 0x400, // State table entry is an indirect state
113 // change, dereference the address in
114 // offset as int for the target state.
115 // This is deprecated. This indicates
116 // the address is direct. (static local).
117 conditionalStateChange = 0x800, // State table entry is an indirect state
118 // change, dereference the address in
119 // offset as int for the target state.
120 // The temporary is an automatic. State
121 // change is used in cases such as
122 // (b?(T1(),foo()):(T2(),foo())),throw 42;
123 // which causes a conditional state change
124 // so that we know if T1 or T2 need to be
125 // destroyed.
126 thisFlag = 0x01, // The address of the object for the
127 // cleanup action is based on the
128 // StateVariable::thisValue.
129 vBaseFlag = 0x02, // The object is of a virtual base class.
130 globalObj = 0x04 // FSMEntry::address is the address of
131 // a global object.
132};
133
134namespace {
135// The finite state machine to be walked.
136struct FSMEntry {
137 union {
138 // Offset of the object within its stack frame or containing object.
139 intptr_t offset;
140 // Address of a global object.
141 intptr_t address;
142 // Address of the next state if it is an old conditional state change entry.
143 intptr_t nextStatePtr;
144 };
145 union {
146 // Address of the destructor function with 1 argument.
147 void (*destructor)(void*);
148 // Address of the destructor function with 2 arguments.
149 void (*xlCDestructor)(void*, size_t);
150 // The address of the catch block or cleanup code.
151 void* landingPad;
152 };
153 union {
154 // The flag for actions (when the value is negative).
155 FSMEntryCount actionFlag;
156 // The element count (when the value is positive or zero).
157 size_t elementCount;
158 };
159 size_t elemSize;
160 FSMEntryFlag flags;
161 uint16_t nextState;
162};
163
164struct FSM {
165 uint32_t magic; // Magic number of the state table.
166 int32_t numberOfStates;
167 FSMEntry table[1]; // Actually table[numberOfStates].
168};
169
170// The state variable on the stack.
171struct StateVariable {
172 int32_t state;
173 struct FSM* table;
174 intptr_t thisValue;
175 int32_t ignoreVBasePtrs;
176};
177} // namespace
178
179// State table magic number
180enum FSMMagic : uint32_t {
181 number = 0xbeefdead, // State table generated by xlC compiler.
182 number2 = 0xbeeedead, // State table generated by early version xlC compiler.
183 number3 = 0x1cedbeef // State table generated by xlclang++ compiler.
184};
185
186constexpr size_t dtorArgument = 0x02; // Flag to destructor indicating to free
187 // virtual bases, don't delete object.
188
189static void invoke_destructor(FSMEntry* fsmEntry, void* addr) {
190 _LIBCXXABI_TRACE_STATETAB("Destruct object=%p, fsmEntry=%p\n", addr, reinterpret_cast<void*>(fsmEntry));
191 try {
192 if (fsmEntry->elementCount == 1) {
193 _LIBCXXABI_TRACE_STATETAB0("calling scalar destructor\n");
194 (*fsmEntry->xlCDestructor)(addr, dtorArgument);
195 _LIBCXXABI_TRACE_STATETAB0("returned from scalar destructor\n");
196 } else {
197 _LIBCXXABI_TRACE_STATETAB0("calling vector destructor\n");
198 __cxa_vec_cleanup(addr, reinterpret_cast<size_t>(fsmEntry->elementCount), fsmEntry->elemSize,
199 fsmEntry->destructor);
200 _LIBCXXABI_TRACE_STATETAB0("returned from vector destructor\n");
201 }
202 } catch (...) {
203 _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in destructor, terminating\n");
204 std::terminate();
205 }
206}
207
208static void invoke_delete(FSMEntry* fsmEntry, void* addr) {
209 char* objectAddress = *reinterpret_cast<char**>(addr);
210
211 _LIBCXXABI_TRACE_STATETAB("Delete object=%p, fsmEntry=%p\n", reinterpret_cast<void*>(objectAddress),
212 reinterpret_cast<void*>(fsmEntry));
213 try {
214 _LIBCXXABI_TRACE_STATETAB0("..calling delete()\n");
215 // 'destructor' holds a function pointer to delete().
216 (*fsmEntry->xlCDestructor)(objectAddress, fsmEntry->elemSize);
217 _LIBCXXABI_TRACE_STATETAB0("..returned from delete()\n");
218 } catch (...) {
219 _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in delete(), terminating\n");
220 std::terminate();
221 }
222}
223
224// Get the frame address of the current function from its traceback table
225// which is at the end of each function.
226static uintptr_t get_frame_addr(_Unwind_Context* context) {
227 int framePointerReg = 1; // default frame pointer == SP.
228 uint32_t* p = reinterpret_cast<uint32_t*>(_Unwind_GetIP(context));
229
230 // Keep looking forward until a word of 0 is found. The traceback
231 // table starts at the following word.
232 while (*p)
233 ++p;
234 tbtable* TBTable = reinterpret_cast<tbtable*>(p + 1);
235
236 p = reinterpret_cast<uint32_t*>(&TBTable->tb_ext);
237
238 // Skip field parminfo if it exists.
239 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
240 ++p;
241
242 // Skip field tb_offset if it exists.
243 if (TBTable->tb.has_tboff)
244 ++p;
245
246 // Skip field hand_mask if it exists.
247 if (TBTable->tb.int_hndl)
248 ++p;
249
250 // Skip fields ctl_info and ctl_info_disp if they exist.
251 if (TBTable->tb.has_ctl)
252 p += 1 + *p;
253
254 // Skip fields name_len and name if exist.
255 if (TBTable->tb.name_present) {
256 const uint16_t name_len = *reinterpret_cast<uint16_t*>(p);
257 p = reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(p) + name_len + sizeof(uint16_t));
258 }
259
260 if (TBTable->tb.uses_alloca)
261 framePointerReg = *reinterpret_cast<char*>(p);
262
263 return _Unwind_GetGR(context, framePointerReg);
264}
265
266// Calculate the object address from the FSM entry.
267static void* compute_addr_from_table(FSMEntry* fsmEntry, StateVariable* const state, _Unwind_Context* context) {
268 void* addr;
269 if (fsmEntry->flags & FSMEntryFlag::globalObj) {
270 addr = reinterpret_cast<void*>(fsmEntry->address);
271 _LIBCXXABI_TRACE_STATETAB("Address calculation (global obj) addr=fsmEntry->address=%p\n", addr);
272 } else if (fsmEntry->flags & FSMEntryFlag::thisFlag) {
273 addr = reinterpret_cast<void*>(state->thisValue + fsmEntry->offset);
274 _LIBCXXABI_TRACE_STATETAB("Address calculation (this obj) fsmEntry->offset=%ld : "
275 "state->thisValue=%ld addr=(fsmEntry->offset+state->thisValue)=%p\n",
276 fsmEntry->offset, state->thisValue, addr);
277 } else if (fsmEntry->flags & FSMEntryFlag::indirect) {
278 addr = reinterpret_cast<void*>(
279 *reinterpret_cast<char**>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset)));
280 _LIBCXXABI_TRACE_STATETAB("Address calculation (indirect obj) addr=%p, fsmEntry->offset=%ld \n",
281 addr, fsmEntry->offset);
282 } else {
283 addr = reinterpret_cast<void*>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset));
284 _LIBCXXABI_TRACE_STATETAB("Address calculation. (local obj) addr=fsmEntry->offset=%p\n",
285 addr);
286 }
287 return addr;
288}
289
290static void scan_state_tab(scan_results& results, _Unwind_Action actions, bool native_exception,
291 _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
292 // Initialize results to found nothing but an error.
293 results.ttypeIndex = 0;
294 results.actionRecord = 0;
295 results.languageSpecificData = 0;
296 results.landingPad = 0;
297 results.adjustedPtr = 0;
298 results.reason = _URC_FATAL_PHASE1_ERROR;
299
300 // Check for consistent actions.
301 if (actions & _UA_SEARCH_PHASE) {
302 // Do Phase 1
303 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) {
304 // None of these flags should be set during Phase 1.
305 // Client error
306 results.reason = _URC_FATAL_PHASE1_ERROR;
307 return;
308 }
309 } else if (actions & _UA_CLEANUP_PHASE) {
310 if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) {
311 // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
312 // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
313 // Client error
314 results.reason = _URC_FATAL_PHASE2_ERROR;
315 return;
316 }
317 } else {
318 // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set.
319 // Client error
320 results.reason = _URC_FATAL_PHASE1_ERROR;
321 return;
322 }
323
324 if (_LIBCXXABI_TRACING_STATETAB) {
325 _LIBCXXABI_TRACE_STATETAB1("\n");
326 _LIBCXXABI_TRACE_STATETAB("%s: actions=%d (", __func__, actions);
327
328 if (_UA_SEARCH_PHASE & actions)
329 _LIBCXXABI_TRACE_STATETAB1("_UA_SEARCH_PHASE ");
330 if (_UA_CLEANUP_PHASE & actions)
331 _LIBCXXABI_TRACE_STATETAB1("_UA_CLEANUP_PHASE ");
332 if (_UA_HANDLER_FRAME & actions)
333 _LIBCXXABI_TRACE_STATETAB1("_UA_HANDLER_FRAME ");
334 if (_UA_FORCE_UNWIND & actions)
335 _LIBCXXABI_TRACE_STATETAB1("_UA_FORCE_UNWIND ");
336 _LIBCXXABI_TRACE_STATETAB1(")\n");
337 _LIBCXXABI_TRACE_STATETAB(" unwind_exception=%p context=%p\n", reinterpret_cast<void*>(unwind_exception),
338 reinterpret_cast<void*>(context));
339 }
340
341 // Start scan by getting state table address.
342 StateVariable* const state = reinterpret_cast<StateVariable* const>(_Unwind_GetLanguageSpecificData(context));
343 if (state->state <= 0) {
344 // The state is not correct - give up on this routine.
345 _LIBCXXABI_TRACE_STATETAB("state=%d and is <= 0), continue unwinding\n", state->state);
346 results.reason = _URC_CONTINUE_UNWIND;
347 return;
348 }
349 // Parse the state table.
350 FSM* const fsm = state->table;
351 FSMEntry* currFSMEntry;
352
353 if (fsm->magic != FSMMagic::number && fsm->magic != FSMMagic::number2 && fsm->magic != FSMMagic::number3) {
354 // Something is wrong with the state table we found.
355 if (_UA_SEARCH_PHASE & actions) {
356 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE1_ERROR\n");
357 results.reason = _URC_FATAL_PHASE1_ERROR;
358 } else if (_UA_CLEANUP_PHASE & actions) {
359 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE2_ERROR\n");
360 results.reason = _URC_FATAL_PHASE2_ERROR;
361 } else {
362 // We should never get here.
363 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table + RT Internal error, return _URC_FATAL_PHASE2_ERROR\n");
364 results.reason = _URC_FATAL_PHASE2_ERROR;
365 }
366 return;
367 }
368
369 if (_LIBCXXABI_TRACING_STATETAB) {
370 // Print the state table for debugging purposes.
371 _LIBCXXABI_TRACE_STATETAB("state->state=%d, state->ignoreVBasePtrs=%d\n", state->state, state->ignoreVBasePtrs);
372 _LIBCXXABI_TRACE_STATETAB("fsm->magic=%#x, fsm->numberOfStates=%d\n", fsm->magic, fsm->numberOfStates);
373 // Print out the FSM table.
374 _LIBCXXABI_TRACE_STATETAB0("FSM table:\n");
375 _LIBCXXABI_TRACE_STATETAB("%12s %10s %8s %10s %7s %7s %7s %7s\n", "Entry Addr", "state", "Offset", "DTR/lpad",
376 "count", "el_size", "flags", "next");
377 for (int i = 0; i < fsm->numberOfStates; i++) {
378 currFSMEntry = &fsm->table[i];
379 _LIBCXXABI_TRACE_STATETAB("%12p (%8d) %8ld %10p %7ld "
380 "%7ld %#7x %7d\n",
381 reinterpret_cast<void*>(&currFSMEntry), i + 1, currFSMEntry->offset,
382 reinterpret_cast<void*>(currFSMEntry->destructor),
383 currFSMEntry->elementCount, currFSMEntry->elemSize, currFSMEntry->flags,
384 currFSMEntry->nextState);
385 }
386 }
387
388 if (_UA_SEARCH_PHASE & actions) {
389 // Start walking the state table. Use a local copy of state->state so when
390 // we return from search phase we don't change the state number.
391 int currState = state->state;
392
393 while (currState > 0) {
394 currFSMEntry = &fsm->table[currState - 1];
395 _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", currState, currFSMEntry->flags);
396
397 if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch) {
398 // Found a catch handler.
399 if (fsm->magic == FSMMagic::number) {
400 _LIBCXXABI_TRACE_STATETAB0("Found a xlC catch handler, return _URC_FATAL_PHASE1_ERROR\n");
401 // xlC catch handlers cannot be entered because they use a
402 // proprietary EH runtime that is not interoperable.
403 results.reason = _URC_FATAL_PHASE1_ERROR;
404 return;
405 }
406 // xlclang++ compiled frames use CXA-abi EH calls and any catch
407 // block will include a catch(...) block so it is safe to assume that
408 // the handler is found without checking the catch match. The
409 // catch(...) block will rethrow the exception if there isn't a
410 // match.
411 _LIBCXXABI_TRACE_STATETAB0("Found a catch handler, return _URC_HANDLER_FOUND\n");
412 results.reason = _URC_HANDLER_FOUND;
413 return;
414 }
415 if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
416 _LIBCXXABI_TRACE_STATETAB0("Found the terminate state, return _URC_HANDLER_FOUND\n");
417 results.reason = _URC_HANDLER_FOUND;
418 return;
419 }
420 if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
421 // Deprecated conditional expression.
422 currState = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
423 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
424 "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
425 currFSMEntry->nextStatePtr, currState);
426 continue; // We are done this iteration of the loop, since
427 // we changed a state.
428 }
429 if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
430 void* addr = compute_addr_from_table(currFSMEntry, state, context);
431 currState = *reinterpret_cast<int*>(addr);
432 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
433 "addr(%p), set state=%d\n", addr, currState);
434 continue; // We are done this iteration of the loop, since we
435 // changed the state.
436 }
437 // Go to the next state.
438 currState = currFSMEntry->nextState;
439 }
440 _LIBCXXABI_TRACE_STATETAB0("No catch handler found, return _URC_CONTINUE_UNWIND\n");
441 results.reason = _URC_CONTINUE_UNWIND;
442 return;
443 }
444 if (_UA_CLEANUP_PHASE & actions) {
445 // Start walking the state table.
446 while (state->state > 0) {
447 currFSMEntry = &fsm->table[state->state - 1];
448
449 if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
450 _LIBCXXABI_TRACE_STATETAB0("Reached terminate state. Call terminate.\n");
451 std::terminate();
452 }
453 // Perform action according to the currFSMEntry->actionFlag,
454 // except when flag is FSMEntryFlag::conditionalStateChange or
455 // FSMEntryFlag::oldConditionalStateChange.
456 _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", state->state, currFSMEntry->flags);
457 if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
458 state->state = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
459 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
460 "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
461 currFSMEntry->nextStatePtr, state->state);
462 continue; // We are done with this iteration of the loop, since we changed a state.
463 }
464 if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
465 // A conditional state table entry holds the address of a local
466 // that holds the next state.
467 void* addr = compute_addr_from_table(currFSMEntry, state, context);
468 state->state = *reinterpret_cast<int*>(addr);
469 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
470 "addr(%p), set state=%d\n", addr, state->state);
471 continue; // We are done with this iteration of the loop, since we changed a state.
472 }
473 if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch || currFSMEntry->actionFlag == FSMEntryCount::endCatch ||
474 currFSMEntry->actionFlag == FSMEntryCount::cleanupLabel) {
475
476 _LIBCXXABI_TRACE_STATETAB(
477 "FSMEntryCount::%s: handler %p/%p, return _URC_HANDLER_FOUND\n",
478 (currFSMEntry->actionFlag == FSMEntryCount::beginCatch
479 ? "beginCatch"
480 : (currFSMEntry->actionFlag == FSMEntryCount::endCatch ? "endCatch" : "cleanupLabel")),
481 currFSMEntry->landingPad, *reinterpret_cast<void**>(currFSMEntry->landingPad));
482
483 state->state = currFSMEntry->nextState;
484 results.landingPad = reinterpret_cast<uintptr_t>(*reinterpret_cast<void**>(currFSMEntry->landingPad));
485 results.reason = _URC_HANDLER_FOUND;
486 return;
487 }
488 if (currFSMEntry->elementCount > 0) {
489 if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag && state->ignoreVBasePtrs) {
490 _LIBCXXABI_TRACE_STATETAB0("Ignoring virtual base dtor.\n");
491 } else {
492 // We need to invoke the virtual base destructor. This must be
493 // a frame from the legacy xlC compiler as the xlclang++ compiler
494 // generates inline cleanup code rather than specifying
495 // the destructor via the state table.
496 void* addr = compute_addr_from_table(currFSMEntry, state, context);
497
498 // An extra indirect to get to the object according to the object
499 // model used by the xlC compiler.
500 addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
501 _LIBCXXABI_TRACE_STATETAB("Invoke dtor for object=%p\n", addr);
502 invoke_destructor(currFSMEntry, addr);
503 }
504 } else if (currFSMEntry->actionFlag == FSMEntryCount::deleteObject) {
505 void* addr = compute_addr_from_table(currFSMEntry, state, context);
506 if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag) {
507 // We need to invoke the virtual base delete function. This must be
508 // a frame from the legacy xlC compiler as the xlclang++ compiler
509 // generates inline cleanup code rather than specifying
510 // the delete function via the state table.
511
512 // An extra indirect to get to the object according to the object
513 // model used by the xlC compiler.
514 addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
515 }
516 _LIBCXXABI_TRACE_STATETAB("Delete object at %p\n", addr);
517 invoke_delete(currFSMEntry, addr);
518 } else {
519 _LIBCXXABI_TRACE_STATETAB("Unknown entry in FSM (count=%ld), ignored\n",
520 currFSMEntry->elementCount);
521 } // End of action switching.
522
523 // Go to next state.
524 state->state = currFSMEntry->nextState;
525 }
526 _LIBCXXABI_TRACE_STATETAB0("No catch handler, return _URC_CONTINUE_UNWIND\n");
527 results.reason = _URC_CONTINUE_UNWIND;
528 return;
529 }
530 _LIBCXXABI_TRACE_STATETAB0("No state table entry for this exception, call_terminate()\n");
531 // It is possible that no state table entry specify how to handle
532 // this exception. By spec, terminate it immediately.
533 call_terminate(native_exception, unwind_exception);
534}
535
536// Personality routine for EH using the state table.
537_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
538__xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
539 _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
540 if (version != 1 || unwind_exception == 0 || context == 0)
541 return _URC_FATAL_PHASE1_ERROR;
542
543 bool native_exception = (exceptionClass & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language);
544 scan_results results;
545 scan_state_tab(results, actions, native_exception, unwind_exception, context);
546 if (actions & _UA_SEARCH_PHASE) {
547 // Phase 1 search: All we're looking for in phase 1 is a handler that
548 // halts unwinding
549 return results.reason;
550 }
551 if (actions & _UA_CLEANUP_PHASE) {
552 // Phase 2 cleanup:
553 if (results.reason == _URC_HANDLER_FOUND) {
554 // Store the address of unwind_exception in the stack field
555 // reserved for compilers (SP + 3 * sizeof(uintptr_t)) in the stack of
556 // the caller of the function containing the landing pad (within the link
557 // area for the call to the latter) for __xlc_exception_handle()
558 // to retrieve when it is called by the landing pad.
559 uintptr_t *currentSP = reinterpret_cast<uintptr_t*>(_Unwind_GetGR(context, 1));
560 uintptr_t *callersSP = reinterpret_cast<uintptr_t*>(currentSP[0]);
561 callersSP[3] = reinterpret_cast<uintptr_t>(unwind_exception);
562 _LIBCXXABI_TRACE_STATETAB("Handshake: save unwind_exception=%p in stack=%p\n",
563 reinterpret_cast<void*>(unwind_exception), reinterpret_cast<void*>(callersSP));
564 // Jump to the handler.
565 _Unwind_SetIP(context, results.landingPad);
566 return _URC_INSTALL_CONTEXT;
567 }
568 // Did not find a handler. Return the results of the scan. Normally
569 // _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR.
570 return results.reason;
571 }
572 // We were called improperly: neither a phase 1 or phase 2 search.
573 return _URC_FATAL_PHASE1_ERROR;
574}
575} // namespace __state_table_eh
576
577// The following are EH helper functions for xlclang++ compiled code.
578
579// __xlc_catch_matchv2
580// Check whether the thrown object matches the catch handler's exception
581// declaration. If there is a match, the function returns true with adjusted
582// address of the thrown object. Otherwise, returns false.
583_LIBCXXABI_FUNC_VIS bool
584__xlc_catch_matchv2(_Unwind_Exception* exceptionObject, std::type_info* catchTypeInfo, void*& obj) {
585 _LIBCXXABI_TRACE_STATETAB("Entering %s, exceptionObject=%p\n", __func__, reinterpret_cast<void*>(exceptionObject));
586
587 if (!__isOurExceptionClass(exceptionObject)) {
588 _LIBCXXABI_TRACE_STATETAB0("No match, not a C++ exception\n");
589 return false;
590 }
591
592 __cxa_exception* exceptionHeader = 0;
593
594 if (__getExceptionClass(exceptionObject) == kOurDependentExceptionClass) {
595 // Walk to the __cxa_dependent_exception primary exception for the
596 // exception object and its type_info.
597 __cxa_dependent_exception* dependentExceptionHeader =
598 reinterpret_cast<__cxa_dependent_exception*>(exceptionObject + 1) - 1;
599 exceptionHeader = reinterpret_cast<__cxa_exception*>(dependentExceptionHeader->primaryException) - 1;
600 _LIBCXXABI_TRACE_STATETAB("exceptionObject 0x%p is a dependent, primary 0x%p\n",
601 reinterpret_cast<void*>(exceptionObject),
602 reinterpret_cast<void*>(&exceptionHeader->unwindHeader));
603 exceptionObject = &exceptionHeader->unwindHeader;
604 } else {
605 _LIBCXXABI_TRACE_STATETAB("exceptionObject %p is NOT a dependent\n", reinterpret_cast<void*>(exceptionObject));
606 exceptionHeader = reinterpret_cast<__cxa_exception*>(exceptionObject + 1) - 1;
607 }
608
609 void* thrownObject = reinterpret_cast<void*>(exceptionObject + 1);
610 std::type_info* throwTypeInfo = exceptionHeader->exceptionType;
611
612 // Get the type info for the thrown type and this catch clause and
613 // see if the catch caluse can catch that type.
614
615 __cxxabiv1::__shim_type_info* catchType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(catchTypeInfo);
616 __cxxabiv1::__shim_type_info* throwType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(throwTypeInfo);
617 _LIBCXXABI_TRACE_STATETAB("UnwindException=%p, thrownObject=%p, throwTypeInfo=%p(%s), catchTypeInfo=%p(%s)\n",
618 reinterpret_cast<void*>(exceptionObject), thrownObject, reinterpret_cast<void*>(throwType),
619 throwType->name(), reinterpret_cast<void*>(catchType), catchType->name());
620 if (catchType->can_catch(throwType, thrownObject)) {
621 exceptionHeader->adjustedPtr = thrownObject;
622 obj = thrownObject;
623 _LIBCXXABI_TRACE_STATETAB("Match found for thrownObject=%p\n", thrownObject);
624 return true;
625 }
626 _LIBCXXABI_TRACE_STATETAB0("No match\n");
627 return false;
628}
629
630// __xlc_throw_badexception
631// This function is for xlclang++. It allocates and throws a bad_exception.
632// During unwinding for this bad_exception, the previous exception which is
633// not matching the throw spec will be cleaned up. Thus having the same
634// effect as replace the top most exception (which is bad) with a bad_exception.
635_LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {
636 _LIBCXXABI_TRACE_STATETAB("Entering function: %s\n\n", __func__);
637 void* newexception = new (__cxa_allocate_exception(sizeof(std::bad_exception))) std::bad_exception;
638 __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);
639}
640
641// skip_non_cxx_eh_aware_frames
642// This function skips non-C++ EH aware stack frames by unwinding from the
643// stack frame pointed by 'Sp' and returns the first C++ EH aware stack frame
644// found. 'Pc' is an instruction address inside the function that owns the
645// stack frame pointed to by 'Sp'.
646static uintptr_t* skip_non_cxx_eh_aware_frames(uint32_t* Pc, uintptr_t* Sp) {
647 uint32_t* currentPc = Pc;
648 uintptr_t* currentStack = Sp;
649
650 // Loop until a C++ EH aware frame is found or the return address is 0,
651 // which is the return address of the startup function '__start'.
652 while (currentPc != 0) {
653 uint32_t* p = currentPc;
654
655 // Keep looking forward until a word of 0 is found. The traceback
656 // table starts at the following word.
657 while (*p)
658 ++p;
659 tbtable* TBTable = reinterpret_cast<tbtable*>(p + 1);
660
661 // A stack frame with a C++ state table is C++ EH aware.
662 if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl)
663 return currentStack;
664
665 // Move up one stack frame.
666 currentStack = reinterpret_cast<uintptr_t*>(currentStack[0]);
667 // Get the value of the LR (saved, prior to incrementing the SP, by the
668 // prolog of the function just inspected) from the frame.
669 currentPc = reinterpret_cast<uint32_t*>(currentStack[2]);
670 }
671 // This should not happen.
672 _LIBCXXABI_TRACE_STATETAB0("skip_non_cxx_eh_aware_frames() reached the end of stack frames, aborting\n");
673 abort();
674}
675
676// __xlc_exception_handle
677// This function is for xlclang++. It returns the address of the exception
678// object stored in the reserved field in the stack of the caller of the
679// function that calls __xlc_exception_handle() (within the link area for the
680// call to the latter). The address is stored by the personality routine for
681// xlclang++ compiled code. If __xlc_exception_handle() is called by
682// non-C++ EH aware functions, their frames are skipped until a C++ EH aware
683// frame is found.
684// Note: make sure __xlc_exception_handle() is a non-leaf function. Currently
685// it calls skip_non_cxx_eh_aware_frames(), which in turn calls abort().
686_LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {
687 // Get the SP of this function, i.e., __xlc_exception_handle().
688 uintptr_t* lastStack = reinterpret_cast<uintptr_t*>(__builtin_frame_address(0));
689 // Move one frame up to the frame of the caller of __xlc_exception_handle().
690 lastStack = reinterpret_cast<uintptr_t*>(lastStack[0]);
691 // Get the return address of this function, i.e., __xlc_exception_handle().
692 uint32_t* returnAddress = reinterpret_cast<uint32_t*>(__builtin_return_address(0));
693
694 // Skip non-C++ EH aware frames and get the first C++ EH aware frame.
695 uintptr_t* callerStack = skip_non_cxx_eh_aware_frames(returnAddress, lastStack);
696
697 // Get the SP of the caller of the C++ EH aware caller.
698 callerStack = reinterpret_cast<uintptr_t*>(callerStack[0]);
699 // Retrieve the exception object in the stack slot saved by the personality.
700 uintptr_t exceptionObject = callerStack[3];
701 _LIBCXXABI_TRACE_STATETAB("Handshake: retrieve exceptionObject=%p from stack=%p\n",
702 reinterpret_cast<void*>(exceptionObject), reinterpret_cast<void*>(callerStack));
703 return exceptionObject;
704}
705
706// xlclang++ may generate calls to __Deleted_Virtual.
707_LIBCXXABI_FUNC_VIS void __Deleted_Virtual() { abort(); }
708
709// __catchThrownException is called during AIX library initialization and
710// termination to handle exceptions. An implementation is also provided in
711// libC.a(shrcore.o). This implementation is provided for applications that
712// link with -lc++ (the xlclang++ or ibm-clang++ link default.)
713_LIBCXXABI_FUNC_VIS int
714__catchThrownException(void (*cdfunc)(void), // function which may fail
715 void (*cleanup)(void*), // cleanup function
716 void* cleanuparg, // parameter to cleanup function
717 int action) { // control exception throwing and termination
718 enum Action : int { None = 0, Rethrow = 1, Terminate = 2 };
719 if (!cdfunc)
720 return 0;
721 if (action == Action::Rethrow && !cleanup) {
722 // No cleanup and rethrow is effectively no-op.
723 // Avoid the catch handler when possible to allow exceptions generated
724 // from xlC binaries to flow through.
725 (*cdfunc)();
726 return 0;
727 }
728 try {
729 (*cdfunc)();
730 } catch (...) {
731 if (action == Action::Terminate)
732 std::terminate();
733 if (cleanup)
734 (*cleanup)(cleanuparg);
735 if (action == Action::Rethrow)
736 throw;
737 assert(action == Action::None);
738 return -1; // FAILED
739 }
740 return 0;
741}
742
743} // extern "C"
744
745} // __cxxabiv1
lib/libtsan/interception/interception_aix.cpp deleted-45
......@@ -1,45 +0,0 @@
1//===-- interception_aix.cpp ------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// AIX-specific interception methods.
12//===----------------------------------------------------------------------===//
13
14#include "interception.h"
15#include "sanitizer_common/sanitizer_common.h"
16
17#if SANITIZER_AIX
18
19# include <dlfcn.h> // for dlsym()
20
21namespace __interception {
22
23static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
24 // AIX dlsym can only defect the functions that are exported, so
25 // on AIX, we can not intercept some basic functions like memcpy.
26 // FIXME: if we are going to ship dynamic asan library, we may need to search
27 // all the loaded modules with RTLD_DEFAULT if RTLD_NEXT failed.
28 void *addr = dlsym(RTLD_NEXT, name);
29
30 // In case `name' is not loaded, dlsym ends up finding the actual wrapper.
31 // We don't want to intercept the wrapper and have it point to itself.
32 if ((uptr)addr == wrapper_addr)
33 addr = nullptr;
34 return addr;
35}
36
37bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
38 uptr wrapper) {
39 void *addr = GetFuncAddr(name, wrapper);
40 *ptr_to_real = (uptr)addr;
41 return addr && (func == wrapper);
42}
43
44} // namespace __interception
45#endif // SANITIZER_AIX
lib/libtsan/interception/interception_aix.h deleted-36
......@@ -1,36 +0,0 @@
1//===-- interception_aix.h --------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// AIX-specific interception methods.
12//===----------------------------------------------------------------------===//
13
14#if SANITIZER_AIX
15
16# if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
17# error \
18 "interception_aix.h should be included from interception library only"
19# endif
20
21# ifndef INTERCEPTION_AIX_H
22# define INTERCEPTION_AIX_H
23
24namespace __interception {
25bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
26 uptr wrapper);
27} // namespace __interception
28
29# define INTERCEPT_FUNCTION_AIX(func) \
30 ::__interception::InterceptFunction( \
31 #func, (::__interception::uptr *)&REAL(func), \
32 (::__interception::uptr) & (func), \
33 (::__interception::uptr) & WRAP(func))
34
35# endif // INTERCEPTION_AIX_H
36#endif // SANITIZER_AIX
lib/libunwind/src/Unwind_AIXExtras.cpp deleted-63
......@@ -1,63 +0,0 @@
1//===--------------------- Unwind_AIXExtras.cpp -------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8//===----------------------------------------------------------------------===//
9
10// This file is only used for AIX.
11#if defined(_AIX)
12
13#include "config.h"
14#include "libunwind_ext.h"
15#include <sys/debug.h>
16
17namespace libunwind {
18// getFuncNameFromTBTable
19// Get the function name from its traceback table.
20char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen,
21 unw_word_t *Offset) {
22 uint32_t *p = reinterpret_cast<uint32_t *>(Pc);
23 *Offset = 0;
24
25 // Keep looking forward until a word of 0 is found. The traceback
26 // table starts at the following word.
27 while (*p)
28 p++;
29 tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
30
31 if (!TBTable->tb.name_present)
32 return NULL;
33
34 // Get to the name of the function.
35 p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
36
37 // Skip field parminfo if it exists.
38 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
39 p++;
40
41 // If the tb_offset field exists, get the offset from the start of
42 // the function to pc. Skip the field.
43 if (TBTable->tb.has_tboff) {
44 unw_word_t StartIp =
45 reinterpret_cast<uintptr_t>(TBTable) - *p - sizeof(uint32_t);
46 *Offset = Pc - StartIp;
47 p++;
48 }
49
50 // Skip field hand_mask if it exists.
51 if (TBTable->tb.int_hndl)
52 p++;
53
54 // Skip fields ctl_info and ctl_info_disp if they exist.
55 if (TBTable->tb.has_ctl) {
56 p += 1 + *p;
57 }
58
59 NameLen = *(reinterpret_cast<uint16_t *>(p));
60 return reinterpret_cast<char *>(p) + sizeof(uint16_t);
61}
62} // namespace libunwind
63#endif // defined(_AIX)
lib/std/Target.zig+6-51
......@@ -24,7 +24,6 @@ pub const Os = struct {
2424 hermit,
2525 managarm,
2626
27 aix,
2827 haiku,
2928 hurd,
3029 illumos,
......@@ -32,7 +31,6 @@ pub const Os = struct {
3231 plan9,
3332 rtems,
3433 serenity,
35 zos,
3634
3735 dragonfly,
3836 freebsd,
......@@ -174,9 +172,7 @@ pub const Os = struct {
174172 .fuchsia,
175173 .hermit,
176174
177 .aix,
178175 .rtems,
179 .zos,
180176
181177 .dragonfly,
182178 .freebsd,
......@@ -418,12 +414,6 @@ pub const Os = struct {
418414 },
419415 },
420416
421 .aix => .{
422 .semver = .{
423 .min = .{ .major = 7, .minor = 2, .patch = 5 },
424 .max = .{ .major = 7, .minor = 3, .patch = 3 },
425 },
426 },
427417 .hurd => .{
428418 .hurd = .{
429419 .range = .{
......@@ -494,12 +484,6 @@ pub const Os = struct {
494484 .max = .{ .major = 6, .minor = 1, .patch = 0 },
495485 },
496486 },
497 .zos => .{
498 .semver = .{
499 .min = .{ .major = 2, .minor = 5, .patch = 0 },
500 .max = .{ .major = 3, .minor = 1, .patch = 0 },
501 },
502 },
503487
504488 .dragonfly => .{
505489 .semver = .{
......@@ -825,7 +809,6 @@ pub const Abi = enum {
825809 => .eabi,
826810 else => .none,
827811 },
828 .aix => if (arch == .powerpc) .eabihf else .none,
829812 .haiku => switch (arch) {
830813 .arm,
831814 .powerpc,
......@@ -917,7 +900,6 @@ pub const Abi = enum {
917900 .managarm,
918901 .plan9,
919902 .serenity,
920 .zos,
921903 .dragonfly,
922904 .driverkit,
923905 .macos,
......@@ -1006,8 +988,6 @@ pub const ObjectFormat = enum {
1006988 coff,
1007989 /// The Executable and Linkable Format used by many Unixes.
1008990 elf,
1009 /// The Generalized Object File Format used by z/OS.
1010 goff,
1011991 /// The Intel HEX format for storing binary code in ASCII text.
1012992 hex,
1013993 /// The Mach object format used by macOS and other Apple platforms.
......@@ -1020,8 +1000,6 @@ pub const ObjectFormat = enum {
10201000 spirv,
10211001 /// The WebAssembly binary format.
10221002 wasm,
1023 /// The eXtended Common Object File Format used by AIX.
1024 xcoff,
10251003
10261004 // LLVM tags deliberately omitted:
10271005 // - dxcontainer
......@@ -1030,7 +1008,7 @@ pub const ObjectFormat = enum {
10301008 return switch (of) {
10311009 .c => ".c",
10321010 .coff => ".obj",
1033 .elf, .goff, .macho, .wasm, .xcoff => ".o",
1011 .elf, .macho, .wasm => ".o",
10341012 .hex => ".ihex",
10351013 .plan9 => arch.plan9Ext(),
10361014 .raw => ".bin",
......@@ -1040,11 +1018,9 @@ pub const ObjectFormat = enum {
10401018
10411019 pub fn default(os_tag: Os.Tag, arch: Cpu.Arch) ObjectFormat {
10421020 return switch (os_tag) {
1043 .aix => .xcoff,
10441021 .driverkit, .ios, .macos, .tvos, .visionos, .watchos => .macho,
10451022 .plan9 => .plan9,
10461023 .uefi, .windows => .coff,
1047 .zos => .goff,
10481024 else => switch (arch) {
10491025 .spirv32, .spirv64 => .spirv,
10501026 .wasm32, .wasm64 => .wasm,
......@@ -2030,10 +2006,7 @@ pub const Cpu = struct {
20302006 .riscv32, .riscv32be => &riscv.cpu.baseline_rv32,
20312007 .riscv64, .riscv64be => &riscv.cpu.baseline_rv64,
20322008 // gcc/clang do not have a generic s390x model.
2033 .s390x => switch (os.tag) {
2034 .zos => &s390x.cpu.arch10,
2035 else => &s390x.cpu.arch8,
2036 },
2009 .s390x => &s390x.cpu.arch8,
20372010 .sparc => &sparc.cpu.v9, // glibc does not work with 'plain' v8.
20382011 .x86 => &x86.cpu.pentium4,
20392012 .x86_64 => switch (os.tag) {
......@@ -2162,7 +2135,6 @@ pub inline fn isWasiLibC(target: *const Target) bool {
21622135/// syscall interface, for example.
21632136pub fn requiresLibC(target: *const Target) bool {
21642137 return switch (target.os.tag) {
2165 .aix,
21662138 .illumos,
21672139 .driverkit,
21682140 .macos,
......@@ -2189,7 +2161,6 @@ pub fn requiresLibC(target: *const Target) bool {
21892161 .fuchsia,
21902162 .managarm,
21912163 .ps3,
2192 .zos,
21932164 .rtems,
21942165 .cuda,
21952166 .nvcl,
......@@ -2347,10 +2318,8 @@ pub const DynamicLinker = struct {
23472318 .hermit,
23482319 .managarm, // Needs to be double-checked.
23492320
2350 .aix,
23512321 .plan9,
23522322 .rtems,
2353 .zos,
23542323
23552324 .uefi,
23562325 .windows,
......@@ -2759,10 +2728,8 @@ pub const DynamicLinker = struct {
27592728 .contiki,
27602729 .hermit,
27612730
2762 .aix,
27632731 .plan9,
27642732 .rtems,
2765 .zos,
27662733
27672734 .uefi,
27682735 .windows,
......@@ -2916,7 +2883,7 @@ pub fn stackAlignment(target: *const Target) u16 {
29162883 // can't handle that level of nuance yet.
29172884 .powerpc64,
29182885 .powerpc64le,
2919 => if (target.os.tag == .linux or target.os.tag == .aix) return 16,
2886 => if (target.os.tag == .linux) return 16,
29202887 .riscv32,
29212888 .riscv32be,
29222889 .riscv64,
......@@ -3112,7 +3079,6 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
31123079 .fuchsia,
31133080 .hermit,
31143081
3115 .aix,
31163082 .haiku,
31173083 .hurd,
31183084 .illumos,
......@@ -3120,7 +3086,6 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
31203086 .plan9,
31213087 .rtems,
31223088 .serenity,
3123 .zos,
31243089
31253090 .freebsd,
31263091 .dragonfly,
......@@ -3175,7 +3140,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
31753140 .muslx32,
31763141 => return 64,
31773142 else => switch (target.os.tag) {
3178 .aix, .freebsd, .netbsd, .openbsd => return 64,
3143 .freebsd, .netbsd, .openbsd => return 64,
31793144 else => return 128,
31803145 },
31813146 },
......@@ -3191,7 +3156,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
31913156 .muslx32,
31923157 => return 64,
31933158 else => switch (target.os.tag) {
3194 .aix, .freebsd, .openbsd => return 64,
3159 .freebsd, .openbsd => return 64,
31953160 else => return 128,
31963161 },
31973162 },
......@@ -3361,13 +3326,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
33613326 .int, .uint, .long, .ulong => return 2,
33623327 else => {},
33633328 },
3364 .powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (target.os.tag) {
3365 .aix => switch (c_type) {
3366 .double, .longdouble => return 4,
3367 else => {},
3368 },
3369 else => {},
3370 },
33713329 .wasm32, .wasm64 => switch (target.os.tag) {
33723330 .emscripten => switch (c_type) {
33733331 .longdouble => return 8,
......@@ -3666,10 +3624,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention
36663624 else
36673625 .{ .powerpc64_elf = .{} },
36683626 .powerpc64le => .{ .powerpc64_elf_v2 = .{} },
3669 .powerpc, .powerpcle => switch (target.os.tag) {
3670 .aix => .{ .powerpc_aix = .{} },
3671 else => .{ .powerpc_sysv = .{} },
3672 },
3627 .powerpc, .powerpcle => .{ .powerpc_sysv = .{} },
36733628 .wasm32, .wasm64 => .{ .wasm_mvp = .{} },
36743629 .arc, .arceb => .{ .arc_sysv = .{} },
36753630 .avr => .avr_gnu,
lib/std/Target/powerpc.zig-30
......@@ -7,10 +7,6 @@ const CpuModel = std.Target.Cpu.Model;
77pub const Feature = enum {
88 @"64bit",
99 @"64bitregs",
10 aix,
11 aix_shared_lib_tls_model_opt,
12 aix_small_local_dynamic_tls,
13 aix_small_local_exec_tls,
1410 allow_unaligned_fp_access,
1511 altivec,
1612 booke,
......@@ -61,7 +57,6 @@ pub const Feature = enum {
6157 longcall,
6258 mfocrf,
6359 mma,
64 modern_aix_as,
6560 msync,
6661 paired_vector_memops,
6762 partword_atomics,
......@@ -110,26 +105,6 @@ pub const all_features = blk: {
110105 .description = "Enable 64-bit registers usage for ppc32 [beta]",
111106 .dependencies = featureSet(&[_]Feature{}),
112107 };
113 result[@intFromEnum(Feature.aix)] = .{
114 .llvm_name = "aix",
115 .description = "AIX OS",
116 .dependencies = featureSet(&[_]Feature{}),
117 };
118 result[@intFromEnum(Feature.aix_shared_lib_tls_model_opt)] = .{
119 .llvm_name = "aix-shared-lib-tls-model-opt",
120 .description = "Tune TLS model at function level in shared library loaded with the main program (for 64-bit AIX only)",
121 .dependencies = featureSet(&[_]Feature{}),
122 };
123 result[@intFromEnum(Feature.aix_small_local_dynamic_tls)] = .{
124 .llvm_name = "aix-small-local-dynamic-tls",
125 .description = "Produce a faster local-dynamic TLS sequence for this function for 64-bit AIX",
126 .dependencies = featureSet(&[_]Feature{}),
127 };
128 result[@intFromEnum(Feature.aix_small_local_exec_tls)] = .{
129 .llvm_name = "aix-small-local-exec-tls",
130 .description = "Produce a TOC-free local-exec TLS sequence for this function for 64-bit AIX",
131 .dependencies = featureSet(&[_]Feature{}),
132 };
133108 result[@intFromEnum(Feature.allow_unaligned_fp_access)] = .{
134109 .llvm_name = "allow-unaligned-fp-access",
135110 .description = "CPU does not trap on unaligned FP access",
......@@ -446,11 +421,6 @@ pub const all_features = blk: {
446421 .power9_altivec,
447422 }),
448423 };
449 result[@intFromEnum(Feature.modern_aix_as)] = .{
450 .llvm_name = "modern-aix-as",
451 .description = "AIX system assembler is modern enough to support new mnes",
452 .dependencies = featureSet(&[_]Feature{}),
453 };
454424 result[@intFromEnum(Feature.msync)] = .{
455425 .llvm_name = "msync",
456426 .description = "Has only the msync instruction instead of sync",
lib/std/builtin.zig+1-4
......@@ -1031,10 +1031,7 @@ pub const VaList = switch (builtin.cpu.arch) {
10311031 .alpha => VaListAlpha,
10321032 .arm, .armeb, .thumb, .thumbeb => VaListArm,
10331033 .hexagon => if (builtin.target.abi.isMusl()) VaListHexagon else *u8,
1034 .powerpc, .powerpcle => switch (builtin.os.tag) {
1035 .aix => *u8,
1036 else => VaListPowerPc,
1037 },
1034 .powerpc, .powerpcle => VaListPowerPc,
10381035 .s390x => VaListS390x,
10391036 .sh, .sheb => VaListSh, // This is wrong for `sh_renesas`: https://github.com/ziglang/zig/issues/24692#issuecomment-3150779829
10401037 .x86_64 => switch (builtin.os.tag) {
lib/std/debug.zig+1-1
......@@ -68,7 +68,7 @@ else switch (std.Target.ObjectFormat.default(native_os, native_arch)) {
6868 else => @import("debug/SelfInfo/Elf.zig"),
6969 },
7070 .macho => @import("debug/SelfInfo/MachO.zig"),
71 .goff, .plan9, .spirv, .wasm, .xcoff => void,
71 .plan9, .spirv, .wasm => void,
7272 .c, .hex, .raw => unreachable,
7373};
7474
lib/std/zig.zig+1-1
......@@ -169,7 +169,7 @@ pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMe
169169 },
170170 .Obj => return std.fmt.allocPrint(allocator, "{s}.obj", .{root_name}),
171171 },
172 .elf, .goff, .xcoff => switch (options.output_mode) {
172 .elf => switch (options.output_mode) {
173173 .Exe => return allocator.dupe(u8, root_name),
174174 .Lib => {
175175 switch (options.link_mode orelse .static) {
lib/zig.h+1-9
......@@ -87,9 +87,7 @@
8787#define zig_big_endian 1
8888#endif
8989
90#if defined(_AIX)
91#define zig_aix
92#elif defined(__MACH__)
90#if defined(__MACH__)
9391#define zig_darwin
9492#elif defined(__DragonFly__)
9593#define zig_dragonfly
......@@ -119,20 +117,14 @@
119117#define zig_wasi
120118#elif defined(_WIN32)
121119#define zig_windows
122#elif defined(__MVS__)
123#define zig_zos
124120#endif
125121
126122#if defined(zig_windows)
127123#define zig_coff
128124#elif defined(__ELF__)
129125#define zig_elf
130#elif defined(zig_zos)
131#define zig_goff
132126#elif defined(zig_darwin)
133127#define zig_macho
134#elif defined(zig_aix)
135#define zig_xcoff
136128#endif
137129
138130#define zig_concat(lhs, rhs) lhs##rhs
src/Compilation/Config.zig+1-1
......@@ -492,7 +492,7 @@ pub fn resolve(options: Options) ResolveError!Config {
492492 if (root_strip and !options.any_non_stripped) break :b .strip;
493493 if (options.debug_format) |x| break :b x;
494494 break :b switch (target.ofmt) {
495 .elf, .goff, .macho, .wasm, .xcoff => .{ .dwarf = .@"32" },
495 .elf, .macho, .wasm => .{ .dwarf = .@"32" },
496496 .coff => .code_view,
497497 .c => switch (target.os.tag) {
498498 .windows, .uefi => .code_view,
src/codegen/llvm.zig+3-21
......@@ -179,9 +179,6 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
179179 try llvm_triple.append('-');
180180
181181 try llvm_triple.appendSlice(switch (target.os.tag) {
182 .aix,
183 .zos,
184 => "ibm",
185182 .driverkit,
186183 .ios,
187184 .macos,
......@@ -214,10 +211,8 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
214211 .openbsd => "openbsd",
215212 .illumos => "solaris",
216213 .windows, .uefi => "windows",
217 .zos => "zos",
218214 .haiku => "haiku",
219215 .rtems => "rtems",
220 .aix => "aix",
221216 .cuda => "cuda",
222217 .nvcl => "nvcl",
223218 .amdhsa => "amdhsa",
......@@ -382,13 +377,9 @@ pub fn dataLayout(target: *const std.Target) []const u8 {
382377 else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
383378 },
384379 .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
385 .powerpc => if (target.os.tag == .aix)
386 "E-m:a-p:32:32-Fi32-i64:64-n32"
387 else
388 "E-m:e-p:32:32-Fn32-i64:64-n32",
380 .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32",
389381 .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32",
390382 .powerpc64 => switch (target.os.tag) {
391 .aix => "E-m:a-Fi64-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512",
392383 .linux => if (target.abi.isMusl())
393384 "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
394385 else
......@@ -425,10 +416,7 @@ pub fn dataLayout(target: *const std.Target) []const u8 {
425416 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
426417 .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64",
427418 .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128",
428 .s390x => if (target.os.tag == .zos)
429 "E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
430 else
431 "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
419 .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
432420 .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) {
433421 .cygnus => "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32",
434422 .gnu => if (target.ofmt == .coff)
......@@ -517,7 +505,7 @@ fn codeModel(model: std.builtin.CodeModel, target: *const std.Target) CodeModel
517505 .extreme, .large => .large,
518506 .kernel => .kernel,
519507 .medany => if (target.cpu.arch.isRISCV()) .medium else .large,
520 .medium => if (target.os.tag == .aix) .large else .medium,
508 .medium => .medium,
521509 .medmid => .medium,
522510 .normal, .medlow, .small => .small,
523511 .tiny => .tiny,
......@@ -12828,12 +12816,6 @@ fn backendSupportsF128(target: *const std.Target) bool {
1282812816 // https://github.com/llvm/llvm-project/issues/41838
1282912817 .sparc,
1283012818 => false,
12831 // https://github.com/llvm/llvm-project/issues/101545
12832 .powerpc,
12833 .powerpcle,
12834 .powerpc64,
12835 .powerpc64le,
12836 => target.os.tag != .aix,
1283712819 .arm,
1283812820 .armeb,
1283912821 .thumb,
src/dev.zig-4
......@@ -104,8 +104,6 @@ pub const Env = enum {
104104 .wasm_linker,
105105 .spirv_linker,
106106 .plan9_linker,
107 .goff_linker,
108 .xcoff_linker,
109107 => true,
110108 .cc_command,
111109 .translate_c_command,
......@@ -293,8 +291,6 @@ pub const Feature = enum {
293291 wasm_linker,
294292 spirv_linker,
295293 plan9_linker,
296 goff_linker,
297 xcoff_linker,
298294};
299295
300296/// Makes the code following the call to this function unreachable if `feature` is disabled.
src/libs/libcxx.zig+1-10
......@@ -79,9 +79,6 @@ const libcxx_base_files = [_][]const u8{
7979 "src/stdexcept.cpp",
8080 "src/string.cpp",
8181 "src/strstream.cpp",
82 "src/support/ibm/mbsnrtowcs.cpp",
83 "src/support/ibm/wcsnrtombs.cpp",
84 "src/support/ibm/xlocale_zos.cpp",
8582 "src/support/win32/locale_win32.cpp",
8683 "src/support/win32/support.cpp",
8784 "src/system_error.cpp",
......@@ -203,8 +200,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
203200 continue;
204201 if (std.mem.startsWith(u8, cxx_src, "src/support/win32/") and target.os.tag != .windows)
205202 continue;
206 if (std.mem.startsWith(u8, cxx_src, "src/support/ibm/") and target.os.tag != .zos)
207 continue;
208203
209204 var cflags = std.array_list.Managed([]const u8).init(arena);
210205
......@@ -223,11 +218,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
223218 try cflags.append("-fvisibility=hidden");
224219 try cflags.append("-fvisibility-inlines-hidden");
225220
226 if (target.os.tag == .zos) {
227 try cflags.append("-fno-aligned-allocation");
228 } else {
229 try cflags.append("-faligned-allocation");
230 }
221 try cflags.append("-faligned-allocation");
231222
232223 try cflags.append("-nostdinc++");
233224 try cflags.append("-std=c++23");
src/libs/libtsan.zig-1
......@@ -480,7 +480,6 @@ const sanitizer_symbolizer_sources = [_][]const u8{
480480};
481481
482482const interception_sources = [_][]const u8{
483 "interception_aix.cpp",
484483 "interception_linux.cpp",
485484 "interception_mac.cpp",
486485 "interception_win.cpp",
src/libs/libunwind.zig-1
......@@ -198,6 +198,5 @@ const unwind_src_list = [_][]const u8{
198198 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-wasm.c",
199199 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",
200200 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",
201 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp",
202201 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "gcc_personality_v0.c",
203202};
src/link.zig+4-18
......@@ -574,9 +574,9 @@ pub const File = struct {
574574 const gpa = comp.gpa;
575575 switch (base.tag) {
576576 .lld => assert(base.file == null),
577 .elf, .macho, .wasm, .goff, .xcoff => {
577 .elf, .macho, .wasm => {
578578 if (base.file != null) return;
579 dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
579 dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker });
580580 const emit = base.emit;
581581 if (base.child_pid) |pid| {
582582 if (builtin.os.tag == .windows) {
......@@ -681,8 +681,8 @@ pub const File = struct {
681681 }
682682 }
683683 },
684 .macho, .wasm, .goff, .xcoff => if (base.file) |f| {
685 dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
684 .macho, .wasm => if (base.file) |f| {
685 dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker });
686686 f.close();
687687 base.file = null;
688688
......@@ -825,7 +825,6 @@ pub const File = struct {
825825 switch (base.tag) {
826826 .lld => unreachable,
827827 .spirv => {},
828 .goff, .xcoff => {},
829828 .plan9 => unreachable,
830829 .elf2, .coff2 => {},
831830 inline else => |tag| {
......@@ -973,7 +972,6 @@ pub const File = struct {
973972 .c => unreachable,
974973 .spirv => unreachable,
975974 .wasm => unreachable,
976 .goff, .xcoff => unreachable,
977975 .plan9 => unreachable,
978976 inline else => |tag| {
979977 dev.check(tag.devFeature());
......@@ -996,7 +994,6 @@ pub const File = struct {
996994 .c => unreachable,
997995 .spirv => unreachable,
998996 .wasm => unreachable,
999 .goff, .xcoff => unreachable,
1000997 .plan9 => unreachable,
1001998 inline else => |tag| {
1002999 dev.check(tag.devFeature());
......@@ -1013,7 +1010,6 @@ pub const File = struct {
10131010 .c => unreachable,
10141011 .spirv => unreachable,
10151012 .wasm => unreachable,
1016 .goff, .xcoff => unreachable,
10171013 .plan9 => unreachable,
10181014 inline else => |tag| {
10191015 dev.check(tag.devFeature());
......@@ -1034,8 +1030,6 @@ pub const File = struct {
10341030 .plan9 => unreachable,
10351031
10361032 .spirv,
1037 .goff,
1038 .xcoff,
10391033 => {},
10401034
10411035 inline else => |tag| {
......@@ -1171,8 +1165,6 @@ pub const File = struct {
11711165 wasm,
11721166 spirv,
11731167 plan9,
1174 goff,
1175 xcoff,
11761168 lld,
11771169
11781170 pub fn Type(comptime tag: Tag) type {
......@@ -1184,8 +1176,6 @@ pub const File = struct {
11841176 .c => C,
11851177 .wasm => Wasm,
11861178 .spirv => SpirV,
1187 .goff => Goff,
1188 .xcoff => Xcoff,
11891179 .lld => Lld,
11901180 .plan9 => comptime unreachable,
11911181 };
......@@ -1200,8 +1190,6 @@ pub const File = struct {
12001190 .plan9 => .plan9,
12011191 .c => .c,
12021192 .spirv => .spirv,
1203 .goff => .goff,
1204 .xcoff => .xcoff,
12051193 .hex => @panic("TODO implement hex object format"),
12061194 .raw => @panic("TODO implement raw object format"),
12071195 };
......@@ -1284,8 +1272,6 @@ pub const File = struct {
12841272 pub const MachO = @import("link/MachO.zig");
12851273 pub const SpirV = @import("link/SpirV.zig");
12861274 pub const Wasm = @import("link/Wasm.zig");
1287 pub const Goff = @import("link/Goff.zig");
1288 pub const Xcoff = @import("link/Xcoff.zig");
12891275 pub const Dwarf = @import("link/Dwarf.zig");
12901276};
12911277
src/link/Elf2.zig-1
......@@ -418,7 +418,6 @@ fn create(
418418 .freestanding, .other => .STANDALONE,
419419 .netbsd => .NETBSD,
420420 .illumos => .SOLARIS,
421 .aix => .AIX,
422421 .freebsd, .ps4 => .FREEBSD,
423422 .openbsd => .OPENBSD,
424423 .cuda => .CUDA,
src/link/Goff.zig deleted-112
......@@ -1,112 +0,0 @@
1//! Stub linker support for GOFF based on LLVM.
2
3const Goff = @This();
4
5const std = @import("std");
6const builtin = @import("builtin");
7
8const Allocator = std.mem.Allocator;
9const assert = std.debug.assert;
10const log = std.log.scoped(.link);
11const Path = std.Build.Cache.Path;
12
13const Zcu = @import("../Zcu.zig");
14const InternPool = @import("../InternPool.zig");
15const Compilation = @import("../Compilation.zig");
16const codegen = @import("../codegen.zig");
17const link = @import("../link.zig");
18const trace = @import("../tracy.zig").trace;
19const build_options = @import("build_options");
20
21base: link.File,
22
23pub fn createEmpty(
24 arena: Allocator,
25 comp: *Compilation,
26 emit: Path,
27 options: link.File.OpenOptions,
28) !*Goff {
29 const target = &comp.root_mod.resolved_target.result;
30 const use_lld = build_options.have_llvm and comp.config.use_lld;
31 const use_llvm = comp.config.use_llvm;
32
33 assert(use_llvm); // Caught by Compilation.Config.resolve.
34 assert(!use_lld); // Caught by Compilation.Config.resolve.
35 assert(target.os.tag == .zos); // Caught by Compilation.Config.resolve.
36
37 const goff = try arena.create(Goff);
38 goff.* = .{
39 .base = .{
40 .tag = .goff,
41 .comp = comp,
42 .emit = emit,
43 .zcu_object_basename = emit.sub_path,
44 .gc_sections = options.gc_sections orelse false,
45 .print_gc_sections = options.print_gc_sections,
46 .stack_size = options.stack_size orelse 0,
47 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
48 .file = null,
49 .build_id = options.build_id,
50 },
51 };
52
53 return goff;
54}
55
56pub fn open(
57 arena: Allocator,
58 comp: *Compilation,
59 emit: Path,
60 options: link.File.OpenOptions,
61) !*Goff {
62 const target = &comp.root_mod.resolved_target.result;
63 assert(target.ofmt == .goff);
64 return createEmpty(arena, comp, emit, options);
65}
66
67pub fn deinit(self: *Goff) void {
68 _ = self;
69}
70
71pub fn updateFunc(
72 self: *Goff,
73 pt: Zcu.PerThread,
74 func_index: InternPool.Index,
75 mir: *const codegen.AnyMir,
76) link.File.UpdateNavError!void {
77 _ = self;
78 _ = pt;
79 _ = func_index;
80 _ = mir;
81 unreachable; // we always use llvm
82}
83
84pub fn updateNav(self: *Goff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
85 _ = self;
86 _ = pt;
87 _ = nav;
88 unreachable; // we always use llvm
89}
90
91pub fn updateExports(
92 self: *Goff,
93 pt: Zcu.PerThread,
94 exported: Zcu.Exported,
95 export_indices: []const Zcu.Export.Index,
96) !void {
97 _ = self;
98 _ = pt;
99 _ = exported;
100 _ = export_indices;
101 unreachable; // we always use llvm
102}
103
104pub fn flush(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
105 if (build_options.skip_non_native and builtin.object_format != .goff)
106 @panic("Attempted to compile for object format that was disabled by build configuration");
107
108 _ = self;
109 _ = arena;
110 _ = tid;
111 _ = prog_node;
112}
src/link/Lld.zig-1
......@@ -348,7 +348,6 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
348348 object_files.items.ptr,
349349 object_files.items.len,
350350 switch (target.os.tag) {
351 .aix => .AIXBIG,
352351 .windows => .COFF,
353352 else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,
354353 },
src/link/Xcoff.zig deleted-112
......@@ -1,112 +0,0 @@
1//! Stub linker support for GOFF based on LLVM.
2
3const Xcoff = @This();
4
5const std = @import("std");
6const builtin = @import("builtin");
7
8const Allocator = std.mem.Allocator;
9const assert = std.debug.assert;
10const log = std.log.scoped(.link);
11const Path = std.Build.Cache.Path;
12
13const Zcu = @import("../Zcu.zig");
14const InternPool = @import("../InternPool.zig");
15const Compilation = @import("../Compilation.zig");
16const codegen = @import("../codegen.zig");
17const link = @import("../link.zig");
18const trace = @import("../tracy.zig").trace;
19const build_options = @import("build_options");
20
21base: link.File,
22
23pub fn createEmpty(
24 arena: Allocator,
25 comp: *Compilation,
26 emit: Path,
27 options: link.File.OpenOptions,
28) !*Xcoff {
29 const target = &comp.root_mod.resolved_target.result;
30 const use_lld = build_options.have_llvm and comp.config.use_lld;
31 const use_llvm = comp.config.use_llvm;
32
33 assert(use_llvm); // Caught by Compilation.Config.resolve.
34 assert(!use_lld); // Caught by Compilation.Config.resolve.
35 assert(target.os.tag == .aix); // Caught by Compilation.Config.resolve.
36
37 const xcoff = try arena.create(Xcoff);
38 xcoff.* = .{
39 .base = .{
40 .tag = .xcoff,
41 .comp = comp,
42 .emit = emit,
43 .zcu_object_basename = emit.sub_path,
44 .gc_sections = options.gc_sections orelse false,
45 .print_gc_sections = options.print_gc_sections,
46 .stack_size = options.stack_size orelse 0,
47 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
48 .file = null,
49 .build_id = options.build_id,
50 },
51 };
52
53 return xcoff;
54}
55
56pub fn open(
57 arena: Allocator,
58 comp: *Compilation,
59 emit: Path,
60 options: link.File.OpenOptions,
61) !*Xcoff {
62 const target = &comp.root_mod.resolved_target.result;
63 assert(target.ofmt == .xcoff);
64 return createEmpty(arena, comp, emit, options);
65}
66
67pub fn deinit(self: *Xcoff) void {
68 _ = self;
69}
70
71pub fn updateFunc(
72 self: *Xcoff,
73 pt: Zcu.PerThread,
74 func_index: InternPool.Index,
75 mir: *const codegen.AnyMir,
76) link.File.UpdateNavError!void {
77 _ = self;
78 _ = pt;
79 _ = func_index;
80 _ = mir;
81 unreachable; // we always use llvm
82}
83
84pub fn updateNav(self: *Xcoff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
85 _ = self;
86 _ = pt;
87 _ = nav;
88 unreachable; // we always use llvm
89}
90
91pub fn updateExports(
92 self: *Xcoff,
93 pt: Zcu.PerThread,
94 exported: Zcu.Exported,
95 export_indices: []const Zcu.Export.Index,
96) !void {
97 _ = self;
98 _ = pt;
99 _ = exported;
100 _ = export_indices;
101 unreachable; // we always use llvm
102}
103
104pub fn flush(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
105 if (build_options.skip_non_native and builtin.object_format != .xcoff)
106 @panic("Attempted to compile for object format that was disabled by build configuration");
107
108 _ = self;
109 _ = arena;
110 _ = tid;
111 _ = prog_node;
112}
src/target.zig-2
......@@ -155,13 +155,11 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat)
155155
156156 .coff,
157157 .elf,
158 .goff,
159158 .hex,
160159 .macho,
161160 .spirv,
162161 .raw,
163162 .wasm,
164 .xcoff,
165163 => {},
166164 }
167165
test/llvm_targets.zig-3
......@@ -175,7 +175,6 @@ const targets = [_]std.Target.Query{
175175 .{ .cpu_arch = .nvptx64, .os_tag = .cuda, .abi = .none },
176176 .{ .cpu_arch = .nvptx64, .os_tag = .nvcl, .abi = .none },
177177
178 .{ .cpu_arch = .powerpc, .os_tag = .aix, .abi = .eabihf },
179178 .{ .cpu_arch = .powerpc, .os_tag = .freestanding, .abi = .eabi },
180179 .{ .cpu_arch = .powerpc, .os_tag = .freestanding, .abi = .eabihf },
181180 .{ .cpu_arch = .powerpc, .os_tag = .haiku, .abi = .eabi },
......@@ -196,7 +195,6 @@ const targets = [_]std.Target.Query{
196195 .{ .cpu_arch = .powerpcle, .os_tag = .freestanding, .abi = .eabi },
197196 .{ .cpu_arch = .powerpcle, .os_tag = .freestanding, .abi = .eabihf },
198197
199 .{ .cpu_arch = .powerpc64, .os_tag = .aix, .abi = .none },
200198 .{ .cpu_arch = .powerpc64, .os_tag = .freebsd, .abi = .none },
201199 .{ .cpu_arch = .powerpc64, .os_tag = .freestanding, .abi = .none },
202200 .{ .cpu_arch = .powerpc64, .os_tag = .linux, .abi = .gnu },
......@@ -239,7 +237,6 @@ const targets = [_]std.Target.Query{
239237 .{ .cpu_arch = .s390x, .os_tag = .freestanding, .abi = .none },
240238 .{ .cpu_arch = .s390x, .os_tag = .linux, .abi = .gnu },
241239 .{ .cpu_arch = .s390x, .os_tag = .linux, .abi = .none },
242 // .{ .cpu_arch = .s390x, .os_tag = .zos, .abi = .none },
243240
244241 .{ .cpu_arch = .sparc, .os_tag = .freestanding, .abi = .none },
245242 .{ .cpu_arch = .sparc, .os_tag = .linux, .abi = .gnu },
tools/update_cpu_features.zig+22
......@@ -1051,6 +1051,28 @@ const targets = [_]ArchTarget{
10511051 .name = "PowerPC",
10521052 .td_name = "PPC",
10531053 },
1054 .feature_overrides = &.{
1055 .{
1056 .llvm_name = "aix",
1057 .omit = true,
1058 },
1059 .{
1060 .llvm_name = "aix-shared-lib-tls-model-opt",
1061 .omit = true,
1062 },
1063 .{
1064 .llvm_name = "aix-small-local-dynamic-tls",
1065 .omit = true,
1066 },
1067 .{
1068 .llvm_name = "aix-small-local-exec-tls",
1069 .omit = true,
1070 },
1071 .{
1072 .llvm_name = "modern-aix-as",
1073 .omit = true,
1074 },
1075 },
10541076 .omit_cpus = &.{
10551077 "ppc32",
10561078 },