forked from OSchip/llvm-project
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:
parent
1ee6352788
commit
cb177f15e7
|
@ -25,9 +25,13 @@ def err_fe_pch_file_modified : Error<
|
|||
def err_fe_pch_file_overridden : Error<
|
||||
"file '%0' from the precompiled header has been overridden">;
|
||||
|
||||
def warn_pch_target_triple : Error<
|
||||
"PCH file was compiled for the target '%0' but the current translation "
|
||||
"unit is being compiled for target '%1'">;
|
||||
def err_pch_targetopt_mismatch : Error<
|
||||
"PCH file was compiled for the %0 '%1' but the current translation "
|
||||
"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 "
|
||||
"PCH file but is currently %select{disabled|enabled}2">;
|
||||
def err_pch_langopt_value_mismatch : Error<
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "clang/Basic/AddressSpaces.h"
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
#include "clang/Basic/VersionTuple.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include <cassert>
|
||||
|
@ -39,7 +40,6 @@ class LangOptions;
|
|||
class MacroBuilder;
|
||||
class SourceLocation;
|
||||
class SourceManager;
|
||||
class TargetOptions;
|
||||
|
||||
namespace Builtin { struct Info; }
|
||||
|
||||
|
@ -62,7 +62,7 @@ enum TargetCXXABI {
|
|||
/// \brief Exposes information about the current target.
|
||||
///
|
||||
class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
TargetOptions *TargetOpts;
|
||||
llvm::IntrusiveRefCntPtr<TargetOptions> TargetOpts;
|
||||
llvm::Triple Triple;
|
||||
protected:
|
||||
// Target values set by the ctor of the actual target implementation. Default
|
||||
|
|
|
@ -15,13 +15,14 @@
|
|||
#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
|
||||
#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
|
||||
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// \brief Options for controlling the target.
|
||||
class TargetOptions {
|
||||
class TargetOptions : public RefCountedBase<TargetOptions> {
|
||||
public:
|
||||
/// If given, the name of the target triple to compile for. If not given the
|
||||
/// target will be selected to match the host.
|
||||
|
@ -40,6 +41,9 @@ public:
|
|||
/// If given, the version string of the linker in use.
|
||||
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
|
||||
/// be a list of strings starting with by '+' or '-'.
|
||||
std::vector<std::string> Features;
|
||||
|
|
|
@ -71,8 +71,8 @@ private:
|
|||
IntrusiveRefCntPtr<TargetInfo> Target;
|
||||
IntrusiveRefCntPtr<Preprocessor> PP;
|
||||
IntrusiveRefCntPtr<ASTContext> Ctx;
|
||||
IntrusiveRefCntPtr<TargetOptions> TargetOpts;
|
||||
ASTReader *Reader;
|
||||
TargetOptions TargetOpts;
|
||||
|
||||
struct ASTWriterData;
|
||||
OwningPtr<ASTWriterData> WriterData;
|
||||
|
@ -91,13 +91,6 @@ private:
|
|||
/// LoadFromCommandLine available.
|
||||
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
|
||||
// that come from the AST itself, not from included precompiled headers.
|
||||
// FIXME: This is temporary; eventually, CIndex will always do this.
|
||||
|
|
|
@ -52,6 +52,9 @@ class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
|
|||
protected:
|
||||
/// Options controlling the language variant.
|
||||
IntrusiveRefCntPtr<LangOptions> LangOpts;
|
||||
|
||||
/// Options controlling the target.
|
||||
IntrusiveRefCntPtr<TargetOptions> TargetOpts;
|
||||
public:
|
||||
CompilerInvocationBase();
|
||||
|
||||
|
@ -59,6 +62,11 @@ public:
|
|||
|
||||
LangOptions *getLangOpts() { 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.
|
||||
|
@ -96,9 +104,6 @@ class CompilerInvocation : public CompilerInvocationBase {
|
|||
/// Options controlling preprocessed output.
|
||||
PreprocessorOutputOptions PreprocessorOutputOpts;
|
||||
|
||||
/// Options controlling the target.
|
||||
TargetOptions TargetOpts;
|
||||
|
||||
public:
|
||||
CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {}
|
||||
|
||||
|
@ -199,11 +204,6 @@ public:
|
|||
return PreprocessorOutputOpts;
|
||||
}
|
||||
|
||||
TargetOptions &getTargetOpts() { return TargetOpts; }
|
||||
const TargetOptions &getTargetOpts() const {
|
||||
return TargetOpts;
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ class ASTStmtReader;
|
|||
class TypeLocReader;
|
||||
struct HeaderFileInfo;
|
||||
class VersionTuple;
|
||||
class TargetOptions;
|
||||
|
||||
struct PCHPredefinesBlock {
|
||||
/// \brief The file ID for this predefines buffer in a PCH file.
|
||||
|
@ -110,11 +111,12 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// \brief Receives the target triple.
|
||||
/// \brief Receives the target options.
|
||||
///
|
||||
/// \returns true to indicate the target triple is invalid or false otherwise.
|
||||
virtual bool ReadTargetTriple(const serialization::ModuleFile &M,
|
||||
StringRef Triple) {
|
||||
/// \returns true to indicate the target options are invalid, or false
|
||||
/// otherwise.
|
||||
virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
|
||||
const TargetOptions &TargetOpts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -158,8 +160,8 @@ public:
|
|||
|
||||
virtual bool ReadLanguageOptions(const serialization::ModuleFile &M,
|
||||
const LangOptions &LangOpts);
|
||||
virtual bool ReadTargetTriple(const serialization::ModuleFile &M,
|
||||
StringRef Triple);
|
||||
virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
|
||||
const TargetOptions &TargetOpts);
|
||||
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
|
||||
StringRef OriginalFileName,
|
||||
std::string &SuggestedPredefines,
|
||||
|
|
|
@ -4635,8 +4635,10 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
|
|||
|
||||
// Apply the user specified deltas.
|
||||
// First the enables.
|
||||
for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
|
||||
ie = Opts.Features.end(); it != ie; ++it) {
|
||||
for (std::vector<std::string>::const_iterator
|
||||
it = Opts.FeaturesAsWritten.begin(),
|
||||
ie = Opts.FeaturesAsWritten.end();
|
||||
it != ie; ++it) {
|
||||
const char *Name = it->c_str();
|
||||
|
||||
if (Name[0] != '+')
|
||||
|
@ -4650,8 +4652,10 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
|
|||
}
|
||||
|
||||
// Then the disables.
|
||||
for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
|
||||
ie = Opts.Features.end(); it != ie; ++it) {
|
||||
for (std::vector<std::string>::const_iterator
|
||||
it = Opts.FeaturesAsWritten.begin(),
|
||||
ie = Opts.FeaturesAsWritten.end();
|
||||
it != ie; ++it) {
|
||||
const char *Name = it->c_str();
|
||||
|
||||
if (Name[0] == '+')
|
||||
|
|
|
@ -503,7 +503,7 @@ class ASTInfoCollector : public ASTReaderListener {
|
|||
ASTContext &Context;
|
||||
LangOptions &LangOpt;
|
||||
HeaderSearch &HSI;
|
||||
TargetOptions &TargetOpts;
|
||||
IntrusiveRefCntPtr<TargetOptions> &TargetOpts;
|
||||
IntrusiveRefCntPtr<TargetInfo> &Target;
|
||||
std::string &Predefines;
|
||||
unsigned &Counter;
|
||||
|
@ -513,7 +513,8 @@ class ASTInfoCollector : public ASTReaderListener {
|
|||
bool InitializedLanguage;
|
||||
public:
|
||||
ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
|
||||
HeaderSearch &HSI, TargetOptions &TargetOpts,
|
||||
HeaderSearch &HSI,
|
||||
IntrusiveRefCntPtr<TargetOptions> &TargetOpts,
|
||||
IntrusiveRefCntPtr<TargetInfo> &Target,
|
||||
std::string &Predefines,
|
||||
unsigned &Counter)
|
||||
|
@ -536,21 +537,18 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual bool ReadTargetTriple(const serialization::ModuleFile &M,
|
||||
StringRef Triple) {
|
||||
virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
|
||||
const TargetOptions &TargetOpts) {
|
||||
// If we've already initialized the target, don't do it again.
|
||||
if (Target)
|
||||
return false;
|
||||
|
||||
assert(M.Kind == serialization::MK_MainFile);
|
||||
|
||||
// FIXME: This is broken, we should store the TargetOptions in the AST file.
|
||||
TargetOpts.ABI = "";
|
||||
TargetOpts.CXXABI = "";
|
||||
TargetOpts.CPU = "";
|
||||
TargetOpts.Features.clear();
|
||||
TargetOpts.Triple = Triple;
|
||||
Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts);
|
||||
|
||||
this->TargetOpts = new TargetOptions(TargetOpts);
|
||||
Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(),
|
||||
*this->TargetOpts);
|
||||
|
||||
updated();
|
||||
return false;
|
||||
|
@ -1098,7 +1096,6 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
|
|||
Clang->setDiagnostics(&getDiagnostics());
|
||||
|
||||
// Create the target instance.
|
||||
Clang->getTargetOpts().Features = TargetFeatures;
|
||||
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
|
||||
Clang->getTargetOpts()));
|
||||
if (!Clang->hasTarget()) {
|
||||
|
@ -1568,7 +1565,6 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
|
|||
Clang->setDiagnostics(&getDiagnostics());
|
||||
|
||||
// Create the target instance.
|
||||
Clang->getTargetOpts().Features = TargetFeatures;
|
||||
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
|
||||
Clang->getTargetOpts()));
|
||||
if (!Clang->hasTarget()) {
|
||||
|
@ -1777,9 +1773,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
|
|||
CI->getFrontendOpts().DisableFree = false;
|
||||
ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
|
||||
|
||||
// Save the target features.
|
||||
AST->TargetFeatures = CI->getTargetOpts().Features;
|
||||
|
||||
// Create the compiler instance to use for building the AST.
|
||||
OwningPtr<CompilerInstance> Clang(new CompilerInstance());
|
||||
|
||||
|
@ -1795,7 +1788,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
|
|||
Clang->setDiagnostics(&AST->getDiagnostics());
|
||||
|
||||
// Create the target instance.
|
||||
Clang->getTargetOpts().Features = AST->TargetFeatures;
|
||||
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
|
||||
Clang->getTargetOpts()));
|
||||
if (!Clang->hasTarget())
|
||||
|
@ -1884,9 +1876,6 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
|
|||
Invocation->getFrontendOpts().DisableFree = false;
|
||||
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
|
||||
|
||||
// Save the target features.
|
||||
TargetFeatures = Invocation->getTargetOpts().Features;
|
||||
|
||||
llvm::MemoryBuffer *OverrideMainBuffer = 0;
|
||||
if (PrecompilePreamble) {
|
||||
PreambleRebuildCounter = 2;
|
||||
|
@ -2396,7 +2385,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
|
|||
StoredDiagnostics);
|
||||
|
||||
// Create the target instance.
|
||||
Clang->getTargetOpts().Features = TargetFeatures;
|
||||
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
|
||||
Clang->getTargetOpts()));
|
||||
if (!Clang->hasTarget()) {
|
||||
|
|
|
@ -35,11 +35,12 @@ using namespace clang;
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CompilerInvocationBase::CompilerInvocationBase()
|
||||
: LangOpts(new LangOptions()) {}
|
||||
: LangOpts(new LangOptions()), TargetOpts(new TargetOptions()) {}
|
||||
|
||||
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
|
||||
: RefCountedBase<CompilerInvocation>(),
|
||||
LangOpts(new LangOptions(*X.getLangOpts())) {}
|
||||
LangOpts(new LangOptions(*X.getLangOpts())),
|
||||
TargetOpts(new TargetOptions(X.getTargetOpts())) {}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility functions.
|
||||
|
@ -927,8 +928,8 @@ static void TargetOptsToArgs(const TargetOptions &Opts,
|
|||
Res.push_back("-target-linker-version", Opts.LinkerVersion);
|
||||
if (!Opts.CXXABI.empty())
|
||||
Res.push_back("-cxx-abi", Opts.CXXABI);
|
||||
for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i)
|
||||
Res.push_back("-target-feature", Opts.Features[i]);
|
||||
for (unsigned i = 0, e = Opts.FeaturesAsWritten.size(); i != e; ++i)
|
||||
Res.push_back("-target-feature", Opts.FeaturesAsWritten[i]);
|
||||
}
|
||||
|
||||
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.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
|
||||
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.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
|
||||
|
||||
|
@ -2431,7 +2432,8 @@ std::string CompilerInvocation::getModuleHash() const {
|
|||
#include "clang/Basic/LangOptions.def"
|
||||
|
||||
// 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.getVendor(), 4);
|
||||
Signature.add((unsigned)T.getOS(), 5);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/FileSystemStatCache.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Basic/VersionTuple.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
|
@ -101,15 +102,68 @@ PCHValidator::ReadLanguageOptions(const ModuleFile &M,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool PCHValidator::ReadTargetTriple(const ModuleFile &M, StringRef Triple) {
|
||||
if (Triple == PP.getTargetInfo().getTriple().str())
|
||||
return false;
|
||||
bool PCHValidator::ReadTargetOptions(const ModuleFile &M,
|
||||
const TargetOptions &TargetOpts) {
|
||||
const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
|
||||
|
||||
Reader.Diag(diag::warn_pch_target_triple)
|
||||
<< Triple << PP.getTargetInfo().getTriple().str();
|
||||
#define CHECK_TARGET_OPT(Field, Name) \
|
||||
if (TargetOpts.Field != ExistingTargetOpts.Field) { \
|
||||
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 {
|
||||
struct EmptyStringRef {
|
||||
bool operator ()(StringRef r) const { return r.empty(); }
|
||||
|
@ -1846,8 +1900,21 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
|
|||
|
||||
RelocatablePCH = Record[4];
|
||||
if (Listener) {
|
||||
std::string TargetTriple(BlobStart, BlobLen);
|
||||
if (Listener->ReadTargetTriple(F, TargetTriple))
|
||||
unsigned Idx = 6;
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/SourceManagerInternals.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Basic/VersionTuple.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
|
@ -984,27 +985,28 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot,
|
|||
|
||||
// Metadata
|
||||
const TargetInfo &Target = Context.getTargetInfo();
|
||||
BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
|
||||
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);
|
||||
|
||||
const TargetOptions &TargetOpts = Target.getTargetOpts();
|
||||
RecordData Record;
|
||||
Record.push_back(METADATA);
|
||||
Record.push_back(VERSION_MAJOR);
|
||||
Record.push_back(VERSION_MINOR);
|
||||
Record.push_back(CLANG_VERSION_MAJOR);
|
||||
Record.push_back(CLANG_VERSION_MINOR);
|
||||
Record.push_back(!isysroot.empty());
|
||||
Record.push_back(ASTHasCompilerErrors);
|
||||
const std::string &Triple = Target.getTriple().getTriple();
|
||||
Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple);
|
||||
AddString(TargetOpts.Triple, Record);
|
||||
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) {
|
||||
serialization::ModuleManager &Mgr = Chain->getModuleManager();
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
enum { apple_cc = __APPLE_CC__ };
|
||||
|
Loading…
Reference in New Issue