9
9
#include " Cygwin.h"
10
10
#include " clang/Config/config.h"
11
11
#include " clang/Driver/CommonArgs.h"
12
+ #include " clang/Driver/Compilation.h"
12
13
#include " clang/Driver/Driver.h"
13
14
#include " clang/Driver/Options.h"
14
15
#include " llvm/Support/Path.h"
@@ -30,6 +31,8 @@ Cygwin::Cygwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
30
31
Generic_GCC::PushPPaths (PPaths);
31
32
32
33
path_list &Paths = getFilePaths ();
34
+ if (GCCInstallation.isValid ())
35
+ Paths.push_back (GCCInstallation.getInstallPath ().str ());
33
36
34
37
Generic_GCC::AddMultiarchPaths (D, SysRoot, " lib" , Paths);
35
38
@@ -107,3 +110,282 @@ void Cygwin::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
107
110
addExternCSystemInclude (DriverArgs, CC1Args, SysRoot + " /usr/include" );
108
111
addExternCSystemInclude (DriverArgs, CC1Args, SysRoot + " /usr/include/w32api" );
109
112
}
113
+
114
+ static bool getStaticPIE (const ArgList &Args, const ToolChain &TC) {
115
+ bool HasStaticPIE = Args.hasArg (options::OPT_static_pie);
116
+ if (HasStaticPIE && Args.hasArg (options::OPT_no_pie)) {
117
+ const Driver &D = TC.getDriver ();
118
+ const llvm::opt::OptTable &Opts = D.getOpts ();
119
+ StringRef StaticPIEName = Opts.getOptionName (options::OPT_static_pie);
120
+ StringRef NoPIEName = Opts.getOptionName (options::OPT_nopie);
121
+ D.Diag (diag::err_drv_cannot_mix_options) << StaticPIEName << NoPIEName;
122
+ }
123
+ return HasStaticPIE;
124
+ }
125
+
126
+ static bool getStatic (const ArgList &Args) {
127
+ return Args.hasArg (options::OPT_static) &&
128
+ !Args.hasArg (options::OPT_static_pie);
129
+ }
130
+
131
+ void cygwin::Linker::ConstructJob (Compilation &C, const JobAction &JA,
132
+ const InputInfo &Output,
133
+ const InputInfoList &Inputs,
134
+ const ArgList &Args,
135
+ const char *LinkingOutput) const {
136
+ const auto &ToolChain = getToolChain ();
137
+ const Driver &D = ToolChain.getDriver ();
138
+
139
+ const bool IsIAMCU = ToolChain.getTriple ().isOSIAMCU ();
140
+ const bool IsVE = ToolChain.getTriple ().isVE ();
141
+ const bool IsStaticPIE = getStaticPIE (Args, ToolChain);
142
+ const bool IsStatic = getStatic (Args);
143
+
144
+ ArgStringList CmdArgs;
145
+
146
+ // Silence warning for "clang -g foo.o -o foo"
147
+ Args.ClaimAllArgs (options::OPT_g_Group);
148
+ // and "clang -emit-llvm foo.o -o foo"
149
+ Args.ClaimAllArgs (options::OPT_emit_llvm);
150
+ // and for "clang -w foo.o -o foo". Other warning options are already
151
+ // handled somewhere else.
152
+ Args.ClaimAllArgs (options::OPT_w);
153
+
154
+ if (!D.SysRoot .empty ())
155
+ CmdArgs.push_back (Args.MakeArgString (" --sysroot=" + D.SysRoot ));
156
+
157
+ if (Args.hasArg (options::OPT_s))
158
+ CmdArgs.push_back (" -s" );
159
+
160
+ CmdArgs.push_back (" -m" );
161
+ switch (ToolChain.getArch ()) {
162
+ case llvm::Triple::x86:
163
+ CmdArgs.push_back (" i386pe" );
164
+ break ;
165
+ case llvm::Triple::x86_64:
166
+ CmdArgs.push_back (" i386pep" );
167
+ break ;
168
+ case llvm::Triple::arm:
169
+ case llvm::Triple::thumb:
170
+ // FIXME: this is incorrect for WinCE
171
+ CmdArgs.push_back (" thumb2pe" );
172
+ break ;
173
+ case llvm::Triple::aarch64:
174
+ if (ToolChain.getEffectiveTriple ().isWindowsArm64EC ())
175
+ CmdArgs.push_back (" arm64ecpe" );
176
+ else
177
+ CmdArgs.push_back (" arm64pe" );
178
+ break ;
179
+ default :
180
+ D.Diag (diag::err_target_unknown_triple)
181
+ << ToolChain.getEffectiveTriple ().str ();
182
+ }
183
+
184
+ CmdArgs.push_back (" --wrap=_Znwm" );
185
+ CmdArgs.push_back (" --wrap=_Znam" );
186
+ CmdArgs.push_back (" --wrap=_ZdlPv" );
187
+ CmdArgs.push_back (" --wrap=_ZdaPv" );
188
+ CmdArgs.push_back (" --wrap=_ZnwmRKSt9nothrow_t" );
189
+ CmdArgs.push_back (" --wrap=_ZnamRKSt9nothrow_t" );
190
+ CmdArgs.push_back (" --wrap=_ZdlPvRKSt9nothrow_t" );
191
+ CmdArgs.push_back (" --wrap=_ZdaPvRKSt9nothrow_t" );
192
+
193
+ const bool IsShared = Args.hasArg (options::OPT_shared);
194
+ if (IsShared)
195
+ CmdArgs.push_back (" -shared" );
196
+ bool IsPIE = false ;
197
+ if (IsStaticPIE) {
198
+ CmdArgs.push_back (" -static" );
199
+ CmdArgs.push_back (" -pie" );
200
+ CmdArgs.push_back (" --no-dynamic-linker" );
201
+ CmdArgs.push_back (" -z" );
202
+ CmdArgs.push_back (" text" );
203
+ } else if (IsStatic) {
204
+ CmdArgs.push_back (" -static" );
205
+ } else if (!Args.hasArg (options::OPT_r)) {
206
+ if (Args.hasArg (options::OPT_rdynamic))
207
+ CmdArgs.push_back (" -export-dynamic" );
208
+ if (!IsShared) {
209
+ IsPIE = Args.hasFlag (options::OPT_pie, options::OPT_no_pie,
210
+ ToolChain.isPIEDefault (Args));
211
+ if (IsPIE)
212
+ CmdArgs.push_back (" -pie" );
213
+ }
214
+ }
215
+
216
+ CmdArgs.push_back (" -o" );
217
+ CmdArgs.push_back (Output.getFilename ());
218
+
219
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles,
220
+ options::OPT_r)) {
221
+ if (IsVE) {
222
+ CmdArgs.push_back (" -z" );
223
+ CmdArgs.push_back (" max-page-size=0x4000000" );
224
+ }
225
+
226
+ if (IsShared) {
227
+ CmdArgs.push_back (" -e" );
228
+ CmdArgs.push_back (ToolChain.getTriple ().isArch32Bit ()
229
+ ? " __cygwin_dll_entry@12"
230
+ : " _cygwin_dll_entry" );
231
+ CmdArgs.push_back (" --enable-auto-image-base" );
232
+ }
233
+
234
+ if (!IsShared)
235
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crt0.o" )));
236
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
237
+ std::string crtbegin =
238
+ ToolChain.getCompilerRT (Args, " crtbegin" , ToolChain::FT_Object);
239
+ if (ToolChain.getVFS ().exists (crtbegin)) {
240
+ std::string P;
241
+ P = crtbegin;
242
+ CmdArgs.push_back (Args.MakeArgString (P));
243
+ }
244
+ }
245
+ if (IsShared)
246
+ CmdArgs.push_back (
247
+ Args.MakeArgString (ToolChain.GetFilePath (" crtbeginS.o" )));
248
+ else
249
+ CmdArgs.push_back (
250
+ Args.MakeArgString (ToolChain.GetFilePath (" crtbegin.o" )));
251
+
252
+ // Add crtfastmath.o if available and fast math is enabled.
253
+ ToolChain.addFastMathRuntimeIfAvailable (Args, CmdArgs);
254
+ }
255
+
256
+ Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_u});
257
+
258
+ ToolChain.AddFilePathLibArgs (Args, CmdArgs);
259
+
260
+ if (D.isUsingLTO ())
261
+ tools::addLTOOptions (ToolChain, Args, CmdArgs, Output, Inputs,
262
+ D.getLTOMode () == LTOK_Thin);
263
+
264
+ if (Args.hasArg (options::OPT_Z_Xlinker__no_demangle))
265
+ CmdArgs.push_back (" --no-demangle" );
266
+
267
+ bool NeedsSanitizerDeps =
268
+ tools::addSanitizerRuntimes (ToolChain, Args, CmdArgs);
269
+ bool NeedsXRayDeps = tools::addXRayRuntime (ToolChain, Args, CmdArgs);
270
+ tools::addLinkerCompressDebugSectionsOption (ToolChain, Args, CmdArgs);
271
+ tools::AddLinkerInputs (ToolChain, Inputs, Args, CmdArgs, JA);
272
+
273
+ tools::addHIPRuntimeLibArgs (ToolChain, C, Args, CmdArgs);
274
+
275
+ // The profile runtime also needs access to system libraries.
276
+ getToolChain ().addProfileRTLibs (Args, CmdArgs);
277
+
278
+ if (D.CCCIsCXX () &&
279
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs,
280
+ options::OPT_r)) {
281
+ if (ToolChain.ShouldLinkCXXStdlib (Args)) {
282
+ bool OnlyLibstdcxxStatic = Args.hasArg (options::OPT_static_libstdcxx) &&
283
+ !Args.hasArg (options::OPT_static);
284
+ if (OnlyLibstdcxxStatic)
285
+ CmdArgs.push_back (" -Bstatic" );
286
+ ToolChain.AddCXXStdlibLibArgs (Args, CmdArgs);
287
+ if (OnlyLibstdcxxStatic)
288
+ CmdArgs.push_back (" -Bdynamic" );
289
+ }
290
+ CmdArgs.push_back (" -lm" );
291
+ }
292
+
293
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
294
+ Args.ClaimAllArgs (options::OPT_stdlib_EQ);
295
+
296
+ // Additional linker set-up and flags for Fortran. This is required in order
297
+ // to generate executables. As Fortran runtime depends on the C runtime,
298
+ // these dependencies need to be listed before the C runtime below (i.e.
299
+ // AddRunTimeLibs).
300
+ if (D.IsFlangMode () &&
301
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
302
+ ToolChain.addFortranRuntimeLibraryPath (Args, CmdArgs);
303
+ ToolChain.addFortranRuntimeLibs (Args, CmdArgs);
304
+ CmdArgs.push_back (" -lm" );
305
+ }
306
+
307
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_r)) {
308
+ if (!Args.hasArg (options::OPT_nodefaultlibs)) {
309
+ if (IsStatic || IsStaticPIE)
310
+ CmdArgs.push_back (" --start-group" );
311
+
312
+ if (NeedsSanitizerDeps)
313
+ tools::linkSanitizerRuntimeDeps (ToolChain, Args, CmdArgs);
314
+
315
+ if (NeedsXRayDeps)
316
+ tools::linkXRayRuntimeDeps (ToolChain, Args, CmdArgs);
317
+
318
+ bool WantPthread = Args.hasArg (options::OPT_pthread) ||
319
+ Args.hasArg (options::OPT_pthreads);
320
+
321
+ // Use the static OpenMP runtime with -static-openmp
322
+ bool StaticOpenMP = Args.hasArg (options::OPT_static_openmp) &&
323
+ !Args.hasArg (options::OPT_static);
324
+
325
+ // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
326
+ // require librt. Most modern Linux platforms do, but some may not.
327
+ if (tools::addOpenMPRuntime (C, CmdArgs, ToolChain, Args, StaticOpenMP,
328
+ JA.isHostOffloading (Action::OFK_OpenMP),
329
+ /* GompNeedsRT= */ true ))
330
+ // OpenMP runtimes implies pthreads when using the GNU toolchain.
331
+ // FIXME: Does this really make sense for all GNU toolchains?
332
+ WantPthread = true ;
333
+
334
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
335
+
336
+ if (WantPthread)
337
+ CmdArgs.push_back (" -lpthread" );
338
+
339
+ if (Args.hasArg (options::OPT_fsplit_stack))
340
+ CmdArgs.push_back (" --wrap=pthread_create" );
341
+
342
+ if (!Args.hasArg (options::OPT_nolibc))
343
+ CmdArgs.push_back (" -lc" );
344
+
345
+ // Cygwin specific
346
+ CmdArgs.push_back (" -lcygwin" );
347
+ CmdArgs.push_back (" -ladvapi32" );
348
+ CmdArgs.push_back (" -lshell32" );
349
+ CmdArgs.push_back (" -luser32" );
350
+ CmdArgs.push_back (" -lkernel32" );
351
+
352
+ // Add IAMCU specific libs, if needed.
353
+ if (IsIAMCU)
354
+ CmdArgs.push_back (" -lgloss" );
355
+
356
+ if (IsStatic || IsStaticPIE)
357
+ CmdArgs.push_back (" --end-group" );
358
+ else
359
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
360
+
361
+ // Add IAMCU specific libs (outside the group), if needed.
362
+ if (IsIAMCU) {
363
+ CmdArgs.push_back (" --as-needed" );
364
+ CmdArgs.push_back (" -lsoftfp" );
365
+ CmdArgs.push_back (" --no-as-needed" );
366
+ }
367
+ }
368
+
369
+ if (!Args.hasArg (options::OPT_nostartfiles) && !IsIAMCU) {
370
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
371
+ std::string crtend =
372
+ ToolChain.getCompilerRT (Args, " crtend" , ToolChain::FT_Object);
373
+ if (ToolChain.getVFS ().exists (crtend)) {
374
+ std::string P;
375
+ P = crtend;
376
+ CmdArgs.push_back (Args.MakeArgString (P));
377
+ }
378
+ }
379
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crtend.o" )));
380
+ }
381
+ }
382
+
383
+ Args.addAllArgs (CmdArgs, {options::OPT_T, options::OPT_t});
384
+
385
+ const char *Exec = Args.MakeArgString (ToolChain.GetLinkerPath ());
386
+ C.addCommand (std::make_unique<Command>(JA, *this ,
387
+ ResponseFileSupport::AtFileCurCP (),
388
+ Exec, CmdArgs, Inputs, Output));
389
+ }
390
+
391
+ auto Cygwin::buildLinker () const -> Tool * { return new cygwin::Linker (*this ); }
0 commit comments