Serialize TargetOptions into an AST file, and make sure that we keep

target options around so they can be accessed at any point (rather
than keeping them transient).

llvm-svn: 166072
This commit is contained in:
Douglas Gregor 2012-10-16 23:40:58 +00:00
parent 1ee6352788
commit cb177f15e7
13 changed files with 156 additions and 83 deletions

View File

@ -25,9 +25,13 @@ def err_fe_pch_file_modified : Error<
def err_fe_pch_file_overridden : Error< def err_fe_pch_file_overridden : Error<
"file '%0' from the precompiled header has been overridden">; "file '%0' from the precompiled header has been overridden">;
def warn_pch_target_triple : Error< def err_pch_targetopt_mismatch : Error<
"PCH file was compiled for the target '%0' but the current translation " "PCH file was compiled for the %0 '%1' but the current translation "
"unit is being compiled for target '%1'">; "unit is being compiled for target '%2'">;
def err_pch_targetopt_feature_mismatch : Error<
"%select{AST file|current translation unit}0 was compiled with the target "
"feature'%1' but the %select{current translation unit is|AST file was}0 "
"not">;
def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in "
"PCH file but is currently %select{disabled|enabled}2">; "PCH file but is currently %select{disabled|enabled}2">;
def err_pch_langopt_value_mismatch : Error< def err_pch_langopt_value_mismatch : Error<

View File

