#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
#define LLVM_CLANG_BASIC_TARGETINFO_H
+// FIXME: Daniel isn't smart enough to use a prototype for this.
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <vector>
/// options.
virtual void getDefaultLangOptions(LangOptions &Opts) {}
- /// HandleTargetFeatures - Handle target-specific options like -mattr=+sse2
- /// and friends. An array of arguments is passed in: if they are all valid,
- /// this should handle them and return -1. If there is an error, the index of
- /// the invalid argument should be returned along with an optional error
- /// string.
- ///
- /// Note that the driver should have already consolidated all the
- /// target-feature settings and passed them to us in the -mattr list. The
- /// -mattr list is treated by the code generator as a diff against the -mcpu
- /// setting, but the driver should pass all enabled options as "+" settings.
- /// This means that the target should only look at + settings.
- virtual int HandleTargetFeatures(std::string *StrArray, unsigned NumStrs,
- std::string &ErrorReason) {
- if (NumStrs == 0)
- return -1;
- return 0;
+ /// getDefaultFeatures - Get the default set of target features for
+ /// the \args CPU; this should include all legal feature strings on
+ /// the target.
+ virtual void getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) {
+ }
+
+ /// HandleTargetOptions - Perform initialization based on the user
+ /// configured set of features.
+ virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features) {
}
// getRegParmMax - Returns maximal number of args passed in registers.
OPTION("<i group>", i_Group, Group, INVALID, INVALID, "", 0, 0, 0)
OPTION("<clang i group>", clang_i_Group, Group, i_Group, INVALID, "", 0, 0, 0)
OPTION("<m group>", m_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<m x86 features group>", m_x86_Features_Group, Group, INVALID, INVALID, "", 0, 0, 0)
OPTION("<u group>", u_Group, Group, INVALID, INVALID, "", 0, 0, 0)
OPTION("<pedantic group>", pedantic_Group, Group, INVALID, INVALID, "", 0, 0, 0)
OPTION("-keep_private_externs", keep__private__externs, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-l", l, JoinedOrSeparate, INVALID, INVALID, "l", 0, 0, 0)
OPTION("-m32", m32, Flag, m_Group, INVALID, "d", 0, 0, 0)
-OPTION("-m3dnowa", m3dnowa, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-m3dnow", m3dnow, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-m3dnowa", m3dnowa, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-m3dnow", m3dnow, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
OPTION("-m64", m64, Flag, m_Group, INVALID, "d", 0, 0, 0)
+OPTION("-march=", march_EQ, Joined, m_Group, INVALID, "d", 0, 0, 0)
OPTION("-mconstant-cfstrings", mconstant_cfstrings, Flag, clang_ignored_m_Group, INVALID, "", 0, 0, 0)
OPTION("-mdynamic-no-pic", mdynamic_no_pic, Joined, m_Group, INVALID, "q", 0, 0, 0)
OPTION("-mfix-and-continue", mfix_and_continue, Flag, clang_ignored_m_Group, INVALID, "", 0, 0, 0)
OPTION("-miphoneos-version-min=", miphoneos_version_min_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
OPTION("-mkernel", mkernel, Flag, m_Group, INVALID, "", 0, 0, 0)
OPTION("-mmacosx-version-min=", mmacosx_version_min_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mmmx", mmmx, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-3dnowa", mno_3dnowa, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-3dnow", mno_3dnow, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mmmx", mmmx, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-3dnowa", mno_3dnowa, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-3dnow", mno_3dnow, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
OPTION("-mno-constant-cfstrings", mno_constant_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-mmx", mno_mmx, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-mmx", mno_mmx, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
OPTION("-mno-pascal-strings", mno_pascal_strings, Flag, m_Group, INVALID, "", 0, 0, 0)
OPTION("-mno-red-zone", mno_red_zone, Flag, m_Group, INVALID, "", 0, 0, 0)
OPTION("-mno-soft-float", mno_soft_float, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse2", mno_sse2, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse3", mno_sse3, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse41", mno_sse41, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse42", mno_sse42, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse4a", mno_sse4a, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse", mno_sse, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-ssse3", mno_ssse3, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse2", mno_sse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse3", mno_sse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse41", mno_sse41, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse42", mno_sse42, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse4a", mno_sse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse", mno_sse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-ssse3", mno_ssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
OPTION("-mno-warn-nonportable-cfstrings", mno_warn_nonportable_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0)
OPTION("-mpascal-strings", mpascal_strings, Flag, m_Group, INVALID, "", 0, 0, 0)
OPTION("-mred-zone", mred_zone, Flag, m_Group, INVALID, "", 0, 0, 0)
OPTION("-msoft-float", msoft_float, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse2", msse2, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse3", msse3, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse41", msse41, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse42", msse42, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse4a", msse4a, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse", msse, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mssse3", mssse3, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse2", msse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse3", msse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse41", msse41, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse42", msse42, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse4a", msse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse", msse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mssse3", mssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
OPTION("-mtune=", mtune_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
OPTION("-multi_module", multi__module, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-multiply_defined_unused", multiply__defined__unused, Separate, INVALID, INVALID, "", 0, 0, 0)
} SSELevel;
public:
X86TargetInfo(const std::string& triple)
- : TargetInfo(triple),
- // FIXME: hard coding to SSE2 for now. This should change to NoMMXSSE so
- // that the driver controls this.
- SSELevel(SSE2) {
+ : TargetInfo(triple), SSELevel(NoMMXSSE) {
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const;
- virtual int HandleTargetFeatures(std::string *StrArray, unsigned NumStrs,
- std::string &ErrorReason);
+ virtual void getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features);
+ virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features);
};
-/// HandleTargetOptions - Handle target-specific options like -msse2 and
-/// friends. An array of arguments is passed in: if they are all valid, this
-/// should handle them and return -1. If there is an error, the index of the
-/// invalid argument should be returned along with an optional error string.
-int X86TargetInfo::HandleTargetFeatures(std::string *StrArray, unsigned NumStrs,
- std::string &ErrorReason) {
- for (unsigned i = 0; i != NumStrs; ++i) {
- const std::string &Feature = StrArray[i];
- if (Feature.size() < 2) return i;
- // Ignore explicitly disabled features.
- if (Feature[0] == '-') continue;
-
- // Feature strings are of the form "+feature".
- if (Feature[0] != '+') return i;
-
- // The set of supported subtarget features is defined in
- // lib/Target/X86/X86.td. Here we recognize and map onto our internal
- // state.
- if (Feature == "+mmx")
- SSELevel = std::max(SSELevel, MMX);
- else if (Feature == "+sse")
- SSELevel = std::max(SSELevel, SSE1);
- else if (Feature == "+sse2")
- SSELevel = std::max(SSELevel, SSE2);
- else if (Feature == "+sse3")
- SSELevel = std::max(SSELevel, SSE3);
- else if (Feature == "+ssse3")
- SSELevel = std::max(SSELevel, SSSE3);
- else if (Feature == "+sse41")
- SSELevel = std::max(SSELevel, SSE41);
- else if (Feature == "+sse42")
- SSELevel = std::max(SSELevel, SSE42);
- else if (Feature == "+64bit" || Feature == "+slow-bt-mem")
- // Ignore these features.
- continue;
- else
- return i;
- }
- return -1;
+void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) {
+ // FIXME: This should not be here.
+ Features["3dnow"] = false;
+ Features["3dnowa"] = false;
+ Features["mmx"] = false;
+ Features["sse"] = false;
+ Features["sse2"] = false;
+ Features["sse3"] = false;
+ Features["ssse3"] = false;
+ Features["sse41"] = false;
+ Features["sse42"] = false;
+
+ // LLVM does not currently recognize this.
+ // Features["sse4a"] = false;
+
+ // FIXME: This *really* should not be here.
+
+ // X86_64 always has SSE2.
+ if (PointerWidth == 64)
+ Features["sse2"] = Features["sse"] = Features["mmx"] = true;
+
+ // FIXME: LLVM says core2 has SSSE3, but gcc doesn't define
+ // __SSSE3__ with it? What else is going on here?
+ if (CPU == "core2")
+ Features["ssse3"] = Features["sse3"] = Features["sse2"] = Features["sse"] =
+ Features["mmx"] = true;
+ else if (CPU == "pentium4")
+ Features["sse2"] = Features["sse"] = Features["mmx"] = true;
+}
+
+/// HandleTargetOptions - Perform initialization based on the user
+/// configured set of features.
+void X86TargetInfo::HandleTargetFeatures(const llvm::StringMap<bool>&Features) {
+ if (Features.lookup("sse42"))
+ SSELevel = SSE42;
+ else if (Features.lookup("sse41"))
+ SSELevel = SSE41;
+ else if (Features.lookup("ssse3"))
+ SSELevel = SSSE3;
+ else if (Features.lookup("sse3"))
+ SSELevel = SSE3;
+ else if (Features.lookup("sse2"))
+ SSELevel = SSE2;
+ else if (Features.lookup("sse"))
+ SSELevel = SSE1;
+ else if (Features.lookup("mmx"))
+ SSELevel = MMX;
}
/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines
using namespace clang::driver;
using namespace clang::driver::tools;
+static const char *MakeFormattedString(const ArgList &Args,
+ const llvm::format_object_base &Fmt) {
+ std::string Str;
+ llvm::raw_string_ostream(Str) << Fmt;
+ return Args.MakeArgString(Str.c_str());
+}
+
void Clang::AddPreprocessingOptions(const Driver &D,
const ArgList &Args,
ArgStringList &CmdArgs,
false))
CmdArgs.push_back("--soft-float");
- // FIXME: Need target hooks.
- if (memcmp(getToolChain().getPlatform().c_str(), "darwin", 6) == 0) {
- if (getToolChain().getArchName() == "x86_64")
- CmdArgs.push_back("--mcpu=core2");
- else if (getToolChain().getArchName() == "i386")
- CmdArgs.push_back("--mcpu=yonah");
- }
-
- // FIXME: Ignores ordering. Also, we need to find a realistic
- // solution for this.
- static const struct {
- options::ID Pos, Neg;
- const char *Name;
- } FeatureOptions[] = {
- { options::OPT_mmmx, options::OPT_mno_mmx, "mmx" },
- { options::OPT_msse, options::OPT_mno_sse, "sse" },
- { options::OPT_msse2, options::OPT_mno_sse2, "sse2" },
- { options::OPT_msse3, options::OPT_mno_sse3, "sse3" },
- { options::OPT_mssse3, options::OPT_mno_ssse3, "ssse3" },
- { options::OPT_msse41, options::OPT_mno_sse41, "sse41" },
- { options::OPT_msse42, options::OPT_mno_sse42, "sse42" },
- { options::OPT_msse4a, options::OPT_mno_sse4a, "sse4a" },
- { options::OPT_m3dnow, options::OPT_mno_3dnow, "3dnow" },
- { options::OPT_m3dnowa, options::OPT_mno_3dnowa, "3dnowa" }
- };
- const unsigned NumFeatureOptions =
- sizeof(FeatureOptions)/sizeof(FeatureOptions[0]);
-
- // FIXME: Avoid std::string
- std::string Attrs;
- for (unsigned i=0; i < NumFeatureOptions; ++i) {
- if (Args.hasArg(FeatureOptions[i].Pos)) {
- if (!Attrs.empty())
- Attrs += ',';
- Attrs += '+';
- Attrs += FeatureOptions[i].Name;
- } else if (Args.hasArg(FeatureOptions[i].Neg)) {
- if (!Attrs.empty())
- Attrs += ',';
- Attrs += '-';
- Attrs += FeatureOptions[i].Name;
+ // FIXME: Handle -mtune=.
+ (void) Args.hasArg(options::OPT_mtune_EQ);
+
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // FIXME: We made need some translation here from the options gcc
+ // takes to names the LLVM backend understand?
+ CmdArgs.push_back("-mcpu");
+ CmdArgs.push_back(A->getValue(Args));
+ } else {
+ // Select default CPU.
+
+ // FIXME: Need target hooks.
+ if (memcmp(getToolChain().getOS().c_str(), "darwin", 6) == 0) {
+ if (getToolChain().getArchName() == "x86_64")
+ CmdArgs.push_back("--mcpu=core2");
+ else if (getToolChain().getArchName() == "i386")
+ CmdArgs.push_back("--mcpu=pentium4");
}
}
- if (!Attrs.empty()) {
- CmdArgs.push_back("--mattr");
- CmdArgs.push_back(Args.MakeArgString(Attrs.c_str()));
+
+ // FIXME: Use iterator.
+ for (ArgList::const_iterator
+ it = Args.begin(), ie = Args.end(); it != ie; ++it) {
+ const Arg *A = *it;
+ if (A->getOption().matches(options::OPT_m_x86_Features_Group)) {
+ const char *Name = A->getOption().getName();
+
+ // Skip over "-m".
+ assert(Name[0] == '-' && Name[1] == 'm' && "Invalid feature name.");
+ Name += 2;
+
+ bool IsNegative = memcmp(Name, "no-", 3) == 0;
+ if (IsNegative)
+ Name += 3;
+
+ A->claim();
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back(MakeFormattedString(Args,
+ llvm::format("%c%s",
+ IsNegative ? '-' : '+',
+ Name)));
+ }
}
if (Args.hasFlag(options::OPT_fmath_errno,
Dest.addCommand(new Command(Exec, CmdArgs));
}
-static const char *MakeFormattedString(const ArgList &Args,
- const llvm::format_object_base &Fmt) {
- std::string Str;
- llvm::raw_string_ostream(Str) << Fmt;
- return Args.MakeArgString(Str.c_str());
-}
-
/// Helper routine for seeing if we should use dsymutil; this is a
/// gcc compatible hack, we should remove it and use the input
/// type information.
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -mcpu=pentium4 -emit-llvm -o %t %s &&
// RUN: grep define %t | count 1 &&
-// RUN: clang-cc -triple i386-apple-darwin9 -g -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -mcpu=pentium4 -g -emit-llvm -o %t %s &&
// RUN: grep define %t | count 1
#include <mmintrin.h>
// RUN: clang -ccc-host-triple i386-apple-darwin9 -### --analyze -o /dev/null %s -msse 2> %t.log &&
// RUN: grep '"-analyze"' %t.log &&
// RUN: grep '"--fmath-errno=0"' %t.log &&
-// RUN: grep '"--mattr" "+sse"' %t.log &&
+// RUN: grep '"-target-feature" "+sse"' %t.log &&
// RUN: grep '"-mmacosx-version-min=10.5.0"' %t.log
// RUN: grep '"-Os"' %t.log &&
// RUN: grep '"-o" .*clang-translation\.c\.out\.tmp\.s' %t.log &&
// RUN: grep '"--asm-verbose"' %t.log &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S %s -o %t.s 2> %t.log
+// RUN: grep '"--mcpu=pentium4"' %t.log &&
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -o %t.s 2> %t.log
+// RUN: grep '"--mcpu=core2"' %t.log &&
// RUN: true
-// RUN: clang-cc -emit-pth -o %t %s &&
-// RUN: clang-cc -token-cache %t %s &&
-// RUN: clang-cc -token-cache %t %s -E %s -o /dev/null
+// RUN: clang-cc -mcpu=pentium4 -emit-pth -o %t %s &&
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s &&
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s -E %s -o /dev/null
#ifdef __APPLE__
#include <Carbon/Carbon.h>
#endif
-// RUN: clang-cc %s -print-stats &&
-// RUN: clang-cc %s -disable-free
+// RUN: clang-cc -mcpu=pentium4 %s -print-stats
#ifdef __APPLE__
#include <Carbon/Carbon.h>
#endif
-// RUN: clang-cc %s -fsyntax-only -print-stats
+// RUN: clang-cc -mcpu=pentium4 %s -fsyntax-only -print-stats
#ifdef __APPLE__
#include <Carbon/Carbon.h>
#endif
-// RUN: clang-cc -emit-pth -o %t %s &&
-// RUN: clang-cc -token-cache %t %s &&
-// RUN: clang-cc -token-cache %t %s -E %s -o /dev/null
+// RUN: clang-cc -mcpu=pentium4 -emit-pth -o %t %s &&
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s &&
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s -E %s -o /dev/null
#ifdef __APPLE__
#include <Cocoa/Cocoa.h>
#endif
-// RUN: clang-cc %s -print-stats &&
-// RUN: clang-cc %s -disable-free
+// RUN: clang-cc -mcpu=pentium4 %s -print-stats
#ifdef __APPLE__
#include <Cocoa/Cocoa.h>
#endif
-// RUN: clang-cc %s -print-stats
+// RUN: clang-cc -mcpu=pentium4 %s -print-stats
#ifdef __APPLE__
#include <Cocoa/Cocoa.h>
#endif
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h"
static llvm::cl::opt<bool>
Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
-static llvm::cl::list<std::string>
-TargetFeatures("mattr", llvm::cl::CommaSeparated,
- llvm::cl::desc("Target specific attributes (-mattr=help for details)"));
-
static llvm::cl::opt<unsigned>
TemplateDepth("ftemplate-depth", llvm::cl::init(99),
llvm::cl::desc("Maximum depth of recursive template "
StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
- TargetInfo *Target) {
+ TargetInfo *Target,
+ const llvm::StringMap<bool> &Features) {
// Allow the target to set the default the langauge options as it sees fit.
Target->getDefaultLangOptions(Options);
-
- // If there are any -mattr options, pass them to the target for validation and
- // processing. The driver should have already consolidated all the
- // target-feature settings and passed them to us in the -mattr list. The
- // -mattr list is treated by the code generator as a diff against the -mcpu
- // setting, but the driver should pass all enabled options as "+" settings.
- // This means that the target should only look at + settings.
- if (!TargetFeatures.empty()) {
- std::string ErrorStr;
- int Opt = Target->HandleTargetFeatures(&TargetFeatures[0],
- TargetFeatures.size(), ErrorStr);
- if (Opt != -1) {
- if (ErrorStr.empty())
- fprintf(stderr, "invalid feature '%s'\n",
- TargetFeatures[Opt].c_str());
- else
- fprintf(stderr, "feature '%s': %s\n",
- TargetFeatures[Opt].c_str(), ErrorStr.c_str());
- exit(1);
- }
- }
+
+ // Pass the map of target features to the target for validation and
+ // processing.
+ Target->HandleTargetFeatures(Features);
if (LangStd == lang_unspecified) {
// Based on the base language, pick one.
TargetCPU("mcpu",
llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"));
+static llvm::cl::list<std::string>
+TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes"));
+
+/// ComputeTargetFeatures - Recompute the target feature list to only
+/// be the list of things that are enabled, based on the target cpu
+/// and feature list.
+static void ComputeFeatureMap(TargetInfo *Target,
+ llvm::StringMap<bool> &Features) {
+ assert(Features.empty() && "invalid map");
+
+ // Initialize the feature map based on the target.
+ Target->getDefaultFeatures(TargetCPU, Features);
+
+ // Apply the user specified deltas.
+ for (llvm::cl::list<std::string>::iterator it = TargetFeatures.begin(),
+ ie = TargetFeatures.end(); it != ie; ++it) {
+ const char *Name = it->c_str();
+
+ // FIXME: Don't handle errors like this.
+ if (Name[0] != '-' && Name[0] != '+') {
+ fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n",
+ Name);
+ exit(1);
+ }
+
+ llvm::StringMap<bool>::iterator it = Features.find(Name + 1);
+ if (it == Features.end()) {
+ fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n",
+ Name);
+ exit(1);
+ }
+
+ // FIXME: Actually, we need to apply all the features implied by
+ // this feature.
+ it->second = (Name[0] == '+');
+ }
+}
+
static void InitializeCompileOptions(CompileOptions &Opts,
- const LangOptions &LangOpts) {
+ const LangOptions &LangOpts,
+ const llvm::StringMap<bool> &Features) {
Opts.OptimizeSize = OptSize;
Opts.DebugInfo = GenerateDebugInfo;
if (OptSize) {
#endif
Opts.CPU = TargetCPU;
- Opts.Features.insert(Opts.Features.end(),
- TargetFeatures.begin(), TargetFeatures.end());
+ Opts.Features.clear();
+ for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
+ ie = Features.end(); it != ie; ++it) {
+ // FIXME: If we are completely confident that we have the right
+ // set, we only need to pass the minuses.
+ std::string Name(it->second ? "+" : "-");
+ Name += it->first();
+ Opts.Features.push_back(Name);
+ }
Opts.NoCommon = NoCommon | LangOpts.CPlusPlus;
static ASTConsumer *CreateASTConsumer(const std::string& InFile,
Diagnostic& Diag, FileManager& FileMgr,
const LangOptions& LangOpts,
+ const llvm::StringMap<bool>& Features,
Preprocessor *PP,
PreprocessorFactory *PPF) {
switch (ProgAction) {
Act = Backend_EmitBC;
CompileOptions Opts;
- InitializeCompileOptions(Opts, LangOpts);
+ InitializeCompileOptions(Opts, LangOpts, Features);
return CreateBackendConsumer(Act, Diag, LangOpts, Opts,
InFile, OutputFile);
}
/// ProcessInputFile - Process a single input file with the specified state.
///
static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
- const std::string &InFile, ProgActions PA) {
+ const std::string &InFile, ProgActions PA,
+ const llvm::StringMap<bool> &Features) {
llvm::OwningPtr<ASTConsumer> Consumer;
bool ClearSourceMgr = false;
FixItRewriter *FixItRewrite = 0;
default:
Consumer.reset(CreateASTConsumer(InFile, PP.getDiagnostics(),
PP.getFileManager(), PP.getLangOptions(),
- &PP, &PPF));
+ Features, &PP, &PPF));
if (!Consumer) {
fprintf(stderr, "Unexpected program action!\n");
// Create a file manager object to provide access to and cache the filesystem.
FileManager FileMgr;
+ // Compute the feature set, unfortunately this effects the language!
+ llvm::StringMap<bool> Features;
+ ComputeFeatureMap(Target.get(), Features);
+
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
const std::string &InFile = InputFilenames[i];
InitializeBaseLanguage();
LangKind LK = GetLanguage(InFile);
InitializeLangOptions(LangInfo, LK);
- InitializeLanguageStandard(LangInfo, LK, Target.get());
+ InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
// Process the -I options and set them in the HeaderInfo.
HeaderSearch HeaderInfo(FileMgr);
((PathDiagnosticClient*)DiagClient.get())->SetPreprocessor(PP.get());
// Process the source file.
- ProcessInputFile(*PP, PPFactory, InFile, ProgAction);
+ ProcessInputFile(*PP, PPFactory, InFile, ProgAction, Features);
HeaderInfo.ClearFileInfo();
DiagClient->setLangOptions(0);