Add TargetOptions and use it when constructing targets.

- This ended up being hard to factor, sorry for the large diff.

 - Some post-commit cleanup to come.

llvm-svn: 88833
This commit is contained in:
Daniel Dunbar 2009-11-15 06:48:46 +00:00
parent c25ca41254
commit b9bbd54fdb
16 changed files with 205 additions and 129 deletions

View File

@ -52,4 +52,11 @@ def warn_integer_too_large_for_signed : Warning<
def note_invalid_subexpr_in_ice : Note<
"subexpression not valid in an integer constant expression">;
// Targets
def err_target_unknown_triple : Error<
"unknown target triple '%0', please use -triple or -arch">;
def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
def err_target_invalid_feature : Error<"invalid target feature '%0'">;
}

View File

@ -9,9 +9,6 @@
let Component = "Frontend" in {
def err_fe_unknown_triple : Error<
"unknown target triple '%0', please use -triple or -arch">;
def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">;
def err_fe_error_opening : Error<"error opening '%0': %1">;
def err_fe_error_reading : Error<"error reading '%0'">;
def err_fe_error_reading_stdin : Error<"error reading stdin">;

View File

@ -28,11 +28,12 @@ class StringRef;
}
namespace clang {
class Diagnostic;
class LangOptions;
class SourceLocation;
class SourceManager;
class LangOptions;
class TargetOptions;
namespace Builtin { struct Info; }
/// TargetInfo - This class exposes information about the current target.
@ -59,9 +60,9 @@ protected:
TargetInfo(const std::string &T);
public:
/// CreateTargetInfo - Return the target info object for the specified target
/// triple.
static TargetInfo* CreateTargetInfo(const std::string &Triple);
/// CreateTargetInfo - Construct a target for the given options.
static TargetInfo* CreateTargetInfo(Diagnostic &Diags,
const TargetOptions &Opts);
virtual ~TargetInfo();

View File

@ -0,0 +1,39 @@
//===--- TargetOptions.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
#include <string>
#include <vector>
namespace clang {
/// TargetOptions - Options for controlling the target.
class 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.
std::string Triple;
/// If given, the name of the target CPU to generate code for.
std::string CPU;
/// If given, the name of the target ABI to use.
std::string ABI;
/// 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;
};
} // end namespace clang
#endif

View File

@ -52,13 +52,6 @@ public:
/// Inlining - The kind of inlining to perform.
InliningMethod Inlining;
/// CPU - An optional CPU to target.
std::string CPU;
/// Features - A list of subtarget features to pass to the code
/// generator.
std::vector<std::string> Features;
public:
CodeGenOptions() {
OptimizationLevel = 0;

View File

@ -25,11 +25,12 @@ namespace llvm {
namespace clang {
class ASTConsumer;
class CodeGenOptions;
class Diagnostic;
class FileManager;
class Preprocessor;
class CodeGenOptions;
class LangOptions;
class Preprocessor;
class TargetOptions;
// AST pretty-printer: prints out the AST in a format that is close to the
// original C code. The output is intended to be in a format such that
@ -81,6 +82,7 @@ ASTConsumer *CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &Features,
const CodeGenOptions &CodeGenOpts,
const TargetOptions &TargetOpts,
const std::string &ModuleID,
llvm::raw_ostream *OS,
llvm::LLVMContext& C);

View File

@ -191,6 +191,13 @@ public:
return Invocation.getPreprocessorOutputOpts();
}
TargetOptions &getTargetOpts() {
return Invocation.getTargetOpts();
}
const TargetOptions &getTargetOpts() const {
return Invocation.getTargetOpts();
}
/// }
/// @name Diagnostics Engine
/// {

View File

@ -11,6 +11,7 @@
#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/Frontend/AnalysisConsumer.h"
#include "clang/Frontend/DependencyOutputOptions.h"
@ -58,6 +59,9 @@ class CompilerInvocation {
/// Options controlling preprocessed output.
PreprocessorOutputOptions PreprocessorOutputOpts;
/// Options controlling the target.
TargetOptions TargetOpts;
public:
CompilerInvocation() {}
@ -110,6 +114,11 @@ public:
return PreprocessorOutputOpts;
}
TargetOptions &getTargetOpts() { return TargetOpts; }
const TargetOptions &getTargetOpts() const {
return TargetOpts;
}
/// @}
};

View File