@ -23,6 +23,7 @@
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/VersionTuple.h" #include "clang/Basic/VersionTuple.h"
#include "clang/Basic/Specifiers.h" #include "clang/Basic/Specifiers.h"
#include <cassert> #include <cassert>
@ -39,7 +40,6 @@ class LangOptions;
class MacroBuilder; class MacroBuilder;
class SourceLocation; class SourceLocation;
class SourceManager; class SourceManager;
class TargetOptions;
namespace Builtin { struct Info; } namespace Builtin { struct Info; }
@ -62,7 +62,7 @@ enum TargetCXXABI {
/// \brief Exposes information about the current target. /// \brief Exposes information about the current target.
/// ///
class TargetInfo : public RefCountedBase<TargetInfo> { class TargetInfo : public RefCountedBase<TargetInfo> {
TargetOptions *TargetOpts; llvm::IntrusiveRefCntPtr<TargetOptions> TargetOpts;
llvm::Triple Triple; llvm::Triple Triple;
protected: protected:
// Target values set by the ctor of the actual target implementation. Default // Target values set by the ctor of the actual target implementation. Default

View File

@ -15,13 +15,14 @@
#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H #ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H #define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include <string> #include <string>
#include <vector> #include <vector>
namespace clang { namespace clang {
/// \brief Options for controlling the target. /// \brief Options for controlling the target.
class TargetOptions { class TargetOptions : public RefCountedBase<TargetOptions> {
public: public:
/// If given, the name of the target triple to compile for. If not given the /// If given, the name of the target triple to compile for. If not given the
/// target will be selected to match the host. /// target will be selected to match the host.
@ -40,6 +41,9 @@ public:
/// If given, the version string of the linker in use. /// If given, the version string of the linker in use.
std::string LinkerVersion; std::string LinkerVersion;
/// \brief The list of target specific features to enable or disable, as written on the command line.
std::vector<std::string> FeaturesAsWritten;
/// The list of target specific features to enable or disable -- this should /// The list of target specific features to enable or disable -- this should
/// be a list of strings starting with by '+' or '-'. /// be a list of strings starting with by '+' or '-'.
std::vector<std::string> Features; std::vector<std::string> Features;

View File

@ -71,8 +71,8 @@ private:
IntrusiveRefCntPtr<TargetInfo> Target; IntrusiveRefCntPtr<TargetInfo> Target;
IntrusiveRefCntPtr<Preprocessor> PP; IntrusiveRefCntPtr<Preprocessor> PP;
IntrusiveRefCntPtr<ASTContext> Ctx; IntrusiveRefCntPtr<ASTContext> Ctx;
IntrusiveRefCntPtr<TargetOptions> TargetOpts;
ASTReader *Reader; ASTReader *Reader;
TargetOptions TargetOpts;
struct ASTWriterData; struct ASTWriterData;
OwningPtr<ASTWriterData> WriterData; OwningPtr<ASTWriterData> WriterData;
@ -91,13 +91,6 @@ private:
/// LoadFromCommandLine available. /// LoadFromCommandLine available.
IntrusiveRefCntPtr<CompilerInvocation> Invocation; IntrusiveRefCntPtr<CompilerInvocation> Invocation;
/// \brief The set of target features.
///
/// FIXME: each time we reparse, we need to restore the set of target
/// features from this vector, because TargetInfo::CreateTargetInfo()
/// mangles the target options in place. Yuck!
std::vector<std::string> TargetFeatures;
// OnlyLocalDecls - when true, walking this AST should only visit declarations // OnlyLocalDecls - when true, walking this AST should only visit declarations
// that come from the AST itself, not from included precompiled headers. // that come from the AST itself, not from included precompiled headers.
// FIXME: This is temporary; eventually, CIndex will always do this. // FIXME: This is temporary; eventually, CIndex will always do this.

View File

@ -52,6 +52,9 @@ class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
protected: protected:
/// Options controlling the language variant. /// Options controlling the language variant.
IntrusiveRefCntPtr<LangOptions> LangOpts; IntrusiveRefCntPtr<LangOptions> LangOpts;
/// Options controlling the target.
IntrusiveRefCntPtr<TargetOptions> TargetOpts;
public: public:
CompilerInvocationBase(); CompilerInvocationBase();
@ -59,6 +62,11 @@ public:
LangOptions *getLangOpts() { return LangOpts.getPtr(); } LangOptions *getLangOpts() { return LangOpts.getPtr(); }
const LangOptions *getLangOpts() const { return LangOpts.getPtr(); } const LangOptions *getLangOpts() const { return LangOpts.getPtr(); }
TargetOptions &getTargetOpts() { return *TargetOpts.getPtr(); }
const TargetOptions &getTargetOpts() const {
return *TargetOpts.getPtr();
}
}; };
/// \brief Helper class for holding the data necessary to invoke the compiler. /// \brief Helper class for holding the data necessary to invoke the compiler.
@ -96,9 +104,6 @@ class CompilerInvocation : public CompilerInvocationBase {
/// Options controlling preprocessed output. /// Options controlling preprocessed output.
PreprocessorOutputOptions PreprocessorOutputOpts; PreprocessorOutputOptions PreprocessorOutputOpts;
/// Options controlling the target.
TargetOptions TargetOpts;
public: public:
CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {} CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {}
@ -199,11 +204,6 @@ public:
return PreprocessorOutputOpts; return PreprocessorOutputOpts;
} }
TargetOptions &getTargetOpts() { return TargetOpts; }
const TargetOptions &getTargetOpts() const {
return TargetOpts;
}
/// @} /// @}
}; };

View File

@ -82,6 +82,7 @@ class ASTStmtReader;
class TypeLocReader; class TypeLocReader;
struct HeaderFileInfo; struct HeaderFileInfo;
class VersionTuple; class VersionTuple;
class TargetOptions;
struct PCHPredefinesBlock { struct PCHPredefinesBlock {
/// \brief The file ID for this predefines buffer in a PCH file. /// \brief The file ID for this predefines buffer in a PCH file.
@ -110,11 +111,12 @@ public:
return false; return false;
} }
/// \brief Receives the target triple. /// \brief Receives the target options.
/// ///
/// \returns true to indicate the target triple is invalid or false otherwise. /// \returns true to indicate the target options are invalid, or false
virtual bool ReadTargetTriple(const serialization::ModuleFile &M, /// otherwise.
StringRef Triple) { virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
const TargetOptions &TargetOpts) {
return false; return false;
} }
@ -158,8 +160,8 @@ public:
virtual bool ReadLanguageOptions(const serialization::ModuleFile &M, virtual bool ReadLanguageOptions(const serialization::ModuleFile &M,
const LangOptions &LangOpts); const LangOptions &LangOpts);
virtual bool ReadTargetTriple(const serialization::ModuleFile &M, virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
StringRef Triple); const TargetOptions &TargetOpts);
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
StringRef OriginalFileName, StringRef OriginalFileName,
std::string &SuggestedPredefines, std::string &SuggestedPredefines,

View File

