summaryrefslogtreecommitdiffstats
path: root/clang/lib/Basic
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Basic')
-rw-r--r--clang/lib/Basic/Diagnostic.cpp232
-rw-r--r--clang/lib/Basic/FileManager.cpp275
-rw-r--r--clang/lib/Basic/IdentifierTable.cpp551
-rw-r--r--clang/lib/Basic/LangOptions.cpp58
-rw-r--r--clang/lib/Basic/Makefile22
-rw-r--r--clang/lib/Basic/SourceLocation.cpp79
-rw-r--r--clang/lib/Basic/SourceManager.cpp574
-rw-r--r--clang/lib/Basic/TargetInfo.cpp210
-rw-r--r--clang/lib/Basic/Targets.cpp757
-rw-r--r--clang/lib/Basic/TokenKinds.cpp29
10 files changed, 2787 insertions, 0 deletions
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
new file mode 100644
index 00000000000..f62b8f126cd
--- /dev/null
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -0,0 +1,232 @@
+//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Diagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cassert>
+#include <vector>
+#include <map>
+#include <cstring>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Builtin Diagnostic information
+//===----------------------------------------------------------------------===//
+
+/// Flag values for diagnostics.
+enum {
+ // Diagnostic classes.
+ NOTE = 0x01,
+ WARNING = 0x02,
+ EXTENSION = 0x03,
+ ERROR = 0x04,
+ class_mask = 0x07
+};
+
+/// DiagnosticFlags - A set of flags, or'd together, that describe the
+/// diagnostic.
+static unsigned char DiagnosticFlags[] = {
+#define DIAG(ENUM,FLAGS,DESC) FLAGS,
+#include "clang/Basic/DiagnosticKinds.def"
+ 0
+};
+
+/// getDiagClass - Return the class field of the diagnostic.
+///
+static unsigned getBuiltinDiagClass(unsigned DiagID) {
+ assert(DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
+ "Diagnostic ID out of range!");
+ return DiagnosticFlags[DiagID] & class_mask;
+}
+
+/// DiagnosticText - An english message to print for the diagnostic. These
+/// should be localized.
+static const char * const DiagnosticText[] = {
+#define DIAG(ENUM,FLAGS,DESC) DESC,
+#include "clang/Basic/DiagnosticKinds.def"
+ 0
+};
+
+//===----------------------------------------------------------------------===//
+// Custom Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ namespace diag {
+ class CustomDiagInfo {
+ typedef std::pair<Diagnostic::Level, std::string> DiagDesc;
+ std::vector<DiagDesc> DiagInfo;
+ std::map<DiagDesc, unsigned> DiagIDs;
+ public:
+
+ /// getDescription - Return the description of the specified custom
+ /// diagnostic.
+ const char *getDescription(unsigned DiagID) const {
+ assert(this && DiagID-diag::NUM_BUILTIN_DIAGNOSTICS < DiagInfo.size() &&
+ "Invalid diagnosic ID");
+ return DiagInfo[DiagID-diag::NUM_BUILTIN_DIAGNOSTICS].second.c_str();
+ }
+
+ /// getLevel - Return the level of the specified custom diagnostic.
+ Diagnostic::Level getLevel(unsigned DiagID) const {
+ assert(this && DiagID-diag::NUM_BUILTIN_DIAGNOSTICS < DiagInfo.size() &&
+ "Invalid diagnosic ID");
+ return DiagInfo[DiagID-diag::NUM_BUILTIN_DIAGNOSTICS].first;
+ }
+
+ unsigned getOrCreateDiagID(Diagnostic::Level L, const char *Message) {
+ DiagDesc D(L, Message);
+ // Check to see if it already exists.
+ std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
+ if (I != DiagIDs.end() && I->first == D)
+ return I->second;
+
+ // If not, assign a new ID.
+ unsigned ID = DiagInfo.size()+diag::NUM_BUILTIN_DIAGNOSTICS;
+ DiagIDs.insert(std::make_pair(D, ID));
+ DiagInfo.push_back(D);
+ return ID;
+ }
+ };
+
+ } // end diag namespace
+} // end clang namespace
+
+
+//===----------------------------------------------------------------------===//
+// Common Diagnostic implementation
+//===----------------------------------------------------------------------===//
+
+Diagnostic::Diagnostic(DiagnosticClient &client) : Client(client) {
+ WarningsAsErrors = false;
+ WarnOnExtensions = false;
+ ErrorOnExtensions = false;
+ // Clear all mappings, setting them to MAP_DEFAULT.
+ memset(DiagMappings, 0, sizeof(DiagMappings));
+
+ ErrorOccurred = false;
+ NumDiagnostics = 0;
+ NumErrors = 0;
+ CustomDiagInfo = 0;
+}
+
+Diagnostic::~Diagnostic() {
+ delete CustomDiagInfo;
+}
+
+/// getCustomDiagID - Return an ID for a diagnostic with the specified message
+/// and level. If this is the first request for this diagnosic, it is
+/// registered and created, otherwise the existing ID is returned.
+unsigned Diagnostic::getCustomDiagID(Level L, const char *Message) {
+ if (CustomDiagInfo == 0)
+ CustomDiagInfo = new diag::CustomDiagInfo();
+ return CustomDiagInfo->getOrCreateDiagID(L, Message);
+}
+
+
+/// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
+/// level of the specified diagnostic ID is a Note, Warning, or Extension.
+/// Note that this only works on builtin diagnostics, not custom ones.
+bool Diagnostic::isBuiltinNoteWarningOrExtension(unsigned DiagID) {
+ return DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
+ getBuiltinDiagClass(DiagID) < ERROR;
+}
+
+
+/// getDescription - Given a diagnostic ID, return a description of the
+/// issue.
+const char *Diagnostic::getDescription(unsigned DiagID) {
+ if (DiagID < diag::NUM_BUILTIN_DIAGNOSTICS)
+ return DiagnosticText[DiagID];
+ else
+ return CustomDiagInfo->getDescription(DiagID);
+}
+
+/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
+/// object, classify the specified diagnostic ID into a Level, consumable by
+/// the DiagnosticClient.
+Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
+ // Handle custom diagnostics, which cannot be mapped.
+ if (DiagID >= diag::NUM_BUILTIN_DIAGNOSTICS)
+ return CustomDiagInfo->getLevel(DiagID);
+
+ unsigned DiagClass = getBuiltinDiagClass(DiagID);
+
+ // Specific non-error diagnostics may be mapped to various levels from ignored
+ // to error.
+ if (DiagClass < ERROR) {
+ switch (getDiagnosticMapping((diag::kind)DiagID)) {
+ case diag::MAP_DEFAULT: break;
+ case diag::MAP_IGNORE: return Ignored;
+ case diag::MAP_WARNING: DiagClass = WARNING; break;
+ case diag::MAP_ERROR: DiagClass = ERROR; break;
+ }
+ }
+
+ // Map diagnostic classes based on command line argument settings.
+ if (DiagClass == EXTENSION) {
+ if (ErrorOnExtensions)
+ DiagClass = ERROR;
+ else if (WarnOnExtensions)
+ DiagClass = WARNING;
+ else
+ return Ignored;
+ }
+
+ // If warnings are to be treated as errors, indicate this as such.
+ if (DiagClass == WARNING && WarningsAsErrors)
+ DiagClass = ERROR;
+
+ switch (DiagClass) {
+ default: assert(0 && "Unknown diagnostic class!");
+ case NOTE: return Diagnostic::Note;
+ case WARNING: return Diagnostic::Warning;
+ case ERROR: return Diagnostic::Error;
+ }
+}
+
+/// Report - Issue the message to the client. If the client wants us to stop
+/// compilation, return true, otherwise return false. DiagID is a member of
+/// the diag::kind enum.
+void Diagnostic::Report(FullSourceLoc Pos, unsigned DiagID,
+ const std::string *Strs, unsigned NumStrs,
+ const SourceRange *Ranges, unsigned NumRanges) {
+
+ // Figure out the diagnostic level of this message.
+ Diagnostic::Level DiagLevel = getDiagnosticLevel(DiagID);
+
+ // If the client doesn't care about this message, don't issue it.
+ if (DiagLevel == Diagnostic::Ignored)
+ return;
+
+ // If this is not an error and we are in a system header, ignore it. We have
+ // to check on the original class here, because we also want to ignore
+ // extensions and warnings in -Werror and -pedantic-errors modes, which *map*
+ // warnings/extensions to errors.
+ if (DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
+ getBuiltinDiagClass(DiagID) != ERROR &&
+ Client.isInSystemHeader(Pos))
+ return;
+
+ if (DiagLevel >= Diagnostic::Error) {
+ ErrorOccurred = true;
+ ++NumErrors;
+ }
+
+ // Finally, report it.
+ Client.HandleDiagnostic(*this, DiagLevel, Pos, (diag::kind)DiagID,
+ Strs, NumStrs, Ranges, NumRanges);
+ ++NumDiagnostics;
+}
+
+DiagnosticClient::~DiagnosticClient() {}
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
new file mode 100644
index 00000000000..cfc08ed084b
--- /dev/null
+++ b/clang/lib/Basic/FileManager.cpp
@@ -0,0 +1,275 @@
+///===--- FileManager.cpp - File System Probing and Caching ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the FileManager interface.
+//
+//===----------------------------------------------------------------------===//
+//
+// TODO: This should index all interesting directories with dirent calls.
+// getdirentries ?
+// opendir/readdir_r/closedir ?
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FileManager.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Bitcode/Serialize.h"
+#include "llvm/Bitcode/Deserialize.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Config/config.h"
+using namespace clang;
+
+// FIXME: Enhance libsystem to support inode and other fields.
+#include <sys/stat.h>
+
+#if defined(_MSC_VER)
+#define S_ISDIR(s) (_S_IFDIR & s)
+#endif
+
+/// NON_EXISTENT_DIR - A special value distinct from null that is used to
+/// represent a dir name that doesn't exist on the disk.
+#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
+
+#ifdef LLVM_ON_WIN32
+
+#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\')
+
+namespace {
+ static std::string GetFullPath(const char *relPath)
+ {
+ char *absPathStrPtr = _fullpath(NULL, relPath, 0);
+ assert(absPathStrPtr && "_fullpath() returned NULL!");
+
+ std::string absPath(absPathStrPtr);
+
+ free(absPathStrPtr);
+ return absPath;
+ }
+}
+
+class FileManager::UniqueDirContainer {
+ /// UniqueDirs - Cache from full path to existing directories/files.
+ ///
+ llvm::StringMap<DirectoryEntry> UniqueDirs;
+
+public:
+ DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
+ std::string FullPath(GetFullPath(Name));
+ return UniqueDirs.GetOrCreateValue(
+ FullPath.c_str(),
+ FullPath.c_str() + FullPath.size()
+ ).getValue();
+ }
+
+ size_t size() { return UniqueDirs.size(); }
+};
+
+class FileManager::UniqueFileContainer {
+ /// UniqueFiles - Cache from full path to existing directories/files.
+ ///
+ llvm::StringMap<FileEntry> UniqueFiles;
+
+public:
+ FileEntry &getFile(const char *Name, struct stat &StatBuf) {
+ std::string FullPath(GetFullPath(Name));
+ return UniqueFiles.GetOrCreateValue(
+ FullPath.c_str(),
+ FullPath.c_str() + FullPath.size()
+ ).getValue();
+ }
+
+ size_t size() { return UniqueFiles.size(); }
+};
+
+#else
+
+#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/')
+
+class FileManager::UniqueDirContainer {
+ /// UniqueDirs - Cache from ID's to existing directories/files.
+ ///
+ std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
+
+public:
+ DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
+ return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
+ }
+
+ size_t size() { return UniqueDirs.size(); }
+};
+
+class FileManager::UniqueFileContainer {
+ /// UniqueFiles - Cache from ID's to existing directories/files.
+ ///
+ std::set<FileEntry> UniqueFiles;
+
+public:
+ FileEntry &getFile(const char *Name, struct stat &StatBuf) {
+ return
+ const_cast<FileEntry&>(
+ *UniqueFiles.insert(FileEntry(StatBuf.st_dev,
+ StatBuf.st_ino)).first);
+ }
+
+ size_t size() { return UniqueFiles.size(); }
+};
+
+#endif
+
+
+FileManager::FileManager() : UniqueDirs(*new UniqueDirContainer),
+ UniqueFiles(*new UniqueFileContainer),
+ DirEntries(64), FileEntries(64), NextFileUID(0)
+{
+ NumDirLookups = NumFileLookups = 0;
+ NumDirCacheMisses = NumFileCacheMisses = 0;
+}
+
+FileManager::~FileManager() {
+ delete &UniqueDirs;
+ delete &UniqueFiles;
+}
+
+
+/// getDirectory - Lookup, cache, and verify the specified directory. This
+/// returns null if the directory doesn't exist.
+///
+const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
+ const char *NameEnd) {
+ ++NumDirLookups;
+ llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
+ DirEntries.GetOrCreateValue(NameStart, NameEnd);
+
+ // See if there is already an entry in the map.
+ if (NamedDirEnt.getValue())
+ return NamedDirEnt.getValue() == NON_EXISTENT_DIR
+ ? 0 : NamedDirEnt.getValue();
+
+ ++NumDirCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedDirEnt.setValue(NON_EXISTENT_DIR);
+
+ // Get the null-terminated directory name as stored as the key of the
+ // DirEntries map.
+ const char *InterndDirName = NamedDirEnt.getKeyData();
+
+ // Check to see if the directory exists.
+ struct stat StatBuf;
+ if (stat(InterndDirName, &StatBuf) || // Error stat'ing.
+ !S_ISDIR(StatBuf.st_mode)) // Not a directory?
+ return 0;
+
+ // It exists. See if we have already opened a directory with the same inode.
+ // This occurs when one dir is symlinked to another, for example.
+ DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf);
+
+ NamedDirEnt.setValue(&UDE);
+ if (UDE.getName()) // Already have an entry with this inode, return it.
+ return &UDE;
+
+ // Otherwise, we don't have this directory yet, add it. We use the string
+ // key from the DirEntries map as the string.
+ UDE.Name = InterndDirName;
+ return &UDE;
+}
+
+/// NON_EXISTENT_FILE - A special value distinct from null that is used to
+/// represent a filename that doesn't exist on the disk.
+#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
+
+/// getFile - Lookup, cache, and verify the specified file. This returns null
+/// if the file doesn't exist.
+///
+const FileEntry *FileManager::getFile(const char *NameStart,
+ const char *NameEnd) {
+ ++NumFileLookups;
+
+ // See if there is already an entry in the map.
+ llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
+ FileEntries.GetOrCreateValue(NameStart, NameEnd);
+
+ // See if there is already an entry in the map.
+ if (NamedFileEnt.getValue())
+ return NamedFileEnt.getValue() == NON_EXISTENT_FILE
+ ? 0 : NamedFileEnt.getValue();
+
+ ++NumFileCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedFileEnt.setValue(NON_EXISTENT_FILE);
+
+ // Figure out what directory it is in. If the string contains a / in it,
+ // strip off everything after it.
+ // FIXME: this logic should be in sys::Path.
+ const char *SlashPos = NameEnd-1;
+ while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
+ --SlashPos;
+
+ const DirectoryEntry *DirInfo;
+ if (SlashPos < NameStart) {
+ // Use the current directory if file has no path component.
+ const char *Name = ".";
+ DirInfo = getDirectory(Name, Name+1);
+ } else if (SlashPos == NameEnd-1)
+ return 0; // If filename ends with a /, it's a directory.
+ else
+ DirInfo = getDirectory(NameStart, SlashPos);
+
+ if (DirInfo == 0) // Directory doesn't exist, file can't exist.
+ return 0;
+
+ // Get the null-terminated file name as stored as the key of the
+ // FileEntries map.
+ const char *InterndFileName = NamedFileEnt.getKeyData();
+
+ // FIXME: Use the directory info to prune this, before doing the stat syscall.
+ // FIXME: This will reduce the # syscalls.
+
+ // Nope, there isn't. Check to see if the file exists.
+ struct stat StatBuf;
+ //llvm::cerr << "STATING: " << Filename;
+ if (stat(InterndFileName, &StatBuf) || // Error stat'ing.
+ S_ISDIR(StatBuf.st_mode)) { // A directory?
+ // If this file doesn't exist, we leave a null in FileEntries for this path.
+ //llvm::cerr << ": Not existing\n";
+ return 0;
+ }
+ //llvm::cerr << ": exists\n";
+
+ // It exists. See if we have already opened a file with the same inode.
+ // This occurs when one dir is symlinked to another, for example.
+ FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf);
+
+ NamedFileEnt.setValue(&UFE);
+ if (UFE.getName()) // Already have an entry with this inode, return it.
+ return &UFE;
+
+ // Otherwise, we don't have this directory yet, add it.
+ // FIXME: Change the name to be a char* that points back to the 'FileEntries'
+ // key.
+ UFE.Name = InterndFileName;
+ UFE.Size = StatBuf.st_size;
+ UFE.ModTime = StatBuf.st_mtime;
+ UFE.Dir = DirInfo;
+ UFE.UID = NextFileUID++;
+ return &UFE;
+}
+
+void FileManager::PrintStats() const {
+ llvm::cerr << "\n*** File Manager Stats:\n";
+ llvm::cerr << UniqueFiles.size() << " files found, "
+ << UniqueDirs.size() << " dirs found.\n";
+ llvm::cerr << NumDirLookups << " dir lookups, "
+ << NumDirCacheMisses << " dir cache misses.\n";
+ llvm::cerr << NumFileLookups << " file lookups, "
+ << NumFileCacheMisses << " file cache misses.\n";
+
+ //llvm::cerr << PagesMapped << BytesOfPagesMapped << FSLookups;
+}
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
new file mode 100644
index 00000000000..65e984a0f78
--- /dev/null
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -0,0 +1,551 @@
+//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IdentifierInfo, IdentifierVisitor, and
+// IdentifierTable interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Bitcode/Serialize.h"
+#include "llvm/Bitcode/Deserialize.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdentifierInfo Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierInfo::IdentifierInfo() {
+ TokenID = tok::identifier;
+ ObjCID = tok::objc_not_keyword;
+ BuiltinID = 0;
+ HasMacro = false;
+ IsExtension = false;
+ IsPoisoned = false;
+ IsCPPOperatorKeyword = false;
+ FETokenInfo = 0;
+}
+
+//===----------------------------------------------------------------------===//
+// IdentifierTable Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
+ // Start with space for 8K identifiers.
+ : HashTable(8192) {
+
+ // Populate the identifier table with info about keywords for the current
+ // language.
+ AddKeywords(LangOpts);
+}
+
+// This cstor is intended to be used only for serialization.
+IdentifierTable::IdentifierTable() : HashTable(8192) {}
+
+//===----------------------------------------------------------------------===//
+// Language Keyword Implementation
+//===----------------------------------------------------------------------===//
+
+/// AddKeyword - This method is used to associate a token ID with specific
+/// identifiers because they are language keywords. This causes the lexer to
+/// automatically map matching identifiers to specialized token codes.
+///
+/// The C90/C99/CPP/CPP0x flags are set to 0 if the token should be
+/// enabled in the specified langauge, set to 1 if it is an extension
+/// in the specified language, and set to 2 if disabled in the
+/// specified language.
+static void AddKeyword(const char *Keyword, unsigned KWLen,
+ tok::TokenKind TokenCode,
+ int C90, int C99, int CXX, int CXX0x, int BoolSupport,
+ const LangOptions &LangOpts, IdentifierTable &Table) {
+ int Flags = 0;
+ if (BoolSupport != 0) {
+ Flags = LangOpts.Boolean ? BoolSupport : 2;
+ } else if (LangOpts.CPlusPlus) {
+ Flags = LangOpts.CPlusPlus0x ? CXX0x : CXX;
+ } else if (LangOpts.C99) {
+ Flags = C99;
+ } else {
+ Flags = C90;
+ }
+
+ // Don't add this keyword if disabled in this language or if an extension
+ // and extensions are disabled.
+ if (Flags + LangOpts.NoExtensions >= 2) return;
+
+ IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
+ Info.setTokenID(TokenCode);
+ Info.setIsExtensionToken(Flags == 1);
+}
+
+static void AddAlias(const char *Keyword, unsigned KWLen,
+ tok::TokenKind AliaseeID,
+ const char *AliaseeKeyword, unsigned AliaseeKWLen,
+ const LangOptions &LangOpts, IdentifierTable &Table) {
+ IdentifierInfo &AliasInfo = Table.get(Keyword, Keyword+KWLen);
+ IdentifierInfo &AliaseeInfo = Table.get(AliaseeKeyword,
+ AliaseeKeyword+AliaseeKWLen);
+ AliasInfo.setTokenID(AliaseeID);
+ AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
+}
+
+/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
+/// representations.
+static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
+ tok::TokenKind TokenCode,
+ IdentifierTable &Table) {
+ IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
+ Info.setTokenID(TokenCode);
+ Info.setIsCPlusPlusOperatorKeyword();
+}
+
+/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
+/// "property".
+static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
+ const char *Name, unsigned NameLen,
+ IdentifierTable &Table) {
+ Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
+}
+
+/// AddKeywords - Add all keywords to the symbol table.
+///
+void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
+ enum {
+ C90Shift = 0,
+ EXTC90 = 1 << C90Shift,
+ NOTC90 = 2 << C90Shift,
+ C99Shift = 2,
+ EXTC99 = 1 << C99Shift,
+ NOTC99 = 2 << C99Shift,
+ CPPShift = 4,
+ EXTCPP = 1 << CPPShift,
+ NOTCPP = 2 << CPPShift,
+ CPP0xShift = 6,
+ EXTCPP0x = 1 << CPP0xShift,
+ NOTCPP0x = 2 << CPP0xShift,
+ BoolShift = 8,
+ BOOLSUPPORT = 1 << BoolShift,
+ Mask = 3
+ };
+
+ // Add keywords and tokens for the current language.
+#define KEYWORD(NAME, FLAGS) \
+ AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
+ ((FLAGS) >> C90Shift) & Mask, \
+ ((FLAGS) >> C99Shift) & Mask, \
+ ((FLAGS) >> CPPShift) & Mask, \
+ ((FLAGS) >> CPP0xShift) & Mask, \
+ ((FLAGS) >> BoolShift) & Mask, LangOpts, *this);
+#define ALIAS(NAME, TOK) \
+ AddAlias(NAME, strlen(NAME), tok::kw_ ## TOK, #TOK, strlen(#TOK), \
+ LangOpts, *this);
+#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
+ if (LangOpts.CXXOperatorNames) \
+ AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
+#define OBJC1_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC1) \
+ AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
+#define OBJC2_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC2) \
+ AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
+#include "clang/Basic/TokenKinds.def"
+}
+
+tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
+ // We use a perfect hash function here involving the length of the keyword,
+ // the first and third character. For preprocessor ID's there are no
+ // collisions (if there were, the switch below would complain about duplicate
+ // case values). Note that this depends on 'if' being null terminated.
+
+#define HASH(LEN, FIRST, THIRD) \
+ (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
+#define CASE(LEN, FIRST, THIRD, NAME) \
+ case HASH(LEN, FIRST, THIRD): \
+ return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
+
+ unsigned Len = getLength();
+ if (Len < 2) return tok::pp_not_keyword;
+ const char *Name = getName();
+ switch (HASH(Len, Name[0], Name[2])) {
+ default: return tok::pp_not_keyword;
+ CASE( 2, 'i', '\0', if);
+ CASE( 4, 'e', 'i', elif);
+ CASE( 4, 'e', 's', else);
+ CASE( 4, 'l', 'n', line);
+ CASE( 4, 's', 'c', sccs);
+ CASE( 5, 'e', 'd', endif);
+ CASE( 5, 'e', 'r', error);
+ CASE( 5, 'i', 'e', ident);
+ CASE( 5, 'i', 'd', ifdef);
+ CASE( 5, 'u', 'd', undef);
+
+ CASE( 6, 'a', 's', assert);
+ CASE( 6, 'd', 'f', define);
+ CASE( 6, 'i', 'n', ifndef);
+ CASE( 6, 'i', 'p', import);
+ CASE( 6, 'p', 'a', pragma);
+
+ CASE( 7, 'd', 'f', defined);
+ CASE( 7, 'i', 'c', include);
+ CASE( 7, 'w', 'r', warning);
+
+ CASE( 8, 'u', 'a', unassert);
+ CASE(12, 'i', 'c', include_next);
+#undef CASE
+#undef HASH
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Stats Implementation
+//===----------------------------------------------------------------------===//
+
+/// PrintStats - Print statistics about how well the identifier table is doing
+/// at hashing identifiers.
+void IdentifierTable::PrintStats() const {
+ unsigned NumBuckets = HashTable.getNumBuckets();
+ unsigned NumIdentifiers = HashTable.getNumItems();
+ unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
+ unsigned AverageIdentifierSize = 0;
+ unsigned MaxIdentifierLength = 0;
+
+ // TODO: Figure out maximum times an identifier had to probe for -stats.
+ for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
+ I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
+ unsigned IdLen = I->getKeyLength();
+ AverageIdentifierSize += IdLen;
+ if (MaxIdentifierLength < IdLen)
+ MaxIdentifierLength = IdLen;
+ }
+
+ fprintf(stderr, "\n*** Identifier Table Stats:\n");
+ fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
+ fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
+ fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
+ NumIdentifiers/(double)NumBuckets);
+ fprintf(stderr, "Ave identifier length: %f\n",
+ (AverageIdentifierSize/(double)NumIdentifiers));
+ fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
+
+ // Compute statistics about the memory allocated for identifiers.
+ HashTable.getAllocator().PrintStats();
+}
+
+//===----------------------------------------------------------------------===//
+// SelectorTable Implementation
+//===----------------------------------------------------------------------===//
+
+unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
+ return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
+}
+
+
+/// MultiKeywordSelector - One of these variable length records is kept for each
+/// selector containing more than one keyword. We use a folding set
+/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
+/// this class is provided strictly through Selector.
+namespace clang {
+class MultiKeywordSelector : public llvm::FoldingSetNode {
+ friend SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer&);
+ MultiKeywordSelector(unsigned nKeys) : NumArgs(nKeys) {}
+public:
+ unsigned NumArgs;
+
+ // Constructor for keyword selectors.
+ MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
+ assert((nKeys > 1) && "not a multi-keyword selector");
+ NumArgs = nKeys;
+
+ // Fill in the trailing keyword array.
+ IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
+ for (unsigned i = 0; i != nKeys; ++i)
+ KeyInfo[i] = IIV[i];
+ }
+
+ // getName - Derive the full selector name and return it.
+ std::string getName() const;
+
+ unsigned getNumArgs() const { return NumArgs; }
+
+ typedef IdentifierInfo *const *keyword_iterator;
+ keyword_iterator keyword_begin() const {
+ return reinterpret_cast<keyword_iterator>(this+1);
+ }
+ keyword_iterator keyword_end() const {
+ return keyword_begin()+NumArgs;
+ }
+ IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
+ assert(i < NumArgs && "getIdentifierInfoForSlot(): illegal index");
+ return keyword_begin()[i];
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ keyword_iterator ArgTys, unsigned NumArgs) {
+ ID.AddInteger(NumArgs);
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ID.AddPointer(ArgTys[i]);
+ }
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, keyword_begin(), NumArgs);
+ }
+};
+} // end namespace clang.
+
+unsigned Selector::getNumArgs() const {
+ unsigned IIF = getIdentifierInfoFlag();
+ if (IIF == ZeroArg)
+ return 0;
+ if (IIF == OneArg)
+ return 1;
+ // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
+ MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
+ return SI->getNumArgs();
+}
+
+IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
+ if (IdentifierInfo *II = getAsIdentifierInfo()) {
+ assert(argIndex == 0 && "illegal keyword index");
+ return II;
+ }
+ // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
+ MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
+ return SI->getIdentifierInfoForSlot(argIndex);
+}
+
+std::string MultiKeywordSelector::getName() const {
+ std::string Result;
+ unsigned Length = 0;
+ for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
+ if (*I)
+ Length += (*I)->getLength();
+ ++Length; // :
+ }
+
+ Result.reserve(Length);
+
+ for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
+ if (*I)
+ Result.insert(Result.end(), (*I)->getName(),
+ (*I)->getName()+(*I)->getLength());
+ Result.push_back(':');
+ }
+
+ return Result;
+}
+
+std::string Selector::getName() const {
+ if (IdentifierInfo *II = getAsIdentifierInfo()) {
+ if (getNumArgs() == 0)
+ return II->getName();
+
+ std::string Res = II->getName();
+ Res += ":";
+ return Res;
+ }
+
+ // We have a multiple keyword selector (no embedded flags).
+ return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
+}
+
+
+Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
+ if (nKeys < 2)
+ return Selector(IIV[0], nKeys);
+
+ llvm::FoldingSet<MultiKeywordSelector> *SelTab;
+
+ SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
+
+ // Unique selector, to guarantee there is one per name.
+ llvm::FoldingSetNodeID ID;
+ MultiKeywordSelector::Profile(ID, IIV, nKeys);
+
+ void *InsertPos = 0;
+ if (MultiKeywordSelector *SI = SelTab->FindNodeOrInsertPos(ID, InsertPos))
+ return Selector(SI);
+
+ // MultiKeywordSelector objects are not allocated with new because they have a
+ // variable size array (for parameter types) at the end of them.
+ MultiKeywordSelector *SI =
+ (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
+ nKeys*sizeof(IdentifierInfo *));
+ new (SI) MultiKeywordSelector(nKeys, IIV);
+ SelTab->InsertNode(SI, InsertPos);
+ return Selector(SI);
+}
+
+SelectorTable::SelectorTable() {
+ Impl = new llvm::FoldingSet<MultiKeywordSelector>;
+}
+
+SelectorTable::~SelectorTable() {
+ delete static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
+}
+
+//===----------------------------------------------------------------------===//
+// Serialization for IdentifierInfo and IdentifierTable.
+//===----------------------------------------------------------------------===//
+
+void IdentifierInfo::Emit(llvm::Serializer& S) const {
+ S.EmitInt(getTokenID());
+ S.EmitInt(getBuiltinID());
+ S.EmitInt(getObjCKeywordID());
+ S.EmitBool(hasMacroDefinition());
+ S.EmitBool(isExtensionToken());
+ S.EmitBool(isPoisoned());
+ S.EmitBool(isCPlusPlusOperatorKeyword());
+ // FIXME: FETokenInfo
+}
+
+void IdentifierInfo::Read(llvm::Deserializer& D) {
+ setTokenID((tok::TokenKind) D.ReadInt());
+ setBuiltinID(D.ReadInt());
+ setObjCKeywordID((tok::ObjCKeywordKind) D.ReadInt());
+ setHasMacroDefinition(D.ReadBool());
+ setIsExtensionToken(D.ReadBool());
+ setIsPoisoned(D.ReadBool());
+ setIsCPlusPlusOperatorKeyword(D.ReadBool());
+ // FIXME: FETokenInfo
+}
+
+void IdentifierTable::Emit(llvm::Serializer& S) const {
+ S.EnterBlock();
+
+ S.EmitPtr(this);
+
+ for (iterator I=begin(), E=end(); I != E; ++I) {
+ const char* Key = I->getKeyData();
+ const IdentifierInfo* Info = &I->getValue();
+
+ bool KeyRegistered = S.isRegistered(Key);
+ bool InfoRegistered = S.isRegistered(Info);
+
+ if (KeyRegistered || InfoRegistered) {
+ // These acrobatics are so that we don't incur the cost of registering
+ // a pointer with the backpatcher during deserialization if nobody
+ // references the object.
+ S.EmitPtr(InfoRegistered ? Info : NULL);
+ S.EmitPtr(KeyRegistered ? Key : NULL);
+ S.EmitCStr(Key);
+ S.Emit(*Info);
+ }
+ }
+
+ S.ExitBlock();
+}
+
+IdentifierTable* IdentifierTable::CreateAndRegister(llvm::Deserializer& D) {
+ llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
+
+ std::vector<char> buff;
+ buff.reserve(200);
+
+ IdentifierTable* t = new IdentifierTable();
+ D.RegisterPtr(t);
+
+ while (!D.FinishedBlock(BLoc)) {
+ llvm::SerializedPtrID InfoPtrID = D.ReadPtrID();
+ llvm::SerializedPtrID KeyPtrID = D.ReadPtrID();
+
+ D.ReadCStr(buff);
+
+ llvm::StringMapEntry<IdentifierInfo>& Entry =
+ t->HashTable.GetOrCreateValue(&buff[0],&buff[0]+buff.size());
+
+ D.Read(Entry.getValue());
+
+ if (InfoPtrID)
+ D.RegisterRef(InfoPtrID,Entry.getValue());
+
+ if (KeyPtrID)
+ D.RegisterPtr(KeyPtrID,Entry.getKeyData());
+ }
+
+ return t;
+}
+
+//===----------------------------------------------------------------------===//
+// Serialization for Selector and SelectorTable.
+//===----------------------------------------------------------------------===//
+
+void Selector::Emit(llvm::Serializer& S) const {
+ S.EmitInt(getIdentifierInfoFlag());
+ S.EmitPtr(reinterpret_cast<void*>(InfoPtr & ~ArgFlags));
+}
+
+Selector Selector::ReadVal(llvm::Deserializer& D) {
+ unsigned flag = D.ReadInt();
+
+ uintptr_t ptr;
+ D.ReadUIntPtr(ptr,false); // No backpatching.
+
+ return Selector(ptr | flag);
+}
+
+void SelectorTable::Emit(llvm::Serializer& S) const {
+ typedef llvm::FoldingSet<MultiKeywordSelector>::iterator iterator;
+ llvm::FoldingSet<MultiKeywordSelector> *SelTab;
+ SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
+
+ S.EnterBlock();
+
+ S.EmitPtr(this);
+
+ for (iterator I=SelTab->begin(), E=SelTab->end(); I != E; ++I) {
+ if (!S.isRegistered(&*I))
+ continue;
+
+ S.FlushRecord(); // Start a new record.
+
+ S.EmitPtr(&*I);
+ S.EmitInt(I->getNumArgs());
+
+ for (MultiKeywordSelector::keyword_iterator KI = I->keyword_begin(),
+ KE = I->keyword_end(); KI != KE; ++KI)
+ S.EmitPtr(*KI);
+ }
+
+ S.ExitBlock();
+}
+
+SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer& D) {
+ llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
+
+ SelectorTable* t = new SelectorTable();
+ D.RegisterPtr(t);
+
+ llvm::FoldingSet<MultiKeywordSelector>& SelTab =
+ *static_cast<llvm::FoldingSet<MultiKeywordSelector>*>(t->Impl);
+
+ while (!D.FinishedBlock(BLoc)) {
+
+ llvm::SerializedPtrID PtrID = D.ReadPtrID();
+ unsigned nKeys = D.ReadInt();
+
+ MultiKeywordSelector *SI =
+ (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
+ nKeys*sizeof(IdentifierInfo *));
+
+ new (SI) MultiKeywordSelector(nKeys);
+
+ D.RegisterPtr(PtrID,SI);
+
+ IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(SI+1);
+
+ for (unsigned i = 0; i != nKeys; ++i)
+ D.ReadPtr(KeyInfo[i],false);
+
+ SelTab.GetOrInsertNode(SI);
+ }
+
+ return t;
+}
diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp
new file mode 100644
index 00000000000..f7fd91fbda5
--- /dev/null
+++ b/clang/lib/Basic/LangOptions.cpp
@@ -0,0 +1,58 @@
+//===--- LangOptions.cpp - Language feature info --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the methods for LangOptions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Bitcode/Serialize.h"
+#include "llvm/Bitcode/Deserialize.h"
+
+using namespace clang;
+
+void LangOptions::Emit(llvm::Serializer& S) const {
+ S.EmitBool((bool) Trigraphs);
+ S.EmitBool((bool) BCPLComment);
+ S.EmitBool((bool) DollarIdents);
+ S.EmitBool((bool) Digraphs);
+ S.EmitBool((bool) HexFloats);
+ S.EmitBool((bool) C99);
+ S.EmitBool((bool) Microsoft);
+ S.EmitBool((bool) CPlusPlus);
+ S.EmitBool((bool) CPlusPlus0x);
+ S.EmitBool((bool) NoExtensions);
+ S.EmitBool((bool) CXXOperatorNames);
+ S.EmitBool((bool) ObjC1);
+ S.EmitBool((bool) ObjC2);
+ S.EmitBool((bool) PascalStrings);
+ S.EmitBool((bool) Boolean);
+ S.EmitBool((bool) WritableStrings);
+ S.EmitBool((bool) LaxVectorConversions);
+}
+
+void LangOptions::Read(llvm::Deserializer& D) {
+ Trigraphs = D.ReadBool() ? 1 : 0;
+ BCPLComment = D.ReadBool() ? 1 : 0;
+ DollarIdents = D.ReadBool() ? 1 : 0;
+ Digraphs = D.ReadBool() ? 1 : 0;
+ HexFloats = D.ReadBool() ? 1 : 0;
+ C99 = D.ReadBool() ? 1 : 0;
+ Microsoft = D.ReadBool() ? 1 : 0;
+ CPlusPlus = D.ReadBool() ? 1 : 0;
+ CPlusPlus0x = D.ReadBool() ? 1 : 0;
+ NoExtensions = D.ReadBool() ? 1 : 0;
+ CXXOperatorNames = D.ReadBool() ? 1 : 0;
+ ObjC1 = D.ReadBool() ? 1 : 0;
+ ObjC2 = D.ReadBool() ? 1 : 0;
+ PascalStrings = D.ReadBool() ? 1 : 0;
+ Boolean = D.ReadBool() ? 1 : 0;
+ WritableStrings = D.ReadBool() ? 1 : 0;
+ LaxVectorConversions = D.ReadBool() ? 1 : 0;
+}
diff --git a/clang/lib/Basic/Makefile b/clang/lib/Basic/Makefile
new file mode 100644
index 00000000000..e95d6dbfa35
--- /dev/null
+++ b/clang/lib/Basic/Makefile
@@ -0,0 +1,22 @@
+##===- clang/lib/Basic/Makefile ----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This implements the Basic library for the C-Language front-end.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME := clangBasic
+BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
+
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include
+
+include $(LEVEL)/Makefile.common
+
diff --git a/clang/lib/Basic/SourceLocation.cpp b/clang/lib/Basic/SourceLocation.cpp
new file mode 100644
index 00000000000..eaf129f251e
--- /dev/null
+++ b/clang/lib/Basic/SourceLocation.cpp
@@ -0,0 +1,79 @@
+//==--- SourceLocation.cpp - Compact identifier for Source Files -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines serialization methods for the SourceLocation class.
+// This file defines accessor methods for the FullSourceLoc class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Bitcode/Serialize.h"
+#include "llvm/Bitcode/Deserialize.h"
+
+using namespace clang;
+
+void SourceLocation::Emit(llvm::Serializer& S) const {
+ S.EmitInt(getRawEncoding());
+}
+
+SourceLocation SourceLocation::ReadVal(llvm::Deserializer& D) {
+ return SourceLocation::getFromRawEncoding(D.ReadInt());
+}
+
+void SourceRange::Emit(llvm::Serializer& S) const {
+ B.Emit(S);
+ E.Emit(S);
+}
+
+SourceRange SourceRange::ReadVal(llvm::Deserializer& D) {
+ SourceLocation A = SourceLocation::ReadVal(D);
+ SourceLocation B = SourceLocation::ReadVal(D);
+ return SourceRange(A,B);
+}
+
+FullSourceLoc FullSourceLoc::getLogicalLoc() {
+ assert (isValid());
+ return FullSourceLoc(SrcMgr->getLogicalLoc(Loc),*SrcMgr);
+}
+
+FullSourceLoc FullSourceLoc::getIncludeLoc() {
+ assert (isValid());
+ return FullSourceLoc(SrcMgr->getIncludeLoc(Loc),*SrcMgr);
+}
+
+unsigned FullSourceLoc::getLineNumber() {
+ assert (isValid());
+ return SrcMgr->getLineNumber(Loc);
+}
+
+unsigned FullSourceLoc::getColumnNumber() {
+ assert (isValid());
+ return SrcMgr->getColumnNumber(Loc);
+}
+
+const char* FullSourceLoc::getSourceName() const {
+ assert (isValid());
+ return SrcMgr->getSourceName(Loc);
+}
+
+const FileEntry* FullSourceLoc::getFileEntryForLoc() const {
+ assert (isValid());
+ return SrcMgr->getFileEntryForLoc(Loc);
+}
+
+const char * FullSourceLoc::getCharacterData() const {
+ assert (isValid());
+ return SrcMgr->getCharacterData(Loc);
+}
+
+const llvm::MemoryBuffer* FullSourceLoc::getBuffer() const {
+ assert (isValid());
+ return SrcMgr->getBuffer(Loc.getFileID());
+}
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
new file mode 100644
index 00000000000..73ac2abe26f
--- /dev/null
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -0,0 +1,574 @@
+//===--- SourceManager.cpp - Track and cache source files -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SourceManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Path.h"
+#include "llvm/Bitcode/Serialize.h"
+#include "llvm/Bitcode/Deserialize.h"
+#include "llvm/Support/Streams.h"
+#include <algorithm>
+#include <fcntl.h>
+using namespace clang;
+using namespace SrcMgr;
+using llvm::MemoryBuffer;
+
+ContentCache::~ContentCache() {
+ delete Buffer;
+ delete [] SourceLineCache;
+}
+
+// FIXME: REMOVE THESE
+#include <unistd.h>
+#include <sys/types.h>
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <sys/uio.h>
+#include <sys/fcntl.h>
+#else
+#include <io.h>
+#endif
+#include <cerrno>
+
+static const MemoryBuffer *ReadFileFast(const FileEntry *FileEnt) {
+#if 0
+ // FIXME: Reintroduce this and zap this function once the common llvm stuff
+ // is fast for the small case.
+ return MemoryBuffer::getFile(FileEnt->getName(), strlen(FileEnt->getName()),
+ FileEnt->getSize());
+#endif
+
+ // If the file is larger than some threshold, use 'read', otherwise use mmap.
+ if (FileEnt->getSize() >= 4096*4)
+ return MemoryBuffer::getFile(FileEnt->getName(), strlen(FileEnt->getName()),
+ 0, FileEnt->getSize());
+
+ MemoryBuffer *SB = MemoryBuffer::getNewUninitMemBuffer(FileEnt->getSize(),
+ FileEnt->getName());
+ char *BufPtr = const_cast<char*>(SB->getBufferStart());
+
+#if defined(LLVM_ON_WIN32)
+ int FD = ::open(FileEnt->getName(), O_RDONLY|O_BINARY);
+#else
+ int FD = ::open(FileEnt->getName(), O_RDONLY);
+#endif
+ if (FD == -1) {
+ delete SB;
+ return 0;
+ }
+
+ unsigned BytesLeft = FileEnt->getSize();
+ while (BytesLeft) {
+ ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
+ if (NumRead != -1) {
+ BytesLeft -= NumRead;
+ BufPtr += NumRead;
+ } else if (errno == EINTR) {
+ // try again
+ } else {
+ // error reading.
+ close(FD);
+ delete SB;
+ return 0;
+ }
+ }
+ close(FD);
+
+ return SB;
+}
+
+
+/// getFileInfo - Create or return a cached FileInfo for the specified file.
+///
+const ContentCache* SourceManager::getContentCache(const FileEntry *FileEnt) {
+
+ assert(FileEnt && "Didn't specify a file entry to use?");
+ // Do we already have information about this file?
+ std::set<ContentCache>::iterator I =
+ FileInfos.lower_bound(ContentCache(FileEnt));
+
+ if (I != FileInfos.end() && I->Entry == FileEnt)
+ return &*I;
+
+ // Nope, get information.
+ const MemoryBuffer *File = ReadFileFast(FileEnt);
+ if (File == 0)
+ return 0;
+
+ ContentCache& Entry = const_cast<ContentCache&>(*FileInfos.insert(I,FileEnt));
+
+ Entry.Buffer = File;
+ Entry.SourceLineCache = 0;
+ Entry.NumLines = 0;
+ return &Entry;
+}
+
+
+/// createMemBufferContentCache - Create a new ContentCache for the specified
+/// memory buffer. This does no caching.
+const ContentCache*
+SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
+ // Add a new ContentCache to the MemBufferInfos list and return it. We
+ // must default construct the object first that the instance actually
+ // stored within MemBufferInfos actually owns the Buffer, and not any
+ // temporary we would use in the call to "push_back".
+ MemBufferInfos.push_back(ContentCache());
+ ContentCache& Entry = const_cast<ContentCache&>(MemBufferInfos.back());
+ Entry.Buffer = Buffer;
+ return &Entry;
+}
+
+
+/// createFileID - Create a new fileID for the specified ContentCache and
+/// include position. This works regardless of whether the ContentCache
+/// corresponds to a file or some other input source.
+unsigned SourceManager::createFileID(const ContentCache *File,
+ SourceLocation IncludePos) {
+ // If FileEnt is really large (e.g. it's a large .i file), we may not be able
+ // to fit an arbitrary position in the file in the FilePos field. To handle
+ // this, we create one FileID for each chunk of the file that fits in a
+ // FilePos field.
+ unsigned FileSize = File->Buffer->getBufferSize();
+ if (FileSize+1 < (1 << SourceLocation::FilePosBits)) {
+ FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File));
+ assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) &&
+ "Ran out of file ID's!");
+ return FileIDs.size();
+ }
+
+ // Create one FileID for each chunk of the file.
+ unsigned Result = FileIDs.size()+1;
+
+ unsigned ChunkNo = 0;
+ while (1) {
+ FileIDs.push_back(FileIDInfo::get(IncludePos, ChunkNo++, File));
+
+ if (FileSize+1 < (1 << SourceLocation::FilePosBits)) break;
+ FileSize -= (1 << SourceLocation::FilePosBits);
+ }
+
+ assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) &&
+ "Ran out of file ID's!");
+ return Result;
+}
+
+/// getInstantiationLoc - Return a new SourceLocation that encodes the fact
+/// that a token from physloc PhysLoc should actually be referenced from
+/// InstantiationLoc.
+SourceLocation SourceManager::getInstantiationLoc(SourceLocation PhysLoc,
+ SourceLocation InstantLoc) {
+ // The specified source location may be a mapped location, due to a macro
+ // instantiation or #line directive. Strip off this information to find out
+ // where the characters are actually located.
+ PhysLoc = getPhysicalLoc(PhysLoc);
+
+ // Resolve InstantLoc down to a real logical location.
+ InstantLoc = getLogicalLoc(InstantLoc);
+
+
+ // If the last macro id is close to the currently requested location, try to
+ // reuse it. This implements a small cache.
+ for (int i = MacroIDs.size()-1, e = MacroIDs.size()-6; i >= 0 && i != e; --i){
+ MacroIDInfo &LastOne = MacroIDs[i];
+
+ // The instanitation point and source physloc have to exactly match to reuse
+ // (for now). We could allow "nearby" instantiations in the future.
+ if (LastOne.getVirtualLoc() != InstantLoc ||
+ LastOne.getPhysicalLoc().getFileID() != PhysLoc.getFileID())
+ continue;
+
+ // Check to see if the physloc of the token came from near enough to reuse.
+ int PhysDelta = PhysLoc.getRawFilePos() -
+ LastOne.getPhysicalLoc().getRawFilePos();
+ if (SourceLocation::isValidMacroPhysOffs(PhysDelta))
+ return SourceLocation::getMacroLoc(i, PhysDelta);
+ }
+
+
+ MacroIDs.push_back(MacroIDInfo::get(InstantLoc, PhysLoc));
+ return SourceLocation::getMacroLoc(MacroIDs.size()-1, 0);
+}
+
+/// getBufferData - Return a pointer to the start and end of the character
+/// data for the specified FileID.
+std::pair<const char*, const char*>
+SourceManager::getBufferData(unsigned FileID) const {
+ const llvm::MemoryBuffer *Buf = getBuffer(FileID);
+ return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
+}
+
+
+/// getCharacterData - Return a pointer to the start of the specified location
+/// in the appropriate MemoryBuffer.
+const char *SourceManager::getCharacterData(SourceLocation SL) const {
+ // Note that this is a hot function in the getSpelling() path, which is
+ // heavily used by -E mode.
+ SL = getPhysicalLoc(SL);
+
+ return getContentCache(SL.getFileID())->Buffer->getBufferStart() +
+ getFullFilePos(SL);
+}
+
+
+/// getColumnNumber - Return the column # for the specified file position.
+/// this is significantly cheaper to compute than the line number. This returns
+/// zero if the column number isn't known.
+unsigned SourceManager::getColumnNumber(SourceLocation Loc) const {
+ unsigned FileID = Loc.getFileID();
+ if (FileID == 0) return 0;
+
+ unsigned FilePos = getFullFilePos(Loc);
+ const MemoryBuffer *Buffer = getBuffer(FileID);
+ const char *Buf = Buffer->getBufferStart();
+
+ unsigned LineStart = FilePos;
+ while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
+ --LineStart;
+ return FilePos-LineStart+1;
+}
+
+/// getSourceName - This method returns the name of the file or buffer that
+/// the SourceLocation specifies. This can be modified with #line directives,
+/// etc.
+const char *SourceManager::getSourceName(SourceLocation Loc) const {
+ unsigned FileID = Loc.getFileID();
+ if (FileID == 0) return "";
+ return getContentCache(FileID)->Buffer->getBufferIdentifier();
+}
+
+static void ComputeLineNumbers(ContentCache* FI) DISABLE_INLINE;
+static void ComputeLineNumbers(ContentCache* FI) {
+ const MemoryBuffer *Buffer = FI->Buffer;
+
+ // Find the file offsets of all of the *physical* source lines. This does
+ // not look at trigraphs, escaped newlines, or anything else tricky.
+ std::vector<unsigned> LineOffsets;
+
+ // Line #1 starts at char 0.
+ LineOffsets.push_back(0);
+
+ const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
+ const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
+ unsigned Offs = 0;
+ while (1) {
+ // Skip over the contents of the line.
+ // TODO: Vectorize this? This is very performance sensitive for programs
+ // with lots of diagnostics and in -E mode.
+ const unsigned char *NextBuf = (const unsigned char *)Buf;
+ while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
+ ++NextBuf;
+ Offs += NextBuf-Buf;
+ Buf = NextBuf;
+
+ if (Buf[0] == '\n' || Buf[0] == '\r') {
+ // If this is \n\r or \r\n, skip both characters.
+ if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
+ ++Offs, ++Buf;
+ ++Offs, ++Buf;
+ LineOffsets.push_back(Offs);
+ } else {
+ // Otherwise, this is a null. If end of file, exit.
+ if (Buf == End) break;
+ // Otherwise, skip the null.
+ ++Offs, ++Buf;
+ }
+ }
+
+ // Copy the offsets into the FileInfo structure.
+ FI->NumLines = LineOffsets.size();
+ FI->SourceLineCache = new unsigned[LineOffsets.size()];
+ std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
+}
+
+/// getLineNumber - Given a SourceLocation, return the physical line number
+/// for the position indicated. This requires building and caching a table of
+/// line offsets for the MemoryBuffer, so this is not cheap: use only when
+/// about to emit a diagnostic.
+unsigned SourceManager::getLineNumber(SourceLocation Loc) {
+ unsigned FileID = Loc.getFileID();
+ if (FileID == 0) return 0;
+
+ ContentCache* Content;
+
+ if (LastLineNoFileIDQuery == FileID)
+ Content = LastLineNoContentCache;
+ else
+ Content = const_cast<ContentCache*>(getContentCache(FileID));
+
+ // If this is the first use of line information for this buffer, compute the
+ /// SourceLineCache for it on demand.
+ if (Content->SourceLineCache == 0)
+ ComputeLineNumbers(Content);
+
+ // Okay, we know we have a line number table. Do a binary search to find the
+ // line number that this character position lands on.
+ unsigned *SourceLineCache = Content->SourceLineCache;
+ unsigned *SourceLineCacheStart = SourceLineCache;
+ unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
+
+ unsigned QueriedFilePos = getFullFilePos(Loc)+1;
+
+ // If the previous query was to the same file, we know both the file pos from
+ // that query and the line number returned. This allows us to narrow the
+ // search space from the entire file to something near the match.
+ if (LastLineNoFileIDQuery == FileID) {
+ if (QueriedFilePos >= LastLineNoFilePos) {
+ SourceLineCache = SourceLineCache+LastLineNoResult-1;
+
+ // The query is likely to be nearby the previous one. Here we check to
+ // see if it is within 5, 10 or 20 lines. It can be far away in cases
+ // where big comment blocks and vertical whitespace eat up lines but
+ // contribute no tokens.
+ if (SourceLineCache+5 < SourceLineCacheEnd) {
+ if (SourceLineCache[5] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+5;
+ else if (SourceLineCache+10 < SourceLineCacheEnd) {
+ if (SourceLineCache[10] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+10;
+ else if (SourceLineCache+20 < SourceLineCacheEnd) {
+ if (SourceLineCache[20] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+20;
+ }
+ }
+ }
+ } else {
+ SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
+ }
+ }
+
+ // If the spread is large, do a "radix" test as our initial guess, based on
+ // the assumption that lines average to approximately the same length.
+ // NOTE: This is currently disabled, as it does not appear to be profitable in
+ // initial measurements.
+ if (0 && SourceLineCacheEnd-SourceLineCache > 20) {
+ unsigned FileLen = Content->SourceLineCache[Content->NumLines-1];
+
+ // Take a stab at guessing where it is.
+ unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen;
+
+ // Check for -10 and +10 lines.
+ unsigned LowerBound = std::max(int(ApproxPos-10), 0);
+ unsigned UpperBound = std::min(ApproxPos+10, FileLen);
+
+ // If the computed lower bound is less than the query location, move it in.
+ if (SourceLineCache < SourceLineCacheStart+LowerBound &&
+ SourceLineCacheStart[LowerBound] < QueriedFilePos)
+ SourceLineCache = SourceLineCacheStart+LowerBound;
+
+ // If the computed upper bound is greater than the query location, move it.
+ if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound &&
+ SourceLineCacheStart[UpperBound] >= QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCacheStart+UpperBound;
+ }
+
+ unsigned *Pos
+ = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
+ unsigned LineNo = Pos-SourceLineCacheStart;
+
+ LastLineNoFileIDQuery = FileID;
+ LastLineNoContentCache = Content;
+ LastLineNoFilePos = QueriedFilePos;
+ LastLineNoResult = LineNo;
+ return LineNo;
+}
+
+/// PrintStats - Print statistics to stderr.
+///
+void SourceManager::PrintStats() const {
+ llvm::cerr << "\n*** Source Manager Stats:\n";
+ llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
+ << " mem buffers mapped, " << FileIDs.size()
+ << " file ID's allocated.\n";
+ llvm::cerr << " " << FileIDs.size() << " normal buffer FileID's, "
+ << MacroIDs.size() << " macro expansion FileID's.\n";
+
+ unsigned NumLineNumsComputed = 0;
+ unsigned NumFileBytesMapped = 0;
+ for (std::set<ContentCache>::const_iterator I =
+ FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
+ NumLineNumsComputed += I->SourceLineCache != 0;
+ NumFileBytesMapped += I->Buffer->getBufferSize();
+ }
+
+ llvm::cerr << NumFileBytesMapped << " bytes of files mapped, "
+ << NumLineNumsComputed << " files with line #'s computed.\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Serialization.
+//===----------------------------------------------------------------------===//
+
+void ContentCache::Emit(llvm::Serializer& S) const {
+ S.FlushRecord();
+ S.EmitPtr(this);
+
+ if (Entry) {
+ llvm::sys::Path Fname(Buffer->getBufferIdentifier());
+
+ if (Fname.isAbsolute())
+ S.EmitCStr(Fname.c_str());
+ else {
+ // Create an absolute path.
+ // FIXME: This will potentially contain ".." and "." in the path.
+ llvm::sys::Path path = llvm::sys::Path::GetCurrentDirectory();
+ path.appendComponent(Fname.c_str());
+ S.EmitCStr(path.c_str());
+ }
+ }
+ else {
+ const char* p = Buffer->getBufferStart();
+ const char* e = Buffer->getBufferEnd();
+
+ S.EmitInt(e-p);
+
+ for ( ; p != e; ++p)
+ S.EmitInt(*p);
+ }
+
+ S.FlushRecord();
+}
+
+void ContentCache::ReadToSourceManager(llvm::Deserializer& D,
+ SourceManager& SMgr,
+ FileManager* FMgr,
+ std::vector<char>& Buf) {
+ if (FMgr) {
+ llvm::SerializedPtrID PtrID = D.ReadPtrID();
+ D.ReadCStr(Buf,false);
+
+ // Create/fetch the FileEntry.
+ const char* start = &Buf[0];
+ const FileEntry* E = FMgr->getFile(start,start+Buf.size());
+
+ // FIXME: Ideally we want a lazy materialization of the ContentCache
+ // anyway, because we don't want to read in source files unless this
+ // is absolutely needed.
+ if (!E)
+ D.RegisterPtr(PtrID,NULL);
+ else
+ // Get the ContextCache object and register it with the deserializer.
+ D.RegisterPtr(PtrID,SMgr.getContentCache(E));
+ }
+ else {
+ // Register the ContextCache object with the deserializer.
+ SMgr.MemBufferInfos.push_back(ContentCache());
+ ContentCache& Entry = const_cast<ContentCache&>(SMgr.MemBufferInfos.back());
+ D.RegisterPtr(&Entry);
+
+ // Create the buffer.
+ unsigned Size = D.ReadInt();
+ Entry.Buffer = MemoryBuffer::getNewUninitMemBuffer(Size);
+
+ // Read the contents of the buffer.
+ char* p = const_cast<char*>(Entry.Buffer->getBufferStart());
+ for (unsigned i = 0; i < Size ; ++i)
+ p[i] = D.ReadInt();
+ }
+}
+
+void FileIDInfo::Emit(llvm::Serializer& S) const {
+ S.Emit(IncludeLoc);
+ S.EmitInt(ChunkNo);
+ S.EmitPtr(Content);
+}
+
+FileIDInfo FileIDInfo::ReadVal(llvm::Deserializer& D) {
+ FileIDInfo I;
+ I.IncludeLoc = SourceLocation::ReadVal(D);
+ I.ChunkNo = D.ReadInt();
+ D.ReadPtr(I.Content,false);
+ return I;
+}
+
+void MacroIDInfo::Emit(llvm::Serializer& S) const {
+ S.Emit(VirtualLoc);
+ S.Emit(PhysicalLoc);
+}
+
+MacroIDInfo MacroIDInfo::ReadVal(llvm::Deserializer& D) {
+ MacroIDInfo I;
+ I.VirtualLoc = SourceLocation::ReadVal(D);
+ I.PhysicalLoc = SourceLocation::ReadVal(D);
+ return I;
+}
+
+void SourceManager::Emit(llvm::Serializer& S) const {
+ S.EnterBlock();
+ S.EmitPtr(this);
+ S.EmitInt(MainFileID);
+
+ // Emit: FileInfos. Just emit the file name.
+ S.EnterBlock();
+
+ std::for_each(FileInfos.begin(),FileInfos.end(),
+ S.MakeEmitter<ContentCache>());
+
+ S.ExitBlock();
+
+ // Emit: MemBufferInfos
+ S.EnterBlock();
+
+ std::for_each(MemBufferInfos.begin(), MemBufferInfos.end(),
+ S.MakeEmitter<ContentCache>());
+
+ S.ExitBlock();
+
+ // Emit: FileIDs
+ S.EmitInt(FileIDs.size());
+ std::for_each(FileIDs.begin(), FileIDs.end(), S.MakeEmitter<FileIDInfo>());
+
+ // Emit: MacroIDs
+ S.EmitInt(MacroIDs.size());
+ std::for_each(MacroIDs.begin(), MacroIDs.end(), S.MakeEmitter<MacroIDInfo>());
+
+ S.ExitBlock();
+}
+
+SourceManager*
+SourceManager::CreateAndRegister(llvm::Deserializer& D, FileManager& FMgr){
+ SourceManager *M = new SourceManager();
+ D.RegisterPtr(M);
+
+ // Read: the FileID of the main source file of the translation unit.
+ M->MainFileID = D.ReadInt();
+
+ std::vector<char> Buf;
+
+ { // Read: FileInfos.
+ llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
+ while (!D.FinishedBlock(BLoc))
+ ContentCache::ReadToSourceManager(D,*M,&FMgr,Buf);
+ }
+
+ { // Read: MemBufferInfos.
+ llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
+ while (!D.FinishedBlock(BLoc))
+ ContentCache::ReadToSourceManager(D,*M,NULL,Buf);
+ }
+
+ // Read: FileIDs.
+ unsigned Size = D.ReadInt();
+ M->FileIDs.reserve(Size);
+ for (; Size > 0 ; --Size)
+ M->FileIDs.push_back(FileIDInfo::ReadVal(D));
+
+ // Read: MacroIDs.
+ Size = D.ReadInt();
+ M->MacroIDs.reserve(Size);
+ for (; Size > 0 ; --Size)
+ M->MacroIDs.push_back(MacroIDInfo::ReadVal(D));
+
+ return M;
+}
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
new file mode 100644
index 00000000000..0a561d75cb8
--- /dev/null
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -0,0 +1,210 @@
+//===--- TargetInfo.cpp - Information about Target machine ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TargetInfo and TargetInfoImpl interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/Builtins.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace clang;
+
+// TargetInfo Constructor.
+TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
+ // Set defaults. These should be overridden by concrete targets as needed.
+ CharIsSigned = true;
+ WCharWidth = WCharAlign = 32;
+ FloatFormat = &llvm::APFloat::IEEEsingle;
+ DoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+}
+
+// Out of line virtual dtor for TargetInfo.
+TargetInfo::~TargetInfo() {}
+
+//===----------------------------------------------------------------------===//
+
+
+static void removeGCCRegisterPrefix(const char *&Name) {
+ if (Name[0] == '%' || Name[0] == '#')
+ Name++;
+}
+
+/// isValidGCCRegisterName - Returns whether the passed in string
+/// is a valid register name according to GCC. This is used by Sema for
+/// inline asm statements.
+bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
+ const char * const *Names;
+ unsigned NumNames;
+
+ // Get rid of any register prefix.
+ removeGCCRegisterPrefix(Name);
+
+
+ if (strcmp(Name, "memory") == 0 ||
+ strcmp(Name, "cc") == 0)
+ return true;
+
+ getGCCRegNames(Names, NumNames);
+
+ // If we have a number it maps to an entry in the register name array.
+ if (isdigit(Name[0])) {
+ char *End;
+ int n = (int)strtol(Name, &End, 0);
+ if (*End == 0)
+ return n >= 0 && (unsigned)n < NumNames;
+ }
+
+ // Check register names.
+ for (unsigned i = 0; i < NumNames; i++) {
+ if (strcmp(Name, Names[i]) == 0)
+ return true;
+ }
+
+ // Now check aliases.
+ const GCCRegAlias *Aliases;
+ unsigned NumAliases;
+
+ getGCCRegAliases(Aliases, NumAliases);
+ for (unsigned i = 0; i < NumAliases; i++) {
+ for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
+ if (!Aliases[i].Aliases[j])
+ break;
+ if (strcmp(Aliases[i].Aliases[j], Name) == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
+ assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
+
+ removeGCCRegisterPrefix(Name);
+
+ const char * const *Names;
+ unsigned NumNames;
+
+ getGCCRegNames(Names, NumNames);
+
+ // First, check if we have a number.
+ if (isdigit(Name[0])) {
+ char *End;
+ int n = (int)strtol(Name, &End, 0);
+ if (*End == 0) {
+ assert(n >= 0 && (unsigned)n < NumNames &&
+ "Out of bounds register number!");
+ return Names[n];
+ }
+ }
+
+ // Now check aliases.
+ const GCCRegAlias *Aliases;
+ unsigned NumAliases;
+
+ getGCCRegAliases(Aliases, NumAliases);
+ for (unsigned i = 0; i < NumAliases; i++) {
+ for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
+ if (!Aliases[i].Aliases[j])
+ break;
+ if (strcmp(Aliases[i].Aliases[j], Name) == 0)
+ return Aliases[i].Register;
+ }
+ }
+
+ return Name;
+}
+
+bool TargetInfo::validateOutputConstraint(const char *Name,
+ ConstraintInfo &info) const
+{
+ // An output constraint must start with '=' or '+'
+ if (*Name != '=' && *Name != '+')
+ return false;
+
+ if (*Name == '+')
+ info = CI_ReadWrite;
+ else
+ info = CI_None;
+
+ Name++;
+ while (*Name) {
+ switch (*Name) {
+ default:
+ if (!validateAsmConstraint(*Name, info)) {
+ // FIXME: This assert is in place temporarily
+ // so we can add more constraints as we hit it.
+ // Eventually, an unknown constraint should just be treated as 'g'.
+ assert(0 && "Unknown output constraint type!");
+ }
+ case '&': // early clobber.
+ break;
+ case 'r': // general register.
+ info = (ConstraintInfo)(info|CI_AllowsRegister);
+ break;
+ case 'm': // memory operand.
+ info = (ConstraintInfo)(info|CI_AllowsMemory);
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
+ break;
+ }
+
+ Name++;
+ }
+
+ return true;
+}
+
+bool TargetInfo::validateInputConstraint(const char *Name,
+ unsigned NumOutputs,
+ ConstraintInfo &info) const {
+ while (*Name) {
+ switch (*Name) {
+ default:
+ // Check if we have a matching constraint
+ if (*Name >= '0' && *Name <= '9') {
+ unsigned i = *Name - '0';
+
+ // Check if matching constraint is out of bounds.
+ if (i >= NumOutputs)
+ return false;
+ } else if (!validateAsmConstraint(*Name, info)) {
+ // FIXME: This assert is in place temporarily
+ // so we can add more constraints as we hit it.
+ // Eventually, an unknown constraint should just be treated as 'g'.
+ assert(0 && "Unknown input constraint type!");
+ }
+ case '%': // commutative
+ // FIXME: Fail if % is used with the last operand.
+ break;
+ case 'i': // immediate integer.
+ case 'I':
+ case 'n': // immediate integer with a known value.
+ break;
+ case 'r': // general register.
+ info = (ConstraintInfo)(info|CI_AllowsRegister);
+ break;
+ case 'm': // memory operand.
+ info = (ConstraintInfo)(info|CI_AllowsMemory);
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
+ break;
+ }
+
+ Name++;
+ }
+
+ return true;
+}
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
new file mode 100644
index 00000000000..e8238daeae3
--- /dev/null
+++ b/clang/lib/Basic/Targets.cpp
@@ -0,0 +1,757 @@
+//===--- Targets.cpp - Implement -arch option and targets -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements construction of a TargetInfo object from a
+// target triple.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Builtins.h"
+#include "clang/AST/TargetBuiltins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Common code shared among targets.
+//===----------------------------------------------------------------------===//
+
+static void Define(std::vector<char> &Buf, const char *Macro,
+ const char *Val = "1") {
+ const char *Def = "#define ";
+ Buf.insert(Buf.end(), Def, Def+strlen(Def));
+ Buf.insert(Buf.end(), Macro, Macro+strlen(Macro));
+ Buf.push_back(' ');
+ Buf.insert(Buf.end(), Val, Val+strlen(Val));
+ Buf.push_back('\n');
+}
+
+
+namespace {
+class DarwinTargetInfo : public TargetInfo {
+public:
+ DarwinTargetInfo(const std::string& triple) : TargetInfo(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.
+#ifdef __APPLE__
+ Define(Defs, "__APPLE__");
+ Define(Defs, "__MACH__");
+#endif
+
+ if (1) {// -fobjc-gc controls this.
+ Define(Defs, "__weak", "");
+ Define(Defs, "__strong", "");
+ } else {
+ Define(Defs, "__weak", "__attribute__((objc_gc(weak)))");
+ Define(Defs, "__strong", "__attribute__((objc_gc(strong)))");
+ Define(Defs, "__OBJC_GC__");
+ }
+
+ // darwin_constant_cfstrings controls this.
+ Define(Defs, "__CONSTANT_CFSTRINGS__");
+
+ if (0) // darwin_pascal_strings
+ Define(Defs, "__PASCAL_STRINGS__");
+ }
+
+};
+
+
+class SolarisTargetInfo : public TargetInfo {
+public:
+ SolarisTargetInfo(const std::string& triple) : TargetInfo(triple) {}
+
+ virtual void getTargetDefines(std::vector<char> &Defs) const {
+// FIXME: we need a real target configuration system. For now, only define
+// __SUN__ if the host has it.
+#ifdef __SUN__
+ Define(Defs, "__SUN__");
+ Define(Defs, "__SOLARIS__");
+#endif
+
+ if (1) {// -fobjc-gc controls this.
+ Define(Defs, "__weak", "");
+ Define(Defs, "__strong", "");
+ } else {
+ Define(Defs, "__weak", "__attribute__((objc_gc(weak)))");
+ Define(Defs, "__strong", "__attribute__((objc_gc(strong)))");
+ Define(Defs, "__OBJC_GC__");
+ }
+ }
+
+};
+} // end anonymous namespace.
+
+
+/// getPowerPCDefines - Return a set of the PowerPC-specific #defines that are
+/// not tied to a specific subtarget.
+static void getPowerPCDefines(std::vector<char> &Defs, bool is64Bit) {
+ // Target identification.
+ Define(Defs, "__ppc__");
+ Define(Defs, "_ARCH_PPC");
+ Define(Defs, "__POWERPC__");
+ if (is64Bit) {
+ Define(Defs, "_ARCH_PPC64");
+ Define(Defs, "_LP64");
+ Define(Defs, "__LP64__");
+ Define(Defs, "__ppc64__");
+ } else {
+ Define(Defs, "__ppc__");
+ }
+
+ // Target properties.
+ Define(Defs, "_BIG_ENDIAN");
+ Define(Defs, "__BIG_ENDIAN__");
+
+ if (is64Bit) {
+ Define(Defs, "__INTMAX_MAX__", "9223372036854775807L");
+ Define(Defs, "__INTMAX_TYPE__", "long int");
+ Define(Defs, "__LONG_MAX__", "9223372036854775807L");
+ Define(Defs, "__PTRDIFF_TYPE__", "long int");
+ Define(Defs, "__UINTMAX_TYPE__", "long unsigned int");
+ } else {
+ Define(Defs, "__INTMAX_MAX__", "9223372036854775807LL");
+ Define(Defs, "__INTMAX_TYPE__", "long long int");
+ Define(Defs, "__LONG_MAX__", "2147483647L");
+ Define(Defs, "__PTRDIFF_TYPE__", "int");
+ Define(Defs, "__UINTMAX_TYPE__", "long long unsigned int");
+ }
+ Define(Defs, "__INT_MAX__", "2147483647");
+ Define(Defs, "__LONG_LONG_MAX__", "9223372036854775807LL");
+ Define(Defs, "__CHAR_BIT__", "8");
+ Define(Defs, "__SCHAR_MAX__", "127");
+ Define(Defs, "__SHRT_MAX__", "32767");
+ Define(Defs, "__SIZE_TYPE__", "long unsigned int");
+
+ // Subtarget options.
+ Define(Defs, "__USER_LABEL_PREFIX__", "_");
+ Define(Defs, "__NATURAL_ALIGNMENT__");
+ Define(Defs, "__REGISTER_PREFIX__", "");
+
+ Define(Defs, "__WCHAR_MAX__", "2147483647");
+ Define(Defs, "__WCHAR_TYPE__", "int");
+ Define(Defs, "__WINT_TYPE__", "int");
+
+ // Float macros.
+ Define(Defs, "__FLT_DENORM_MIN__", "1.40129846e-45F");
+ Define(Defs, "__FLT_DIG__", "6");
+ Define(Defs, "__FLT_EPSILON__", "1.19209290e-7F");
+ Define(Defs, "__FLT_EVAL_METHOD__", "0");
+ Define(Defs, "__FLT_HAS_INFINITY__");
+ Define(Defs, "__FLT_HAS_QUIET_NAN__");
+ Define(Defs, "__FLT_MANT_DIG__", "24");
+ Define(Defs, "__FLT_MAX_10_EXP__", "38");
+ Define(Defs, "__FLT_MAX_EXP__", "128");
+ Define(Defs, "__FLT_MAX__", "3.40282347e+38F");
+ Define(Defs, "__FLT_MIN_10_EXP__", "(-37)");
+ Define(Defs, "__FLT_MIN_EXP__", "(-125)");
+ Define(Defs, "__FLT_MIN__", "1.17549435e-38F");
+ Define(Defs, "__FLT_RADIX__", "2");
+
+ // double macros.
+ Define(Defs, "__DBL_DENORM_MIN__", "4.9406564584124654e-324");
+ Define(Defs, "__DBL_DIG__", "15");
+ Define(Defs, "__DBL_EPSILON__", "2.2204460492503131e-16");
+ Define(Defs, "__DBL_HAS_INFINITY__");
+ Define(Defs, "__DBL_HAS_QUIET_NAN__");
+ Define(Defs, "__DBL_MANT_DIG__", "53");
+ Define(Defs, "__DBL_MAX_10_EXP__", "308");
+ Define(Defs, "__DBL_MAX_EXP__", "1024");
+ Define(Defs, "__DBL_MAX__", "1.7976931348623157e+308");
+ Define(Defs, "__DBL_MIN_10_EXP__", "(-307)");
+ Define(Defs, "__DBL_MIN_EXP__", "(-1021)");
+ Define(Defs, "__DBL_MIN__", "2.2250738585072014e-308");
+ Define(Defs, "__DECIMAL_DIG__", "33");
+
+ // 128-bit long double macros.
+ Define(Defs, "__LDBL_DENORM_MIN__",
+ "4.94065645841246544176568792868221e-324L");
+ Define(Defs, "__LDBL_DIG__", "31");
+ Define(Defs, "__LDBL_EPSILON__",
+ "4.94065645841246544176568792868221e-324L");
+ Define(Defs, "__LDBL_HAS_INFINITY__");
+ Define(Defs, "__LDBL_HAS_QUIET_NAN__");
+ Define(Defs, "__LDBL_MANT_DIG__", "106");
+ Define(Defs, "__LDBL_MAX_10_EXP__", "308");
+ Define(Defs, "__LDBL_MAX_EXP__", "1024");
+ Define(Defs, "__LDBL_MAX__",
+ "1.79769313486231580793728971405301e+308L");
+ Define(Defs, "__LDBL_MIN_10_EXP__", "(-291)");
+ Define(Defs, "__LDBL_MIN_EXP__", "(-968)");
+ Define(Defs, "__LDBL_MIN__",
+ "2.00416836000897277799610805135016e-292L");
+ Define(Defs, "__LONG_DOUBLE_128__");
+}
+
+/// getX86Defines - Return a set of the X86-specific #defines that are
+/// not tied to a specific subtarget.
+static void getX86Defines(std::vector<char> &Defs, bool is64Bit) {
+ // Target identification.
+ if (is64Bit) {
+ Define(Defs, "_LP64");
+ Define(Defs, "__LP64__");
+ Define(Defs, "__amd64__");
+ Define(Defs, "__amd64");
+ Define(Defs, "__x86_64");
+ Define(Defs, "__x86_64__");
+ } else {
+ Define(Defs, "__i386__");
+ Define(Defs, "__i386");
+ Define(Defs, "i386");
+ }
+
+ // Target properties.
+ Define(Defs, "__LITTLE_ENDIAN__");
+
+ if (is64Bit) {
+ Define(Defs, "__INTMAX_MAX__", "9223372036854775807L");
+ Define(Defs, "__INTMAX_TYPE__", "long int");
+ Define(Defs, "__LONG_MAX__", "9223372036854775807L");
+ Define(Defs, "__PTRDIFF_TYPE__", "long int");
+ Define(Defs, "__UINTMAX_TYPE__", "long unsigned int");
+ Define(Defs, "__SIZE_TYPE__", "long unsigned int");
+ } else {
+ Define(Defs, "__INTMAX_MAX__", "9223372036854775807LL");
+ Define(Defs, "__INTMAX_TYPE__", "long long int");
+ Define(Defs, "__LONG_MAX__", "2147483647L");
+ Define(Defs, "__PTRDIFF_TYPE__", "int");
+ Define(Defs, "__UINTMAX_TYPE__", "long long unsigned int");
+ Define(Defs, "__SIZE_TYPE__", "unsigned int");
+ }
+ Define(Defs, "__CHAR_BIT__", "8");
+ Define(Defs, "__INT_MAX__", "2147483647");
+ Define(Defs, "__LONG_LONG_MAX__", "9223372036854775807LL");
+ Define(Defs, "__SCHAR_MAX__", "127");
+ Define(Defs, "__SHRT_MAX__", "32767");
+
+ // Subtarget options.
+ Define(Defs, "__nocona");
+ Define(Defs, "__nocona__");
+ Define(Defs, "__tune_nocona__");
+ Define(Defs, "__SSE2_MATH__");
+ Define(Defs, "__SSE2__");
+ Define(Defs, "__SSE_MATH__");
+ Define(Defs, "__SSE__");
+ Define(Defs, "__MMX__");
+ Define(Defs, "__REGISTER_PREFIX__", "");
+
+ Define(Defs, "__WCHAR_MAX__", "2147483647");
+ Define(Defs, "__WCHAR_TYPE__", "int");
+ Define(Defs, "__WINT_TYPE__", "int");
+
+ // Float macros.
+ Define(Defs, "__FLT_DENORM_MIN__", "1.40129846e-45F");
+ Define(Defs, "__FLT_DIG__", "6");
+ Define(Defs, "__FLT_EPSILON__", "1.19209290e-7F");
+ Define(Defs, "__FLT_EVAL_METHOD__", "0");
+ Define(Defs, "__FLT_HAS_INFINITY__");
+ Define(Defs, "__FLT_HAS_QUIET_NAN__");
+ Define(Defs, "__FLT_MANT_DIG__", "24");
+ Define(Defs, "__FLT_MAX_10_EXP__", "38");
+ Define(Defs, "__FLT_MAX_EXP__", "128");
+ Define(Defs, "__FLT_MAX__", "3.40282347e+38F");
+ Define(Defs, "__FLT_MIN_10_EXP__", "(-37)");
+ Define(Defs, "__FLT_MIN_EXP__", "(-125)");
+ Define(Defs, "__FLT_MIN__", "1.17549435e-38F");
+ Define(Defs, "__FLT_RADIX__", "2");
+
+ // Double macros.
+ Define(Defs, "__DBL_DENORM_MIN__", "4.9406564584124654e-324");
+ Define(Defs, "__DBL_DIG__", "15");
+ Define(Defs, "__DBL_EPSILON__", "2.2204460492503131e-16");
+ Define(Defs, "__DBL_HAS_INFINITY__");
+ Define(Defs, "__DBL_HAS_QUIET_NAN__");
+ Define(Defs, "__DBL_MANT_DIG__", "53");
+ Define(Defs, "__DBL_MAX_10_EXP__", "308");
+ Define(Defs, "__DBL_MAX_EXP__", "1024");
+ Define(Defs, "__DBL_MAX__", "1.7976931348623157e+308");
+ Define(Defs, "__DBL_MIN_10_EXP__", "(-307)");
+ Define(Defs, "__DBL_MIN_EXP__", "(-1021)");
+ Define(Defs, "__DBL_MIN__", "2.2250738585072014e-308");
+ Define(Defs, "__DECIMAL_DIG__", "21");
+
+ // 80-bit Long double macros.
+ Define(Defs, "__LDBL_DENORM_MIN__", "3.64519953188247460253e-4951L");
+ Define(Defs, "__LDBL_DIG__", "18");
+ Define(Defs, "__LDBL_EPSILON__", "1.08420217248550443401e-19L");
+ Define(Defs, "__LDBL_HAS_INFINITY__");
+ Define(Defs, "__LDBL_HAS_QUIET_NAN__");
+ Define(Defs, "__LDBL_MANT_DIG__", "64");
+ Define(Defs, "__LDBL_MAX_10_EXP__", "4932");
+ Define(Defs, "__LDBL_MAX_EXP__", "16384");
+ Define(Defs, "__LDBL_MAX__", "1.18973149535723176502e+4932L");
+ Define(Defs, "__LDBL_MIN_10_EXP__", "(-4931)");
+ Define(Defs, "__LDBL_MIN_EXP__", "(-16381)");
+ Define(Defs, "__LDBL_MIN__", "3.36210314311209350626e-4932L");
+}
+
+static const char* getI386VAListDeclaration() {
+ return "typedef char* __builtin_va_list;";
+}
+
+static const char* getX86_64VAListDeclaration() {
+ return
+ "typedef struct __va_list_tag {"
+ " unsigned gp_offset;"
+ " unsigned fp_offset;"
+ " void* overflow_arg_area;"
+ " void* reg_save_area;"
+ "} __builtin_va_list[1];";
+}
+
+static const char* getPPCVAListDeclaration() {
+ return
+ "typedef struct __va_list_tag {"
+ " unsigned char gpr;"
+ " unsigned char fpr;"
+ " unsigned short reserved;"
+ " void* overflow_arg_area;"
+ " void* reg_save_area;"
+ "} __builtin_va_list[1];";
+}
+
+
+/// PPC builtin info.
+namespace clang {
+namespace PPC {
+
+ static const Builtin::Info BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS },
+#include "clang/AST/PPCBuiltins.def"
+ };
+
+ static void getBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) {
+ Records = BuiltinInfo;
+ NumRecords = LastTSBuiltin-Builtin::FirstTSBuiltin;
+ }
+
+ static const char * const GCCRegNames[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "8", "9", "10", "11", "12", "13", "14", "15",
+ "16", "17", "18", "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28", "29", "30", "31",
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "8", "9", "10", "11", "12", "13", "14", "15",
+ "16", "17", "18", "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28", "29", "30", "31",
+ "mq", "lr", "ctr", "ap",
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "xer",
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "8", "9", "10", "11", "12", "13", "14", "15",
+ "16", "17", "18", "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28", "29", "30", "31",
+ "vrsave", "vscr",
+ "spe_acc", "spefscr",
+ "sfp"
+ };
+
+ static void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
+ // While some of these aliases do map to different registers
+ // they still share the same register name.
+ { { "cc", "cr0", "fr0", "r0", "v0"}, "0" },
+ { { "cr1", "fr1", "r1", "sp", "v1"}, "1" },
+ { { "cr2", "fr2", "r2", "toc", "v2"}, "2" },
+ { { "cr3", "fr3", "r3", "v3"}, "3" },
+ { { "cr4", "fr4", "r4", "v4"}, "4" },
+ { { "cr5", "fr5", "r5", "v5"}, "5" },
+ { { "cr6", "fr6", "r6", "v6"}, "6" },
+ { { "cr7", "fr7", "r7", "v7"}, "7" },
+ { { "fr8", "r8", "v8"}, "8" },
+ { { "fr9", "r9", "v9"}, "9" },
+ { { "fr10", "r10", "v10"}, "10" },
+ { { "fr11", "r11", "v11"}, "11" },
+ { { "fr12", "r12", "v12"}, "12" },
+ { { "fr13", "r13", "v13"}, "13" },
+ { { "fr14", "r14", "v14"}, "14" },
+ { { "fr15", "r15", "v15"}, "15" },
+ { { "fr16", "r16", "v16"}, "16" },
+ { { "fr17", "r17", "v17"}, "17" },
+ { { "fr18", "r18", "v18"}, "18" },
+ { { "fr19", "r19", "v19"}, "19" },
+ { { "fr20", "r20", "v20"}, "20" },
+ { { "fr21", "r21", "v21"}, "21" },
+ { { "fr22", "r22", "v22"}, "22" },
+ { { "fr23", "r23", "v23"}, "23" },
+ { { "fr24", "r24", "v24"}, "24" },
+ { { "fr25", "r25", "v25"}, "25" },
+ { { "fr26", "r26", "v26"}, "26" },
+ { { "fr27", "r27", "v27"}, "27" },
+ { { "fr28", "r28", "v28"}, "28" },
+ { { "fr29", "r29", "v29"}, "29" },
+ { { "fr30", "r30", "v30"}, "30" },
+ { { "fr31", "r31", "v31"}, "31" },
+ };
+
+ static void getGCCRegAliases(const TargetInfo::GCCRegAlias *&Aliases,
+ unsigned &NumAliases) {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+ }
+
+ static bool validateAsmConstraint(char c,
+ TargetInfo::ConstraintInfo &info) {
+ switch (c) {
+ default: return false;
+ case 'O': // Zero
+ return true;
+ case 'b': // Base register
+ case 'f': // Floating point register
+ info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister);
+ return true;
+ }
+ }
+
+ const char *getClobbers() {
+ return 0;
+ }
+
+ const char *getTargetPrefix() {
+ return "ppc";
+ }
+
+} // End namespace PPC
+
+/// X86 builtin info.
+namespace X86 {
+ static const Builtin::Info BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS },
+#include "clang/AST/X86Builtins.def"
+ };
+
+ static void getBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) {
+ Records = BuiltinInfo;
+ NumRecords = LastTSBuiltin-Builtin::FirstTSBuiltin;
+ }
+
+ static const char *GCCRegNames[] = {
+ "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
+ "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+ "argp", "flags", "fspr", "dirflag", "frame",
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
+ };
+
+ static void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
+ { { "al", "ah", "eax", "rax" }, "ax" },
+ { { "bl", "bh", "ebx", "rbx" }, "bx" },
+ { { "cl", "ch", "ecx", "rcx" }, "cx" },
+ { { "dl", "dh", "edx", "rdx" }, "dx" },
+ { { "esi", "rsi" }, "si" },
+ { { "esp", "rsp" }, "sp" },
+ { { "ebp", "rbp" }, "bp" },
+ };
+
+ static void getGCCRegAliases(const TargetInfo::GCCRegAlias *&Aliases,
+ unsigned &NumAliases) {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+ }
+
+ static bool validateAsmConstraint(char c,
+ TargetInfo::ConstraintInfo &info) {
+ switch (c) {
+ default: return false;
+ case 'a': // eax.
+ case 'b': // ebx.
+ case 'c': // ecx.
+ case 'd': // edx.
+ case 'S': // esi.
+ case 'D': // edi.
+ case 'A': // edx:eax.
+ case 't': // top of floating point stack.
+ case 'u': // second from top of floating point stack.
+ case 'q': // a, b, c, d registers or any integer register in 64-bit.
+ case 'Z': // 32-bit integer constant for use with zero-extending x86_64
+ // instructions.
+ case 'N': // unsigned 8-bit integer constant for use with in and out
+ // instructions.
+ info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister);
+ return true;
+ }
+ }
+
+ static std::string convertConstraint(const char Constraint) {
+ switch (Constraint) {
+ case 'a': return std::string("{ax}");
+ case 'b': return std::string("{bx}");
+ case 'c': return std::string("{cx}");
+ case 'd': return std::string("{dx}");
+ case 'S': return std::string("{si}");
+ case 'D': return std::string("{di}");
+ case 't': // top of floating point stack.
+ return std::string("{st}");
+ case 'u': // second from top of floating point stack.
+ return std::string("{st(1)}"); // second from top of floating point stack.
+ default:
+ return std::string(1, Constraint);
+ }
+ }
+
+ const char *getClobbers() {
+ return "~{dirflag},~{fpsr},~{flags}";
+ }
+
+ const char *getTargetPrefix() {
+ return "x86";
+ }
+
+} // End namespace X86
+} // end namespace clang.
+
+//===----------------------------------------------------------------------===//
+// Specific target implementations.
+//===----------------------------------------------------------------------===//
+
+
+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);
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ PPC::getBuiltins(Records, NumRecords);
+ }
+ virtual const char *getVAListDeclaration() const {
+ return getPPCVAListDeclaration();
+ }
+ virtual const char *getTargetPrefix() const {
+ return PPC::getTargetPrefix();
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ PPC::getGCCRegNames(Names, NumNames);
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ PPC::getGCCRegAliases(Aliases, NumAliases);
+ }
+ virtual bool validateAsmConstraint(char c,
+ TargetInfo::ConstraintInfo &info) const {
+ return PPC::validateAsmConstraint(c, info);
+ }
+ virtual const char *getClobbers() const {
+ return PPC::getClobbers();
+ }
+};
+} // end anonymous namespace.
+
+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);
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ PPC::getBuiltins(Records, NumRecords);
+ }
+ virtual const char *getVAListDeclaration() const {
+ return getPPCVAListDeclaration();
+ }
+ virtual const char *getTargetPrefix() const {
+ return PPC::getTargetPrefix();
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ PPC::getGCCRegNames(Names, NumNames);
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ PPC::getGCCRegAliases(Aliases, NumAliases);
+ }
+ virtual bool validateAsmConstraint(char c,
+ TargetInfo::ConstraintInfo &info) const {
+ return PPC::validateAsmConstraint(c, info);
+ }
+ virtual const char *getClobbers() const {
+ return PPC::getClobbers();
+ }
+};
+} // end anonymous namespace.
+
+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);
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ X86::getBuiltins(Records, NumRecords);
+ }
+ virtual const char *getVAListDeclaration() const {
+ return getI386VAListDeclaration();
+ }
+ virtual const char *getTargetPrefix() const {
+ return X86::getTargetPrefix();
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ X86::getGCCRegNames(Names, NumNames);
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ X86::getGCCRegAliases(Aliases, NumAliases);
+ }
+ virtual bool validateAsmConstraint(char c,
+ TargetInfo::ConstraintInfo &info) const {
+ return X86::validateAsmConstraint(c, info);
+ }
+
+ virtual std::string convertConstraint(const char Constraint) const {
+ return X86::convertConstraint(Constraint);
+ }
+
+ virtual const char *getClobbers() const {
+ return X86::getClobbers();
+ }
+};
+} // end anonymous namespace.
+
+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);
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ X86::getBuiltins(Records, NumRecords);
+ }
+ virtual const char *getVAListDeclaration() const {
+ return getX86_64VAListDeclaration();
+ }
+ virtual const char *getTargetPrefix() const {
+ return X86::getTargetPrefix();
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ X86::getGCCRegNames(Names, NumNames);
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ X86::getGCCRegAliases(Aliases, NumAliases);
+ }
+ virtual bool validateAsmConstraint(char c,
+ TargetInfo::ConstraintInfo &info) const {
+ return X86::validateAsmConstraint(c, info);
+ }
+ virtual std::string convertConstraint(const char Constraint) const {
+ return X86::convertConstraint(Constraint);
+ }
+ virtual const char *getClobbers() const {
+ return X86::getClobbers();
+ }
+};
+} // end anonymous namespace.
+
+namespace {
+class SolarisSparcV8TargetInfo : public SolarisTargetInfo {
+public:
+ SolarisSparcV8TargetInfo(const std::string& triple) : SolarisTargetInfo(triple) {}
+
+ virtual void getTargetDefines(std::vector<char> &Defines) const {
+ SolarisTargetInfo::getTargetDefines(Defines);
+// getSparcDefines(Defines, false);
+ Define(Defines, "__sparc");
+ Define(Defines, "__sparcv8");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ PPC::getBuiltins(Records, NumRecords);
+ }
+ virtual const char *getVAListDeclaration() const {
+ return getPPCVAListDeclaration();
+ }
+ virtual const char *getTargetPrefix() const {
+ return PPC::getTargetPrefix();
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ PPC::getGCCRegNames(Names, NumNames);
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ PPC::getGCCRegAliases(Aliases, NumAliases);
+ }
+ virtual bool validateAsmConstraint(char c,
+ TargetInfo::ConstraintInfo &info) const {
+ return PPC::validateAsmConstraint(c, info);
+ }
+ virtual const char *getClobbers() const {
+ return PPC::getClobbers();
+ }
+};
+
+} // end anonymous namespace.
+
+
+//===----------------------------------------------------------------------===//
+// Driver code
+//===----------------------------------------------------------------------===//
+
+static inline 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);
+}
+
+/// CreateTargetInfo - Return the target info object for the specified target
+/// triple.
+TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
+ if (T.find("ppc-") == 0 || T.find("powerpc-") == 0)
+ return new DarwinPPCTargetInfo(T);
+
+ if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0)
+ return new DarwinPPC64TargetInfo(T);
+
+ if (T.find("sparc-") == 0)
+ return new SolarisSparcV8TargetInfo(T); // ugly hack
+
+ if (T.find("x86_64-") == 0)
+ return new DarwinX86_64TargetInfo(T);
+
+ if (IsX86(T))
+ return new DarwinI386TargetInfo(T);
+
+ return NULL;
+}
+
diff --git a/clang/lib/Basic/TokenKinds.cpp b/clang/lib/Basic/TokenKinds.cpp
new file mode 100644
index 00000000000..bde8a5598b4
--- /dev/null
+++ b/clang/lib/Basic/TokenKinds.cpp
@@ -0,0 +1,29 @@
+//===--- TokenKinds.cpp - Token Kinds Support -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TokenKind enum and support functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TokenKinds.h"
+
+#include <cassert>
+using namespace clang;
+
+static const char * const TokNames[] = {
+#define TOK(X) #X,
+#define KEYWORD(X,Y) #X,
+#include "clang/Basic/TokenKinds.def"
+ 0
+};
+
+const char *tok::getTokenName(enum TokenKind Kind) {
+ assert(Kind < tok::NUM_TOKENS);
+ return TokNames[Kind];
+}
OpenPOWER on IntegriCloud