[clang] [Clang][Driver] Revise Cygwin ToolChain to call linker directly (PR #147960)
Tomohiro Kashiwada via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 13 16:37:24 PDT 2025
================
@@ -107,3 +110,282 @@ void Cygwin::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/w32api");
}
+
+void cygwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const auto &ToolChain = getToolChain();
+ const Driver &D = ToolChain.getDriver();
+
+ const bool IsStatic = Args.hasArg(options::OPT_static);
+
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ CmdArgs.push_back("-m");
+ switch (ToolChain.getArch()) {
+ case llvm::Triple::x86:
+ CmdArgs.push_back("i386pe");
+ break;
+ case llvm::Triple::x86_64:
+ CmdArgs.push_back("i386pep");
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ // FIXME: this is incorrect for WinCE
+ CmdArgs.push_back("thumb2pe");
+ break;
+ case llvm::Triple::aarch64:
+ if (Args.hasArg(options::OPT_marm64x))
+ CmdArgs.push_back("arm64xpe");
+ else if (ToolChain.getEffectiveTriple().isWindowsArm64EC())
+ CmdArgs.push_back("arm64ecpe");
+ else
+ CmdArgs.push_back("arm64pe");
+ break;
+ case llvm::Triple::mipsel:
+ CmdArgs.push_back("mipspe");
+ break;
+ default:
+ D.Diag(diag::err_target_unknown_triple)
+ << ToolChain.getEffectiveTriple().str();
+ }
+
+ Arg *SubsysArg =
+ Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
+ if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
+ CmdArgs.push_back("--subsystem");
+ CmdArgs.push_back("windows");
+ } else if (SubsysArg &&
+ SubsysArg->getOption().matches(options::OPT_mconsole)) {
+ CmdArgs.push_back("--subsystem");
+ CmdArgs.push_back("console");
+ }
+
+ CmdArgs.push_back("--wrap=_Znwm");
+ CmdArgs.push_back("--wrap=_Znam");
+ CmdArgs.push_back("--wrap=_ZdlPv");
+ CmdArgs.push_back("--wrap=_ZdaPv");
+ CmdArgs.push_back("--wrap=_ZnwmRKSt9nothrow_t");
+ CmdArgs.push_back("--wrap=_ZnamRKSt9nothrow_t");
+ CmdArgs.push_back("--wrap=_ZdlPvRKSt9nothrow_t");
+ CmdArgs.push_back("--wrap=_ZdaPvRKSt9nothrow_t");
----------------
kikairoya wrote:
`GlobalDecl` isn't accessible from this context. The `Driver` component can reference only the `Basic` component.
However, I found a way to see what `size_t` does mean on target triple (see diff).
<details>
<summary>diff</summary>
```diff
diff --git a/clang/lib/Driver/ToolChains/Cygwin.cpp b/clang/lib/Driver/ToolChains/Cygwin.cpp
index 079911b0f0ac..e2561172d386 100644
--- a/clang/lib/Driver/ToolChains/Cygwin.cpp
+++ b/clang/lib/Driver/ToolChains/Cygwin.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "Cygwin.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Config/config.h"
#include "clang/Driver/CommonArgs.h"
#include "clang/Driver/Compilation.h"
@@ -177,24 +178,32 @@ void cygwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("console");
}
- if (ToolChain.getTriple().isArch32Bit()) {
- CmdArgs.push_back("--wrap=_Znwj");
- CmdArgs.push_back("--wrap=_Znaj");
- CmdArgs.push_back("--wrap=_ZdlPv");
- CmdArgs.push_back("--wrap=_ZdaPv");
- CmdArgs.push_back("--wrap=_ZnwjRKSt9nothrow_t");
- CmdArgs.push_back("--wrap=_ZnajRKSt9nothrow_t");
- CmdArgs.push_back("--wrap=_ZdlPvRKSt9nothrow_t");
- CmdArgs.push_back("--wrap=_ZdaPvRKSt9nothrow_t");
- } else {
- CmdArgs.push_back("--wrap=_Znwm");
- CmdArgs.push_back("--wrap=_Znam");
- CmdArgs.push_back("--wrap=_ZdlPv");
- CmdArgs.push_back("--wrap=_ZdaPv");
- CmdArgs.push_back("--wrap=_ZnwmRKSt9nothrow_t");
- CmdArgs.push_back("--wrap=_ZnamRKSt9nothrow_t");
- CmdArgs.push_back("--wrap=_ZdlPvRKSt9nothrow_t");
- CmdArgs.push_back("--wrap=_ZdaPvRKSt9nothrow_t");
+ auto TI = targets::AllocateTarget(ToolChain.getTriple(), {});
+ const auto TypeChar = [&]() {
+ switch (TI->getSizeType()) {
+ case TransferrableTargetInfo::UnsignedShort:
+ return 't';
+ case TransferrableTargetInfo::UnsignedInt:
+ return 'j';
+ case TransferrableTargetInfo::UnsignedLong:
+ return 'm';
+ case TransferrableTargetInfo::UnsignedLongLong:
+ return 'y';
+ default:
+ llvm_unreachable("Invalid SizeType");
+ }
+ }();
+ const auto *const LabelPrefix = TI->getUserLabelPrefix();
+ std::string WrapPrefix = "--wrap=";
+ if (LabelPrefix)
+ WrapPrefix += LabelPrefix;
+ for (std::string S : {"_Znw%", "_Zna%", "_ZdlPv", "_ZdaPv",
+ "_Znw%RKSt9nothrow_t", "_Zna%RKSt9nothrow_t",
+ "_ZdlPvRKSt9nothrow_t", "_ZdaPvRKSt9nothrow_t"}) {
+ auto Pos = S.find('%');
+ if (Pos != S.npos)
+ S[Pos] = TypeChar;
+ CmdArgs.push_back(Args.MakeArgString(WrapPrefix + S));
}
if (Args.hasArg(options::OPT_mdll))
```
</details>
BTW, `gcc -m32` doesn't wrap `new` properly (perhaps the old i686-native gcc can?) and the different mangling rule between `new` and `delete` is found from `libstdxx_wrapper.cc` in `cygwin1.dll`.
```
$ echo 'int main() { auto p = new int(3); delete p; }' | g++ -m64 -xc++ - -nostartfiles -nodefaultlibs -Wl,--no-demangle,--entry, -shared -fno-sized-deallocation
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccc30TZw.o:<stdin>:(.text+0x9): undefined reference to `__main'
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccc30TZw.o:<stdin>:(.text+0x13): undefined reference to `__wrap__Znwm'
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccc30TZw.o:<stdin>:(.text+0x2e): undefined reference to `__wrap__ZdlPv'
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccc30TZw.o:<stdin>:(.text+0x3f): undefined reference to `__wrap__ZdlPv'
collect2: エラー: ld はステータス 1 で終了しました
$ echo 'int main() { auto p = new int(3); delete p; }' | g++ -m32 -xc++ - -nostartfiles -nodefaultlibs -Wl,--no-demangle,--entry, -shared -fno-sized-deallocation
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccAA6tBm.o:<stdin>:(.text+0x7): undefined reference to `___main'
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccAA6tBm.o:<stdin>:(.text+0x13): undefined reference to `__Znwj'
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccAA6tBm.o:<stdin>:(.text+0x2d): undefined reference to `___wrap__ZdlPv'
/usr/lib/gcc/x86_64-pc-cygwin/16/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccAA6tBm.o:<stdin>:(.text+0x3c): undefined reference to `___wrap__ZdlPv'
collect2: エラー: ld はステータス 1 で終了しました
```
https://github.com/llvm/llvm-project/pull/147960
More information about the cfe-commits
mailing list