forked from OSchip/llvm-project
Implemented initial support for "-triple" option to the clang driver. This
replaces the functionality previously provided by just "-arch" (which is still supported but has different semantics). The new behavior is as follows: (1) If the user does not specify -triple: (a) If no -arch options are specified, the target triple used is the host triple (in llvm/Config/config.h). (b) If one or more -arch's are specified (and no -triple), then there is one triple for each -arch, where the specified arch is substituted for the arch in the host triple. Example: host triple = i686-apple-darwin9 command: clang -arch ppc -arch ppc64 ... triples used: ppc-apple-darwin9 ppc64-apple-darwin9 (2) The user does specify a -triple (only one allowed): (a) If no -arch options are specified, the triple specified by -triple is used. E.g clang -triple i686-apple-darwin9 (b) If one or more -arch options are specified, then the triple specified by -triple is used as the primary target, and the arch's specified by -arch are used to create secondary targets. For example: clang -triple i686-apple-darwin9 -arch ppc -arch ppc64 has the following targets: i686-apple-darwin9 (primary target) ppc-apple-darwin9 ppc64-apple-darwin9 Other changes related to the changes to the driver: - TargetInfoImpl now includes the triple string. - TargetInfo::getTargetTriple returns the triple for its primary target. - test case test/Parser/portability.c has been updated because "-arch linux" is no longer valid ("linux" is an OS, not an arch); instead we use a bogus architecture "bogusW16W16" where WCharWidth=16 and WCharAlign=16. llvm-svn: 44551
This commit is contained in:
parent
e5a91b4924
commit
b061554caa
|
@ -52,6 +52,10 @@ void TargetInfo::getLongDoubleInfo(uint64_t &Size, unsigned &Align,
|
|||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const char* TargetInfo::getTargetTriple() const {
|
||||
return PrimaryTarget->getTargetTriple();
|
||||
}
|
||||
|
||||
/// DiagnoseNonPortability - When a use of a non-portable target feature is
|
||||
/// used, this method emits the diagnostic and marks the translation unit as
|
||||
/// non-portable.
|
||||
|
|
|
@ -18,25 +18,11 @@
|
|||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
/// Note: a hard coded list of targets is clearly silly, these should be
|
||||
/// dynamicly registered and loadable with "-load".
|
||||
enum SupportedTargets {
|
||||
target_ppc, target_ppc64,
|
||||
target_i386, target_x86_64,
|
||||
target_linux_i386
|
||||
};
|
||||
|
||||
static llvm::cl::list<SupportedTargets>
|
||||
Archs("arch", llvm::cl::desc("Architectures to compile for"),
|
||||
llvm::cl::values(clEnumValN(target_ppc, "ppc", "32-bit Darwin PowerPC"),
|
||||
clEnumValN(target_ppc64, "ppc64", "64-bit Darwin PowerPC"),
|
||||
clEnumValN(target_i386, "i386", "32-bit Darwin X86"),
|
||||
clEnumValN(target_x86_64, "x86_64","64-bit Darwin X86"),
|
||||
clEnumValN(target_linux_i386,"linux", "Linux i386"),
|
||||
clEnumValEnd));
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Common code shared among targets.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -55,6 +41,8 @@ static void Define(std::vector<char> &Buf, const char *Macro,
|
|||
namespace {
|
||||
class DarwinTargetInfo : public TargetInfoImpl {
|
||||
public:
|
||||
DarwinTargetInfo(const std::string& triple) : TargetInfoImpl(triple) {}
|
||||
|
||||
virtual void getTargetDefines(std::vector<char> &Defs) const {
|
||||
// FIXME: we need a real target configuration system. For now, only define
|
||||
// __APPLE__ if the host has it.
|
||||
|
@ -504,6 +492,8 @@ namespace X86 {
|
|||
namespace {
|
||||
class DarwinPPCTargetInfo : public DarwinTargetInfo {
|
||||
public:
|
||||
DarwinPPCTargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {}
|
||||
|
||||
virtual void getTargetDefines(std::vector<char> &Defines) const {
|
||||
DarwinTargetInfo::getTargetDefines(Defines);
|
||||
getPowerPCDefines(Defines, false);
|
||||
|
@ -536,6 +526,8 @@ public:
|
|||
namespace {
|
||||
class DarwinPPC64TargetInfo : public DarwinTargetInfo {
|
||||
public:
|
||||
DarwinPPC64TargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {}
|
||||
|
||||
virtual void getTargetDefines(std::vector<char> &Defines) const {
|
||||
DarwinTargetInfo::getTargetDefines(Defines);
|
||||
getPowerPCDefines(Defines, true);
|
||||
|
@ -568,6 +560,8 @@ public:
|
|||
namespace {
|
||||
class DarwinI386TargetInfo : public DarwinTargetInfo {
|
||||
public:
|
||||
DarwinI386TargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {}
|
||||
|
||||
virtual void getTargetDefines(std::vector<char> &Defines) const {
|
||||
DarwinTargetInfo::getTargetDefines(Defines);
|
||||
getX86Defines(Defines, false);
|
||||
|
@ -600,6 +594,8 @@ public:
|
|||
namespace {
|
||||
class DarwinX86_64TargetInfo : public DarwinTargetInfo {
|
||||
public:
|
||||
DarwinX86_64TargetInfo(const std::string& triple) :DarwinTargetInfo(triple) {}
|
||||
|
||||
virtual void getTargetDefines(std::vector<char> &Defines) const {
|
||||
DarwinTargetInfo::getTargetDefines(Defines);
|
||||
getX86Defines(Defines, true);
|
||||
|
@ -632,7 +628,7 @@ public:
|
|||
namespace {
|
||||
class LinuxTargetInfo : public DarwinTargetInfo {
|
||||
public:
|
||||
LinuxTargetInfo() {
|
||||
LinuxTargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {
|
||||
// Note: I have no idea if this is right, just for testing.
|
||||
WCharWidth = 16;
|
||||
WCharAlign = 16;
|
||||
|
@ -672,48 +668,52 @@ public:
|
|||
// Driver code
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static bool IsX86(const std::string& TT) {
|
||||
return (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
|
||||
TT[4] == '-' && TT[1] - '3' < 6);
|
||||
}
|
||||
|
||||
/// CreateTarget - Create the TargetInfoImpl object for the specified target
|
||||
/// enum value.
|
||||
static TargetInfoImpl *CreateTarget(SupportedTargets T) {
|
||||
switch (T) {
|
||||
default: assert(0 && "Unknown target!");
|
||||
case target_ppc: return new DarwinPPCTargetInfo();
|
||||
case target_ppc64: return new DarwinPPC64TargetInfo();
|
||||
case target_i386: return new DarwinI386TargetInfo();
|
||||
case target_x86_64: return new DarwinX86_64TargetInfo();
|
||||
case target_linux_i386: return new LinuxTargetInfo();
|
||||
static TargetInfoImpl *CreateTarget(const std::string& T) {
|
||||
if (T.find("darwin") != std::string::npos) {
|
||||
if (T.find("ppc-") == 0)
|
||||
return new DarwinPPCTargetInfo(T);
|
||||
else if (T.find("ppc64-") == 0)
|
||||
return new DarwinPPC64TargetInfo(T);
|
||||
else if (T.find("x86_64-") == 0)
|
||||
return new DarwinX86_64TargetInfo(T);
|
||||
else if (IsX86(T))
|
||||
return new DarwinI386TargetInfo(T);
|
||||
else if (T.find("bogusW16W16-") == 0) // For testing portability.
|
||||
return new LinuxTargetInfo(T);
|
||||
}
|
||||
else {
|
||||
// Make a copy of the triple that is all lowercase.
|
||||
std::string T_lower(T);
|
||||
std::transform(T_lower.begin(), T_lower.end(),
|
||||
T_lower.begin(), (int(*)(int)) std::tolower);
|
||||
|
||||
if (T_lower.find("linux") != std::string::npos && IsX86(T))
|
||||
return new LinuxTargetInfo(T);
|
||||
}
|
||||
|
||||
assert (false && "Unknown target!");
|
||||
}
|
||||
|
||||
/// CreateTargetInfo - Return the set of target info objects as specified by
|
||||
/// the -arch command line option.
|
||||
TargetInfo *clang::CreateTargetInfo(Diagnostic &Diags) {
|
||||
// If the user didn't specify at least one architecture, auto-sense the
|
||||
// current host. TODO: This is a hack. :)
|
||||
if (Archs.empty()) {
|
||||
#ifndef __APPLE__
|
||||
// Assume non-apple = i386 for now.
|
||||
Archs.push_back(target_i386);
|
||||
#elif (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
|
||||
defined(__ppc64__)
|
||||
Archs.push_back(target_ppc64);
|
||||
#elif defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
|
||||
Archs.push_back(target_ppc);
|
||||
#elif defined(__x86_64__)
|
||||
Archs.push_back(target_x86_64);
|
||||
#elif defined(__i386__) || defined(i386) || defined(_M_IX86)
|
||||
Archs.push_back(target_i386);
|
||||
#else
|
||||
// Don't know what this is!
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
TargetInfo *clang::CreateTargetInfo(const std::vector<std::string>& triples,
|
||||
Diagnostic &Diags) {
|
||||
|
||||
assert (!triples.empty() && "No target triple.");
|
||||
|
||||
// Create the primary target and target info.
|
||||
TargetInfo *TI = new TargetInfo(CreateTarget(Archs[0]), &Diags);
|
||||
TargetInfo *TI = new TargetInfo(CreateTarget(triples[0]), &Diags);
|
||||
|
||||
// Add all secondary targets.
|
||||
for (unsigned i = 1, e = Archs.size(); i != e; ++i)
|
||||
TI->AddSecondaryTarget(CreateTarget(Archs[i]));
|
||||
for (unsigned i = 1, e = triples.size(); i != e; ++i)
|
||||
TI->AddSecondaryTarget(CreateTarget(triples[i]));
|
||||
|
||||
return TI;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/System/Signals.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include <memory>
|
||||
using namespace clang;
|
||||
|
||||
|
@ -389,6 +390,67 @@ static void InitializeDiagnostics(Diagnostic &Diags) {
|
|||
Diags.setDiagnosticMapping(diag::warn_floatingpoint_eq, diag::MAP_IGNORE);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Target Triple Processing.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static llvm::cl::opt<std::string>
|
||||
TargetTriple("triple",
|
||||
llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)."));
|
||||
|
||||
static llvm::cl::list<std::string>
|
||||
Archs("arch",
|
||||
llvm::cl::desc("Specify target architecture (e.g. i686)."));
|
||||
|
||||
namespace {
|
||||
class TripleProcessor {
|
||||
llvm::StringMap<char> TriplesProcessed;
|
||||
std::vector<std::string>& triples;
|
||||
public:
|
||||
TripleProcessor(std::vector<std::string>& t) : triples(t) {}
|
||||
|
||||
void addTriple(const std::string& t) {
|
||||
if (TriplesProcessed.find(t.c_str(),t.c_str()+t.size()) ==
|
||||
TriplesProcessed.end()) {
|
||||
triples.push_back(t);
|
||||
TriplesProcessed.GetOrCreateValue(t.c_str(),t.c_str()+t.size());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static void CreateTargetTriples(std::vector<std::string>& triples) {
|
||||
std::string base_triple;
|
||||
|
||||
// Initialize base triple. If a -triple option has been specified, use
|
||||
// that triple. Otherwise, default to the host triple.
|
||||
if (TargetTriple.getValue().empty())
|
||||
base_triple = LLVM_HOSTTRIPLE;
|
||||
else
|
||||
base_triple = TargetTriple.getValue();
|
||||
|
||||
// Decompose the base triple into "arch" and suffix.
|
||||
std::string::size_type firstDash = base_triple.find("-");
|
||||
|
||||
// FIXME: Make this a diagnostic.
|
||||
assert (firstDash != std::string::npos);
|
||||
|
||||
std::string suffix(base_triple,firstDash+1);
|
||||
// FIXME: Make this a diagnostic.
|
||||
assert (!suffix.empty());
|
||||
|
||||
// Create triple cacher.
|
||||
TripleProcessor tp(triples);
|
||||
|
||||
// Add the primary triple to our set of triples if we are using the
|
||||
// host-triple with no archs or using a specified target triple.
|
||||
if (!TargetTriple.getValue().empty() || Archs.empty())
|
||||
tp.addTriple(base_triple);
|
||||
|
||||
for (unsigned i = 0, e = Archs.size(); i !=e; ++i)
|
||||
tp.addTriple(Archs[i] + "-" + suffix);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Preprocessor Initialization
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -914,7 +976,19 @@ int main(int argc, char **argv) {
|
|||
// Get information about the targets being compiled for. Note that this
|
||||
// pointer and the TargetInfoImpl objects are never deleted by this toy
|
||||
// driver.
|
||||
TargetInfo *Target = CreateTargetInfo(Diags);
|
||||
TargetInfo *Target;
|
||||
|
||||
{ // Create triples, and create the TargetInfo.
|
||||
std::vector<std::string> triples;
|
||||
CreateTargetTriples(triples);
|
||||
fprintf(stderr, "Targets:");
|
||||
for (std::vector<std::string>::iterator I = triples.begin(), E = triples.end(); I !=E ; ++I)
|
||||
fprintf (stderr, " %s", I->c_str());
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
Target = CreateTargetInfo(triples,Diags);
|
||||
}
|
||||
|
||||
if (Target == 0) {
|
||||
fprintf(stderr,
|
||||
"Sorry, don't know what target this is, please use -arch.\n");
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#ifndef LLVM_CLANG_CLANG_H
|
||||
#define LLVM_CLANG_CLANG_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
class Preprocessor;
|
||||
struct LangOptions;
|
||||
|
@ -33,7 +36,8 @@ MinimalAction *CreatePrintParserActionsAction(IdentifierTable &);
|
|||
|
||||
/// CreateTargetInfo - Return the set of target info objects as specified by
|
||||
/// the -arch command line option.
|
||||
TargetInfo *CreateTargetInfo(Diagnostic &Diags);
|
||||
TargetInfo *CreateTargetInfo(const std::vector<std::string>& triples,
|
||||
Diagnostic &Diags);
|
||||
|
||||
/// EmitLLVMFromASTs - Implement -emit-llvm, which generates llvm IR from C.
|
||||
void EmitLLVMFromASTs(Preprocessor &PP, unsigned MainFileID,
|
||||
|
|
|
@ -245,11 +245,10 @@ public:
|
|||
return static_cast<unsigned>(Size);
|
||||
}
|
||||
|
||||
const char *getTargetTriple() {
|
||||
// FIXME !
|
||||
return "i686-apple-darwin9";
|
||||
}
|
||||
const char *getTargetDescription() {
|
||||
/// getTargetTriple - Return the target triple of the primary target.
|
||||
const char *getTargetTriple() const;
|
||||
|
||||
const char *getTargetDescription() const {
|
||||
// FIXME !
|
||||
// Hard code darwin-x86 for now.
|
||||
return "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:\
|
||||
|
@ -270,10 +269,17 @@ class TargetInfoImpl {
|
|||
protected:
|
||||
unsigned WCharWidth; /// sizeof(wchar_t) in bits. Default value is 32.
|
||||
unsigned WCharAlign; /// alignof(wchar_t) in bits. Default value is 32.
|
||||
std::string Triple;
|
||||
public:
|
||||
TargetInfoImpl() : WCharWidth(32), WCharAlign(32) {}
|
||||
TargetInfoImpl(const std::string& triple)
|
||||
: WCharWidth(32), WCharAlign(32), Triple(triple) {}
|
||||
|
||||
virtual ~TargetInfoImpl() {}
|
||||
|
||||
/// getTargetTriple - Return the string representing the target triple this
|
||||
/// TargetInfoImpl object was created from.
|
||||
const char* getTargetTriple() const { return Triple.c_str(); }
|
||||
|
||||
/// getTargetDefines - Return a list of the target-specific #define values set
|
||||
/// when compiling to this target. Each string should be of the form
|
||||
/// "#define X Y\n".
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang -arch ppc -arch linux -fsyntax-only %s 2>&1 | grep note | wc -l | grep 1
|
||||
// RUN: clang -arch ppc -arch bogusW16W16 -fsyntax-only %s 2>&1 | grep note | wc -l | grep 1
|
||||
|
||||
// wchar_t varies across targets.
|
||||
void *X = L"foo";
|
||||
|
|
Loading…
Reference in New Issue