@ -85,13 +85,6 @@ public:
unsigned ShowTimers : 1; ///< Show timers for individual
/// actions.
/// If given, the name of the target triple to compile for. If not given the
/// target will be selected to match the host.
std::string TargetTriple;
/// If given, the name of the target ABI to use.
std::string TargetABI;
/// The input files and their types.
std::vector<std::pair<InputKind, std::string> > Inputs;

View File

@ -12,11 +12,14 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@ -1836,9 +1839,7 @@ namespace {
// Driver code
//===----------------------------------------------------------------------===//
/// CreateTargetInfo - Return the target info object for the specified target
/// triple.
TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
static TargetInfo *AllocateTarget(const std::string &T) {
llvm::Triple Triple(T);
llvm::Triple::OSType os = Triple.getOS();
@ -1942,3 +1943,53 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
}
}
}
/// CreateTargetInfo - Return the target info object for the specified target
/// triple.
TargetInfo *TargetInfo::CreateTargetInfo(Diagnostic &Diags,
const TargetOptions &Opts) {
llvm::Triple Triple(Opts.Triple);
// Construct the target
llvm::OwningPtr<TargetInfo> Target(AllocateTarget(Triple.str()));
if (!Target) {
Diags.Report(diag::err_target_unknown_triple) << Triple.str();
return 0;
}
// Set the target ABI if specified.
if (!Opts.ABI.empty() && !Target->setABI(Opts.ABI)) {
Diags.Report(diag::err_target_unknown_abi) << Opts.ABI;
return 0;
}
// Compute the default target features, we need the target to handle this
// because features may have dependencies on one another.
llvm::StringMap<bool> Features;
Target->getDefaultFeatures(Opts.CPU, Features);
// Apply the user specified deltas.
for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
ie = Opts.Features.end(); it != ie; ++it) {
const char *Name = it->c_str();
// Apply the feature via the target.
if ((Name[0] != '-' && Name[0] != '+') ||
!Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
Diags.Report(diag::err_target_invalid_feature) << Name;
return 0;
}
}
// Add the features to the compile options.
//
// FIXME: If we are completely confident that we have the right set, we only
// need to pass the minuses.
std::vector<std::string> StrFeatures;
for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
ie = Features.end(); it != ie; ++it)
StrFeatures.push_back(std::string(it->second ? "+" : "-") + it->first());
Target->HandleTargetFeatures(StrFeatures);
return Target.take();
}

View File

@ -18,6 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Compiler.h"
@ -132,7 +133,14 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
// PCH loaded successfully. Now create the preprocessor.
// Get information about the target being compiled for.
AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple));
//
// FIXME: This is broken, we should store the TargetOptions in the PCH.
TargetOptions TargetOpts;
TargetOpts.ABI = "";
TargetOpts.CPU = "";
TargetOpts.Features.clear();
TargetOpts.Triple = TargetTriple;
AST->Target.reset(TargetInfo::CreateTargetInfo(AST->Diags, TargetOpts));
AST->PP.reset(new Preprocessor(AST->Diags, LangInfo, *AST->Target.get(),
AST->getSourceManager(), HeaderInfo));
Preprocessor &PP = *AST->PP.get();

View File

@ -8,12 +8,13 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/ASTConsumers.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
@ -41,6 +42,7 @@ namespace {
class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
BackendAction Action;
CodeGenOptions CodeGenOpts;
TargetOptions TargetOpts;
llvm::raw_ostream *AsmOutStream;
llvm::formatted_raw_ostream FormattedOutStream;
ASTContext *Context;
@ -76,10 +78,11 @@ namespace {
public:
BackendConsumer(BackendAction action, Diagnostic &Diags,
const LangOptions &langopts, const CodeGenOptions &compopts,
const std::string &infile, llvm::raw_ostream* OS,
LLVMContext& C) :
const TargetOptions &targetopts, const std::string &infile,
llvm::raw_ostream* OS, LLVMContext& C) :
Action(action),
CodeGenOpts(compopts),
TargetOpts(targetopts),
AsmOutStream(OS),
LLVMIRGeneration("LLVM IR Generation Time"),
CodeGenerationTime("Code Generation Time"),
@ -213,12 +216,12 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
}
std::string FeaturesStr;
if (CodeGenOpts.CPU.size() || CodeGenOpts.Features.size()) {
if (TargetOpts.CPU.size() || TargetOpts.Features.size()) {
SubtargetFeatures Features;
Features.setCPU(CodeGenOpts.CPU);
Features.setCPU(TargetOpts.CPU);
for (std::vector<std::string>::iterator
it = CodeGenOpts.Features.begin(),
ie = CodeGenOpts.Features.end(); it != ie; ++it)
it = TargetOpts.Features.begin(),
ie = TargetOpts.Features.end(); it != ie; ++it)
Features.AddFeature(*it);
FeaturesStr = Features.getString();
}
@ -371,9 +374,10 @@ ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &LangOpts,
const CodeGenOptions &CodeGenOpts,
const TargetOptions &TargetOpts,
const std::string& InFile,
llvm::raw_ostream* OS,
LLVMContext& C) {
return new BackendConsumer(Action, Diags, LangOpts, CodeGenOpts,
InFile, OS, C);
TargetOpts, InFile, OS, C);
}

