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,289 @@ 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 = static_cast <const Cygwin &>(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) << ToolChain.getEffectiveTriple ().str ();
181
+ }
182
+
183
+ CmdArgs.push_back (" --wrap=_Znwm" );
184
+ CmdArgs.push_back (" --wrap=_Znam" );
185
+ CmdArgs.push_back (" --wrap=_ZdlPv" );
186
+ CmdArgs.push_back (" --wrap=_ZdaPv" );
187
+ CmdArgs.push_back (" --wrap=_ZnwmRKSt9nothrow_t" );
188
+ CmdArgs.push_back (" --wrap=_ZnamRKSt9nothrow_t" );
189
+ CmdArgs.push_back (" --wrap=_ZdlPvRKSt9nothrow_t" );
190
+ CmdArgs.push_back (" --wrap=_ZdaPvRKSt9nothrow_t" );
191
+
192
+ const bool IsShared = Args.hasArg (options::OPT_shared);
193
+ if (IsShared)
194
+ CmdArgs.push_back (" -shared" );
195
+ bool IsPIE = false ;
196
+ if (IsStaticPIE) {
197
+ CmdArgs.push_back (" -static" );
198
+ CmdArgs.push_back (" -pie" );
199
+ CmdArgs.push_back (" --no-dynamic-linker" );
200
+ CmdArgs.push_back (" -z" );
201
+ CmdArgs.push_back (" text" );
202
+ } else if (IsStatic) {
203
+ CmdArgs.push_back (" -static" );
204
+ } else if (!Args.hasArg (options::OPT_r)) {
205
+ if (Args.hasArg (options::OPT_rdynamic))
206
+ CmdArgs.push_back (" -export-dynamic" );
207
+ if (!IsShared) {
208
+ IsPIE = Args.hasFlag (options::OPT_pie, options::OPT_no_pie,
209
+ ToolChain.isPIEDefault (Args));
210
+ if (IsPIE)
211
+ CmdArgs.push_back (" -pie" );
212
+ }
213
+ }
214
+
215
+ CmdArgs.push_back (" -o" );
216
+ CmdArgs.push_back (Output.getFilename ());
217
+
218
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles,
219
+ options::OPT_r)) {
220
+ if (IsVE) {
221
+ CmdArgs.push_back (" -z" );
222
+ CmdArgs.push_back (" max-page-size=0x4000000" );
223
+ }
224
+
225
+ if (IsShared) {
226
+ CmdArgs.push_back (" -e" );
227
+ CmdArgs.push_back (" _cygwin_dll_entry" );
228
+ CmdArgs.push_back (" --enable-auto-image-base" );
229
+ }
230
+
231
+ if (!IsShared)
232
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crt0.o" )));
233
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
234
+ std::string crtbegin = ToolChain.getCompilerRT (Args, " crtbegin" ,
235
+ ToolChain::FT_Object);
236
+ if (ToolChain.getVFS ().exists (crtbegin)) {
237
+ std::string P;
238
+ P = crtbegin;
239
+ CmdArgs.push_back (Args.MakeArgString (P));
240
+ }
241
+ }
242
+ if (IsShared)
243
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crtbeginS.o" )));
244
+ else
245
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crtbegin.o" )));
246
+
247
+ // Add crtfastmath.o if available and fast math is enabled.
248
+ ToolChain.addFastMathRuntimeIfAvailable (Args, CmdArgs);
249
+ }
250
+
251
+ Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_u});
252
+
253
+ ToolChain.AddFilePathLibArgs (Args, CmdArgs);
254
+
255
+ CmdArgs.push_back (Args.MakeArgString (
256
+ " -L" + ToolChain.getGCCInstallation ().getInstallPath ()));
257
+
258
+ if (D.isUsingLTO ()) {
259
+ assert (!Inputs.empty () && " Must have at least one input." );
260
+ // Find the first filename InputInfo object.
261
+ auto Input = llvm::find_if (
262
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename (); });
263
+ if (Input == Inputs.end ())
264
+ // For a very rare case, all of the inputs to the linker are
265
+ // InputArg. If that happens, just use the first InputInfo.
266
+ Input = Inputs.begin ();
267
+
268
+ tools::addLTOOptions (ToolChain, Args, CmdArgs, Output, *Input,
269
+ D.getLTOMode () == LTOK_Thin);
270
+ }
271
+
272
+ if (Args.hasArg (options::OPT_Z_Xlinker__no_demangle))
273
+ CmdArgs.push_back (" --no-demangle" );
274
+
275
+ bool NeedsSanitizerDeps = tools::addSanitizerRuntimes (ToolChain, Args, CmdArgs);
276
+ bool NeedsXRayDeps = tools::addXRayRuntime (ToolChain, Args, CmdArgs);
277
+ tools::addLinkerCompressDebugSectionsOption (ToolChain, Args, CmdArgs);
278
+ tools::AddLinkerInputs (ToolChain, Inputs, Args, CmdArgs, JA);
279
+
280
+ tools::addHIPRuntimeLibArgs (ToolChain, C, Args, CmdArgs);
281
+
282
+ // The profile runtime also needs access to system libraries.
283
+ getToolChain ().addProfileRTLibs (Args, CmdArgs);
284
+
285
+ if (D.CCCIsCXX () &&
286
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs,
287
+ options::OPT_r)) {
288
+ if (ToolChain.ShouldLinkCXXStdlib (Args)) {
289
+ bool OnlyLibstdcxxStatic = Args.hasArg (options::OPT_static_libstdcxx) &&
290
+ !Args.hasArg (options::OPT_static);
291
+ if (OnlyLibstdcxxStatic)
292
+ CmdArgs.push_back (" -Bstatic" );
293
+ ToolChain.AddCXXStdlibLibArgs (Args, CmdArgs);
294
+ if (OnlyLibstdcxxStatic)
295
+ CmdArgs.push_back (" -Bdynamic" );
296
+ }
297
+ CmdArgs.push_back (" -lm" );
298
+ }
299
+
300
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
301
+ Args.ClaimAllArgs (options::OPT_stdlib_EQ);
302
+
303
+ // Additional linker set-up and flags for Fortran. This is required in order
304
+ // to generate executables. As Fortran runtime depends on the C runtime,
305
+ // these dependencies need to be listed before the C runtime below (i.e.
306
+ // AddRunTimeLibs).
307
+ if (D.IsFlangMode () &&
308
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
309
+ tools::addFortranRuntimeLibraryPath (ToolChain, Args, CmdArgs);
310
+ tools::addFortranRuntimeLibs (ToolChain, Args, CmdArgs);
311
+ CmdArgs.push_back (" -lm" );
312
+ }
313
+
314
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_r)) {
315
+ if (!Args.hasArg (options::OPT_nodefaultlibs)) {
316
+ if (IsStatic || IsStaticPIE)
317
+ CmdArgs.push_back (" --start-group" );
318
+
319
+ if (NeedsSanitizerDeps)
320
+ tools::linkSanitizerRuntimeDeps (ToolChain, Args, CmdArgs);
321
+
322
+ if (NeedsXRayDeps)
323
+ tools::linkXRayRuntimeDeps (ToolChain, Args, CmdArgs);
324
+
325
+ bool WantPthread = Args.hasArg (options::OPT_pthread) ||
326
+ Args.hasArg (options::OPT_pthreads);
327
+
328
+ // Use the static OpenMP runtime with -static-openmp
329
+ bool StaticOpenMP = Args.hasArg (options::OPT_static_openmp) &&
330
+ !Args.hasArg (options::OPT_static);
331
+
332
+ // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
333
+ // require librt. Most modern Linux platforms do, but some may not.
334
+ if (tools::addOpenMPRuntime (C, CmdArgs, ToolChain, Args, StaticOpenMP,
335
+ JA.isHostOffloading (Action::OFK_OpenMP),
336
+ /* GompNeedsRT= */ true ))
337
+ // OpenMP runtimes implies pthreads when using the GNU toolchain.
338
+ // FIXME: Does this really make sense for all GNU toolchains?
339
+ WantPthread = true ;
340
+
341
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
342
+
343
+ if (WantPthread)
344
+ CmdArgs.push_back (" -lpthread" );
345
+
346
+ if (Args.hasArg (options::OPT_fsplit_stack))
347
+ CmdArgs.push_back (" --wrap=pthread_create" );
348
+
349
+ if (!Args.hasArg (options::OPT_nolibc))
350
+ CmdArgs.push_back (" -lc" );
351
+
352
+ // Cygwin specific
353
+ CmdArgs.push_back (" -lcygwin" );
354
+ CmdArgs.push_back (" -ladvapi32" );
355
+ CmdArgs.push_back (" -lshell32" );
356
+ CmdArgs.push_back (" -luser32" );
357
+ CmdArgs.push_back (" -lkernel32" );
358
+
359
+ // Add IAMCU specific libs, if needed.
360
+ if (IsIAMCU)
361
+ CmdArgs.push_back (" -lgloss" );
362
+
363
+ if (IsStatic || IsStaticPIE)
364
+ CmdArgs.push_back (" --end-group" );
365
+ else
366
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
367
+
368
+ // Add IAMCU specific libs (outside the group), if needed.
369
+ if (IsIAMCU) {
370
+ CmdArgs.push_back (" --as-needed" );
371
+ CmdArgs.push_back (" -lsoftfp" );
372
+ CmdArgs.push_back (" --no-as-needed" );
373
+ }
374
+ }
375
+
376
+ if (!Args.hasArg (options::OPT_nostartfiles) && !IsIAMCU) {
377
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
378
+ std::string crtend = ToolChain.getCompilerRT (Args, " crtend" ,
379
+ ToolChain::FT_Object);
380
+ if (ToolChain.getVFS ().exists (crtend)) {
381
+ std::string P;
382
+ P = crtend;
383
+ CmdArgs.push_back (Args.MakeArgString (P));
384
+ }
385
+ }
386
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crtend.o" )));
387
+ }
388
+ }
389
+
390
+ Args.addAllArgs (CmdArgs, {options::OPT_T, options::OPT_t});
391
+
392
+ const char *Exec = Args.MakeArgString (ToolChain.GetLinkerPath ());
393
+ C.addCommand (std::make_unique<Command>(JA, *this ,
394
+ ResponseFileSupport::AtFileCurCP (),
395
+ Exec, CmdArgs, Inputs, Output));
396
+ }
397
+
398
+ auto Cygwin::buildLinker () const -> Tool * { return new cygwin::Linker (*this ); }
0 commit comments