@ -4635,8 +4635,10 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
// Apply the user specified deltas. // Apply the user specified deltas.
// First the enables. // First the enables.
for (std::vector<std::string>::const_iterator it = Opts.Features.begin(), for (std::vector<std::string>::const_iterator
ie = Opts.Features.end(); it != ie; ++it) { it = Opts.FeaturesAsWritten.begin(),
ie = Opts.FeaturesAsWritten.end();
it != ie; ++it) {
const char *Name = it->c_str(); const char *Name = it->c_str();
if (Name[0] != '+') if (Name[0] != '+')
@ -4650,8 +4652,10 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
} }
// Then the disables. // Then the disables.
for (std::vector<std::string>::const_iterator it = Opts.Features.begin(), for (std::vector<std::string>::const_iterator
ie = Opts.Features.end(); it != ie; ++it) { it = Opts.FeaturesAsWritten.begin(),
ie = Opts.FeaturesAsWritten.end();
it != ie; ++it) {
const char *Name = it->c_str(); const char *Name = it->c_str();
if (Name[0] == '+') if (Name[0] == '+')

View File

@ -503,7 +503,7 @@ class ASTInfoCollector : public ASTReaderListener {
ASTContext &Context; ASTContext &Context;
LangOptions &LangOpt; LangOptions &LangOpt;
HeaderSearch &HSI; HeaderSearch &HSI;
TargetOptions &TargetOpts; IntrusiveRefCntPtr<TargetOptions> &TargetOpts;
IntrusiveRefCntPtr<TargetInfo> &Target; IntrusiveRefCntPtr<TargetInfo> &Target;
std::string &Predefines; std::string &Predefines;
unsigned &Counter; unsigned &Counter;
@ -513,7 +513,8 @@ class ASTInfoCollector : public ASTReaderListener {
bool InitializedLanguage; bool InitializedLanguage;
public: public:
ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt, ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
HeaderSearch &HSI, TargetOptions &TargetOpts, HeaderSearch &HSI,
IntrusiveRefCntPtr<TargetOptions> &TargetOpts,
IntrusiveRefCntPtr<TargetInfo> &Target, IntrusiveRefCntPtr<TargetInfo> &Target,
std::string &Predefines, std::string &Predefines,
unsigned &Counter) unsigned &Counter)
@ -536,21 +537,18 @@ public:
return false; return false;
} }
virtual bool ReadTargetTriple(const serialization::ModuleFile &M, virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
StringRef Triple) { const TargetOptions &TargetOpts) {
// If we've already initialized the target, don't do it again. // If we've already initialized the target, don't do it again.
if (Target) if (Target)
return false; return false;
assert(M.Kind == serialization::MK_MainFile); assert(M.Kind == serialization::MK_MainFile);
// FIXME: This is broken, we should store the TargetOptions in the AST file.
TargetOpts.ABI = ""; this->TargetOpts = new TargetOptions(TargetOpts);
TargetOpts.CXXABI = ""; Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(),
TargetOpts.CPU = ""; *this->TargetOpts);
TargetOpts.Features.clear();
TargetOpts.Triple = Triple;
Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts);
updated(); updated();
return false; return false;
@ -1098,7 +1096,6 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Clang->setDiagnostics(&getDiagnostics()); Clang->setDiagnostics(&getDiagnostics());
// Create the target instance. // Create the target instance.
Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts())); Clang->getTargetOpts()));
if (!Clang->hasTarget()) { if (!Clang->hasTarget()) {
@ -1568,9 +1565,8 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Clang->setDiagnostics(&getDiagnostics()); Clang->setDiagnostics(&getDiagnostics());
// Create the target instance. // Create the target instance.
Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts())); Clang->getTargetOpts()));
if (!Clang->hasTarget()) { if (!Clang->hasTarget()) {
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
Preamble.clear(); Preamble.clear();
@ -1777,9 +1773,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
CI->getFrontendOpts().DisableFree = false; CI->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts()); ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
// Save the target features.
AST->TargetFeatures = CI->getTargetOpts().Features;
// Create the compiler instance to use for building the AST. // Create the compiler instance to use for building the AST.
OwningPtr<CompilerInstance> Clang(new CompilerInstance()); OwningPtr<CompilerInstance> Clang(new CompilerInstance());
@ -1795,7 +1788,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
Clang->setDiagnostics(&AST->getDiagnostics()); Clang->setDiagnostics(&AST->getDiagnostics());
// Create the target instance. // Create the target instance.
Clang->getTargetOpts().Features = AST->TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts())); Clang->getTargetOpts()));
if (!Clang->hasTarget()) if (!Clang->hasTarget())
@ -1884,9 +1876,6 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
Invocation->getFrontendOpts().DisableFree = false; Invocation->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
// Save the target features.
TargetFeatures = Invocation->getTargetOpts().Features;
llvm::MemoryBuffer *OverrideMainBuffer = 0; llvm::MemoryBuffer *OverrideMainBuffer = 0;
if (PrecompilePreamble) { if (PrecompilePreamble) {
PreambleRebuildCounter = 2; PreambleRebuildCounter = 2;
@ -2396,7 +2385,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
StoredDiagnostics); StoredDiagnostics);
// Create the target instance. // Create the target instance.
Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts())); Clang->getTargetOpts()));
if (!Clang->hasTarget()) { if (!Clang->hasTarget()) {

View File

@ -35,11 +35,12 @@ using namespace clang;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
CompilerInvocationBase::CompilerInvocationBase() CompilerInvocationBase::CompilerInvocationBase()
: LangOpts(new LangOptions()) {} : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
: RefCountedBase<CompilerInvocation>(), : RefCountedBase<CompilerInvocation>(),
LangOpts(new LangOptions(*X.getLangOpts())) {} LangOpts(new LangOptions(*X.getLangOpts())),
TargetOpts(new TargetOptions(X.getTargetOpts())) {}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Utility functions. // Utility functions.
@ -927,8 +928,8 @@ static void TargetOptsToArgs(const TargetOptions &Opts,
Res.push_back("-target-linker-version", Opts.LinkerVersion); Res.push_back("-target-linker-version", Opts.LinkerVersion);
if (!Opts.CXXABI.empty()) if (!Opts.CXXABI.empty())
Res.push_back("-cxx-abi", Opts.CXXABI); Res.push_back("-cxx-abi", Opts.CXXABI);
for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) for (unsigned i = 0, e = Opts.FeaturesAsWritten.size(); i != e; ++i)
Res.push_back("-target-feature", Opts.Features[i]); Res.push_back("-target-feature", Opts.FeaturesAsWritten[i]);
} }
void CompilerInvocation::toArgs(std::vector<std::string> &Res) const { void CompilerInvocation::toArgs(std::vector<std::string> &Res) const {
@ -2285,7 +2286,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
Opts.ABI = Args.getLastArgValue(OPT_target_abi); Opts.ABI = Args.getLastArgValue(OPT_target_abi);
Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi); Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
Opts.CPU = Args.getLastArgValue(OPT_target_cpu); Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
Opts.Features = Args.getAllArgValues(OPT_target_feature); Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version); Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
@ -2431,7 +2432,8 @@ std::string CompilerInvocation::getModuleHash() const {
#include "clang/Basic/LangOptions.def" #include "clang/Basic/LangOptions.def"
// Extend the signature with the target triple // Extend the signature with the target triple
llvm::Triple T(TargetOpts.Triple); // FIXME: Add target options.
llvm::Triple T(TargetOpts->Triple);
Signature.add((unsigned)T.getArch(), 5); Signature.add((unsigned)T.getArch(), 5);
Signature.add((unsigned)T.getVendor(), 4); Signature.add((unsigned)T.getVendor(), 4);
Signature.add((unsigned)T.getOS(), 5); Signature.add((unsigned)T.getOS(), 5);

View File

@ -37,6 +37,7 @@
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h" #include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h" #include "clang/Basic/Version.h"
#include "clang/Basic/VersionTuple.h" #include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
@ -101,13 +102,66 @@ PCHValidator::ReadLanguageOptions(const ModuleFile &M,
return false; return false;
} }
bool PCHValidator::ReadTargetTriple(const ModuleFile &M, StringRef Triple) { bool PCHValidator::ReadTargetOptions(const ModuleFile &M,
if (Triple == PP.getTargetInfo().getTriple().str()) const TargetOptions &TargetOpts) {
return false; const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
Reader.Diag(diag::warn_pch_target_triple) #define CHECK_TARGET_OPT(Field, Name) \
<< Triple << PP.getTargetInfo().getTriple().str(); if (TargetOpts.Field != ExistingTargetOpts.Field) { \
return true; Reader.Diag(diag::err_pch_targetopt_mismatch) \
<< Name << TargetOpts.Field << ExistingTargetOpts.Field; \
return true; \
}
CHECK_TARGET_OPT(Triple, "target");
CHECK_TARGET_OPT(CPU, "target CPU");
CHECK_TARGET_OPT(ABI, "target ABI");
CHECK_TARGET_OPT(CXXABI, "target C++ ABI");
CHECK_TARGET_OPT(LinkerVersion, "target linker version");
#undef CHECK_TARGET_OPT
// Compare feature sets.
SmallVector<StringRef, 4> ExistingFeatures(
ExistingTargetOpts.FeaturesAsWritten.begin(),
ExistingTargetOpts.FeaturesAsWritten.end());
SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
TargetOpts.FeaturesAsWritten.end());
std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
std::sort(ReadFeatures.begin(), ReadFeatures.end());
unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();
unsigned ReadIdx = 0, ReadN = ReadFeatures.size();
while (ExistingIdx < ExistingN && ReadIdx < ReadN) {
if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {
++ExistingIdx;
++ReadIdx;
continue;
}
if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
<< false << ReadFeatures[ReadIdx];
return true;
}
Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
<< true << ExistingFeatures[ExistingIdx];
return true;
}
if (ExistingIdx < ExistingN) {
Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
<< true << ExistingFeatures[ExistingIdx];
return true;
}
if (ReadIdx < ReadN) {
Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
<< false << ReadFeatures[ReadIdx];
return true;
}
return false;
} }
namespace { namespace {
@ -1834,7 +1888,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case METADATA: { case METADATA: {
if (Record[0] != VERSION_MAJOR && !DisableValidation) { if (Record[0] != VERSION_MAJOR && !DisableValidation) {
Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
: diag::warn_pch_version_too_new); : diag::warn_pch_version_too_new);
return IgnorePCH; return IgnorePCH;
} }
@ -1846,8 +1900,21 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
RelocatablePCH = Record[4]; RelocatablePCH = Record[4];
if (Listener) { if (Listener) {
std::string TargetTriple(BlobStart, BlobLen); unsigned Idx = 6;
if (Listener->ReadTargetTriple(F, TargetTriple)) TargetOptions TargetOpts;
TargetOpts.Triple = ReadString(Record, Idx);
TargetOpts.CPU = ReadString(Record, Idx);
TargetOpts.ABI = ReadString(Record, Idx);
TargetOpts.CXXABI = ReadString(Record, Idx);
TargetOpts.LinkerVersion = ReadString(Record, Idx);
for (unsigned N = Record[Idx++]; N; --N) {
TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
}
for (unsigned N = Record[Idx++]; N; --N) {
TargetOpts.Features.push_back(ReadString(Record, Idx));
}
if (Listener->ReadTargetOptions(F, TargetOpts))
return IgnorePCH; return IgnorePCH;
} }
break; break;

View File

@ -35,6 +35,7 @@
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h" #include "clang/Basic/Version.h"
#include "clang/Basic/VersionTuple.h" #include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/APFloat.h" #include "llvm/ADT/APFloat.h"
@ -984,27 +985,28 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot,
// Metadata // Metadata
const TargetInfo &Target = Context.getTargetInfo(); const TargetInfo &Target = Context.getTargetInfo();
BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev(); const TargetOptions &TargetOpts = Target.getTargetOpts();
MetaAbbrev->Add(BitCodeAbbrevOp(METADATA));
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST major
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST minor
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Has errors
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple
unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
RecordData Record; RecordData Record;
Record.push_back(METADATA);
Record.push_back(VERSION_MAJOR); Record.push_back(VERSION_MAJOR);
Record.push_back(VERSION_MINOR); Record.push_back(VERSION_MINOR);
Record.push_back(CLANG_VERSION_MAJOR); Record.push_back(CLANG_VERSION_MAJOR);
Record.push_back(CLANG_VERSION_MINOR); Record.push_back(CLANG_VERSION_MINOR);
Record.push_back(!isysroot.empty()); Record.push_back(!isysroot.empty());
Record.push_back(ASTHasCompilerErrors); Record.push_back(ASTHasCompilerErrors);
const std::string &Triple = Target.getTriple().getTriple(); AddString(TargetOpts.Triple, Record);
Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple); AddString(TargetOpts.CPU, Record);
AddString(TargetOpts.ABI, Record);
AddString(TargetOpts.CXXABI, Record);
AddString(TargetOpts.LinkerVersion, Record);
Record.push_back(TargetOpts.FeaturesAsWritten.size());
for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {
AddString(TargetOpts.FeaturesAsWritten[I], Record);
}
Record.push_back(TargetOpts.Features.size());
for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) {
AddString(TargetOpts.Features[I], Record);
}
Stream.EmitRecord(METADATA, Record);
if (Chain) { if (Chain) {
serialization::ModuleManager &Mgr = Chain->getModuleManager(); serialization::ModuleManager &Mgr = Chain->getModuleManager();

View File

@ -0,0 +1,5 @@
// RUN: %clang_cc1 -triple=x86_64-apple-darwin9 -emit-pch -o %t.pch %S/target-options.h
// RUN: not %clang_cc1 -triple=x86_64-unknown-freebsd7.0 -include-pch %t.pch %s -emit-llvm -o - > %t.err 2>&1
// RUN: FileCheck %s < %t.err
// CHECK: for the target

View File

@ -0,0 +1,2 @@
enum { apple_cc = __APPLE_CC__ };