View File

@ -170,8 +170,8 @@ ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(),
CI.getCodeGenOpts(), InFile, OS.take(),
CI.getLLVMContext());
CI.getCodeGenOpts(), CI.getTargetOpts(), InFile,
OS.take(), CI.getLLVMContext());
}
EmitAssemblyAction::EmitAssemblyAction()

View File

@ -14,6 +14,7 @@
#include "Options.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/AnalysisConsumer.h"
#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/Frontend/DependencyOutputOptions.h"
@ -27,6 +28,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/RegistryParser.h"
#include "llvm/System/Host.h"
#include <stdio.h>
using namespace clang;
@ -193,13 +195,6 @@ OptLevel("O", llvm::cl::Prefix,
static llvm::cl::opt<bool>
OptSize("Os", llvm::cl::desc("Optimize for size"));
static llvm::cl::opt<std::string>
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"));
}
//===----------------------------------------------------------------------===//
@ -297,7 +292,6 @@ VerifyDiagnostics("verify",
}
//===----------------------------------------------------------------------===//
// Frontend Options
//===----------------------------------------------------------------------===//
@ -455,14 +449,6 @@ static llvm::cl::opt<bool>
Stats("print-stats",
llvm::cl::desc("Print performance metrics and statistics"));
static llvm::cl::opt<std::string>
TargetABI("target-abi",
llvm::cl::desc("Target a particular ABI type"));
static llvm::cl::opt<std::string>
TargetTriple("triple",
llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
static llvm::cl::opt<bool>
TimeReport("ftime-report",
llvm::cl::desc("Print the amount of time each "
@ -793,49 +779,37 @@ static llvm::cl::opt<bool>
DumpDefines("dD", llvm::cl::desc("Print macro definitions in -E mode in "
"addition to normal output"));
}
//===----------------------------------------------------------------------===//
// Target Options
//===----------------------------------------------------------------------===//
namespace targetoptions {
static llvm::cl::opt<std::string>
TargetABI("target-abi",
llvm::cl::desc("Target a particular ABI type"));
static llvm::cl::opt<std::string>
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"));
static llvm::cl::opt<std::string>
TargetTriple("triple",
llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
}
//===----------------------------------------------------------------------===//
// Option Object Construction
//===----------------------------------------------------------------------===//
void clang::InitializeCodeGenOptions(CodeGenOptions &Opts,
const TargetInfo &Target) {
void clang::InitializeCodeGenOptions(CodeGenOptions &Opts) {
using namespace codegenoptions;
// Compute the target features, we need the target to handle this because
// features may have dependencies on one another.
llvm::StringMap<bool> Features;
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);
}
// Apply the feature via the target.
if (!Target.setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
fprintf(stderr, "error: clang-cc: invalid target feature name: %s\n",
Name + 1);
exit(1);
}
}
// Add the features to the compile options.
//
// FIXME: If we are completely confident that we have the right set, we only
// need to pass the minuses.
for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
ie = Features.end(); it != ie; ++it)
Opts.Features.push_back(std::string(it->second ? "+" : "-") + it->first());
// -Os implies -O2
Opts.OptimizationLevel = OptSize ? 2 : OptLevel;
@ -843,7 +817,6 @@ void clang::InitializeCodeGenOptions(CodeGenOptions &Opts,
Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
: CodeGenOptions::OnlyAlwaysInlining;
Opts.CPU = TargetCPU;
Opts.DebugInfo = GenerateDebugInfo;
Opts.DisableLLVMOpts = DisableLLVMOptimizations;
Opts.DisableRedZone = DisableRedZone;
@ -908,8 +881,6 @@ void clang::InitializeFrontendOptions(FrontendOptions &Opts) {
Opts.ShowMacrosInCodeCompletion = CodeCompletionWantsMacros;
Opts.ShowStats = Stats;
Opts.ShowTimers = TimeReport;
Opts.TargetABI = TargetABI;
Opts.TargetTriple = TargetTriple;
Opts.ViewClassInheritance = InheritanceViewCls;
// '-' is the default input if none is given.
@ -1160,14 +1131,9 @@ void clang::InitializeLangOptions(LangOptions &Options,
Options.setVisibilityMode(SymbolVisibility);
Options.OverflowChecking = OverflowChecking;
// Allow the target to set the default the language options as it sees fit.
Target.getDefaultLangOptions(Options);
// Pass the map of target features to the target for validation and
// processing.
Target.HandleTargetFeatures(CodeGenOpts.Features);
if (LangStd == lang_unspecified) {
// Based on the base language, pick one.
switch (IK) {
@ -1363,3 +1329,16 @@ clang::InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts) {
Opts.ShowComments = EnableCommentOutput;
Opts.ShowMacroComments = EnableMacroCommentOutput;
}
void clang::InitializeTargetOptions(TargetOptions &Opts) {
using namespace targetoptions;
Opts.ABI = TargetABI;
Opts.CPU = TargetCPU;
Opts.Triple = TargetTriple;
Opts.Features = TargetFeatures;
// Use the host triple if unspecified.
if (Opts.Triple.empty())
Opts.Triple = llvm::sys::getHostTriple();
}

View File

@ -25,6 +25,7 @@ class LangOptions;
class PreprocessorOptions;
class PreprocessorOutputOptions;
class TargetInfo;
class TargetOptions;
void InitializeAnalyzerOptions(AnalyzerOptions &Opts);
@ -34,8 +35,7 @@ void InitializeDiagnosticOptions(DiagnosticOptions &Opts);
void InitializeFrontendOptions(FrontendOptions &Opts);
void InitializeCodeGenOptions(CodeGenOptions &Opts,
const TargetInfo &Target);
void InitializeCodeGenOptions(CodeGenOptions &Opts);
void InitializeHeaderSearchOptions(HeaderSearchOptions &Opts,
llvm::StringRef BuiltinIncludePath,
@ -50,6 +50,8 @@ void InitializePreprocessorOptions(PreprocessorOptions &Opts);
void InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts);
void InitializeTargetOptions(TargetOptions &Opts);
} // end namespace clang
#endif

View File

@ -156,37 +156,21 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message) {
static TargetInfo *
ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags,
const char *Argv0, bool &IsAST) {
// Initialize frontend options.
InitializeFrontendOptions(Opts.getFrontendOpts());
// FIXME: The target information in frontend options should be split out into
// TargetOptions, and the target options in codegen options should move there
// as well. Then we could properly initialize in layering order.
// Initialize base triple. If a -triple option has been specified, use
// that triple. Otherwise, default to the host triple.
llvm::Triple Triple(Opts.getFrontendOpts().TargetTriple);
if (Triple.getTriple().empty())
Triple = llvm::Triple(llvm::sys::getHostTriple());
// Initialize target options.
InitializeTargetOptions(Opts.getTargetOpts());
// Get information about the target being compiled for.
TargetInfo *Target = TargetInfo::CreateTargetInfo(Triple.getTriple());
if (!Target) {
Diags.Report(diag::err_fe_unknown_triple) << Triple.getTriple().c_str();
llvm::OwningPtr<TargetInfo> Target(
TargetInfo::CreateTargetInfo(Diags, Opts.getTargetOpts()));
if (!Target)
return 0;
}
// Set the target ABI if specified.
if (!Opts.getFrontendOpts().TargetABI.empty() &&
!Target->setABI(Opts.getFrontendOpts().TargetABI)) {
Diags.Report(diag::err_fe_unknown_target_abi)
<< Opts.getFrontendOpts().TargetABI;
return 0;
}
// Initialize backend options, which may also be used to key some language
// options.
InitializeCodeGenOptions(Opts.getCodeGenOpts(), *Target);
InitializeCodeGenOptions(Opts.getCodeGenOpts());
// Initialize frontend options.
InitializeFrontendOptions(Opts.getFrontendOpts());
// Determine the input language, we currently require all files to match.
FrontendOptions::InputKind IK = Opts.getFrontendOpts().Inputs[0].first;
@ -231,7 +215,7 @@ ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags,
Opts.getCodeGenOpts().NoCommon = 1;
Opts.getCodeGenOpts().TimePasses = Opts.getFrontendOpts().ShowTimers;
return Target;
return Target.take();
}
int main(int argc, char **argv) {