Tools.cpp revision 208600
1193326Sed//===--- Tools.cpp - Tools Implementations ------------------------------*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed
10193326Sed#include "Tools.h"
11193326Sed
12193326Sed#include "clang/Driver/Action.h"
13193326Sed#include "clang/Driver/Arg.h"
14193326Sed#include "clang/Driver/ArgList.h"
15198893Srdivacky#include "clang/Driver/Driver.h"
16198893Srdivacky#include "clang/Driver/DriverDiagnostic.h"
17193326Sed#include "clang/Driver/Compilation.h"
18193326Sed#include "clang/Driver/Job.h"
19193326Sed#include "clang/Driver/HostInfo.h"
20193326Sed#include "clang/Driver/Option.h"
21199512Srdivacky#include "clang/Driver/Options.h"
22193326Sed#include "clang/Driver/ToolChain.h"
23193326Sed#include "clang/Driver/Util.h"
24193326Sed
25198092Srdivacky#include "llvm/ADT/SmallString.h"
26198893Srdivacky#include "llvm/ADT/StringSwitch.h"
27198092Srdivacky#include "llvm/ADT/Twine.h"
28193326Sed#include "llvm/Support/Format.h"
29193326Sed#include "llvm/Support/raw_ostream.h"
30199482Srdivacky#include "llvm/System/Host.h"
31198893Srdivacky#include "llvm/System/Process.h"
32193326Sed
33193326Sed#include "InputInfo.h"
34193326Sed#include "ToolChains.h"
35193326Sed
36193326Sedusing namespace clang::driver;
37193326Sedusing namespace clang::driver::tools;
38193326Sed
39198092Srdivacky/// CheckPreprocessingOptions - Perform some validation of preprocessing
40198092Srdivacky/// arguments that is shared with gcc.
41198092Srdivackystatic void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
42198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC))
43198092Srdivacky    if (!Args.hasArg(options::OPT_E))
44198092Srdivacky      D.Diag(clang::diag::err_drv_argument_only_allowed_with)
45198092Srdivacky        << A->getAsString(Args) << "-E";
46198092Srdivacky}
47198092Srdivacky
48198092Srdivacky/// CheckCodeGenerationOptions - Perform some validation of code generation
49198092Srdivacky/// arguments that is shared with gcc.
50198092Srdivackystatic void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
51198092Srdivacky  // In gcc, only ARM checks this, but it seems reasonable to check universally.
52198092Srdivacky  if (Args.hasArg(options::OPT_static))
53198092Srdivacky    if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
54198092Srdivacky                                       options::OPT_mdynamic_no_pic))
55198092Srdivacky      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
56198092Srdivacky        << A->getAsString(Args) << "-static";
57198092Srdivacky}
58198092Srdivacky
59206084Srdivacky// Quote target names for inclusion in GNU Make dependency files.
60206084Srdivacky// Only the characters '$', '#', ' ', '\t' are quoted.
61206084Srdivackystatic void QuoteTarget(llvm::StringRef Target,
62206084Srdivacky                        llvm::SmallVectorImpl<char> &Res) {
63206084Srdivacky  for (unsigned i = 0, e = Target.size(); i != e; ++i) {
64206084Srdivacky    switch (Target[i]) {
65206084Srdivacky    case ' ':
66206084Srdivacky    case '\t':
67206084Srdivacky      // Escape the preceding backslashes
68206084Srdivacky      for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
69206084Srdivacky        Res.push_back('\\');
70206084Srdivacky
71206084Srdivacky      // Escape the space/tab
72206084Srdivacky      Res.push_back('\\');
73206084Srdivacky      break;
74206084Srdivacky    case '$':
75206084Srdivacky      Res.push_back('$');
76206084Srdivacky      break;
77206084Srdivacky    case '#':
78206084Srdivacky      Res.push_back('\\');
79206084Srdivacky      break;
80206084Srdivacky    default:
81206084Srdivacky      break;
82206084Srdivacky    }
83206084Srdivacky
84206084Srdivacky    Res.push_back(Target[i]);
85206084Srdivacky  }
86206084Srdivacky}
87206084Srdivacky
88198092Srdivackyvoid Clang::AddPreprocessingOptions(const Driver &D,
89193326Sed                                    const ArgList &Args,
90193326Sed                                    ArgStringList &CmdArgs,
91193326Sed                                    const InputInfo &Output,
92193326Sed                                    const InputInfoList &Inputs) const {
93194179Sed  Arg *A;
94194179Sed
95198092Srdivacky  CheckPreprocessingOptions(D, Args);
96194179Sed
97198092Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_C);
98198092Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_CC);
99198092Srdivacky
100193326Sed  // Handle dependency file generation.
101193326Sed  if ((A = Args.getLastArg(options::OPT_M)) ||
102193326Sed      (A = Args.getLastArg(options::OPT_MM)) ||
103193326Sed      (A = Args.getLastArg(options::OPT_MD)) ||
104193326Sed      (A = Args.getLastArg(options::OPT_MMD))) {
105193326Sed    // Determine the output location.
106193326Sed    const char *DepFile;
107193326Sed    if (Output.getType() == types::TY_Dependencies) {
108193326Sed      if (Output.isPipe())
109193326Sed        DepFile = "-";
110193326Sed      else
111193326Sed        DepFile = Output.getFilename();
112193326Sed    } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
113193326Sed      DepFile = MF->getValue(Args);
114199512Srdivacky    } else if (A->getOption().matches(options::OPT_M) ||
115199512Srdivacky               A->getOption().matches(options::OPT_MM)) {
116193326Sed      DepFile = "-";
117193326Sed    } else {
118193326Sed      DepFile = darwin::CC1::getDependencyFileName(Args, Inputs);
119193326Sed    }
120193326Sed    CmdArgs.push_back("-dependency-file");
121193326Sed    CmdArgs.push_back(DepFile);
122193326Sed
123206084Srdivacky    // Add a default target if one wasn't specified.
124193326Sed    if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
125193326Sed      const char *DepTarget;
126193326Sed
127193326Sed      // If user provided -o, that is the dependency target, except
128193326Sed      // when we are only generating a dependency file.
129193326Sed      Arg *OutputOpt = Args.getLastArg(options::OPT_o);
130193326Sed      if (OutputOpt && Output.getType() != types::TY_Dependencies) {
131193326Sed        DepTarget = OutputOpt->getValue(Args);
132193326Sed      } else {
133193326Sed        // Otherwise derive from the base input.
134193326Sed        //
135193326Sed        // FIXME: This should use the computed output file location.
136193326Sed        llvm::sys::Path P(Inputs[0].getBaseInput());
137193326Sed
138193326Sed        P.eraseSuffix();
139193326Sed        P.appendSuffix("o");
140198092Srdivacky        DepTarget = Args.MakeArgString(P.getLast());
141193326Sed      }
142193326Sed
143193326Sed      CmdArgs.push_back("-MT");
144206084Srdivacky      llvm::SmallString<128> Quoted;
145206084Srdivacky      QuoteTarget(DepTarget, Quoted);
146206084Srdivacky      CmdArgs.push_back(Args.MakeArgString(Quoted));
147193326Sed    }
148193326Sed
149199512Srdivacky    if (A->getOption().matches(options::OPT_M) ||
150199512Srdivacky        A->getOption().matches(options::OPT_MD))
151193326Sed      CmdArgs.push_back("-sys-header-deps");
152193326Sed  }
153193326Sed
154193326Sed  Args.AddLastArg(CmdArgs, options::OPT_MP);
155193326Sed
156206084Srdivacky  // Convert all -MQ <target> args to -MT <quoted target>
157206084Srdivacky  for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
158206084Srdivacky                                             options::OPT_MQ),
159206084Srdivacky         ie = Args.filtered_end(); it != ie; ++it) {
160206084Srdivacky
161206084Srdivacky    it->claim();
162206084Srdivacky
163206084Srdivacky    if (it->getOption().matches(options::OPT_MQ)) {
164206084Srdivacky      CmdArgs.push_back("-MT");
165206084Srdivacky      llvm::SmallString<128> Quoted;
166206084Srdivacky      QuoteTarget(it->getValue(Args), Quoted);
167206084Srdivacky      CmdArgs.push_back(Args.MakeArgString(Quoted));
168206084Srdivacky
169206084Srdivacky    // -MT flag - no change
170206084Srdivacky    } else {
171206084Srdivacky      it->render(Args, CmdArgs);
172206084Srdivacky    }
173206084Srdivacky  }
174206084Srdivacky
175193326Sed  // Add -i* options, and automatically translate to
176193326Sed  // -include-pch/-include-pth for transparent PCH support. It's
177193326Sed  // wonky, but we include looking for .gch so we can support seamless
178193326Sed  // replacement into a build system already set up to be generating
179193326Sed  // .gch files.
180199990Srdivacky  for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
181199990Srdivacky         ie = Args.filtered_end(); it != ie; ++it) {
182199990Srdivacky    const Arg *A = it;
183193326Sed
184193326Sed    if (A->getOption().matches(options::OPT_include)) {
185198398Srdivacky      // Use PCH if the user requested it, except for C++ (for now).
186198398Srdivacky      bool UsePCH = D.CCCUsePCH;
187198398Srdivacky      if (types::isCXX(Inputs[0].getType()))
188198398Srdivacky        UsePCH = false;
189198398Srdivacky
190193326Sed      bool FoundPTH = false;
191193326Sed      bool FoundPCH = false;
192193326Sed      llvm::sys::Path P(A->getValue(Args));
193198398Srdivacky      if (UsePCH) {
194193326Sed        P.appendSuffix("pch");
195193326Sed        if (P.exists())
196193326Sed          FoundPCH = true;
197198092Srdivacky        else
198193326Sed          P.eraseSuffix();
199193326Sed      }
200193326Sed
201193326Sed      if (!FoundPCH) {
202193326Sed        P.appendSuffix("pth");
203198092Srdivacky        if (P.exists())
204193326Sed          FoundPTH = true;
205193326Sed        else
206193326Sed          P.eraseSuffix();
207198092Srdivacky      }
208198092Srdivacky
209193326Sed      if (!FoundPCH && !FoundPTH) {
210193326Sed        P.appendSuffix("gch");
211193326Sed        if (P.exists()) {
212198398Srdivacky          FoundPCH = UsePCH;
213198398Srdivacky          FoundPTH = !UsePCH;
214193326Sed        }
215198092Srdivacky        else
216193326Sed          P.eraseSuffix();
217193326Sed      }
218193326Sed
219193326Sed      if (FoundPCH || FoundPTH) {
220193326Sed        A->claim();
221198398Srdivacky        if (UsePCH)
222193326Sed          CmdArgs.push_back("-include-pch");
223193326Sed        else
224193326Sed          CmdArgs.push_back("-include-pth");
225198092Srdivacky        CmdArgs.push_back(Args.MakeArgString(P.str()));
226193326Sed        continue;
227193326Sed      }
228193326Sed    }
229193326Sed
230193326Sed    // Not translated, render as usual.
231193326Sed    A->claim();
232193326Sed    A->render(Args, CmdArgs);
233193326Sed  }
234193326Sed
235193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
236193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
237193326Sed
238193326Sed  // Add -Wp, and -Xassembler if using the preprocessor.
239193326Sed
240193326Sed  // FIXME: There is a very unfortunate problem here, some troubled
241193326Sed  // souls abuse -Wp, to pass preprocessor options in gcc syntax. To
242193326Sed  // really support that we would have to parse and then translate
243193326Sed  // those options. :(
244193326Sed  Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
245193326Sed                       options::OPT_Xpreprocessor);
246198893Srdivacky
247198893Srdivacky  // -I- is a deprecated GCC feature, reject it.
248198893Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_I_))
249198893Srdivacky    D.Diag(clang::diag::err_drv_I_dash_not_supported) << A->getAsString(Args);
250193326Sed}
251193326Sed
252198092Srdivacky/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
253198092Srdivacky//
254198092Srdivacky// FIXME: tblgen this.
255199990Srdivackystatic const char *getARMTargetCPU(const ArgList &Args) {
256198092Srdivacky  // FIXME: Warn on inconsistent use of -mcpu and -march.
257198092Srdivacky
258198092Srdivacky  // If we have -mcpu=, use that.
259198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
260198092Srdivacky    return A->getValue(Args);
261198092Srdivacky
262198092Srdivacky  // Otherwise, if we have -march= choose the base CPU for that arch.
263198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
264198092Srdivacky    llvm::StringRef MArch = A->getValue(Args);
265198092Srdivacky
266198092Srdivacky    if (MArch == "armv2" || MArch == "armv2a")
267198092Srdivacky      return "arm2";
268198092Srdivacky    if (MArch == "armv3")
269198092Srdivacky      return "arm6";
270198092Srdivacky    if (MArch == "armv3m")
271198092Srdivacky      return "arm7m";
272198092Srdivacky    if (MArch == "armv4" || MArch == "armv4t")
273198092Srdivacky      return "arm7tdmi";
274198092Srdivacky    if (MArch == "armv5" || MArch == "armv5t")
275198092Srdivacky      return "arm10tdmi";
276198092Srdivacky    if (MArch == "armv5e" || MArch == "armv5te")
277198092Srdivacky      return "arm1026ejs";
278198092Srdivacky    if (MArch == "armv5tej")
279201361Srdivacky      return "arm926ej-s";
280198092Srdivacky    if (MArch == "armv6" || MArch == "armv6k")
281198092Srdivacky      return "arm1136jf-s";
282198092Srdivacky    if (MArch == "armv6j")
283198092Srdivacky      return "arm1136j-s";
284198092Srdivacky    if (MArch == "armv6z" || MArch == "armv6zk")
285198092Srdivacky      return "arm1176jzf-s";
286198092Srdivacky    if (MArch == "armv6t2")
287198092Srdivacky      return "arm1156t2-s";
288198092Srdivacky    if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
289198092Srdivacky      return "cortex-a8";
290198092Srdivacky    if (MArch == "armv7r" || MArch == "armv7-r")
291198092Srdivacky      return "cortex-r4";
292198092Srdivacky    if (MArch == "armv7m" || MArch == "armv7-m")
293198092Srdivacky      return "cortex-m3";
294198092Srdivacky    if (MArch == "ep9312")
295198092Srdivacky      return "ep9312";
296198092Srdivacky    if (MArch == "iwmmxt")
297198092Srdivacky      return "iwmmxt";
298198092Srdivacky    if (MArch == "xscale")
299198092Srdivacky      return "xscale";
300198092Srdivacky  }
301198092Srdivacky
302198092Srdivacky  // Otherwise return the most base CPU LLVM supports.
303198092Srdivacky  return "arm7tdmi";
304198092Srdivacky}
305198092Srdivacky
306198092Srdivacky/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
307198092Srdivacky/// CPU.
308198092Srdivacky//
309198092Srdivacky// FIXME: This is redundant with -mcpu, why does LLVM use this.
310198092Srdivacky// FIXME: tblgen this, or kill it!
311198092Srdivackystatic const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
312198092Srdivacky  if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" ||
313198092Srdivacky      CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" ||
314198092Srdivacky      CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" ||
315198092Srdivacky      CPU == "arm940t" || CPU == "ep9312")
316198092Srdivacky    return "v4t";
317198092Srdivacky
318198092Srdivacky  if (CPU == "arm10tdmi" || CPU == "arm1020t")
319198092Srdivacky    return "v5";
320198092Srdivacky
321198092Srdivacky  if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" ||
322198092Srdivacky      CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" ||
323198092Srdivacky      CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" ||
324198092Srdivacky      CPU == "iwmmxt")
325198092Srdivacky    return "v5e";
326198092Srdivacky
327198092Srdivacky  if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" ||
328198092Srdivacky      CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore")
329198092Srdivacky    return "v6";
330198092Srdivacky
331198092Srdivacky  if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s")
332198092Srdivacky    return "v6t2";
333198092Srdivacky
334198092Srdivacky  if (CPU == "cortex-a8" || CPU == "cortex-a9")
335198092Srdivacky    return "v7";
336198092Srdivacky
337198092Srdivacky  return "";
338198092Srdivacky}
339198092Srdivacky
340198092Srdivacky/// getLLVMTriple - Get the LLVM triple to use for a particular toolchain, which
341198092Srdivacky/// may depend on command line arguments.
342198092Srdivackystatic std::string getLLVMTriple(const ToolChain &TC, const ArgList &Args) {
343198092Srdivacky  switch (TC.getTriple().getArch()) {
344198092Srdivacky  default:
345198092Srdivacky    return TC.getTripleString();
346198092Srdivacky
347198092Srdivacky  case llvm::Triple::arm:
348198092Srdivacky  case llvm::Triple::thumb: {
349198092Srdivacky    // FIXME: Factor into subclasses.
350198092Srdivacky    llvm::Triple Triple = TC.getTriple();
351198092Srdivacky
352198092Srdivacky    // Thumb2 is the default for V7 on Darwin.
353198092Srdivacky    //
354198092Srdivacky    // FIXME: Thumb should just be another -target-feaure, not in the triple.
355198092Srdivacky    llvm::StringRef Suffix = getLLVMArchSuffixForARM(getARMTargetCPU(Args));
356198092Srdivacky    bool ThumbDefault =
357198092Srdivacky      (Suffix == "v7" && TC.getTriple().getOS() == llvm::Triple::Darwin);
358198092Srdivacky    std::string ArchName = "arm";
359198092Srdivacky    if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
360198092Srdivacky      ArchName = "thumb";
361198092Srdivacky    Triple.setArchName(ArchName + Suffix.str());
362198092Srdivacky
363198092Srdivacky    return Triple.getTriple();
364198092Srdivacky  }
365198092Srdivacky  }
366198092Srdivacky}
367198092Srdivacky
368199482Srdivacky// FIXME: Move to target hook.
369199482Srdivackystatic bool isSignedCharDefault(const llvm::Triple &Triple) {
370199482Srdivacky  switch (Triple.getArch()) {
371199482Srdivacky  default:
372199482Srdivacky    return true;
373199482Srdivacky
374199482Srdivacky  case llvm::Triple::ppc:
375199482Srdivacky  case llvm::Triple::ppc64:
376199482Srdivacky    if (Triple.getOS() == llvm::Triple::Darwin)
377199482Srdivacky      return true;
378199482Srdivacky    return false;
379199482Srdivacky
380199482Srdivacky  case llvm::Triple::systemz:
381199482Srdivacky    return false;
382199482Srdivacky  }
383199482Srdivacky}
384199482Srdivacky
385198092Srdivackyvoid Clang::AddARMTargetArgs(const ArgList &Args,
386198092Srdivacky                             ArgStringList &CmdArgs) const {
387201361Srdivacky  const Driver &D = getToolChain().getDriver();
388198092Srdivacky
389198092Srdivacky  // Select the ABI to use.
390198092Srdivacky  //
391198092Srdivacky  // FIXME: Support -meabi.
392198092Srdivacky  const char *ABIName = 0;
393198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
394198092Srdivacky    ABIName = A->getValue(Args);
395198092Srdivacky  } else {
396198092Srdivacky    // Select the default based on the platform.
397198092Srdivacky    switch (getToolChain().getTriple().getOS()) {
398198092Srdivacky      // FIXME: Is this right for non-Darwin and non-Linux?
399198092Srdivacky    default:
400198092Srdivacky      ABIName = "aapcs";
401198092Srdivacky      break;
402198092Srdivacky
403198092Srdivacky    case llvm::Triple::Darwin:
404198092Srdivacky      ABIName = "apcs-gnu";
405198092Srdivacky      break;
406198092Srdivacky
407198092Srdivacky    case llvm::Triple::Linux:
408198092Srdivacky      ABIName = "aapcs-linux";
409198092Srdivacky      break;
410198092Srdivacky    }
411198092Srdivacky  }
412198092Srdivacky  CmdArgs.push_back("-target-abi");
413198092Srdivacky  CmdArgs.push_back(ABIName);
414198092Srdivacky
415198092Srdivacky  // Set the CPU based on -march= and -mcpu=.
416201361Srdivacky  CmdArgs.push_back("-target-cpu");
417199990Srdivacky  CmdArgs.push_back(getARMTargetCPU(Args));
418198092Srdivacky
419198092Srdivacky  // Select the float ABI as determined by -msoft-float, -mhard-float, and
420198092Srdivacky  // -mfloat-abi=.
421198092Srdivacky  llvm::StringRef FloatABI;
422198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
423198092Srdivacky                               options::OPT_mhard_float,
424198092Srdivacky                               options::OPT_mfloat_abi_EQ)) {
425198092Srdivacky    if (A->getOption().matches(options::OPT_msoft_float))
426198092Srdivacky      FloatABI = "soft";
427198092Srdivacky    else if (A->getOption().matches(options::OPT_mhard_float))
428198092Srdivacky      FloatABI = "hard";
429198092Srdivacky    else {
430198092Srdivacky      FloatABI = A->getValue(Args);
431198092Srdivacky      if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
432198092Srdivacky        D.Diag(clang::diag::err_drv_invalid_mfloat_abi)
433198092Srdivacky          << A->getAsString(Args);
434198092Srdivacky        FloatABI = "soft";
435198092Srdivacky      }
436198092Srdivacky    }
437198092Srdivacky  }
438198092Srdivacky
439198092Srdivacky  // If unspecified, choose the default based on the platform.
440198092Srdivacky  if (FloatABI.empty()) {
441198092Srdivacky    // FIXME: This is wrong for non-Darwin, we don't have a mechanism yet for
442198092Srdivacky    // distinguishing things like linux-eabi vs linux-elf.
443198092Srdivacky    switch (getToolChain().getTriple().getOS()) {
444198092Srdivacky    case llvm::Triple::Darwin: {
445198092Srdivacky      // Darwin defaults to "softfp" for v6 and v7.
446198092Srdivacky      //
447198092Srdivacky      // FIXME: Factor out an ARM class so we can cache the arch somewhere.
448198092Srdivacky      llvm::StringRef ArchName = getLLVMArchSuffixForARM(getARMTargetCPU(Args));
449198092Srdivacky      if (ArchName.startswith("v6") || ArchName.startswith("v7"))
450198092Srdivacky        FloatABI = "softfp";
451198092Srdivacky      else
452198092Srdivacky        FloatABI = "soft";
453198092Srdivacky      break;
454198092Srdivacky    }
455198092Srdivacky
456198092Srdivacky    default:
457198092Srdivacky      // Assume "soft", but warn the user we are guessing.
458198092Srdivacky      FloatABI = "soft";
459198092Srdivacky      D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft";
460198092Srdivacky      break;
461198092Srdivacky    }
462198092Srdivacky  }
463198092Srdivacky
464198092Srdivacky  if (FloatABI == "soft") {
465198092Srdivacky    // Floating point operations and argument passing are soft.
466198092Srdivacky    //
467198092Srdivacky    // FIXME: This changes CPP defines, we need -target-soft-float.
468199990Srdivacky    CmdArgs.push_back("-msoft-float");
469200583Srdivacky    CmdArgs.push_back("-mfloat-abi");
470200583Srdivacky    CmdArgs.push_back("soft");
471198092Srdivacky  } else if (FloatABI == "softfp") {
472198092Srdivacky    // Floating point operations are hard, but argument passing is soft.
473200583Srdivacky    CmdArgs.push_back("-mfloat-abi");
474200583Srdivacky    CmdArgs.push_back("soft");
475198092Srdivacky  } else {
476198092Srdivacky    // Floating point operations and argument passing are hard.
477198092Srdivacky    assert(FloatABI == "hard" && "Invalid float abi!");
478200583Srdivacky    CmdArgs.push_back("-mfloat-abi");
479200583Srdivacky    CmdArgs.push_back("hard");
480198092Srdivacky  }
481201361Srdivacky
482201361Srdivacky  // Set appropriate target features for floating point mode.
483201361Srdivacky  //
484201361Srdivacky  // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
485201361Srdivacky  // yet (it uses the -mfloat-abi and -msoft-float options above), and it is
486201361Srdivacky  // stripped out by the ARM target.
487201361Srdivacky
488201361Srdivacky  // Use software floating point operations?
489201361Srdivacky  if (FloatABI == "soft") {
490201361Srdivacky    CmdArgs.push_back("-target-feature");
491201361Srdivacky    CmdArgs.push_back("+soft-float");
492201361Srdivacky  }
493201361Srdivacky
494201361Srdivacky  // Use software floating point argument passing?
495201361Srdivacky  if (FloatABI != "hard") {
496201361Srdivacky    CmdArgs.push_back("-target-feature");
497201361Srdivacky    CmdArgs.push_back("+soft-float-abi");
498201361Srdivacky  }
499201361Srdivacky
500201361Srdivacky  // Honor -mfpu=.
501201361Srdivacky  //
502201361Srdivacky  // FIXME: Centralize feature selection, defaulting shouldn't be also in the
503201361Srdivacky  // frontend target.
504201361Srdivacky  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
505201361Srdivacky    llvm::StringRef FPU = A->getValue(Args);
506201361Srdivacky
507201361Srdivacky    // Set the target features based on the FPU.
508201361Srdivacky    if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
509201361Srdivacky      // Disable any default FPU support.
510201361Srdivacky      CmdArgs.push_back("-target-feature");
511201361Srdivacky      CmdArgs.push_back("-vfp2");
512201361Srdivacky      CmdArgs.push_back("-target-feature");
513201361Srdivacky      CmdArgs.push_back("-vfp3");
514201361Srdivacky      CmdArgs.push_back("-target-feature");
515201361Srdivacky      CmdArgs.push_back("-neon");
516201361Srdivacky    } else if (FPU == "vfp") {
517201361Srdivacky      CmdArgs.push_back("-target-feature");
518201361Srdivacky      CmdArgs.push_back("+vfp2");
519201361Srdivacky    } else if (FPU == "vfp3") {
520201361Srdivacky      CmdArgs.push_back("-target-feature");
521201361Srdivacky      CmdArgs.push_back("+vfp3");
522201361Srdivacky    } else if (FPU == "neon") {
523201361Srdivacky      CmdArgs.push_back("-target-feature");
524201361Srdivacky      CmdArgs.push_back("+neon");
525201361Srdivacky    } else
526201361Srdivacky      D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
527201361Srdivacky  }
528198092Srdivacky}
529198092Srdivacky
530204643Srdivackyvoid Clang::AddMIPSTargetArgs(const ArgList &Args,
531204643Srdivacky                             ArgStringList &CmdArgs) const {
532204643Srdivacky  const Driver &D = getToolChain().getDriver();
533204643Srdivacky
534204643Srdivacky  // Select the ABI to use.
535204643Srdivacky  const char *ABIName = 0;
536204643Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
537204643Srdivacky    ABIName = A->getValue(Args);
538204643Srdivacky  } else {
539204643Srdivacky    ABIName = "o32";
540204643Srdivacky  }
541204643Srdivacky
542204643Srdivacky  CmdArgs.push_back("-target-abi");
543204643Srdivacky  CmdArgs.push_back(ABIName);
544204643Srdivacky
545204643Srdivacky  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
546204643Srdivacky    llvm::StringRef MArch = A->getValue(Args);
547204643Srdivacky    CmdArgs.push_back("-target-cpu");
548204643Srdivacky
549204643Srdivacky    if ((MArch == "r2000") || (MArch == "r3000"))
550204643Srdivacky      CmdArgs.push_back("mips1");
551204643Srdivacky    else if (MArch == "r6000")
552204643Srdivacky      CmdArgs.push_back("mips2");
553204643Srdivacky    else
554204643Srdivacky      CmdArgs.push_back(MArch.str().c_str());
555204643Srdivacky  }
556204643Srdivacky
557204643Srdivacky  // Select the float ABI as determined by -msoft-float, -mhard-float, and
558204643Srdivacky  llvm::StringRef FloatABI;
559204643Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
560204643Srdivacky                               options::OPT_mhard_float)) {
561204643Srdivacky    if (A->getOption().matches(options::OPT_msoft_float))
562204643Srdivacky      FloatABI = "soft";
563204643Srdivacky    else if (A->getOption().matches(options::OPT_mhard_float))
564204643Srdivacky      FloatABI = "hard";
565204643Srdivacky  }
566204643Srdivacky
567204643Srdivacky  // If unspecified, choose the default based on the platform.
568204643Srdivacky  if (FloatABI.empty()) {
569207619Srdivacky    // Assume "soft", but warn the user we are guessing.
570207619Srdivacky    FloatABI = "soft";
571207619Srdivacky    D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft";
572204643Srdivacky  }
573204643Srdivacky
574204643Srdivacky  if (FloatABI == "soft") {
575204643Srdivacky    // Floating point operations and argument passing are soft.
576204643Srdivacky    //
577204643Srdivacky    // FIXME: This changes CPP defines, we need -target-soft-float.
578204643Srdivacky    CmdArgs.push_back("-msoft-float");
579204643Srdivacky  } else {
580204643Srdivacky    assert(FloatABI == "hard" && "Invalid float abi!");
581204643Srdivacky    CmdArgs.push_back("-mhard-float");
582204643Srdivacky  }
583204643Srdivacky}
584204643Srdivacky
585198092Srdivackyvoid Clang::AddX86TargetArgs(const ArgList &Args,
586198092Srdivacky                             ArgStringList &CmdArgs) const {
587198092Srdivacky  if (!Args.hasFlag(options::OPT_mred_zone,
588198092Srdivacky                    options::OPT_mno_red_zone,
589198092Srdivacky                    true) ||
590198092Srdivacky      Args.hasArg(options::OPT_mkernel) ||
591198092Srdivacky      Args.hasArg(options::OPT_fapple_kext))
592199990Srdivacky    CmdArgs.push_back("-disable-red-zone");
593198092Srdivacky
594198092Srdivacky  if (Args.hasFlag(options::OPT_msoft_float,
595198092Srdivacky                   options::OPT_mno_soft_float,
596198092Srdivacky                   false))
597199990Srdivacky    CmdArgs.push_back("-no-implicit-float");
598198092Srdivacky
599199482Srdivacky  const char *CPUName = 0;
600198092Srdivacky  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
601199482Srdivacky    if (llvm::StringRef(A->getValue(Args)) == "native") {
602199482Srdivacky      // FIXME: Reject attempts to use -march=native unless the target matches
603199482Srdivacky      // the host.
604199482Srdivacky      //
605199482Srdivacky      // FIXME: We should also incorporate the detected target features for use
606199482Srdivacky      // with -native.
607199482Srdivacky      std::string CPU = llvm::sys::getHostCPUName();
608199482Srdivacky      if (!CPU.empty())
609199482Srdivacky        CPUName = Args.MakeArgString(CPU);
610199482Srdivacky    } else
611199482Srdivacky      CPUName = A->getValue(Args);
612199482Srdivacky  }
613198092Srdivacky
614199482Srdivacky  // Select the default CPU if none was given (or detection failed).
615199482Srdivacky  if (!CPUName) {
616198092Srdivacky    // FIXME: Need target hooks.
617203955Srdivacky    if (getToolChain().getOS().startswith("darwin")) {
618198092Srdivacky      if (getToolChain().getArchName() == "x86_64")
619199482Srdivacky        CPUName = "core2";
620198092Srdivacky      else if (getToolChain().getArchName() == "i386")
621199482Srdivacky        CPUName = "yonah";
622207619Srdivacky    } else if (getToolChain().getOS().startswith("haiku"))  {
623207619Srdivacky      if (getToolChain().getArchName() == "x86_64")
624207619Srdivacky        CPUName = "x86-64";
625207619Srdivacky      else if (getToolChain().getArchName() == "i386")
626207619Srdivacky        CPUName = "i586";
627198092Srdivacky    } else {
628198092Srdivacky      if (getToolChain().getArchName() == "x86_64")
629199482Srdivacky        CPUName = "x86-64";
630198092Srdivacky      else if (getToolChain().getArchName() == "i386")
631199482Srdivacky        CPUName = "pentium4";
632198092Srdivacky    }
633198092Srdivacky  }
634198092Srdivacky
635199482Srdivacky  if (CPUName) {
636201361Srdivacky    CmdArgs.push_back("-target-cpu");
637199482Srdivacky    CmdArgs.push_back(CPUName);
638199482Srdivacky  }
639199482Srdivacky
640199990Srdivacky  for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
641199990Srdivacky         ie = Args.filtered_end(); it != ie; ++it) {
642199990Srdivacky    llvm::StringRef Name = it->getOption().getName();
643199990Srdivacky    it->claim();
644198092Srdivacky
645199990Srdivacky    // Skip over "-m".
646199990Srdivacky    assert(Name.startswith("-m") && "Invalid feature name.");
647199990Srdivacky    Name = Name.substr(2);
648198092Srdivacky
649199990Srdivacky    bool IsNegative = Name.startswith("no-");
650199990Srdivacky    if (IsNegative)
651199990Srdivacky      Name = Name.substr(3);
652198092Srdivacky
653199990Srdivacky    CmdArgs.push_back("-target-feature");
654199990Srdivacky    CmdArgs.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
655198092Srdivacky  }
656198092Srdivacky}
657198092Srdivacky
658198092Srdivackystatic bool needsExceptions(const ArgList &Args,  types::ID InputType,
659198092Srdivacky                            const llvm::Triple &Triple) {
660198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
661198092Srdivacky                               options::OPT_fno_exceptions)) {
662198092Srdivacky    if (A->getOption().matches(options::OPT_fexceptions))
663198092Srdivacky      return true;
664198092Srdivacky    else
665198092Srdivacky      return false;
666198092Srdivacky  }
667198092Srdivacky  switch (InputType) {
668198092Srdivacky  case types::TY_CXX: case types::TY_CXXHeader:
669198092Srdivacky  case types::TY_PP_CXX: case types::TY_PP_CXXHeader:
670198092Srdivacky  case types::TY_ObjCXX: case types::TY_ObjCXXHeader:
671198092Srdivacky  case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader:
672198092Srdivacky    return true;
673198092Srdivacky
674198092Srdivacky  case types::TY_ObjC: case types::TY_ObjCHeader:
675198092Srdivacky  case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader:
676198092Srdivacky    if (Args.hasArg(options::OPT_fobjc_nonfragile_abi))
677198092Srdivacky      return true;
678198092Srdivacky    if (Triple.getOS() != llvm::Triple::Darwin)
679198092Srdivacky      return false;
680198092Srdivacky    return (Triple.getDarwinMajorNumber() >= 9 &&
681198092Srdivacky            Triple.getArch() == llvm::Triple::x86_64);
682198092Srdivacky
683198092Srdivacky  default:
684198092Srdivacky    return false;
685198092Srdivacky  }
686198092Srdivacky}
687198092Srdivacky
688198893Srdivacky/// getEffectiveClangTriple - Get the "effective" target triple, which is the
689198893Srdivacky/// triple for the target but with the OS version potentially modified for
690198893Srdivacky/// Darwin's -mmacosx-version-min.
691198893Srdivackystatic std::string getEffectiveClangTriple(const Driver &D,
692198893Srdivacky                                           const ToolChain &TC,
693198893Srdivacky                                           const ArgList &Args) {
694198893Srdivacky  llvm::Triple Triple(getLLVMTriple(TC, Args));
695198893Srdivacky
696203955Srdivacky  // Handle -mmacosx-version-min and -miphoneos-version-min.
697198893Srdivacky  if (Triple.getOS() != llvm::Triple::Darwin) {
698198893Srdivacky    // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
699198893Srdivacky    // non-Darwin.
700198893Srdivacky    if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
701198893Srdivacky                                 options::OPT_miphoneos_version_min_EQ))
702198893Srdivacky      D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
703203955Srdivacky  } else {
704203955Srdivacky    const toolchains::Darwin &DarwinTC(
705203955Srdivacky      reinterpret_cast<const toolchains::Darwin&>(TC));
706205408Srdivacky
707205408Srdivacky    // If the target isn't initialized (e.g., an unknown Darwin platform, return
708205408Srdivacky    // the default triple).
709205408Srdivacky    if (!DarwinTC.isTargetInitialized())
710205408Srdivacky      return Triple.getTriple();
711205408Srdivacky
712203955Srdivacky    unsigned Version[3];
713203955Srdivacky    DarwinTC.getTargetVersion(Version);
714198893Srdivacky
715203955Srdivacky    // Mangle the target version into the OS triple component.  For historical
716203955Srdivacky    // reasons that make little sense, the version passed here is the "darwin"
717203955Srdivacky    // version, which drops the 10 and offsets by 4. See inverse code when
718203955Srdivacky    // setting the OS version preprocessor define.
719203955Srdivacky    if (!DarwinTC.isTargetIPhoneOS()) {
720203955Srdivacky      Version[0] = Version[1] + 4;
721203955Srdivacky      Version[1] = Version[2];
722203955Srdivacky      Version[2] = 0;
723203955Srdivacky    } else {
724203955Srdivacky      // Use the environment to communicate that we are targetting iPhoneOS.
725203955Srdivacky      Triple.setEnvironmentName("iphoneos");
726203955Srdivacky    }
727198893Srdivacky
728198893Srdivacky    llvm::SmallString<16> Str;
729203955Srdivacky    llvm::raw_svector_ostream(Str) << "darwin" << Version[0]
730203955Srdivacky                                   << "." << Version[1] << "." << Version[2];
731198893Srdivacky    Triple.setOSName(Str.str());
732198893Srdivacky  }
733198893Srdivacky
734198893Srdivacky  return Triple.getTriple();
735198893Srdivacky}
736198893Srdivacky
737193326Sedvoid Clang::ConstructJob(Compilation &C, const JobAction &JA,
738193326Sed                         Job &Dest,
739193326Sed                         const InputInfo &Output,
740193326Sed                         const InputInfoList &Inputs,
741193326Sed                         const ArgList &Args,
742193326Sed                         const char *LinkingOutput) const {
743205408Srdivacky  bool KernelOrKext = Args.hasArg(options::OPT_mkernel,
744205408Srdivacky                                  options::OPT_fapple_kext);
745201361Srdivacky  const Driver &D = getToolChain().getDriver();
746193326Sed  ArgStringList CmdArgs;
747193326Sed
748193326Sed  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
749193326Sed
750200583Srdivacky  // Invoke ourselves in -cc1 mode.
751200583Srdivacky  //
752200583Srdivacky  // FIXME: Implement custom jobs for internal actions.
753200583Srdivacky  CmdArgs.push_back("-cc1");
754200583Srdivacky
755198893Srdivacky  // Add the "effective" target triple.
756193326Sed  CmdArgs.push_back("-triple");
757198893Srdivacky  std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
758198893Srdivacky  CmdArgs.push_back(Args.MakeArgString(TripleStr));
759198092Srdivacky
760198893Srdivacky  // Select the appropriate action.
761193326Sed  if (isa<AnalyzeJobAction>(JA)) {
762193326Sed    assert(JA.getType() == types::TY_Plist && "Invalid output type.");
763193326Sed    CmdArgs.push_back("-analyze");
764193326Sed  } else if (isa<PreprocessJobAction>(JA)) {
765193326Sed    if (Output.getType() == types::TY_Dependencies)
766193326Sed      CmdArgs.push_back("-Eonly");
767193326Sed    else
768193326Sed      CmdArgs.push_back("-E");
769203955Srdivacky  } else if (isa<AssembleJobAction>(JA)) {
770203955Srdivacky    CmdArgs.push_back("-emit-obj");
771208600Srdivacky
772208600Srdivacky    // At -O0, we use -mrelax-all by default.
773208600Srdivacky    bool IsOpt = false;
774208600Srdivacky    if (Arg *A = Args.getLastArg(options::OPT_O_Group))
775208600Srdivacky      IsOpt = !A->getOption().matches(options::OPT_O0);
776208600Srdivacky    if (Args.hasFlag(options::OPT_mrelax_all,
777208600Srdivacky                      options::OPT_mno_relax_all,
778208600Srdivacky                      !IsOpt))
779208600Srdivacky      CmdArgs.push_back("-mrelax-all");
780193326Sed  } else if (isa<PrecompileJobAction>(JA)) {
781198398Srdivacky    // Use PCH if the user requested it, except for C++ (for now).
782198398Srdivacky    bool UsePCH = D.CCCUsePCH;
783198398Srdivacky    if (types::isCXX(Inputs[0].getType()))
784198398Srdivacky      UsePCH = false;
785198398Srdivacky
786198398Srdivacky    if (UsePCH)
787193326Sed      CmdArgs.push_back("-emit-pch");
788193326Sed    else
789193326Sed      CmdArgs.push_back("-emit-pth");
790193326Sed  } else {
791193326Sed    assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
792193326Sed
793193326Sed    if (JA.getType() == types::TY_Nothing) {
794193326Sed      CmdArgs.push_back("-fsyntax-only");
795193326Sed    } else if (JA.getType() == types::TY_LLVMAsm) {
796193326Sed      CmdArgs.push_back("-emit-llvm");
797193326Sed    } else if (JA.getType() == types::TY_LLVMBC) {
798193326Sed      CmdArgs.push_back("-emit-llvm-bc");
799193326Sed    } else if (JA.getType() == types::TY_PP_Asm) {
800193326Sed      CmdArgs.push_back("-S");
801198092Srdivacky    } else if (JA.getType() == types::TY_AST) {
802198092Srdivacky      CmdArgs.push_back("-emit-pch");
803203955Srdivacky    } else if (JA.getType() == types::TY_RewrittenObjC) {
804203955Srdivacky      CmdArgs.push_back("-rewrite-objc");
805203955Srdivacky    } else {
806203955Srdivacky      assert(JA.getType() == types::TY_PP_Asm &&
807203955Srdivacky             "Unexpected output type!");
808193326Sed    }
809193326Sed  }
810193326Sed
811193326Sed  // The make clang go fast button.
812193326Sed  CmdArgs.push_back("-disable-free");
813193326Sed
814203955Srdivacky  // Disable the verification pass in -asserts builds.
815203955Srdivacky#ifdef NDEBUG
816203955Srdivacky  CmdArgs.push_back("-disable-llvm-verifier");
817203955Srdivacky#endif
818203955Srdivacky
819193326Sed  // Set the main file name, so that debug info works even with
820193326Sed  // -save-temps.
821193326Sed  CmdArgs.push_back("-main-file-name");
822193326Sed  CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs));
823193326Sed
824193326Sed  // Some flags which affect the language (via preprocessor
825193326Sed  // defines). See darwin::CC1::AddCPPArgs.
826193326Sed  if (Args.hasArg(options::OPT_static))
827193326Sed    CmdArgs.push_back("-static-define");
828193326Sed
829193326Sed  if (isa<AnalyzeJobAction>(JA)) {
830198092Srdivacky    // Enable region store model by default.
831198092Srdivacky    CmdArgs.push_back("-analyzer-store=region");
832198092Srdivacky
833200583Srdivacky    // Treat blocks as analysis entry points.
834200583Srdivacky    CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
835200583Srdivacky
836193326Sed    // Add default argument set.
837193326Sed    if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
838203955Srdivacky      CmdArgs.push_back("-analyzer-check-dead-stores");
839207619Srdivacky      // Do not enable the security-syntatic check since it
840207619Srdivacky      // it needs to be refined (known issues).
841207619Srdivacky      // CmdArgs.push_back("-analyzer-check-security-syntactic");
842203955Srdivacky      CmdArgs.push_back("-analyzer-check-objc-mem");
843193326Sed      CmdArgs.push_back("-analyzer-eagerly-assume");
844203955Srdivacky      CmdArgs.push_back("-analyzer-check-objc-methodsigs");
845193326Sed      // Do not enable the missing -dealloc check.
846203955Srdivacky      // '-analyzer-check-objc-missing-dealloc',
847203955Srdivacky      CmdArgs.push_back("-analyzer-check-objc-unused-ivars");
848193326Sed    }
849193326Sed
850193326Sed    // Set the output format. The default is plist, for (lame) historical
851193326Sed    // reasons.
852193326Sed    CmdArgs.push_back("-analyzer-output");
853193326Sed    if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
854193326Sed      CmdArgs.push_back(A->getValue(Args));
855193326Sed    else
856193326Sed      CmdArgs.push_back("plist");
857193326Sed
858206084Srdivacky    // Disable the presentation of standard compiler warnings when
859206084Srdivacky    // using --analyze.  We only want to show static analyzer diagnostics
860206084Srdivacky    // or frontend errors.
861206084Srdivacky    CmdArgs.push_back("-w");
862206084Srdivacky
863193326Sed    // Add -Xanalyzer arguments when running as analyzer.
864193326Sed    Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
865198092Srdivacky  }
866198092Srdivacky
867198092Srdivacky  CheckCodeGenerationOptions(D, Args);
868198092Srdivacky
869193326Sed  // Perform argument translation for LLVM backend. This
870193326Sed  // takes some care in reconciling with llvm-gcc. The
871193326Sed  // issue is that llvm-gcc translates these options based on
872193326Sed  // the values in cc1, whereas we are processing based on
873193326Sed  // the driver arguments.
874193326Sed
875193326Sed  // This comes from the default translation the driver + cc1
876193326Sed  // would do to enable flag_pic.
877193326Sed  //
878193326Sed  // FIXME: Centralize this code.
879193326Sed  bool PICEnabled = (Args.hasArg(options::OPT_fPIC) ||
880193326Sed                     Args.hasArg(options::OPT_fpic) ||
881193326Sed                     Args.hasArg(options::OPT_fPIE) ||
882193326Sed                     Args.hasArg(options::OPT_fpie));
883193326Sed  bool PICDisabled = (Args.hasArg(options::OPT_mkernel) ||
884193326Sed                      Args.hasArg(options::OPT_static));
885193326Sed  const char *Model = getToolChain().GetForcedPicModel();
886193326Sed  if (!Model) {
887193326Sed    if (Args.hasArg(options::OPT_mdynamic_no_pic))
888193326Sed      Model = "dynamic-no-pic";
889193326Sed    else if (PICDisabled)
890193326Sed      Model = "static";
891193326Sed    else if (PICEnabled)
892193326Sed      Model = "pic";
893193326Sed    else
894193326Sed      Model = getToolChain().GetDefaultRelocationModel();
895193326Sed  }
896199990Srdivacky  if (llvm::StringRef(Model) != "pic") {
897199990Srdivacky    CmdArgs.push_back("-mrelocation-model");
898199990Srdivacky    CmdArgs.push_back(Model);
899199990Srdivacky  }
900193326Sed
901193326Sed  // Infer the __PIC__ value.
902193326Sed  //
903193326Sed  // FIXME:  This isn't quite right on Darwin, which always sets
904193326Sed  // __PIC__=2.
905193326Sed  if (strcmp(Model, "pic") == 0 || strcmp(Model, "dynamic-no-pic") == 0) {
906199990Srdivacky    CmdArgs.push_back("-pic-level");
907199990Srdivacky    CmdArgs.push_back(Args.hasArg(options::OPT_fPIC) ? "2" : "1");
908193326Sed  }
909199990Srdivacky  if (!Args.hasFlag(options::OPT_fmerge_all_constants,
910199990Srdivacky                    options::OPT_fno_merge_all_constants))
911199990Srdivacky    CmdArgs.push_back("-no-merge-all-constants");
912193326Sed
913199990Srdivacky  // LLVM Code Generator Options.
914199990Srdivacky
915193326Sed  // FIXME: Set --enable-unsafe-fp-math.
916198092Srdivacky  if (Args.hasFlag(options::OPT_fno_omit_frame_pointer,
917198092Srdivacky                   options::OPT_fomit_frame_pointer))
918199990Srdivacky    CmdArgs.push_back("-mdisable-fp-elim");
919193326Sed  if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
920199990Srdivacky                    options::OPT_fno_zero_initialized_in_bss))
921199990Srdivacky    CmdArgs.push_back("-mno-zero-initialized-in-bss");
922208600Srdivacky
923208600Srdivacky  // Decide whether to use verbose asm. Verbose assembly is the default on
924208600Srdivacky  // toolchains which have the integrated assembler on by default.
925208600Srdivacky  bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault();
926208600Srdivacky  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
927208600Srdivacky                   IsVerboseAsmDefault) ||
928208600Srdivacky      Args.hasArg(options::OPT_dA))
929199990Srdivacky    CmdArgs.push_back("-masm-verbose");
930208600Srdivacky
931199990Srdivacky  if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
932199990Srdivacky    CmdArgs.push_back("-mdebug-pass");
933199990Srdivacky    CmdArgs.push_back("Structure");
934199990Srdivacky  }
935199990Srdivacky  if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
936199990Srdivacky    CmdArgs.push_back("-mdebug-pass");
937199990Srdivacky    CmdArgs.push_back("Arguments");
938199990Srdivacky  }
939198092Srdivacky
940204643Srdivacky  // Enable -mconstructor-aliases except on darwin, where we have to
941204643Srdivacky  // work around a linker bug;  see <rdar://problem/7651567>.
942204643Srdivacky  if (getToolChain().getTriple().getOS() != llvm::Triple::Darwin)
943204643Srdivacky    CmdArgs.push_back("-mconstructor-aliases");
944204643Srdivacky
945198092Srdivacky  // This is a coarse approximation of what llvm-gcc actually does, both
946198092Srdivacky  // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
947198092Srdivacky  // complicated ways.
948198092Srdivacky  bool AsynchronousUnwindTables =
949198092Srdivacky    Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
950198092Srdivacky                 options::OPT_fno_asynchronous_unwind_tables,
951198092Srdivacky                 getToolChain().IsUnwindTablesDefault() &&
952205408Srdivacky                 !KernelOrKext);
953198092Srdivacky  if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
954198092Srdivacky                   AsynchronousUnwindTables))
955199990Srdivacky    CmdArgs.push_back("-munwind-tables");
956193326Sed
957199990Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
958199990Srdivacky    CmdArgs.push_back("-mlimit-float-precision");
959199990Srdivacky    CmdArgs.push_back(A->getValue(Args));
960199990Srdivacky  }
961199990Srdivacky
962193326Sed  // FIXME: Handle -mtune=.
963193326Sed  (void) Args.hasArg(options::OPT_mtune_EQ);
964193326Sed
965198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
966199990Srdivacky    CmdArgs.push_back("-mcode-model");
967193326Sed    CmdArgs.push_back(A->getValue(Args));
968193326Sed  }
969193326Sed
970198092Srdivacky  // Add target specific cpu and features flags.
971198092Srdivacky  switch(getToolChain().getTriple().getArch()) {
972198092Srdivacky  default:
973198092Srdivacky    break;
974193326Sed
975198092Srdivacky  case llvm::Triple::arm:
976198092Srdivacky  case llvm::Triple::thumb:
977198092Srdivacky    AddARMTargetArgs(Args, CmdArgs);
978198092Srdivacky    break;
979193326Sed
980204643Srdivacky  case llvm::Triple::mips:
981204643Srdivacky  case llvm::Triple::mipsel:
982204643Srdivacky    AddMIPSTargetArgs(Args, CmdArgs);
983204643Srdivacky    break;
984204643Srdivacky
985198092Srdivacky  case llvm::Triple::x86:
986198092Srdivacky  case llvm::Triple::x86_64:
987198092Srdivacky    AddX86TargetArgs(Args, CmdArgs);
988198092Srdivacky    break;
989193326Sed  }
990193326Sed
991202379Srdivacky  // -fno-math-errno is default.
992202379Srdivacky  if (Args.hasFlag(options::OPT_fmath_errno,
993193326Sed                   options::OPT_fno_math_errno,
994202379Srdivacky                   false))
995202379Srdivacky    CmdArgs.push_back("-fmath-errno");
996193326Sed
997208600Srdivacky  // Explicitly error on some things we know we don't support and can't just
998208600Srdivacky  // ignore.
999208600Srdivacky  types::ID InputType = Inputs[0].getType();
1000193326Sed  Arg *Unsupported;
1001193326Sed  if ((Unsupported = Args.getLastArg(options::OPT_MG)) ||
1002200583Srdivacky      (Unsupported = Args.getLastArg(options::OPT_iframework)) ||
1003200583Srdivacky      (Unsupported = Args.getLastArg(options::OPT_fshort_enums)))
1004193326Sed    D.Diag(clang::diag::err_drv_clang_unsupported)
1005193326Sed      << Unsupported->getOption().getName();
1006193326Sed
1007208600Srdivacky  if (types::isCXX(InputType) &&
1008208600Srdivacky      getToolChain().getTriple().getOS() == llvm::Triple::Darwin &&
1009208600Srdivacky      getToolChain().getTriple().getArch() == llvm::Triple::x86) {
1010208600Srdivacky    if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)))
1011208600Srdivacky      D.Diag(clang::diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
1012208600Srdivacky        << Unsupported->getOption().getName();
1013208600Srdivacky  }
1014208600Srdivacky
1015193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_v);
1016193326Sed  Args.AddLastArg(CmdArgs, options::OPT_P);
1017198092Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
1018193326Sed
1019193326Sed  // Special case debug options to only pass -g to clang. This is
1020193326Sed  // wrong.
1021204962Srdivacky  Args.ClaimAllArgs(options::OPT_g_Group);
1022208600Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_g_Group))
1023208600Srdivacky    if (!A->getOption().matches(options::OPT_g0))
1024208600Srdivacky      CmdArgs.push_back("-g");
1025193326Sed
1026208600Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
1027208600Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
1028208600Srdivacky
1029193326Sed  Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
1030206084Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
1031198893Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
1032193326Sed
1033200583Srdivacky  // Pass the path to compiler resource files.
1034200583Srdivacky  CmdArgs.push_back("-resource-dir");
1035202879Srdivacky  CmdArgs.push_back(D.ResourceDir.c_str());
1036193326Sed
1037193326Sed  // Add preprocessing options like -I, -D, etc. if we are using the
1038193326Sed  // preprocessor.
1039193326Sed  //
1040193326Sed  // FIXME: Support -fpreprocessed
1041193326Sed  if (types::getPreprocessedType(InputType) != types::TY_INVALID)
1042193326Sed    AddPreprocessingOptions(D, Args, CmdArgs, Output, Inputs);
1043193326Sed
1044198092Srdivacky  // Manually translate -O to -O2 and -O4 to -O3; let clang reject
1045193326Sed  // others.
1046193326Sed  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
1047199512Srdivacky    if (A->getOption().matches(options::OPT_O4))
1048193326Sed      CmdArgs.push_back("-O3");
1049208600Srdivacky    else if (A->getOption().matches(options::OPT_O) &&
1050208600Srdivacky             A->getValue(Args)[0] == '\0')
1051198092Srdivacky      CmdArgs.push_back("-O2");
1052193326Sed    else
1053193326Sed      A->render(Args, CmdArgs);
1054193326Sed  }
1055193326Sed
1056198893Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
1057198893Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_pedantic);
1058198893Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
1059193326Sed  Args.AddLastArg(CmdArgs, options::OPT_w);
1060193326Sed
1061193326Sed  // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
1062193326Sed  // (-ansi is equivalent to -std=c89).
1063193326Sed  //
1064193326Sed  // If a std is supplied, only add -trigraphs if it follows the
1065193326Sed  // option.
1066193326Sed  if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
1067193326Sed    if (Std->getOption().matches(options::OPT_ansi))
1068198398Srdivacky      if (types::isCXX(InputType))
1069198893Srdivacky        CmdArgs.push_back("-std=c++98");
1070198398Srdivacky      else
1071198893Srdivacky        CmdArgs.push_back("-std=c89");
1072193326Sed    else
1073193326Sed      Std->render(Args, CmdArgs);
1074193326Sed
1075193326Sed    if (Arg *A = Args.getLastArg(options::OPT_trigraphs))
1076193326Sed      if (A->getIndex() > Std->getIndex())
1077193326Sed        A->render(Args, CmdArgs);
1078193326Sed  } else {
1079193326Sed    // Honor -std-default.
1080203955Srdivacky    //
1081203955Srdivacky    // FIXME: Clang doesn't correctly handle -std= when the input language
1082203955Srdivacky    // doesn't match. For the time being just ignore this for C++ inputs;
1083203955Srdivacky    // eventually we want to do all the standard defaulting here instead of
1084203955Srdivacky    // splitting it between the driver and clang -cc1.
1085203955Srdivacky    if (!types::isCXX(InputType))
1086203955Srdivacky        Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
1087203955Srdivacky                                  "-std=", /*Joined=*/true);
1088193326Sed    Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
1089193326Sed  }
1090193326Sed
1091208600Srdivacky  // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'.
1092208600Srdivacky  if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) {
1093208600Srdivacky    if (Asm->getOption().matches(options::OPT_fasm))
1094208600Srdivacky      CmdArgs.push_back("-fgnu-keywords");
1095208600Srdivacky    else
1096208600Srdivacky      CmdArgs.push_back("-fno-gnu-keywords");
1097208600Srdivacky  }
1098208600Srdivacky
1099193326Sed  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) {
1100193326Sed    CmdArgs.push_back("-ftemplate-depth");
1101193326Sed    CmdArgs.push_back(A->getValue(Args));
1102193326Sed  }
1103193326Sed
1104199512Srdivacky  if (Args.hasArg(options::OPT__relocatable_pch))
1105199990Srdivacky    CmdArgs.push_back("-relocatable-pch");
1106198092Srdivacky
1107198893Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
1108198893Srdivacky    CmdArgs.push_back("-fconstant-string-class");
1109198893Srdivacky    CmdArgs.push_back(A->getValue(Args));
1110198893Srdivacky  }
1111198092Srdivacky
1112202379Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
1113202379Srdivacky    CmdArgs.push_back("-ftabstop");
1114202379Srdivacky    CmdArgs.push_back(A->getValue(Args));
1115202379Srdivacky  }
1116202379Srdivacky
1117207619Srdivacky  CmdArgs.push_back("-ferror-limit");
1118207619Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
1119207619Srdivacky    CmdArgs.push_back(A->getValue(Args));
1120207619Srdivacky  else
1121207619Srdivacky    CmdArgs.push_back("19");
1122207619Srdivacky
1123208600Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
1124208600Srdivacky    CmdArgs.push_back("-fmacro-backtrace-limit");
1125207632Srdivacky    CmdArgs.push_back(A->getValue(Args));
1126208600Srdivacky  }
1127208600Srdivacky
1128208600Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
1129208600Srdivacky    CmdArgs.push_back("-ftemplate-backtrace-limit");
1130207619Srdivacky    CmdArgs.push_back(A->getValue(Args));
1131208600Srdivacky  }
1132208600Srdivacky
1133198893Srdivacky  // Pass -fmessage-length=.
1134199990Srdivacky  CmdArgs.push_back("-fmessage-length");
1135198893Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
1136199990Srdivacky    CmdArgs.push_back(A->getValue(Args));
1137198893Srdivacky  } else {
1138198893Srdivacky    // If -fmessage-length=N was not specified, determine whether this is a
1139198893Srdivacky    // terminal and, if so, implicitly define -fmessage-length appropriately.
1140198893Srdivacky    unsigned N = llvm::sys::Process::StandardErrColumns();
1141198893Srdivacky    CmdArgs.push_back(Args.MakeArgString(llvm::Twine(N)));
1142198893Srdivacky  }
1143198893Srdivacky
1144200583Srdivacky  if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) {
1145200583Srdivacky    CmdArgs.push_back("-fvisibility");
1146200583Srdivacky    CmdArgs.push_back(A->getValue(Args));
1147200583Srdivacky  }
1148200583Srdivacky
1149205408Srdivacky  // -fhosted is default.
1150205408Srdivacky  if (KernelOrKext || Args.hasFlag(options::OPT_ffreestanding,
1151205408Srdivacky                                   options::OPT_fhosted,
1152205408Srdivacky                                   false))
1153205408Srdivacky    CmdArgs.push_back("-ffreestanding");
1154205408Srdivacky
1155200583Srdivacky  // Forward -f (flag) options which we can pass directly.
1156200583Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_fcatch_undefined_behavior);
1157193326Sed  Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
1158193326Sed  Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
1159205408Srdivacky
1160205408Srdivacky  // -flax-vector-conversions is default.
1161205408Srdivacky  if (!Args.hasFlag(options::OPT_flax_vector_conversions,
1162205408Srdivacky                    options::OPT_fno_lax_vector_conversions))
1163205408Srdivacky    CmdArgs.push_back("-fno-lax-vector-conversions");
1164205408Srdivacky
1165207619Srdivacky  // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
1166207619Srdivacky  // takes precedence.
1167207619Srdivacky  const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only);
1168207619Srdivacky  if (!GCArg)
1169207619Srdivacky    GCArg = Args.getLastArg(options::OPT_fobjc_gc);
1170207619Srdivacky  if (GCArg) {
1171207619Srdivacky    if (getToolChain().SupportsObjCGC()) {
1172207619Srdivacky      GCArg->render(Args, CmdArgs);
1173207619Srdivacky    } else {
1174207619Srdivacky      // FIXME: We should move this to a hard error.
1175207619Srdivacky      D.Diag(clang::diag::warn_drv_objc_gc_unsupported)
1176207619Srdivacky        << GCArg->getAsString(Args);
1177207619Srdivacky    }
1178207619Srdivacky  }
1179207619Srdivacky
1180193326Sed  Args.AddLastArg(CmdArgs, options::OPT_fno_caret_diagnostics);
1181193326Sed  Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
1182193326Sed  Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
1183193326Sed  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
1184193326Sed  Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
1185193326Sed  Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
1186193326Sed  Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
1187193326Sed
1188198092Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_pthread);
1189198092Srdivacky
1190199482Srdivacky  // -stack-protector=0 is default.
1191199482Srdivacky  unsigned StackProtectorLevel = 0;
1192195341Sed  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
1193195341Sed                               options::OPT_fstack_protector_all,
1194195341Sed                               options::OPT_fstack_protector)) {
1195199482Srdivacky    if (A->getOption().matches(options::OPT_fstack_protector))
1196199482Srdivacky      StackProtectorLevel = 1;
1197199482Srdivacky    else if (A->getOption().matches(options::OPT_fstack_protector_all))
1198199482Srdivacky      StackProtectorLevel = 2;
1199199482Srdivacky  } else
1200199482Srdivacky    StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel();
1201199482Srdivacky  if (StackProtectorLevel) {
1202199482Srdivacky    CmdArgs.push_back("-stack-protector");
1203199482Srdivacky    CmdArgs.push_back(Args.MakeArgString(llvm::Twine(StackProtectorLevel)));
1204195341Sed  }
1205195341Sed
1206193326Sed  // Forward -f options with positive and negative forms; we translate
1207193326Sed  // these by hand.
1208193326Sed
1209199482Srdivacky  // -fbuiltin is default.
1210193326Sed  if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
1211199512Srdivacky    CmdArgs.push_back("-fno-builtin");
1212193326Sed
1213201361Srdivacky  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
1214201361Srdivacky                    options::OPT_fno_assume_sane_operator_new))
1215201361Srdivacky    CmdArgs.push_back("-fno-assume-sane-operator-new");
1216201361Srdivacky
1217199482Srdivacky  // -fblocks=0 is default.
1218199482Srdivacky  if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
1219199482Srdivacky                   getToolChain().IsBlocksDefault())) {
1220199482Srdivacky    CmdArgs.push_back("-fblocks");
1221193326Sed  }
1222193326Sed
1223207619Srdivacky  // -faccess-control is default.
1224207619Srdivacky  if (Args.hasFlag(options::OPT_fno_access_control,
1225207619Srdivacky                   options::OPT_faccess_control,
1226205408Srdivacky                   false))
1227207619Srdivacky    CmdArgs.push_back("-fno-access-control");
1228205408Srdivacky
1229199990Srdivacky  // -fexceptions=0 is default.
1230198092Srdivacky  if (needsExceptions(Args, InputType, getToolChain().getTriple()))
1231198092Srdivacky    CmdArgs.push_back("-fexceptions");
1232198092Srdivacky
1233203955Srdivacky  if (getToolChain().UseSjLjExceptions())
1234203955Srdivacky    CmdArgs.push_back("-fsjlj-exceptions");
1235203955Srdivacky
1236199482Srdivacky  // -frtti is default.
1237205408Srdivacky  if (KernelOrKext ||
1238205408Srdivacky      !Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti))
1239199512Srdivacky    CmdArgs.push_back("-fno-rtti");
1240198092Srdivacky
1241199482Srdivacky  // -fsigned-char is default.
1242199990Srdivacky  if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
1243199482Srdivacky                    isSignedCharDefault(getToolChain().getTriple())))
1244199990Srdivacky    CmdArgs.push_back("-fno-signed-char");
1245199482Srdivacky
1246203955Srdivacky  // -fthreadsafe-static is default.
1247203955Srdivacky  if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
1248203955Srdivacky                    options::OPT_fno_threadsafe_statics))
1249203955Srdivacky    CmdArgs.push_back("-fno-threadsafe-statics");
1250203955Srdivacky
1251205408Srdivacky  // -fuse-cxa-atexit is default.
1252205408Srdivacky  if (KernelOrKext || !Args.hasFlag(options::OPT_fuse_cxa_atexit,
1253205408Srdivacky                                    options::OPT_fno_use_cxa_atexit))
1254205408Srdivacky    CmdArgs.push_back("-fno-use-cxa-atexit");
1255205408Srdivacky
1256199482Srdivacky  // -fms-extensions=0 is default.
1257199990Srdivacky  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
1258199482Srdivacky                   getToolChain().getTriple().getOS() == llvm::Triple::Win32))
1259199482Srdivacky    CmdArgs.push_back("-fms-extensions");
1260199482Srdivacky
1261207619Srdivacky  // -fgnu-keywords default varies depending on language; only pass if
1262207619Srdivacky  // specified.
1263207619Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords,
1264207619Srdivacky                               options::OPT_fno_gnu_keywords))
1265207619Srdivacky    A->render(Args, CmdArgs);
1266207619Srdivacky
1267199482Srdivacky  // -fnext-runtime is default.
1268199990Srdivacky  if (!Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
1269199482Srdivacky                    getToolChain().getTriple().getOS() == llvm::Triple::Darwin))
1270199482Srdivacky    CmdArgs.push_back("-fgnu-runtime");
1271199482Srdivacky
1272199482Srdivacky  // -fobjc-nonfragile-abi=0 is default.
1273199482Srdivacky  if (types::isObjC(InputType)) {
1274207619Srdivacky    unsigned Version = 1;
1275199482Srdivacky    if (Args.hasArg(options::OPT_fobjc_nonfragile_abi) ||
1276207619Srdivacky        getToolChain().IsObjCNonFragileABIDefault())
1277207619Srdivacky      Version = 2;
1278207619Srdivacky    if (Arg *A = Args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
1279207619Srdivacky      if (llvm::StringRef(A->getValue(Args)) == "1")
1280207619Srdivacky        Version = 1;
1281207619Srdivacky      else if (llvm::StringRef(A->getValue(Args)) == "2")
1282207619Srdivacky        Version = 2;
1283207619Srdivacky      else
1284207619Srdivacky        D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
1285207619Srdivacky    }
1286207619Srdivacky
1287207619Srdivacky    if (Version == 2) {
1288199482Srdivacky      CmdArgs.push_back("-fobjc-nonfragile-abi");
1289207619Srdivacky
1290207619Srdivacky      // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
1291207619Srdivacky      // legacy is the default.
1292207619Srdivacky      if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
1293207619Srdivacky                        options::OPT_fno_objc_legacy_dispatch,
1294207619Srdivacky                        getToolChain().IsObjCLegacyDispatchDefault())) {
1295207619Srdivacky        if (getToolChain().UseObjCMixedDispatch())
1296207619Srdivacky          CmdArgs.push_back("-fobjc-dispatch-method=mixed");
1297207619Srdivacky        else
1298207619Srdivacky          CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
1299207619Srdivacky      }
1300203955Srdivacky    }
1301208600Srdivacky
1302208600Srdivacky    // FIXME: -fobjc-nonfragile-abi2 is a transient option meant to expose
1303208600Srdivacky    // features in testing.  It will eventually be removed.
1304208600Srdivacky    if (Args.hasArg(options::OPT_fobjc_nonfragile_abi2))
1305208600Srdivacky      CmdArgs.push_back("-fobjc-nonfragile-abi2");
1306199482Srdivacky  }
1307199482Srdivacky
1308203955Srdivacky  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
1309203955Srdivacky                    options::OPT_fno_assume_sane_operator_new))
1310203955Srdivacky    CmdArgs.push_back("-fno-assume-sane-operator-new");
1311203955Srdivacky
1312207619Srdivacky  // -fconstant-cfstrings is default, and may be subject to argument translation
1313207619Srdivacky  // on Darwin.
1314207619Srdivacky  if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
1315207619Srdivacky                    options::OPT_fno_constant_cfstrings) ||
1316207619Srdivacky      !Args.hasFlag(options::OPT_mconstant_cfstrings,
1317207619Srdivacky                    options::OPT_mno_constant_cfstrings))
1318207619Srdivacky    CmdArgs.push_back("-fno-constant-cfstrings");
1319207619Srdivacky
1320199482Srdivacky  // -fshort-wchar default varies depending on platform; only
1321193576Sed  // pass if specified.
1322207619Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar))
1323207619Srdivacky    A->render(Args, CmdArgs);
1324193576Sed
1325198893Srdivacky  // -fno-pascal-strings is default, only pass non-default. If the tool chain
1326198893Srdivacky  // happened to translate to -mpascal-strings, we want to back translate here.
1327193326Sed  //
1328193326Sed  // FIXME: This is gross; that translation should be pulled from the
1329193326Sed  // tool chain.
1330193326Sed  if (Args.hasFlag(options::OPT_fpascal_strings,
1331193326Sed                   options::OPT_fno_pascal_strings,
1332193326Sed                   false) ||
1333193326Sed      Args.hasFlag(options::OPT_mpascal_strings,
1334193326Sed                   options::OPT_mno_pascal_strings,
1335193326Sed                   false))
1336193326Sed    CmdArgs.push_back("-fpascal-strings");
1337193326Sed
1338193326Sed  // -fcommon is default, only pass non-default.
1339193326Sed  if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
1340193326Sed    CmdArgs.push_back("-fno-common");
1341193326Sed
1342193326Sed  // -fsigned-bitfields is default, and clang doesn't yet support
1343193326Sed  // --funsigned-bitfields.
1344198092Srdivacky  if (!Args.hasFlag(options::OPT_fsigned_bitfields,
1345193326Sed                    options::OPT_funsigned_bitfields))
1346193326Sed    D.Diag(clang::diag::warn_drv_clang_unsupported)
1347193326Sed      << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
1348193326Sed
1349193326Sed  // -fdiagnostics-fixit-info is default, only pass non-default.
1350198092Srdivacky  if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
1351193326Sed                    options::OPT_fno_diagnostics_fixit_info))
1352193326Sed    CmdArgs.push_back("-fno-diagnostics-fixit-info");
1353193326Sed
1354203955Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_binary);
1355203955Srdivacky
1356193326Sed  // Enable -fdiagnostics-show-option by default.
1357198092Srdivacky  if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
1358193326Sed                   options::OPT_fno_diagnostics_show_option))
1359193326Sed    CmdArgs.push_back("-fdiagnostics-show-option");
1360198893Srdivacky
1361208600Srdivacky  if (const Arg *A =
1362208600Srdivacky        Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
1363208600Srdivacky    CmdArgs.push_back("-fdiagnostics-show-category");
1364208600Srdivacky    CmdArgs.push_back(A->getValue(Args));
1365208600Srdivacky  }
1366208600Srdivacky
1367198893Srdivacky  // Color diagnostics are the default, unless the terminal doesn't support
1368198893Srdivacky  // them.
1369198893Srdivacky  if (Args.hasFlag(options::OPT_fcolor_diagnostics,
1370198893Srdivacky                   options::OPT_fno_color_diagnostics) &&
1371198893Srdivacky      llvm::sys::Process::StandardErrHasColors())
1372198893Srdivacky    CmdArgs.push_back("-fcolor-diagnostics");
1373198893Srdivacky
1374194179Sed  if (!Args.hasFlag(options::OPT_fshow_source_location,
1375194179Sed                    options::OPT_fno_show_source_location))
1376194179Sed    CmdArgs.push_back("-fno-show-source-location");
1377193326Sed
1378193326Sed  // -fdollars-in-identifiers default varies depending on platform and
1379193326Sed  // language; only pass if specified.
1380198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
1381193326Sed                               options::OPT_fno_dollars_in_identifiers)) {
1382193326Sed    if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
1383201361Srdivacky      CmdArgs.push_back("-fdollars-in-identifiers");
1384193326Sed    else
1385201361Srdivacky      CmdArgs.push_back("-fno-dollars-in-identifiers");
1386193326Sed  }
1387193326Sed
1388193326Sed  // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
1389193326Sed  // practical purposes.
1390198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
1391193326Sed                               options::OPT_fno_unit_at_a_time)) {
1392193326Sed    if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
1393198092Srdivacky      D.Diag(clang::diag::warn_drv_clang_unsupported) << A->getAsString(Args);
1394193326Sed  }
1395198092Srdivacky
1396198092Srdivacky  // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
1397198092Srdivacky  //
1398200583Srdivacky  // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
1399198092Srdivacky#if 0
1400198092Srdivacky  if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin &&
1401198092Srdivacky      (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
1402198092Srdivacky       getToolChain().getTriple().getArch() == llvm::Triple::thumb)) {
1403198092Srdivacky    if (!Args.hasArg(options::OPT_fbuiltin_strcat))
1404198092Srdivacky      CmdArgs.push_back("-fno-builtin-strcat");
1405198092Srdivacky    if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
1406198092Srdivacky      CmdArgs.push_back("-fno-builtin-strcpy");
1407198092Srdivacky  }
1408198092Srdivacky#endif
1409198092Srdivacky
1410198092Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_traditional,
1411198092Srdivacky                               options::OPT_traditional_cpp))
1412198092Srdivacky    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
1413198092Srdivacky
1414193326Sed  Args.AddLastArg(CmdArgs, options::OPT_dM);
1415193326Sed  Args.AddLastArg(CmdArgs, options::OPT_dD);
1416193326Sed
1417207619Srdivacky  // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
1418207619Srdivacky  // parser.
1419193326Sed  Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
1420207619Srdivacky  for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
1421207619Srdivacky         ie = Args.filtered_end(); it != ie; ++it) {
1422207619Srdivacky    it->claim();
1423193326Sed
1424207619Srdivacky    // We translate this by hand to the -cc1 argument, since nightly test uses
1425207619Srdivacky    // it and developers have been trained to spell it with -mllvm.
1426207619Srdivacky    if (llvm::StringRef(it->getValue(Args, 0)) == "-disable-llvm-optzns")
1427207619Srdivacky      CmdArgs.push_back("-disable-llvm-optzns");
1428207619Srdivacky    else
1429207619Srdivacky      it->render(Args, CmdArgs);
1430207619Srdivacky  }
1431207619Srdivacky
1432193326Sed  if (Output.getType() == types::TY_Dependencies) {
1433193326Sed    // Handled with other dependency code.
1434193326Sed  } else if (Output.isPipe()) {
1435193326Sed    CmdArgs.push_back("-o");
1436193326Sed    CmdArgs.push_back("-");
1437193326Sed  } else if (Output.isFilename()) {
1438193326Sed    CmdArgs.push_back("-o");
1439193326Sed    CmdArgs.push_back(Output.getFilename());
1440193326Sed  } else {
1441193326Sed    assert(Output.isNothing() && "Invalid output.");
1442193326Sed  }
1443193326Sed
1444193326Sed  for (InputInfoList::const_iterator
1445193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
1446193326Sed    const InputInfo &II = *it;
1447193326Sed    CmdArgs.push_back("-x");
1448193326Sed    CmdArgs.push_back(types::getTypeName(II.getType()));
1449193326Sed    if (II.isPipe())
1450193326Sed      CmdArgs.push_back("-");
1451193326Sed    else if (II.isFilename())
1452193326Sed      CmdArgs.push_back(II.getFilename());
1453193326Sed    else
1454193326Sed      II.getInputArg().renderAsInput(Args, CmdArgs);
1455193326Sed  }
1456193326Sed
1457198893Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_undef);
1458198893Srdivacky
1459193326Sed  const char *Exec =
1460200583Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "clang"));
1461201361Srdivacky
1462201361Srdivacky  // Optionally embed the -cc1 level arguments into the debug info, for build
1463201361Srdivacky  // analysis.
1464201361Srdivacky  if (getToolChain().UseDwarfDebugFlags()) {
1465201361Srdivacky    llvm::SmallString<256> Flags;
1466201361Srdivacky    Flags += Exec;
1467201361Srdivacky    for (unsigned i = 0, e = CmdArgs.size(); i != e; ++i) {
1468201361Srdivacky      Flags += " ";
1469201361Srdivacky      Flags += CmdArgs[i];
1470201361Srdivacky    }
1471201361Srdivacky    CmdArgs.push_back("-dwarf-debug-flags");
1472201361Srdivacky    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
1473201361Srdivacky  }
1474201361Srdivacky
1475200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
1476193326Sed
1477193326Sed  // Explicitly warn that these options are unsupported, even though
1478193326Sed  // we are allowing compilation to continue.
1479199990Srdivacky  for (arg_iterator it = Args.filtered_begin(options::OPT_pg),
1480199990Srdivacky         ie = Args.filtered_end(); it != ie; ++it) {
1481199990Srdivacky    it->claim();
1482199990Srdivacky    D.Diag(clang::diag::warn_drv_clang_unsupported) << it->getAsString(Args);
1483193326Sed  }
1484193326Sed
1485193326Sed  // Claim some arguments which clang supports automatically.
1486193326Sed
1487207619Srdivacky  // -fpch-preprocess is used with gcc to add a special marker in the output to
1488207619Srdivacky  // include the PCH file. Clang's PTH solution is completely transparent, so we
1489207619Srdivacky  // do not need to deal with it at all.
1490193326Sed  Args.ClaimAllArgs(options::OPT_fpch_preprocess);
1491193326Sed
1492193326Sed  // Claim some arguments which clang doesn't support, but we don't
1493193326Sed  // care to warn the user about.
1494199990Srdivacky  Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
1495199990Srdivacky  Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);
1496193326Sed}
1497193326Sed
1498208600Srdivackyvoid ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
1499208600Srdivacky                           Job &Dest,
1500208600Srdivacky                           const InputInfo &Output,
1501208600Srdivacky                           const InputInfoList &Inputs,
1502208600Srdivacky                           const ArgList &Args,
1503208600Srdivacky                           const char *LinkingOutput) const {
1504208600Srdivacky  const Driver &D = getToolChain().getDriver();
1505208600Srdivacky  ArgStringList CmdArgs;
1506208600Srdivacky
1507208600Srdivacky  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
1508208600Srdivacky  const InputInfo &Input = Inputs[0];
1509208600Srdivacky
1510208600Srdivacky  // Invoke ourselves in -cc1as mode.
1511208600Srdivacky  //
1512208600Srdivacky  // FIXME: Implement custom jobs for internal actions.
1513208600Srdivacky  CmdArgs.push_back("-cc1as");
1514208600Srdivacky
1515208600Srdivacky  // Add the "effective" target triple.
1516208600Srdivacky  CmdArgs.push_back("-triple");
1517208600Srdivacky  std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
1518208600Srdivacky  CmdArgs.push_back(Args.MakeArgString(TripleStr));
1519208600Srdivacky
1520208600Srdivacky  // Set the output mode, we currently only expect to be used as a real
1521208600Srdivacky  // assembler.
1522208600Srdivacky  CmdArgs.push_back("-filetype");
1523208600Srdivacky  CmdArgs.push_back("obj");
1524208600Srdivacky
1525208600Srdivacky  // At -O0, we use -mrelax-all by default.
1526208600Srdivacky  bool IsOpt = false;
1527208600Srdivacky  if (Arg *A = Args.getLastArg(options::OPT_O_Group))
1528208600Srdivacky    IsOpt = !A->getOption().matches(options::OPT_O0);
1529208600Srdivacky  if (Args.hasFlag(options::OPT_mrelax_all,
1530208600Srdivacky                    options::OPT_mno_relax_all,
1531208600Srdivacky                    !IsOpt))
1532208600Srdivacky    CmdArgs.push_back("-mrelax-all");
1533208600Srdivacky
1534208600Srdivacky  // FIXME: Add -force_cpusubtype_ALL support, once we have it.
1535208600Srdivacky
1536208600Srdivacky  // FIXME: Add -g support, once we have it.
1537208600Srdivacky
1538208600Srdivacky  // FIXME: Add -static support, once we have it.
1539208600Srdivacky
1540208600Srdivacky  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
1541208600Srdivacky                       options::OPT_Xassembler);
1542208600Srdivacky
1543208600Srdivacky  assert(Output.isFilename() && "Unexpected lipo output.");
1544208600Srdivacky  CmdArgs.push_back("-o");
1545208600Srdivacky  CmdArgs.push_back(Output.getFilename());
1546208600Srdivacky
1547208600Srdivacky  if (Input.isPipe()) {
1548208600Srdivacky    CmdArgs.push_back("-");
1549208600Srdivacky  } else {
1550208600Srdivacky    assert(Input.isFilename() && "Invalid input.");
1551208600Srdivacky    CmdArgs.push_back(Input.getFilename());
1552208600Srdivacky  }
1553208600Srdivacky
1554208600Srdivacky  const char *Exec =
1555208600Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "clang"));
1556208600Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
1557208600Srdivacky}
1558208600Srdivacky
1559193326Sedvoid gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
1560193326Sed                               Job &Dest,
1561193326Sed                               const InputInfo &Output,
1562193326Sed                               const InputInfoList &Inputs,
1563193326Sed                               const ArgList &Args,
1564193326Sed                               const char *LinkingOutput) const {
1565201361Srdivacky  const Driver &D = getToolChain().getDriver();
1566193326Sed  ArgStringList CmdArgs;
1567193326Sed
1568193326Sed  for (ArgList::const_iterator
1569193326Sed         it = Args.begin(), ie = Args.end(); it != ie; ++it) {
1570193326Sed    Arg *A = *it;
1571193326Sed    if (A->getOption().hasForwardToGCC()) {
1572193326Sed      // It is unfortunate that we have to claim here, as this means
1573193326Sed      // we will basically never report anything interesting for
1574193326Sed      // platforms using a generic gcc, even if we are just using gcc
1575193326Sed      // to get to the assembler.
1576193326Sed      A->claim();
1577193326Sed      A->render(Args, CmdArgs);
1578193326Sed    }
1579193326Sed  }
1580193326Sed
1581203955Srdivacky  RenderExtraToolArgs(JA, CmdArgs);
1582193326Sed
1583193326Sed  // If using a driver driver, force the arch.
1584193326Sed  const std::string &Arch = getToolChain().getArchName();
1585201361Srdivacky  if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin) {
1586193326Sed    CmdArgs.push_back("-arch");
1587193326Sed
1588193326Sed    // FIXME: Remove these special cases.
1589193326Sed    if (Arch == "powerpc")
1590193326Sed      CmdArgs.push_back("ppc");
1591193326Sed    else if (Arch == "powerpc64")
1592193326Sed      CmdArgs.push_back("ppc64");
1593193326Sed    else
1594198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(Arch));
1595193326Sed  }
1596193326Sed
1597193326Sed  // Try to force gcc to match the tool chain we want, if we recognize
1598193326Sed  // the arch.
1599193326Sed  //
1600193326Sed  // FIXME: The triple class should directly provide the information we want
1601193326Sed  // here.
1602193326Sed  if (Arch == "i386" || Arch == "powerpc")
1603193326Sed    CmdArgs.push_back("-m32");
1604193326Sed  else if (Arch == "x86_64" || Arch == "powerpc64")
1605193326Sed    CmdArgs.push_back("-m64");
1606193326Sed
1607193326Sed  if (Output.isPipe()) {
1608193326Sed    CmdArgs.push_back("-o");
1609193326Sed    CmdArgs.push_back("-");
1610193326Sed  } else if (Output.isFilename()) {
1611193326Sed    CmdArgs.push_back("-o");
1612193326Sed    CmdArgs.push_back(Output.getFilename());
1613193326Sed  } else {
1614193326Sed    assert(Output.isNothing() && "Unexpected output");
1615193326Sed    CmdArgs.push_back("-fsyntax-only");
1616193326Sed  }
1617193326Sed
1618193326Sed
1619193326Sed  // Only pass -x if gcc will understand it; otherwise hope gcc
1620193326Sed  // understands the suffix correctly. The main use case this would go
1621193326Sed  // wrong in is for linker inputs if they happened to have an odd
1622193326Sed  // suffix; really the only way to get this to happen is a command
1623193326Sed  // like '-x foobar a.c' which will treat a.c like a linker input.
1624193326Sed  //
1625193326Sed  // FIXME: For the linker case specifically, can we safely convert
1626193326Sed  // inputs into '-Wl,' options?
1627193326Sed  for (InputInfoList::const_iterator
1628193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
1629193326Sed    const InputInfo &II = *it;
1630193326Sed
1631198092Srdivacky    // Don't try to pass LLVM or AST inputs to a generic gcc.
1632193326Sed    if (II.getType() == types::TY_LLVMBC)
1633193326Sed      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
1634198092Srdivacky        << getToolChain().getTripleString();
1635198092Srdivacky    else if (II.getType() == types::TY_AST)
1636198092Srdivacky      D.Diag(clang::diag::err_drv_no_ast_support)
1637198092Srdivacky        << getToolChain().getTripleString();
1638193326Sed
1639193326Sed    if (types::canTypeBeUserSpecified(II.getType())) {
1640193326Sed      CmdArgs.push_back("-x");
1641193326Sed      CmdArgs.push_back(types::getTypeName(II.getType()));
1642193326Sed    }
1643193326Sed
1644193326Sed    if (II.isPipe())
1645193326Sed      CmdArgs.push_back("-");
1646193326Sed    else if (II.isFilename())
1647193326Sed      CmdArgs.push_back(II.getFilename());
1648193326Sed    else
1649193326Sed      // Don't render as input, we need gcc to do the translations.
1650193326Sed      II.getInputArg().render(Args, CmdArgs);
1651193326Sed  }
1652193326Sed
1653201361Srdivacky  const char *GCCName = getToolChain().getDriver().CCCGenericGCCName.c_str();
1654193326Sed  const char *Exec =
1655198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, GCCName));
1656200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
1657193326Sed}
1658193326Sed
1659203955Srdivackyvoid gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
1660203955Srdivacky                                          ArgStringList &CmdArgs) const {
1661193326Sed  CmdArgs.push_back("-E");
1662193326Sed}
1663193326Sed
1664203955Srdivackyvoid gcc::Precompile::RenderExtraToolArgs(const JobAction &JA,
1665203955Srdivacky                                          ArgStringList &CmdArgs) const {
1666193326Sed  // The type is good enough.
1667193326Sed}
1668193326Sed
1669203955Srdivackyvoid gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
1670203955Srdivacky                                       ArgStringList &CmdArgs) const {
1671203955Srdivacky  const Driver &D = getToolChain().getDriver();
1672203955Srdivacky
1673203955Srdivacky  // If -flto, etc. are present then make sure not to force assembly output.
1674203955Srdivacky  if (JA.getType() == types::TY_LLVMBC)
1675203955Srdivacky    CmdArgs.push_back("-c");
1676203955Srdivacky  else {
1677203955Srdivacky    if (JA.getType() != types::TY_PP_Asm)
1678203955Srdivacky      D.Diag(clang::diag::err_drv_invalid_gcc_output_type)
1679203955Srdivacky        << getTypeName(JA.getType());
1680203955Srdivacky
1681203955Srdivacky    CmdArgs.push_back("-S");
1682203955Srdivacky  }
1683193326Sed}
1684193326Sed
1685203955Srdivackyvoid gcc::Assemble::RenderExtraToolArgs(const JobAction &JA,
1686203955Srdivacky                                        ArgStringList &CmdArgs) const {
1687193326Sed  CmdArgs.push_back("-c");
1688193326Sed}
1689193326Sed
1690203955Srdivackyvoid gcc::Link::RenderExtraToolArgs(const JobAction &JA,
1691203955Srdivacky                                    ArgStringList &CmdArgs) const {
1692193326Sed  // The types are (hopefully) good enough.
1693193326Sed}
1694193326Sed
1695193326Sedconst char *darwin::CC1::getCC1Name(types::ID Type) const {
1696193326Sed  switch (Type) {
1697193326Sed  default:
1698193326Sed    assert(0 && "Unexpected type for Darwin CC1 tool.");
1699193326Sed  case types::TY_Asm:
1700193326Sed  case types::TY_C: case types::TY_CHeader:
1701193326Sed  case types::TY_PP_C: case types::TY_PP_CHeader:
1702193326Sed    return "cc1";
1703193326Sed  case types::TY_ObjC: case types::TY_ObjCHeader:
1704193326Sed  case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader:
1705193326Sed    return "cc1obj";
1706193326Sed  case types::TY_CXX: case types::TY_CXXHeader:
1707193326Sed  case types::TY_PP_CXX: case types::TY_PP_CXXHeader:
1708193326Sed    return "cc1plus";
1709193326Sed  case types::TY_ObjCXX: case types::TY_ObjCXXHeader:
1710193326Sed  case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader:
1711193326Sed    return "cc1objplus";
1712193326Sed  }
1713193326Sed}
1714193326Sed
1715193326Sedconst char *darwin::CC1::getBaseInputName(const ArgList &Args,
1716193326Sed                                          const InputInfoList &Inputs) {
1717193326Sed  llvm::sys::Path P(Inputs[0].getBaseInput());
1718198092Srdivacky  return Args.MakeArgString(P.getLast());
1719193326Sed}
1720193326Sed
1721193326Sedconst char *darwin::CC1::getBaseInputStem(const ArgList &Args,
1722193326Sed                                          const InputInfoList &Inputs) {
1723193326Sed  const char *Str = getBaseInputName(Args, Inputs);
1724193326Sed
1725193326Sed  if (const char *End = strchr(Str, '.'))
1726198092Srdivacky    return Args.MakeArgString(std::string(Str, End));
1727193326Sed
1728193326Sed  return Str;
1729193326Sed}
1730193326Sed
1731193326Sedconst char *
1732193326Seddarwin::CC1::getDependencyFileName(const ArgList &Args,
1733193326Sed                                   const InputInfoList &Inputs) {
1734193326Sed  // FIXME: Think about this more.
1735193326Sed  std::string Res;
1736193326Sed
1737193326Sed  if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
1738193326Sed    std::string Str(OutputOpt->getValue(Args));
1739193326Sed
1740193326Sed    Res = Str.substr(0, Str.rfind('.'));
1741193326Sed  } else
1742193326Sed    Res = darwin::CC1::getBaseInputStem(Args, Inputs);
1743193326Sed
1744198092Srdivacky  return Args.MakeArgString(Res + ".d");
1745193326Sed}
1746193326Sed
1747193326Sedvoid darwin::CC1::AddCC1Args(const ArgList &Args,
1748193326Sed                             ArgStringList &CmdArgs) const {
1749201361Srdivacky  const Driver &D = getToolChain().getDriver();
1750198092Srdivacky
1751198092Srdivacky  CheckCodeGenerationOptions(D, Args);
1752198092Srdivacky
1753193326Sed  // Derived from cc1 spec.
1754193326Sed  if (!Args.hasArg(options::OPT_mkernel) && !Args.hasArg(options::OPT_static) &&
1755193326Sed      !Args.hasArg(options::OPT_mdynamic_no_pic))
1756193326Sed    CmdArgs.push_back("-fPIC");
1757193326Sed
1758198092Srdivacky  if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
1759198092Srdivacky      getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
1760198092Srdivacky    if (!Args.hasArg(options::OPT_fbuiltin_strcat))
1761198092Srdivacky      CmdArgs.push_back("-fno-builtin-strcat");
1762198092Srdivacky    if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
1763198092Srdivacky      CmdArgs.push_back("-fno-builtin-strcpy");
1764198092Srdivacky  }
1765198092Srdivacky
1766193326Sed  // gcc has some code here to deal with when no -mmacosx-version-min
1767193326Sed  // and no -miphoneos-version-min is present, but this never happens
1768193326Sed  // due to tool chain specific argument translation.
1769193326Sed
1770193326Sed  if (Args.hasArg(options::OPT_g_Flag) &&
1771193326Sed      !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols))
1772193326Sed    CmdArgs.push_back("-feliminate-unused-debug-symbols");
1773193326Sed}
1774193326Sed
1775193326Sedvoid darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
1776193326Sed                                    const InputInfoList &Inputs,
1777193326Sed                                    const ArgStringList &OutputArgs) const {
1778201361Srdivacky  const Driver &D = getToolChain().getDriver();
1779193326Sed
1780193326Sed  // Derived from cc1_options spec.
1781193326Sed  if (Args.hasArg(options::OPT_fast) ||
1782193326Sed      Args.hasArg(options::OPT_fastf) ||
1783193326Sed      Args.hasArg(options::OPT_fastcp))
1784193326Sed    CmdArgs.push_back("-O3");
1785193326Sed
1786193326Sed  if (Arg *A = Args.getLastArg(options::OPT_pg))
1787193326Sed    if (Args.hasArg(options::OPT_fomit_frame_pointer))
1788193326Sed      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1789193326Sed        << A->getAsString(Args) << "-fomit-frame-pointer";
1790193326Sed
1791193326Sed  AddCC1Args(Args, CmdArgs);
1792193326Sed
1793193326Sed  if (!Args.hasArg(options::OPT_Q))
1794193326Sed    CmdArgs.push_back("-quiet");
1795193326Sed
1796193326Sed  CmdArgs.push_back("-dumpbase");
1797193326Sed  CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs));
1798193326Sed
1799193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_d_Group);
1800193326Sed
1801193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
1802193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_a_Group);
1803193326Sed
1804193326Sed  // FIXME: The goal is to use the user provided -o if that is our
1805193326Sed  // final output, otherwise to drive from the original input
1806193326Sed  // name. Find a clean way to go about this.
1807193326Sed  if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) &&
1808193326Sed      Args.hasArg(options::OPT_o)) {
1809193326Sed    Arg *OutputOpt = Args.getLastArg(options::OPT_o);
1810193326Sed    CmdArgs.push_back("-auxbase-strip");
1811193326Sed    CmdArgs.push_back(OutputOpt->getValue(Args));
1812193326Sed  } else {
1813193326Sed    CmdArgs.push_back("-auxbase");
1814193326Sed    CmdArgs.push_back(darwin::CC1::getBaseInputStem(Args, Inputs));
1815193326Sed  }
1816193326Sed
1817193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_g_Group);
1818193326Sed
1819193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_O);
1820193326Sed  // FIXME: -Wall is getting some special treatment. Investigate.
1821193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
1822193326Sed  Args.AddLastArg(CmdArgs, options::OPT_w);
1823193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
1824193326Sed                  options::OPT_trigraphs);
1825193326Sed  if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
1826193326Sed    // Honor -std-default.
1827193326Sed    Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
1828193326Sed                              "-std=", /*Joined=*/true);
1829193326Sed  }
1830193326Sed
1831193326Sed  if (Args.hasArg(options::OPT_v))
1832193326Sed    CmdArgs.push_back("-version");
1833193326Sed  if (Args.hasArg(options::OPT_pg))
1834193326Sed    CmdArgs.push_back("-p");
1835193326Sed  Args.AddLastArg(CmdArgs, options::OPT_p);
1836193326Sed
1837193326Sed  // The driver treats -fsyntax-only specially.
1838198092Srdivacky  if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
1839198092Srdivacky      getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
1840198092Srdivacky    // Removes -fbuiltin-str{cat,cpy}; these aren't recognized by cc1 but are
1841198092Srdivacky    // used to inhibit the default -fno-builtin-str{cat,cpy}.
1842198092Srdivacky    //
1843198092Srdivacky    // FIXME: Should we grow a better way to deal with "removing" args?
1844199990Srdivacky    for (arg_iterator it = Args.filtered_begin(options::OPT_f_Group,
1845199990Srdivacky                                               options::OPT_fsyntax_only),
1846199990Srdivacky           ie = Args.filtered_end(); it != ie; ++it) {
1847199990Srdivacky      if (!it->getOption().matches(options::OPT_fbuiltin_strcat) &&
1848199990Srdivacky          !it->getOption().matches(options::OPT_fbuiltin_strcpy)) {
1849199990Srdivacky        it->claim();
1850199990Srdivacky        it->render(Args, CmdArgs);
1851198092Srdivacky      }
1852198092Srdivacky    }
1853198092Srdivacky  } else
1854198092Srdivacky    Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
1855193326Sed
1856193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_undef);
1857193326Sed  if (Args.hasArg(options::OPT_Qn))
1858193326Sed    CmdArgs.push_back("-fno-ident");
1859193326Sed
1860193326Sed  // FIXME: This isn't correct.
1861193326Sed  //Args.AddLastArg(CmdArgs, options::OPT__help)
1862193326Sed  //Args.AddLastArg(CmdArgs, options::OPT__targetHelp)
1863193326Sed
1864193326Sed  CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
1865193326Sed
1866193326Sed  // FIXME: Still don't get what is happening here. Investigate.
1867193326Sed  Args.AddAllArgs(CmdArgs, options::OPT__param);
1868193326Sed
1869193326Sed  if (Args.hasArg(options::OPT_fmudflap) ||
1870193326Sed      Args.hasArg(options::OPT_fmudflapth)) {
1871193326Sed    CmdArgs.push_back("-fno-builtin");
1872193326Sed    CmdArgs.push_back("-fno-merge-constants");
1873193326Sed  }
1874193326Sed
1875193326Sed  if (Args.hasArg(options::OPT_coverage)) {
1876193326Sed    CmdArgs.push_back("-fprofile-arcs");
1877193326Sed    CmdArgs.push_back("-ftest-coverage");
1878193326Sed  }
1879193326Sed
1880193326Sed  if (types::isCXX(Inputs[0].getType()))
1881193326Sed    CmdArgs.push_back("-D__private_extern__=extern");
1882193326Sed}
1883193326Sed
1884193326Sedvoid darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
1885193326Sed                                    const InputInfoList &Inputs,
1886193326Sed                                    const ArgStringList &OutputArgs) const {
1887193326Sed  // Derived from cpp_options
1888193326Sed  AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
1889193326Sed
1890193326Sed  CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
1891193326Sed
1892193326Sed  AddCC1Args(Args, CmdArgs);
1893193326Sed
1894193326Sed  // NOTE: The code below has some commonality with cpp_options, but
1895193326Sed  // in classic gcc style ends up sending things in different
1896193326Sed  // orders. This may be a good merge candidate once we drop pedantic
1897193326Sed  // compatibility.
1898193326Sed
1899193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
1900193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
1901193326Sed                  options::OPT_trigraphs);
1902193326Sed  if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
1903193326Sed    // Honor -std-default.
1904193326Sed    Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
1905193326Sed                              "-std=", /*Joined=*/true);
1906193326Sed  }
1907193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
1908193326Sed  Args.AddLastArg(CmdArgs, options::OPT_w);
1909193326Sed
1910193326Sed  // The driver treats -fsyntax-only specially.
1911193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
1912193326Sed
1913193326Sed  if (Args.hasArg(options::OPT_g_Group) && !Args.hasArg(options::OPT_g0) &&
1914193326Sed      !Args.hasArg(options::OPT_fno_working_directory))
1915193326Sed    CmdArgs.push_back("-fworking-directory");
1916193326Sed
1917193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_O);
1918193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_undef);
1919193326Sed  if (Args.hasArg(options::OPT_save_temps))
1920193326Sed    CmdArgs.push_back("-fpch-preprocess");
1921193326Sed}
1922193326Sed
1923193326Sedvoid darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args,
1924193326Sed                                          ArgStringList &CmdArgs,
1925198092Srdivacky                                          const InputInfoList &Inputs) const {
1926201361Srdivacky  const Driver &D = getToolChain().getDriver();
1927193326Sed
1928198092Srdivacky  CheckPreprocessingOptions(D, Args);
1929198092Srdivacky
1930193326Sed  // Derived from cpp_unique_options.
1931198092Srdivacky  // -{C,CC} only with -E is checked in CheckPreprocessingOptions().
1932198092Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_C);
1933198092Srdivacky  Args.AddLastArg(CmdArgs, options::OPT_CC);
1934193326Sed  if (!Args.hasArg(options::OPT_Q))
1935193326Sed    CmdArgs.push_back("-quiet");
1936193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_nostdinc);
1937206084Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_nostdincxx);
1938193326Sed  Args.AddLastArg(CmdArgs, options::OPT_v);
1939193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
1940193326Sed  Args.AddLastArg(CmdArgs, options::OPT_P);
1941193326Sed
1942193326Sed  // FIXME: Handle %I properly.
1943193326Sed  if (getToolChain().getArchName() == "x86_64") {
1944193326Sed    CmdArgs.push_back("-imultilib");
1945193326Sed    CmdArgs.push_back("x86_64");
1946193326Sed  }
1947193326Sed
1948193326Sed  if (Args.hasArg(options::OPT_MD)) {
1949193326Sed    CmdArgs.push_back("-MD");
1950193326Sed    CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
1951193326Sed  }
1952193326Sed
1953193326Sed  if (Args.hasArg(options::OPT_MMD)) {
1954193326Sed    CmdArgs.push_back("-MMD");
1955193326Sed    CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
1956193326Sed  }
1957193326Sed
1958193326Sed  Args.AddLastArg(CmdArgs, options::OPT_M);
1959193326Sed  Args.AddLastArg(CmdArgs, options::OPT_MM);
1960193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_MF);
1961193326Sed  Args.AddLastArg(CmdArgs, options::OPT_MG);
1962193326Sed  Args.AddLastArg(CmdArgs, options::OPT_MP);
1963193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_MQ);
1964193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_MT);
1965193326Sed  if (!Args.hasArg(options::OPT_M) && !Args.hasArg(options::OPT_MM) &&
1966193326Sed      (Args.hasArg(options::OPT_MD) || Args.hasArg(options::OPT_MMD))) {
1967193326Sed    if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
1968193326Sed      CmdArgs.push_back("-MQ");
1969193326Sed      CmdArgs.push_back(OutputOpt->getValue(Args));
1970193326Sed    }
1971193326Sed  }
1972193326Sed
1973193326Sed  Args.AddLastArg(CmdArgs, options::OPT_remap);
1974193326Sed  if (Args.hasArg(options::OPT_g3))
1975193326Sed    CmdArgs.push_back("-dD");
1976193326Sed  Args.AddLastArg(CmdArgs, options::OPT_H);
1977193326Sed
1978193326Sed  AddCPPArgs(Args, CmdArgs);
1979193326Sed
1980193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U, options::OPT_A);
1981193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_i_Group);
1982193326Sed
1983193326Sed  for (InputInfoList::const_iterator
1984193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
1985193326Sed    const InputInfo &II = *it;
1986193326Sed
1987193326Sed    if (II.isPipe())
1988193326Sed      CmdArgs.push_back("-");
1989193326Sed    else
1990193326Sed      CmdArgs.push_back(II.getFilename());
1991193326Sed  }
1992193326Sed
1993193326Sed  Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
1994193326Sed                       options::OPT_Xpreprocessor);
1995193326Sed
1996193326Sed  if (Args.hasArg(options::OPT_fmudflap)) {
1997193326Sed    CmdArgs.push_back("-D_MUDFLAP");
1998193326Sed    CmdArgs.push_back("-include");
1999193326Sed    CmdArgs.push_back("mf-runtime.h");
2000193326Sed  }
2001193326Sed
2002193326Sed  if (Args.hasArg(options::OPT_fmudflapth)) {
2003193326Sed    CmdArgs.push_back("-D_MUDFLAP");
2004193326Sed    CmdArgs.push_back("-D_MUDFLAPTH");
2005193326Sed    CmdArgs.push_back("-include");
2006193326Sed    CmdArgs.push_back("mf-runtime.h");
2007193326Sed  }
2008193326Sed}
2009193326Sed
2010193326Sedvoid darwin::CC1::AddCPPArgs(const ArgList &Args,
2011193326Sed                             ArgStringList &CmdArgs) const {
2012193326Sed  // Derived from cpp spec.
2013193326Sed
2014193326Sed  if (Args.hasArg(options::OPT_static)) {
2015193326Sed    // The gcc spec is broken here, it refers to dynamic but
2016193326Sed    // that has been translated. Start by being bug compatible.
2017193326Sed
2018193326Sed    // if (!Args.hasArg(arglist.parser.dynamicOption))
2019193326Sed    CmdArgs.push_back("-D__STATIC__");
2020193326Sed  } else
2021193326Sed    CmdArgs.push_back("-D__DYNAMIC__");
2022193326Sed
2023193326Sed  if (Args.hasArg(options::OPT_pthread))
2024193326Sed    CmdArgs.push_back("-D_REENTRANT");
2025193326Sed}
2026193326Sed
2027193326Sedvoid darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
2028193326Sed                                      Job &Dest, const InputInfo &Output,
2029193326Sed                                      const InputInfoList &Inputs,
2030193326Sed                                      const ArgList &Args,
2031193326Sed                                      const char *LinkingOutput) const {
2032193326Sed  ArgStringList CmdArgs;
2033193326Sed
2034193326Sed  assert(Inputs.size() == 1 && "Unexpected number of inputs!");
2035193326Sed
2036193326Sed  CmdArgs.push_back("-E");
2037193326Sed
2038193326Sed  if (Args.hasArg(options::OPT_traditional) ||
2039193326Sed      Args.hasArg(options::OPT_traditional_cpp))
2040193326Sed    CmdArgs.push_back("-traditional-cpp");
2041193326Sed
2042193326Sed  ArgStringList OutputArgs;
2043193326Sed  if (Output.isFilename()) {
2044193326Sed    OutputArgs.push_back("-o");
2045193326Sed    OutputArgs.push_back(Output.getFilename());
2046193326Sed  } else {
2047193326Sed    assert(Output.isPipe() && "Unexpected CC1 output.");
2048193326Sed  }
2049193326Sed
2050193326Sed  if (Args.hasArg(options::OPT_E)) {
2051193326Sed    AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
2052193326Sed  } else {
2053193326Sed    AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
2054193326Sed    CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
2055193326Sed  }
2056193326Sed
2057193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_d_Group);
2058193326Sed
2059193326Sed  const char *CC1Name = getCC1Name(Inputs[0].getType());
2060193326Sed  const char *Exec =
2061198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name));
2062200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2063193326Sed}
2064193326Sed
2065193326Sedvoid darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
2066193326Sed                                   Job &Dest, const InputInfo &Output,
2067193326Sed                                   const InputInfoList &Inputs,
2068193326Sed                                   const ArgList &Args,
2069193326Sed                                   const char *LinkingOutput) const {
2070201361Srdivacky  const Driver &D = getToolChain().getDriver();
2071193326Sed  ArgStringList CmdArgs;
2072193326Sed
2073193326Sed  assert(Inputs.size() == 1 && "Unexpected number of inputs!");
2074193326Sed
2075193326Sed  types::ID InputType = Inputs[0].getType();
2076193326Sed  const Arg *A;
2077198092Srdivacky  if ((A = Args.getLastArg(options::OPT_traditional)))
2078193326Sed    D.Diag(clang::diag::err_drv_argument_only_allowed_with)
2079193326Sed      << A->getAsString(Args) << "-E";
2080193326Sed
2081193326Sed  if (Output.getType() == types::TY_LLVMAsm)
2082193326Sed    CmdArgs.push_back("-emit-llvm");
2083193326Sed  else if (Output.getType() == types::TY_LLVMBC)
2084193326Sed    CmdArgs.push_back("-emit-llvm-bc");
2085198092Srdivacky  else if (Output.getType() == types::TY_AST)
2086198092Srdivacky    D.Diag(clang::diag::err_drv_no_ast_support)
2087198092Srdivacky      << getToolChain().getTripleString();
2088203955Srdivacky  else if (JA.getType() != types::TY_PP_Asm &&
2089203955Srdivacky           JA.getType() != types::TY_PCH)
2090203955Srdivacky    D.Diag(clang::diag::err_drv_invalid_gcc_output_type)
2091203955Srdivacky      << getTypeName(JA.getType());
2092193326Sed
2093193326Sed  ArgStringList OutputArgs;
2094193326Sed  if (Output.getType() != types::TY_PCH) {
2095193326Sed    OutputArgs.push_back("-o");
2096193326Sed    if (Output.isPipe())
2097193326Sed      OutputArgs.push_back("-");
2098193326Sed    else if (Output.isNothing())
2099193326Sed      OutputArgs.push_back("/dev/null");
2100193326Sed    else
2101193326Sed      OutputArgs.push_back(Output.getFilename());
2102193326Sed  }
2103193326Sed
2104193326Sed  // There is no need for this level of compatibility, but it makes
2105193326Sed  // diffing easier.
2106193326Sed  bool OutputArgsEarly = (Args.hasArg(options::OPT_fsyntax_only) ||
2107193326Sed                          Args.hasArg(options::OPT_S));
2108193326Sed
2109193326Sed  if (types::getPreprocessedType(InputType) != types::TY_INVALID) {
2110193326Sed    AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
2111193326Sed    if (OutputArgsEarly) {
2112193326Sed      AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
2113193326Sed    } else {
2114193326Sed      AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
2115193326Sed      CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
2116193326Sed    }
2117193326Sed  } else {
2118193326Sed    CmdArgs.push_back("-fpreprocessed");
2119193326Sed
2120193326Sed    for (InputInfoList::const_iterator
2121193326Sed           it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2122193326Sed      const InputInfo &II = *it;
2123193326Sed
2124198092Srdivacky      // Reject AST inputs.
2125198092Srdivacky      if (II.getType() == types::TY_AST) {
2126198092Srdivacky        D.Diag(clang::diag::err_drv_no_ast_support)
2127198092Srdivacky          << getToolChain().getTripleString();
2128198092Srdivacky        return;
2129198092Srdivacky      }
2130198092Srdivacky
2131193326Sed      if (II.isPipe())
2132193326Sed        CmdArgs.push_back("-");
2133193326Sed      else
2134193326Sed        CmdArgs.push_back(II.getFilename());
2135193326Sed    }
2136193326Sed
2137193326Sed    if (OutputArgsEarly) {
2138193326Sed      AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
2139193326Sed    } else {
2140193326Sed      AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
2141193326Sed      CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
2142193326Sed    }
2143193326Sed  }
2144193326Sed
2145193326Sed  if (Output.getType() == types::TY_PCH) {
2146193326Sed    assert(Output.isFilename() && "Invalid PCH output.");
2147193326Sed
2148193326Sed    CmdArgs.push_back("-o");
2149193326Sed    // NOTE: gcc uses a temp .s file for this, but there doesn't seem
2150193326Sed    // to be a good reason.
2151193326Sed    CmdArgs.push_back("/dev/null");
2152193326Sed
2153193326Sed    CmdArgs.push_back("--output-pch=");
2154193326Sed    CmdArgs.push_back(Output.getFilename());
2155193326Sed  }
2156193326Sed
2157193326Sed  const char *CC1Name = getCC1Name(Inputs[0].getType());
2158193326Sed  const char *Exec =
2159198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name));
2160200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2161193326Sed}
2162193326Sed
2163193326Sedvoid darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
2164193326Sed                                    Job &Dest, const InputInfo &Output,
2165193326Sed                                    const InputInfoList &Inputs,
2166193326Sed                                    const ArgList &Args,
2167193326Sed                                    const char *LinkingOutput) const {
2168193326Sed  ArgStringList CmdArgs;
2169193326Sed
2170193326Sed  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
2171193326Sed  const InputInfo &Input = Inputs[0];
2172193326Sed
2173193326Sed  // Bit of a hack, this is only used for original inputs.
2174193326Sed  //
2175193326Sed  // FIXME: This is broken for preprocessed .s inputs.
2176193326Sed  if (Input.isFilename() &&
2177193326Sed      strcmp(Input.getFilename(), Input.getBaseInput()) == 0) {
2178193326Sed    if (Args.hasArg(options::OPT_gstabs))
2179193326Sed      CmdArgs.push_back("--gstabs");
2180193326Sed    else if (Args.hasArg(options::OPT_g_Group))
2181193326Sed      CmdArgs.push_back("--gdwarf2");
2182193326Sed  }
2183193326Sed
2184193326Sed  // Derived from asm spec.
2185198092Srdivacky  AddDarwinArch(Args, CmdArgs);
2186193326Sed
2187203955Srdivacky  if (!getDarwinToolChain().isTargetIPhoneOS() ||
2188198092Srdivacky      Args.hasArg(options::OPT_force__cpusubtype__ALL))
2189198092Srdivacky    CmdArgs.push_back("-force_cpusubtype_ALL");
2190198092Srdivacky
2191198092Srdivacky  if (getToolChain().getTriple().getArch() != llvm::Triple::x86_64 &&
2192198092Srdivacky      (Args.hasArg(options::OPT_mkernel) ||
2193193326Sed       Args.hasArg(options::OPT_static) ||
2194198092Srdivacky       Args.hasArg(options::OPT_fapple_kext)))
2195193326Sed    CmdArgs.push_back("-static");
2196193326Sed
2197193326Sed  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
2198193326Sed                       options::OPT_Xassembler);
2199193326Sed
2200193326Sed  assert(Output.isFilename() && "Unexpected lipo output.");
2201193326Sed  CmdArgs.push_back("-o");
2202193326Sed  CmdArgs.push_back(Output.getFilename());
2203193326Sed
2204193326Sed  if (Input.isPipe()) {
2205193326Sed    CmdArgs.push_back("-");
2206193326Sed  } else {
2207193326Sed    assert(Input.isFilename() && "Invalid input.");
2208193326Sed    CmdArgs.push_back(Input.getFilename());
2209193326Sed  }
2210193326Sed
2211193326Sed  // asm_final spec is empty.
2212193326Sed
2213193326Sed  const char *Exec =
2214198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
2215200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2216193326Sed}
2217193326Sed
2218193326Sed/// Helper routine for seeing if we should use dsymutil; this is a
2219193326Sed/// gcc compatible hack, we should remove it and use the input
2220193326Sed/// type information.
2221193326Sedstatic bool isSourceSuffix(const char *Str) {
2222193326Sed  // match: 'C', 'CPP', 'c', 'cc', 'cp', 'c++', 'cpp', 'cxx', 'm',
2223193326Sed  // 'mm'.
2224198893Srdivacky  return llvm::StringSwitch<bool>(Str)
2225198893Srdivacky           .Case("C", true)
2226198893Srdivacky           .Case("c", true)
2227198893Srdivacky           .Case("m", true)
2228198893Srdivacky           .Case("cc", true)
2229198893Srdivacky           .Case("cp", true)
2230198893Srdivacky           .Case("mm", true)
2231198893Srdivacky           .Case("CPP", true)
2232198893Srdivacky           .Case("c++", true)
2233198893Srdivacky           .Case("cpp", true)
2234198893Srdivacky           .Case("cxx", true)
2235198893Srdivacky           .Default(false);
2236193326Sed}
2237193326Sed
2238198092Srdivackyvoid darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
2239198092Srdivacky                                       ArgStringList &CmdArgs) const {
2240202879Srdivacky  llvm::StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);
2241202879Srdivacky
2242193326Sed  // Derived from darwin_arch spec.
2243193326Sed  CmdArgs.push_back("-arch");
2244202879Srdivacky  CmdArgs.push_back(Args.MakeArgString(ArchName));
2245198092Srdivacky
2246202879Srdivacky  // FIXME: Is this needed anymore?
2247202879Srdivacky  if (ArchName == "arm")
2248198092Srdivacky    CmdArgs.push_back("-force_cpusubtype_ALL");
2249193326Sed}
2250193326Sed
2251193326Sedvoid darwin::Link::AddLinkArgs(const ArgList &Args,
2252193326Sed                               ArgStringList &CmdArgs) const {
2253201361Srdivacky  const Driver &D = getToolChain().getDriver();
2254193326Sed
2255193326Sed  // Derived from the "link" spec.
2256193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_static);
2257193326Sed  if (!Args.hasArg(options::OPT_static))
2258193326Sed    CmdArgs.push_back("-dynamic");
2259193326Sed  if (Args.hasArg(options::OPT_fgnu_runtime)) {
2260193326Sed    // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
2261193326Sed    // here. How do we wish to handle such things?
2262193326Sed  }
2263193326Sed
2264193326Sed  if (!Args.hasArg(options::OPT_dynamiclib)) {
2265202879Srdivacky    AddDarwinArch(Args, CmdArgs);
2266202879Srdivacky    // FIXME: Why do this only on this path?
2267202879Srdivacky    Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
2268193326Sed
2269193326Sed    Args.AddLastArg(CmdArgs, options::OPT_bundle);
2270193326Sed    Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
2271193326Sed    Args.AddAllArgs(CmdArgs, options::OPT_client__name);
2272193326Sed
2273193326Sed    Arg *A;
2274193326Sed    if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
2275193326Sed        (A = Args.getLastArg(options::OPT_current__version)) ||
2276193326Sed        (A = Args.getLastArg(options::OPT_install__name)))
2277193326Sed      D.Diag(clang::diag::err_drv_argument_only_allowed_with)
2278193326Sed        << A->getAsString(Args) << "-dynamiclib";
2279193326Sed
2280193326Sed    Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
2281193326Sed    Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
2282193326Sed    Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
2283193326Sed  } else {
2284193326Sed    CmdArgs.push_back("-dylib");
2285193326Sed
2286193326Sed    Arg *A;
2287193326Sed    if ((A = Args.getLastArg(options::OPT_bundle)) ||
2288193326Sed        (A = Args.getLastArg(options::OPT_bundle__loader)) ||
2289193326Sed        (A = Args.getLastArg(options::OPT_client__name)) ||
2290193326Sed        (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
2291193326Sed        (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
2292193326Sed        (A = Args.getLastArg(options::OPT_private__bundle)))
2293193326Sed      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
2294193326Sed        << A->getAsString(Args) << "-dynamiclib";
2295193326Sed
2296193326Sed    Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
2297193326Sed                              "-dylib_compatibility_version");
2298193326Sed    Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
2299193326Sed                              "-dylib_current_version");
2300193326Sed
2301202879Srdivacky    AddDarwinArch(Args, CmdArgs);
2302193326Sed
2303193326Sed    Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
2304193326Sed                              "-dylib_install_name");
2305193326Sed  }
2306193326Sed
2307193326Sed  Args.AddLastArg(CmdArgs, options::OPT_all__load);
2308193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
2309193326Sed  Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
2310203955Srdivacky  if (getDarwinToolChain().isTargetIPhoneOS())
2311198092Srdivacky    Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
2312193326Sed  Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
2313193326Sed  Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
2314193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
2315193326Sed  Args.AddLastArg(CmdArgs, options::OPT_dynamic);
2316193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
2317193326Sed  Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
2318193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
2319193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_image__base);
2320193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_init);
2321193326Sed
2322203955Srdivacky  // Adding all arguments doesn't make sense here but this is what gcc does. One
2323203955Srdivacky  // of this should always be present thanks to argument translation.
2324203955Srdivacky  assert((Args.hasArg(options::OPT_mmacosx_version_min_EQ) ||
2325203955Srdivacky          Args.hasArg(options::OPT_miphoneos_version_min_EQ)) &&
2326203955Srdivacky         "Missing version argument (lost in translation)?");
2327198092Srdivacky  Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
2328198893Srdivacky                            "-macosx_version_min");
2329193326Sed  Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ,
2330193326Sed                            "-iphoneos_version_min");
2331193326Sed  Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
2332193326Sed  Args.AddLastArg(CmdArgs, options::OPT_multi__module);
2333193326Sed  Args.AddLastArg(CmdArgs, options::OPT_single__module);
2334193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
2335193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
2336193326Sed
2337193326Sed  if (Args.hasArg(options::OPT_fpie))
2338193326Sed    CmdArgs.push_back("-pie");
2339193326Sed
2340193326Sed  Args.AddLastArg(CmdArgs, options::OPT_prebind);
2341193326Sed  Args.AddLastArg(CmdArgs, options::OPT_noprebind);
2342193326Sed  Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
2343193326Sed  Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
2344193326Sed  Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
2345193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
2346193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
2347193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
2348193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_segprot);
2349193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
2350193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
2351193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
2352193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
2353193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
2354193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
2355193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
2356198092Srdivacky
2357193326Sed  Args.AddAllArgsTranslated(CmdArgs, options::OPT_isysroot, "-syslibroot");
2358203955Srdivacky  if (getDarwinToolChain().isTargetIPhoneOS()) {
2359198092Srdivacky    if (!Args.hasArg(options::OPT_isysroot)) {
2360198092Srdivacky      CmdArgs.push_back("-syslibroot");
2361198092Srdivacky      CmdArgs.push_back("/Developer/SDKs/Extra");
2362198092Srdivacky    }
2363198092Srdivacky  }
2364198092Srdivacky
2365193326Sed  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
2366193326Sed  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
2367193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
2368193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_undefined);
2369193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
2370193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
2371193326Sed  Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
2372193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_y);
2373193326Sed  Args.AddLastArg(CmdArgs, options::OPT_w);
2374193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
2375193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
2376193326Sed  Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
2377193326Sed  Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
2378193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
2379193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
2380193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
2381193326Sed  Args.AddLastArg(CmdArgs, options::OPT_whyload);
2382193326Sed  Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
2383193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
2384193326Sed  Args.AddLastArg(CmdArgs, options::OPT_dylinker);
2385193326Sed  Args.AddLastArg(CmdArgs, options::OPT_Mach);
2386193326Sed}
2387193326Sed
2388193326Sedvoid darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
2389193326Sed                                Job &Dest, const InputInfo &Output,
2390193326Sed                                const InputInfoList &Inputs,
2391193326Sed                                const ArgList &Args,
2392193326Sed                                const char *LinkingOutput) const {
2393193326Sed  assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
2394198092Srdivacky
2395193326Sed  // The logic here is derived from gcc's behavior; most of which
2396193326Sed  // comes from specs (starting with link_command). Consult gcc for
2397193326Sed  // more information.
2398193326Sed  ArgStringList CmdArgs;
2399193326Sed
2400193326Sed  // I'm not sure why this particular decomposition exists in gcc, but
2401193326Sed  // we follow suite for ease of comparison.
2402193326Sed  AddLinkArgs(Args, CmdArgs);
2403193326Sed
2404193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
2405193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_s);
2406193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_t);
2407193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
2408193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
2409193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_A);
2410193326Sed  Args.AddLastArg(CmdArgs, options::OPT_e);
2411193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
2412193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_r);
2413193326Sed
2414193326Sed  CmdArgs.push_back("-o");
2415193326Sed  CmdArgs.push_back(Output.getFilename());
2416193326Sed
2417193326Sed  if (!Args.hasArg(options::OPT_A) &&
2418193326Sed      !Args.hasArg(options::OPT_nostdlib) &&
2419193326Sed      !Args.hasArg(options::OPT_nostartfiles)) {
2420193326Sed    // Derived from startfile spec.
2421193326Sed    if (Args.hasArg(options::OPT_dynamiclib)) {
2422193326Sed      // Derived from darwin_dylib1 spec.
2423203955Srdivacky      if (getDarwinToolChain().isTargetIPhoneOS()) {
2424203955Srdivacky        if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
2425203955Srdivacky          CmdArgs.push_back("-ldylib1.o");
2426203955Srdivacky      } else {
2427203955Srdivacky        if (getDarwinToolChain().isMacosxVersionLT(10, 5))
2428203955Srdivacky          CmdArgs.push_back("-ldylib1.o");
2429203955Srdivacky        else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
2430203955Srdivacky          CmdArgs.push_back("-ldylib1.10.5.o");
2431203955Srdivacky      }
2432193326Sed    } else {
2433193326Sed      if (Args.hasArg(options::OPT_bundle)) {
2434193326Sed        if (!Args.hasArg(options::OPT_static)) {
2435193326Sed          // Derived from darwin_bundle1 spec.
2436203955Srdivacky          if (getDarwinToolChain().isTargetIPhoneOS()) {
2437203955Srdivacky            if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
2438203955Srdivacky              CmdArgs.push_back("-lbundle1.o");
2439203955Srdivacky          } else {
2440203955Srdivacky            if (getDarwinToolChain().isMacosxVersionLT(10, 6))
2441203955Srdivacky              CmdArgs.push_back("-lbundle1.o");
2442203955Srdivacky          }
2443193326Sed        }
2444193326Sed      } else {
2445193326Sed        if (Args.hasArg(options::OPT_pg)) {
2446193326Sed          if (Args.hasArg(options::OPT_static) ||
2447193326Sed              Args.hasArg(options::OPT_object) ||
2448193326Sed              Args.hasArg(options::OPT_preload)) {
2449193326Sed            CmdArgs.push_back("-lgcrt0.o");
2450193326Sed          } else {
2451193326Sed            CmdArgs.push_back("-lgcrt1.o");
2452193326Sed
2453193326Sed            // darwin_crt2 spec is empty.
2454193326Sed          }
2455193326Sed        } else {
2456193326Sed          if (Args.hasArg(options::OPT_static) ||
2457193326Sed              Args.hasArg(options::OPT_object) ||
2458193326Sed              Args.hasArg(options::OPT_preload)) {
2459193326Sed            CmdArgs.push_back("-lcrt0.o");
2460193326Sed          } else {
2461193326Sed            // Derived from darwin_crt1 spec.
2462203955Srdivacky            if (getDarwinToolChain().isTargetIPhoneOS()) {
2463203955Srdivacky              if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
2464203955Srdivacky                CmdArgs.push_back("-lcrt1.o");
2465203955Srdivacky              else
2466203955Srdivacky                CmdArgs.push_back("-lcrt1.3.1.o");
2467203955Srdivacky            } else {
2468203955Srdivacky              if (getDarwinToolChain().isMacosxVersionLT(10, 5))
2469203955Srdivacky                CmdArgs.push_back("-lcrt1.o");
2470203955Srdivacky              else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
2471203955Srdivacky                CmdArgs.push_back("-lcrt1.10.5.o");
2472203955Srdivacky              else
2473203955Srdivacky                CmdArgs.push_back("-lcrt1.10.6.o");
2474193326Sed
2475203955Srdivacky              // darwin_crt2 spec is empty.
2476203955Srdivacky            }
2477193326Sed          }
2478193326Sed        }
2479193326Sed      }
2480193326Sed    }
2481193326Sed
2482203955Srdivacky    if (!getDarwinToolChain().isTargetIPhoneOS() &&
2483203955Srdivacky        Args.hasArg(options::OPT_shared_libgcc) &&
2484203955Srdivacky        getDarwinToolChain().isMacosxVersionLT(10, 5)) {
2485198092Srdivacky      const char *Str =
2486198092Srdivacky        Args.MakeArgString(getToolChain().GetFilePath(C, "crt3.o"));
2487198092Srdivacky      CmdArgs.push_back(Str);
2488193326Sed    }
2489193326Sed  }
2490193326Sed
2491193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_L);
2492193326Sed
2493193326Sed  if (Args.hasArg(options::OPT_fopenmp))
2494193326Sed    // This is more complicated in gcc...
2495193326Sed    CmdArgs.push_back("-lgomp");
2496193326Sed
2497198092Srdivacky  getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs);
2498193326Sed
2499193326Sed  for (InputInfoList::const_iterator
2500193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2501193326Sed    const InputInfo &II = *it;
2502193326Sed    if (II.isFilename())
2503193326Sed      CmdArgs.push_back(II.getFilename());
2504193326Sed    else
2505193326Sed      II.getInputArg().renderAsInput(Args, CmdArgs);
2506193326Sed  }
2507193326Sed
2508193326Sed  if (LinkingOutput) {
2509193326Sed    CmdArgs.push_back("-arch_multiple");
2510193326Sed    CmdArgs.push_back("-final_output");
2511193326Sed    CmdArgs.push_back(LinkingOutput);
2512193326Sed  }
2513193326Sed
2514193326Sed  if (Args.hasArg(options::OPT_fprofile_arcs) ||
2515193326Sed      Args.hasArg(options::OPT_fprofile_generate) ||
2516193326Sed      Args.hasArg(options::OPT_fcreate_profile) ||
2517193326Sed      Args.hasArg(options::OPT_coverage))
2518193326Sed    CmdArgs.push_back("-lgcov");
2519193326Sed
2520193326Sed  if (Args.hasArg(options::OPT_fnested_functions))
2521193326Sed    CmdArgs.push_back("-allow_stack_execute");
2522193326Sed
2523193326Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
2524193326Sed      !Args.hasArg(options::OPT_nodefaultlibs)) {
2525193326Sed    // FIXME: g++ is more complicated here, it tries to put -lstdc++
2526193326Sed    // before -lm, for example.
2527201361Srdivacky    if (getToolChain().getDriver().CCCIsCXX)
2528193326Sed      CmdArgs.push_back("-lstdc++");
2529193326Sed
2530193326Sed    // link_ssp spec is empty.
2531193326Sed
2532198092Srdivacky    // Let the tool chain choose which runtime library to link.
2533198092Srdivacky    getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
2534193326Sed  }
2535193326Sed
2536193326Sed  if (!Args.hasArg(options::OPT_A) &&
2537193326Sed      !Args.hasArg(options::OPT_nostdlib) &&
2538193326Sed      !Args.hasArg(options::OPT_nostartfiles)) {
2539193326Sed    // endfile_spec is empty.
2540193326Sed  }
2541193326Sed
2542193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
2543193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_F);
2544193326Sed
2545193326Sed  const char *Exec =
2546198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
2547200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2548193326Sed
2549193326Sed  // Find the first non-empty base input (we want to ignore linker
2550193326Sed  // inputs).
2551193326Sed  const char *BaseInput = "";
2552193326Sed  for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
2553193326Sed    if (Inputs[i].getBaseInput()[0] != '\0') {
2554193326Sed      BaseInput = Inputs[i].getBaseInput();
2555193326Sed      break;
2556193326Sed    }
2557193326Sed  }
2558193326Sed
2559193326Sed  // Run dsymutil if we are making an executable in a single step.
2560193326Sed  //
2561193326Sed  // FIXME: Currently we don't want to do this when we are part of a
2562193326Sed  // universal build step, as this would end up creating stray temp
2563193326Sed  // files.
2564193326Sed  if (!LinkingOutput &&
2565193326Sed      Args.getLastArg(options::OPT_g_Group) &&
2566193326Sed      !Args.getLastArg(options::OPT_gstabs) &&
2567193326Sed      !Args.getLastArg(options::OPT_g0)) {
2568193326Sed    // FIXME: This is gross, but matches gcc. The test only considers
2569193326Sed    // the suffix (not the -x type), and then only of the first
2570193326Sed    // source input. Awesome.
2571193326Sed    const char *Suffix = strrchr(BaseInput, '.');
2572193326Sed    if (Suffix && isSourceSuffix(Suffix + 1)) {
2573193326Sed      const char *Exec =
2574198092Srdivacky        Args.MakeArgString(getToolChain().GetProgramPath(C, "dsymutil"));
2575193326Sed      ArgStringList CmdArgs;
2576193326Sed      CmdArgs.push_back(Output.getFilename());
2577200583Srdivacky      C.getJobs().addCommand(new Command(JA, *this, Exec, CmdArgs));
2578193326Sed    }
2579193326Sed  }
2580193326Sed}
2581193326Sed
2582193326Sedvoid darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
2583193326Sed                                Job &Dest, const InputInfo &Output,
2584193326Sed                                const InputInfoList &Inputs,
2585193326Sed                                const ArgList &Args,
2586193326Sed                                const char *LinkingOutput) const {
2587193326Sed  ArgStringList CmdArgs;
2588193326Sed
2589193326Sed  CmdArgs.push_back("-create");
2590193326Sed  assert(Output.isFilename() && "Unexpected lipo output.");
2591193326Sed
2592193326Sed  CmdArgs.push_back("-output");
2593193326Sed  CmdArgs.push_back(Output.getFilename());
2594193326Sed
2595193326Sed  for (InputInfoList::const_iterator
2596193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2597193326Sed    const InputInfo &II = *it;
2598193326Sed    assert(II.isFilename() && "Unexpected lipo input.");
2599193326Sed    CmdArgs.push_back(II.getFilename());
2600193326Sed  }
2601193326Sed  const char *Exec =
2602198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "lipo"));
2603200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2604193326Sed}
2605193326Sed
2606198092Srdivackyvoid auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
2607198893Srdivacky                                      Job &Dest, const InputInfo &Output,
2608198893Srdivacky                                      const InputInfoList &Inputs,
2609198893Srdivacky                                      const ArgList &Args,
2610198893Srdivacky                                      const char *LinkingOutput) const {
2611198092Srdivacky  ArgStringList CmdArgs;
2612198092Srdivacky
2613198092Srdivacky  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
2614198092Srdivacky                       options::OPT_Xassembler);
2615198092Srdivacky
2616198092Srdivacky  CmdArgs.push_back("-o");
2617198092Srdivacky  if (Output.isPipe())
2618198092Srdivacky    CmdArgs.push_back("-");
2619198092Srdivacky  else
2620198092Srdivacky    CmdArgs.push_back(Output.getFilename());
2621198092Srdivacky
2622198092Srdivacky  for (InputInfoList::const_iterator
2623198092Srdivacky         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2624198092Srdivacky    const InputInfo &II = *it;
2625198092Srdivacky    if (II.isPipe())
2626198092Srdivacky      CmdArgs.push_back("-");
2627198092Srdivacky    else
2628198092Srdivacky      CmdArgs.push_back(II.getFilename());
2629198092Srdivacky  }
2630198092Srdivacky
2631198092Srdivacky  const char *Exec =
2632198398Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "gas"));
2633200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2634198092Srdivacky}
2635198092Srdivacky
2636198092Srdivackyvoid auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
2637198893Srdivacky                                  Job &Dest, const InputInfo &Output,
2638198893Srdivacky                                  const InputInfoList &Inputs,
2639198893Srdivacky                                  const ArgList &Args,
2640198893Srdivacky                                  const char *LinkingOutput) const {
2641201361Srdivacky  const Driver &D = getToolChain().getDriver();
2642198092Srdivacky  ArgStringList CmdArgs;
2643198092Srdivacky
2644198092Srdivacky  if ((!Args.hasArg(options::OPT_nostdlib)) &&
2645198893Srdivacky      (!Args.hasArg(options::OPT_shared))) {
2646198092Srdivacky    CmdArgs.push_back("-e");
2647198398Srdivacky    CmdArgs.push_back("_start");
2648198092Srdivacky  }
2649198092Srdivacky
2650198092Srdivacky  if (Args.hasArg(options::OPT_static)) {
2651198092Srdivacky    CmdArgs.push_back("-Bstatic");
2652198398Srdivacky    CmdArgs.push_back("-dn");
2653198092Srdivacky  } else {
2654198398Srdivacky//    CmdArgs.push_back("--eh-frame-hdr");
2655198092Srdivacky    CmdArgs.push_back("-Bdynamic");
2656198092Srdivacky    if (Args.hasArg(options::OPT_shared)) {
2657198092Srdivacky      CmdArgs.push_back("-shared");
2658198092Srdivacky    } else {
2659198398Srdivacky      CmdArgs.push_back("--dynamic-linker");
2660198092Srdivacky      CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
2661198092Srdivacky    }
2662198092Srdivacky  }
2663198092Srdivacky
2664198092Srdivacky  if (Output.isPipe()) {
2665198092Srdivacky    CmdArgs.push_back("-o");
2666198092Srdivacky    CmdArgs.push_back("-");
2667198092Srdivacky  } else if (Output.isFilename()) {
2668198092Srdivacky    CmdArgs.push_back("-o");
2669198092Srdivacky    CmdArgs.push_back(Output.getFilename());
2670198092Srdivacky  } else {
2671198092Srdivacky    assert(Output.isNothing() && "Invalid output.");
2672198092Srdivacky  }
2673198092Srdivacky
2674198092Srdivacky  if (!Args.hasArg(options::OPT_nostdlib) &&
2675198092Srdivacky      !Args.hasArg(options::OPT_nostartfiles)) {
2676198092Srdivacky    if (!Args.hasArg(options::OPT_shared)) {
2677198398Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
2678198398Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
2679198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
2680198092Srdivacky    } else {
2681198398Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
2682198092Srdivacky    }
2683198398Srdivacky    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
2684198092Srdivacky  }
2685198092Srdivacky
2686198893Srdivacky  CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
2687198893Srdivacky                                       + getToolChain().getTripleString()
2688198893Srdivacky                                       + "/4.2.4"));
2689198092Srdivacky
2690198092Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_L);
2691198092Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
2692198092Srdivacky  Args.AddAllArgs(CmdArgs, options::OPT_e);
2693198092Srdivacky
2694198092Srdivacky  for (InputInfoList::const_iterator
2695198092Srdivacky         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2696198092Srdivacky    const InputInfo &II = *it;
2697198092Srdivacky
2698198092Srdivacky    // Don't try to pass LLVM inputs to a generic gcc.
2699198092Srdivacky    if (II.getType() == types::TY_LLVMBC)
2700198092Srdivacky      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
2701198092Srdivacky        << getToolChain().getTripleString();
2702198092Srdivacky
2703198092Srdivacky    if (II.isPipe())
2704198092Srdivacky      CmdArgs.push_back("-");
2705198092Srdivacky    else if (II.isFilename())
2706198092Srdivacky      CmdArgs.push_back(II.getFilename());
2707198092Srdivacky    else
2708198092Srdivacky      II.getInputArg().renderAsInput(Args, CmdArgs);
2709198092Srdivacky  }
2710198092Srdivacky
2711198092Srdivacky  if (!Args.hasArg(options::OPT_nostdlib) &&
2712198092Srdivacky      !Args.hasArg(options::OPT_nodefaultlibs)) {
2713198092Srdivacky    // FIXME: For some reason GCC passes -lgcc before adding
2714198092Srdivacky    // the default system libraries. Just mimic this for now.
2715198092Srdivacky    CmdArgs.push_back("-lgcc");
2716198092Srdivacky
2717198092Srdivacky    if (Args.hasArg(options::OPT_pthread))
2718198092Srdivacky      CmdArgs.push_back("-pthread");
2719198092Srdivacky    if (!Args.hasArg(options::OPT_shared))
2720198092Srdivacky      CmdArgs.push_back("-lc");
2721198092Srdivacky    CmdArgs.push_back("-lgcc");
2722198092Srdivacky  }
2723198092Srdivacky
2724198092Srdivacky  if (!Args.hasArg(options::OPT_nostdlib) &&
2725198092Srdivacky      !Args.hasArg(options::OPT_nostartfiles)) {
2726198092Srdivacky    if (!Args.hasArg(options::OPT_shared))
2727198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
2728198398Srdivacky//    else
2729198398Srdivacky//      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
2730198092Srdivacky  }
2731198092Srdivacky
2732198092Srdivacky  const char *Exec =
2733198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
2734200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2735198092Srdivacky}
2736198092Srdivacky
2737195341Sedvoid openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
2738195341Sed                                     Job &Dest, const InputInfo &Output,
2739195341Sed                                     const InputInfoList &Inputs,
2740195341Sed                                     const ArgList &Args,
2741198092Srdivacky                                     const char *LinkingOutput) const {
2742195341Sed  ArgStringList CmdArgs;
2743193326Sed
2744195341Sed  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
2745195341Sed                       options::OPT_Xassembler);
2746195341Sed
2747195341Sed  CmdArgs.push_back("-o");
2748195341Sed  if (Output.isPipe())
2749195341Sed    CmdArgs.push_back("-");
2750195341Sed  else
2751195341Sed    CmdArgs.push_back(Output.getFilename());
2752195341Sed
2753195341Sed  for (InputInfoList::const_iterator
2754195341Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2755195341Sed    const InputInfo &II = *it;
2756195341Sed    if (II.isPipe())
2757195341Sed      CmdArgs.push_back("-");
2758195341Sed    else
2759195341Sed      CmdArgs.push_back(II.getFilename());
2760195341Sed  }
2761195341Sed
2762195341Sed  const char *Exec =
2763198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
2764200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2765195341Sed}
2766195341Sed
2767195341Sedvoid openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
2768195341Sed                                 Job &Dest, const InputInfo &Output,
2769195341Sed                                 const InputInfoList &Inputs,
2770195341Sed                                 const ArgList &Args,
2771195341Sed                                 const char *LinkingOutput) const {
2772201361Srdivacky  const Driver &D = getToolChain().getDriver();
2773195341Sed  ArgStringList CmdArgs;
2774195341Sed
2775198092Srdivacky  if ((!Args.hasArg(options::OPT_nostdlib)) &&
2776198893Srdivacky      (!Args.hasArg(options::OPT_shared))) {
2777198092Srdivacky    CmdArgs.push_back("-e");
2778198092Srdivacky    CmdArgs.push_back("__start");
2779198092Srdivacky  }
2780198092Srdivacky
2781195341Sed  if (Args.hasArg(options::OPT_static)) {
2782195341Sed    CmdArgs.push_back("-Bstatic");
2783195341Sed  } else {
2784195341Sed    CmdArgs.push_back("--eh-frame-hdr");
2785198092Srdivacky    CmdArgs.push_back("-Bdynamic");
2786195341Sed    if (Args.hasArg(options::OPT_shared)) {
2787198092Srdivacky      CmdArgs.push_back("-shared");
2788195341Sed    } else {
2789195341Sed      CmdArgs.push_back("-dynamic-linker");
2790195341Sed      CmdArgs.push_back("/usr/libexec/ld.so");
2791195341Sed    }
2792195341Sed  }
2793195341Sed
2794195341Sed  if (Output.isPipe()) {
2795195341Sed    CmdArgs.push_back("-o");
2796195341Sed    CmdArgs.push_back("-");
2797195341Sed  } else if (Output.isFilename()) {
2798195341Sed    CmdArgs.push_back("-o");
2799195341Sed    CmdArgs.push_back(Output.getFilename());
2800195341Sed  } else {
2801195341Sed    assert(Output.isNothing() && "Invalid output.");
2802195341Sed  }
2803195341Sed
2804195341Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
2805195341Sed      !Args.hasArg(options::OPT_nostartfiles)) {
2806195341Sed    if (!Args.hasArg(options::OPT_shared)) {
2807198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o")));
2808198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
2809195341Sed    } else {
2810198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
2811195341Sed    }
2812195341Sed  }
2813195341Sed
2814198893Srdivacky  std::string Triple = getToolChain().getTripleString();
2815198893Srdivacky  if (Triple.substr(0, 6) == "x86_64")
2816198893Srdivacky    Triple.replace(0, 6, "amd64");
2817198893Srdivacky  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
2818198893Srdivacky                                       "/3.3.5"));
2819198092Srdivacky
2820195341Sed  Args.AddAllArgs(CmdArgs, options::OPT_L);
2821195341Sed  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
2822195341Sed  Args.AddAllArgs(CmdArgs, options::OPT_e);
2823195341Sed
2824195341Sed  for (InputInfoList::const_iterator
2825195341Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2826195341Sed    const InputInfo &II = *it;
2827195341Sed
2828195341Sed    // Don't try to pass LLVM inputs to a generic gcc.
2829195341Sed    if (II.getType() == types::TY_LLVMBC)
2830195341Sed      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
2831198092Srdivacky        << getToolChain().getTripleString();
2832195341Sed
2833195341Sed    if (II.isPipe())
2834195341Sed      CmdArgs.push_back("-");
2835195341Sed    else if (II.isFilename())
2836195341Sed      CmdArgs.push_back(II.getFilename());
2837195341Sed    else
2838195341Sed      II.getInputArg().renderAsInput(Args, CmdArgs);
2839195341Sed  }
2840195341Sed
2841195341Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
2842195341Sed      !Args.hasArg(options::OPT_nodefaultlibs)) {
2843198092Srdivacky    // FIXME: For some reason GCC passes -lgcc before adding
2844198092Srdivacky    // the default system libraries. Just mimic this for now.
2845198092Srdivacky    CmdArgs.push_back("-lgcc");
2846195341Sed
2847195341Sed    if (Args.hasArg(options::OPT_pthread))
2848195341Sed      CmdArgs.push_back("-pthread");
2849198092Srdivacky    if (!Args.hasArg(options::OPT_shared))
2850198092Srdivacky      CmdArgs.push_back("-lc");
2851198092Srdivacky    CmdArgs.push_back("-lgcc");
2852195341Sed  }
2853195341Sed
2854195341Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
2855195341Sed      !Args.hasArg(options::OPT_nostartfiles)) {
2856195341Sed    if (!Args.hasArg(options::OPT_shared))
2857198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
2858195341Sed    else
2859198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
2860195341Sed  }
2861195341Sed
2862195341Sed  const char *Exec =
2863198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
2864200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2865195341Sed}
2866195341Sed
2867193326Sedvoid freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
2868193326Sed                                     Job &Dest, const InputInfo &Output,
2869193326Sed                                     const InputInfoList &Inputs,
2870193326Sed                                     const ArgList &Args,
2871198092Srdivacky                                     const char *LinkingOutput) const {
2872193326Sed  ArgStringList CmdArgs;
2873193326Sed
2874193326Sed  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
2875193326Sed  // instruct as in the base system to assemble 32-bit code.
2876193326Sed  if (getToolChain().getArchName() == "i386")
2877193326Sed    CmdArgs.push_back("--32");
2878193326Sed
2879204643Srdivacky
2880204643Srdivacky  // Set byte order explicitly
2881204643Srdivacky  if (getToolChain().getArchName() == "mips")
2882204643Srdivacky    CmdArgs.push_back("-EB");
2883204643Srdivacky  else if (getToolChain().getArchName() == "mipsel")
2884204643Srdivacky    CmdArgs.push_back("-EL");
2885204643Srdivacky
2886193326Sed  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
2887193326Sed                       options::OPT_Xassembler);
2888193326Sed
2889193326Sed  CmdArgs.push_back("-o");
2890193326Sed  if (Output.isPipe())
2891193326Sed    CmdArgs.push_back("-");
2892193326Sed  else
2893193326Sed    CmdArgs.push_back(Output.getFilename());
2894193326Sed
2895193326Sed  for (InputInfoList::const_iterator
2896193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2897193326Sed    const InputInfo &II = *it;
2898193326Sed    if (II.isPipe())
2899193326Sed      CmdArgs.push_back("-");
2900193326Sed    else
2901193326Sed      CmdArgs.push_back(II.getFilename());
2902193326Sed  }
2903193326Sed
2904193326Sed  const char *Exec =
2905198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
2906200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
2907193326Sed}
2908193326Sed
2909193326Sedvoid freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
2910193326Sed                                 Job &Dest, const InputInfo &Output,
2911193326Sed                                 const InputInfoList &Inputs,
2912193326Sed                                 const ArgList &Args,
2913193326Sed                                 const char *LinkingOutput) const {
2914201361Srdivacky  const Driver &D = getToolChain().getDriver();
2915193326Sed  ArgStringList CmdArgs;
2916193326Sed
2917193326Sed  if (Args.hasArg(options::OPT_static)) {
2918193326Sed    CmdArgs.push_back("-Bstatic");
2919193326Sed  } else {
2920193326Sed    CmdArgs.push_back("--eh-frame-hdr");
2921193326Sed    if (Args.hasArg(options::OPT_shared)) {
2922193326Sed      CmdArgs.push_back("-Bshareable");
2923193326Sed    } else {
2924193326Sed      CmdArgs.push_back("-dynamic-linker");
2925193326Sed      CmdArgs.push_back("/libexec/ld-elf.so.1");
2926193326Sed    }
2927193326Sed  }
2928193326Sed
2929193326Sed  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
2930193326Sed  // instruct ld in the base system to link 32-bit code.
2931193326Sed  if (getToolChain().getArchName() == "i386") {
2932193326Sed    CmdArgs.push_back("-m");
2933193326Sed    CmdArgs.push_back("elf_i386_fbsd");
2934193326Sed  }
2935193326Sed
2936193326Sed  if (Output.isPipe()) {
2937193326Sed    CmdArgs.push_back("-o");
2938193326Sed    CmdArgs.push_back("-");
2939193326Sed  } else if (Output.isFilename()) {
2940193326Sed    CmdArgs.push_back("-o");
2941193326Sed    CmdArgs.push_back(Output.getFilename());
2942193326Sed  } else {
2943193326Sed    assert(Output.isNothing() && "Invalid output.");
2944193326Sed  }
2945193326Sed
2946193326Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
2947193326Sed      !Args.hasArg(options::OPT_nostartfiles)) {
2948193326Sed    if (!Args.hasArg(options::OPT_shared)) {
2949198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
2950198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
2951198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
2952193326Sed    } else {
2953198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
2954198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
2955193326Sed    }
2956193326Sed  }
2957193326Sed
2958193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_L);
2959193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
2960193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_e);
2961193326Sed
2962193326Sed  for (InputInfoList::const_iterator
2963193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
2964193326Sed    const InputInfo &II = *it;
2965193326Sed
2966193326Sed    // Don't try to pass LLVM inputs to a generic gcc.
2967193326Sed    if (II.getType() == types::TY_LLVMBC)
2968193326Sed      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
2969198092Srdivacky        << getToolChain().getTripleString();
2970193326Sed
2971193326Sed    if (II.isPipe())
2972193326Sed      CmdArgs.push_back("-");
2973193326Sed    else if (II.isFilename())
2974193326Sed      CmdArgs.push_back(II.getFilename());
2975193326Sed    else
2976193326Sed      II.getInputArg().renderAsInput(Args, CmdArgs);
2977193326Sed  }
2978193326Sed
2979193326Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
2980193326Sed      !Args.hasArg(options::OPT_nodefaultlibs)) {
2981204643Srdivacky    if (D.CCCIsCXX) {
2982204643Srdivacky      CmdArgs.push_back("-lstdc++");
2983204643Srdivacky      CmdArgs.push_back("-lm");
2984204643Srdivacky    }
2985193326Sed    // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
2986193326Sed    // the default system libraries. Just mimic this for now.
2987193326Sed    CmdArgs.push_back("-lgcc");
2988193326Sed    if (Args.hasArg(options::OPT_static)) {
2989193326Sed      CmdArgs.push_back("-lgcc_eh");
2990193326Sed    } else {
2991193326Sed      CmdArgs.push_back("--as-needed");
2992193326Sed      CmdArgs.push_back("-lgcc_s");
2993193326Sed      CmdArgs.push_back("--no-as-needed");
2994193326Sed    }
2995193326Sed
2996193326Sed    if (Args.hasArg(options::OPT_pthread))
2997193326Sed      CmdArgs.push_back("-lpthread");
2998193326Sed    CmdArgs.push_back("-lc");
2999193326Sed
3000193326Sed    CmdArgs.push_back("-lgcc");
3001193326Sed    if (Args.hasArg(options::OPT_static)) {
3002193326Sed      CmdArgs.push_back("-lgcc_eh");
3003193326Sed    } else {
3004193326Sed      CmdArgs.push_back("--as-needed");
3005193326Sed      CmdArgs.push_back("-lgcc_s");
3006193326Sed      CmdArgs.push_back("--no-as-needed");
3007193326Sed    }
3008193326Sed  }
3009193326Sed
3010193326Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
3011193326Sed      !Args.hasArg(options::OPT_nostartfiles)) {
3012193326Sed    if (!Args.hasArg(options::OPT_shared))
3013198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
3014193326Sed    else
3015198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
3016198092Srdivacky    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
3017193326Sed  }
3018193326Sed
3019193326Sed  const char *Exec =
3020198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
3021200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
3022193326Sed}
3023193326Sed
3024193326Sed/// DragonFly Tools
3025193326Sed
3026193326Sed// For now, DragonFly Assemble does just about the same as for
3027193326Sed// FreeBSD, but this may change soon.
3028193326Sedvoid dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
3029198893Srdivacky                                       Job &Dest, const InputInfo &Output,
3030198893Srdivacky                                       const InputInfoList &Inputs,
3031198893Srdivacky                                       const ArgList &Args,
3032198893Srdivacky                                       const char *LinkingOutput) const {
3033193326Sed  ArgStringList CmdArgs;
3034193326Sed
3035193326Sed  // When building 32-bit code on DragonFly/pc64, we have to explicitly
3036193326Sed  // instruct as in the base system to assemble 32-bit code.
3037193326Sed  if (getToolChain().getArchName() == "i386")
3038193326Sed    CmdArgs.push_back("--32");
3039193326Sed
3040193326Sed  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
3041193326Sed                       options::OPT_Xassembler);
3042193326Sed
3043193326Sed  CmdArgs.push_back("-o");
3044193326Sed  if (Output.isPipe())
3045193326Sed    CmdArgs.push_back("-");
3046193326Sed  else
3047193326Sed    CmdArgs.push_back(Output.getFilename());
3048193326Sed
3049193326Sed  for (InputInfoList::const_iterator
3050193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
3051193326Sed    const InputInfo &II = *it;
3052193326Sed    if (II.isPipe())
3053193326Sed      CmdArgs.push_back("-");
3054193326Sed    else
3055193326Sed      CmdArgs.push_back(II.getFilename());
3056193326Sed  }
3057193326Sed
3058193326Sed  const char *Exec =
3059198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
3060200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
3061193326Sed}
3062193326Sed
3063193326Sedvoid dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
3064193326Sed                                 Job &Dest, const InputInfo &Output,
3065193326Sed                                 const InputInfoList &Inputs,
3066193326Sed                                 const ArgList &Args,
3067193326Sed                                 const char *LinkingOutput) const {
3068201361Srdivacky  const Driver &D = getToolChain().getDriver();
3069193326Sed  ArgStringList CmdArgs;
3070193326Sed
3071193326Sed  if (Args.hasArg(options::OPT_static)) {
3072193326Sed    CmdArgs.push_back("-Bstatic");
3073193326Sed  } else {
3074193326Sed    if (Args.hasArg(options::OPT_shared))
3075193326Sed      CmdArgs.push_back("-Bshareable");
3076193326Sed    else {
3077193326Sed      CmdArgs.push_back("-dynamic-linker");
3078193326Sed      CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
3079193326Sed    }
3080193326Sed  }
3081193326Sed
3082193326Sed  // When building 32-bit code on DragonFly/pc64, we have to explicitly
3083193326Sed  // instruct ld in the base system to link 32-bit code.
3084193326Sed  if (getToolChain().getArchName() == "i386") {
3085193326Sed    CmdArgs.push_back("-m");
3086193326Sed    CmdArgs.push_back("elf_i386");
3087193326Sed  }
3088193326Sed
3089193326Sed  if (Output.isPipe()) {
3090193326Sed    CmdArgs.push_back("-o");
3091193326Sed    CmdArgs.push_back("-");
3092193326Sed  } else if (Output.isFilename()) {
3093193326Sed    CmdArgs.push_back("-o");
3094193326Sed    CmdArgs.push_back(Output.getFilename());
3095193326Sed  } else {
3096193326Sed    assert(Output.isNothing() && "Invalid output.");
3097193326Sed  }
3098193326Sed
3099193326Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
3100193326Sed      !Args.hasArg(options::OPT_nostartfiles)) {
3101193326Sed    if (!Args.hasArg(options::OPT_shared)) {
3102198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
3103198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
3104198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
3105193326Sed    } else {
3106198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
3107198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
3108193326Sed    }
3109193326Sed  }
3110193326Sed
3111193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_L);
3112193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
3113193326Sed  Args.AddAllArgs(CmdArgs, options::OPT_e);
3114193326Sed
3115193326Sed  for (InputInfoList::const_iterator
3116193326Sed         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
3117193326Sed    const InputInfo &II = *it;
3118193326Sed
3119193326Sed    // Don't try to pass LLVM inputs to a generic gcc.
3120193326Sed    if (II.getType() == types::TY_LLVMBC)
3121193326Sed      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
3122198092Srdivacky        << getToolChain().getTripleString();
3123193326Sed
3124193326Sed    if (II.isPipe())
3125193326Sed      CmdArgs.push_back("-");
3126193326Sed    else if (II.isFilename())
3127193326Sed      CmdArgs.push_back(II.getFilename());
3128193326Sed    else
3129193326Sed      II.getInputArg().renderAsInput(Args, CmdArgs);
3130193326Sed  }
3131193326Sed
3132193326Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
3133193326Sed      !Args.hasArg(options::OPT_nodefaultlibs)) {
3134193326Sed    // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
3135193326Sed    //         rpaths
3136193326Sed    CmdArgs.push_back("-L/usr/lib/gcc41");
3137193326Sed
3138193326Sed    if (!Args.hasArg(options::OPT_static)) {
3139193326Sed      CmdArgs.push_back("-rpath");
3140193326Sed      CmdArgs.push_back("/usr/lib/gcc41");
3141193326Sed
3142193326Sed      CmdArgs.push_back("-rpath-link");
3143193326Sed      CmdArgs.push_back("/usr/lib/gcc41");
3144193326Sed
3145193326Sed      CmdArgs.push_back("-rpath");
3146193326Sed      CmdArgs.push_back("/usr/lib");
3147193326Sed
3148193326Sed      CmdArgs.push_back("-rpath-link");
3149193326Sed      CmdArgs.push_back("/usr/lib");
3150193326Sed    }
3151193326Sed
3152193326Sed    if (Args.hasArg(options::OPT_shared)) {
3153193326Sed      CmdArgs.push_back("-lgcc_pic");
3154193326Sed    } else {
3155193326Sed      CmdArgs.push_back("-lgcc");
3156193326Sed    }
3157193326Sed
3158193326Sed
3159193326Sed    if (Args.hasArg(options::OPT_pthread))
3160198893Srdivacky      CmdArgs.push_back("-lpthread");
3161193326Sed
3162193326Sed    if (!Args.hasArg(options::OPT_nolibc)) {
3163193326Sed      CmdArgs.push_back("-lc");
3164193326Sed    }
3165193326Sed
3166193326Sed    if (Args.hasArg(options::OPT_shared)) {
3167193326Sed      CmdArgs.push_back("-lgcc_pic");
3168193326Sed    } else {
3169193326Sed      CmdArgs.push_back("-lgcc");
3170193326Sed    }
3171193326Sed  }
3172193326Sed
3173193326Sed  if (!Args.hasArg(options::OPT_nostdlib) &&
3174193326Sed      !Args.hasArg(options::OPT_nostartfiles)) {
3175193326Sed    if (!Args.hasArg(options::OPT_shared))
3176198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
3177193326Sed    else
3178198092Srdivacky      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
3179198092Srdivacky    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
3180193326Sed  }
3181193326Sed
3182193326Sed  const char *Exec =
3183198092Srdivacky    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
3184200583Srdivacky  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
3185193326Sed}
3186