From f64de4ef969445d1dc6c76ccd421aa0439c63609 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Sun, 16 Aug 2026 04:55:03 +0000
Subject: [PATCH] [clang] Restore Darwin PowerPC target info (from
 iains/LLVM-7-branch)

Upstream removed DarwinPPC32TargetInfo/DarwinPPC64TargetInfo from clang,
so in this clang 17 a ppc-apple-* triple falls through to the bare
ELF-flavored PPC32/PPC64TargetInfo: no __APPLE__/__MACH__/availability
predefines, ELF 'm:e' data layout (tapi's APIVisitor derives the leading
'_' Mach-O symbol prefix from that string via
llvm::Mangler::getNameWithPrefix, so every extracted symbol would be
unprefixed), wrong va_list, no '#pragma options align=mac68k'. This
breaks the clang-parsing tapi drivers (installapi / api-verify / sdkdb)
for ppc targets; the binary-reading paths never instantiate a ppc
TargetInfo and were already fine.

Restore the two target-info classes, taking the content from Iain
Sandoe's LLVM-7-branch (7.1.1-Darwin-WIP), which forward-ports ABI fixes
matching Apple gcc-4.x over what upstream clang 7 had:

- __ppc__/__PPC__ are 32-bit-only on Darwin and __ppc64__ is defined for
  64-bit (Apple GCC semantics; upstream clang 17 never defines __ppc64__
  at all, which TargetConditionals.h and friends depend on).
- _CALL_DARWIN, and __APPLE_ALTIVEC__ when AltiVec is enabled.
- ABI tags 'darwin32'/'darwin64' instead of inheriting 'elfv1', which
  also stops _CALL_ELF from being defined on Darwin.
- ppc32 data layout carries his embedded-alignment refinements
  (i64:32:64, i1:32:32); verified against LLVM 17's DataLayout parser
  rules (only i8 has a natural-alignment requirement).

Adaptations to this clang 17 base, not in his tree:
- resetDataLayout() now takes the user-label prefix; pass "_".
- Int64Type = SignedLongLong on darwin64 (Darwin int64_t is long long
  even in LP64), mirroring DarwinX86_64TargetInfo.
- Triple checks use isOSDarwin() so ppc-apple-macosx* triples (what tapi
  constructs) match, not just -darwin ones.
- His getEmbeddedAlignForSize() record-layout hook is NOT ported: it
  needs a custom TargetInfo virtual plus RecordLayoutBuilder support,
  and struct-field alignment never affects symbol extraction. Instead
  keep old upstream's LongLongAlign = 32 approximation.

Dispatch in Targets.cpp mirrors the historical form: isOSDarwin() check
ahead of the per-OS switch for ppc and ppc64.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AN7qpyGgKic6UMdej1TVJd
---
 src/clang/lib/Basic/Targets.cpp     |  4 ++++
 src/clang/lib/Basic/Targets/PPC.cpp | 17 +++++++++++++--
 src/clang/lib/Basic/Targets/PPC.h   | 34 +++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/src/clang/lib/Basic/Targets.cpp b/src/clang/lib/Basic/Targets.cpp
index 636b59f..52826ef 100644
--- a/src/clang/lib/Basic/Targets.cpp
+++ b/src/clang/lib/Basic/Targets.cpp
@@ -361,6 +361,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
     return std::make_unique<Le64TargetInfo>(Triple, Opts);
 
   case llvm::Triple::ppc:
+    if (Triple.isOSDarwin())
+      return std::make_unique<DarwinPPC32TargetInfo>(Triple, Opts);
     switch (os) {
     case llvm::Triple::Linux:
       return std::make_unique<LinuxTargetInfo<PPC32TargetInfo>>(Triple, Opts);
@@ -389,6 +391,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
     }
 
   case llvm::Triple::ppc64:
+    if (Triple.isOSDarwin())
+      return std::make_unique<DarwinPPC64TargetInfo>(Triple, Opts);
     switch (os) {
     case llvm::Triple::Linux:
       return std::make_unique<LinuxTargetInfo<PPC64TargetInfo>>(Triple, Opts);
diff --git a/src/clang/lib/Basic/Targets/PPC.cpp b/src/clang/lib/Basic/Targets/PPC.cpp
index 89aa9bd..1f6e9f2 100644
--- a/src/clang/lib/Basic/Targets/PPC.cpp
+++ b/src/clang/lib/Basic/Targets/PPC.cpp
@@ -274,9 +274,15 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
   if (getTriple().isOSAIX() || getTriple().isOSLinux())
     defineXLCompatMacros(Builder);
 
+  bool IsDarwin = getTriple().isOSDarwin();
+
   // Target identification.
-  Builder.defineMacro("__ppc__");
-  Builder.defineMacro("__PPC__");
+  // Darwin, following Apple GCC, splits these on pointer size: __ppc__ and
+  // __PPC__ are 32-bit only there, __ppc64__ is defined for 64-bit.
+  if (PointerWidth == 32 || !IsDarwin) {
+    Builder.defineMacro("__ppc__");
+    Builder.defineMacro("__PPC__");
+  }
   Builder.defineMacro("_ARCH_PPC");
   Builder.defineMacro("__powerpc__");
   Builder.defineMacro("__POWERPC__");
@@ -284,6 +290,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("_ARCH_PPC64");
     Builder.defineMacro("__powerpc64__");
     Builder.defineMacro("__PPC64__");
+    if (IsDarwin)
+      Builder.defineMacro("__ppc64__");
   } else if (getTriple().isOSAIX()) {
     // The XL compilers on AIX define _ARCH_PPC64 for both 32 and 64-bit modes.
     Builder.defineMacro("_ARCH_PPC64");
@@ -317,6 +325,9 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
   if (getTriple().getOS() == llvm::Triple::Linux && PointerWidth == 64)
     Builder.defineMacro("_CALL_LINUX", "1");
 
+  if (IsDarwin)
+    Builder.defineMacro("_CALL_DARWIN", "1");
+
   // Subtarget options.
   if (!getTriple().isOSAIX()){
     Builder.defineMacro("__NATURAL_ALIGNMENT__");
@@ -382,6 +393,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
   if (HasAltivec) {
     Builder.defineMacro("__VEC__", "10206");
     Builder.defineMacro("__ALTIVEC__");
+    if (IsDarwin)
+      Builder.defineMacro("__APPLE_ALTIVEC__");
   }
   if (HasSPE) {
     Builder.defineMacro("__SPE__");
diff --git a/src/clang/lib/Basic/Targets/PPC.h b/src/clang/lib/Basic/Targets/PPC.h
index bc06e79..93b9ae1 100644
--- a/src/clang/lib/Basic/Targets/PPC.h
+++ b/src/clang/lib/Basic/Targets/PPC.h
@@ -485,6 +485,40 @@ public:
   }
 };
 
+class LLVM_LIBRARY_VISIBILITY DarwinPPC32TargetInfo
+    : public DarwinTargetInfo<PPC32TargetInfo> {
+public:
+  DarwinPPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+      : DarwinTargetInfo<PPC32TargetInfo>(Triple, Opts) {
+    HasAlignMac68kSupport = true;
+    BoolWidth = BoolAlign = 32; // XXX support -mone-byte-bool?
+    PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726
+    LongLongAlign = 32;
+    ABI = "darwin32";
+    // Note that, other than vectors, the on-stack alignment of all types is
+    // only 4 bytes (this includes aggregates containing vectors), and 64-bit
+    // entities embedded in aggregates are 4-byte aligned.
+    resetDataLayout("E-m:o-p:32:32-f64:32:64-i64:32:64-n32-i1:32:32", "_");
+  }
+
+  BuiltinVaListKind getBuiltinVaListKind() const override {
+    return TargetInfo::CharPtrBuiltinVaList;
+  }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinPPC64TargetInfo
+    : public DarwinTargetInfo<PPC64TargetInfo> {
+public:
+  DarwinPPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+      : DarwinTargetInfo<PPC64TargetInfo>(Triple, Opts) {
+    HasAlignMac68kSupport = true;
+    // Darwin int64_t is long long even in LP64, unlike the ELF ppc64 ABIs.
+    Int64Type = SignedLongLong;
+    ABI = "darwin64";
+    resetDataLayout("E-m:o-i64:64-n32:64", "_");
+  }
+};
+
 class LLVM_LIBRARY_VISIBILITY AIXPPC32TargetInfo :
   public AIXTargetInfo<PPC32TargetInfo> {
 public:
-- 
2.43.0

