diff options
Diffstat (limited to 'lib/Basic')
-rw-r--r-- | lib/Basic/Builtins.cpp | 18 | ||||
-rw-r--r-- | lib/Basic/CMakeLists.txt | 11 | ||||
-rw-r--r-- | lib/Basic/ConvertUTF.c | 606 | ||||
-rw-r--r-- | lib/Basic/Diagnostic.cpp | 121 | ||||
-rw-r--r-- | lib/Basic/FileManager.cpp | 88 | ||||
-rw-r--r-- | lib/Basic/IdentifierTable.cpp | 58 | ||||
-rw-r--r-- | lib/Basic/Makefile | 11 | ||||
-rw-r--r-- | lib/Basic/SourceLocation.cpp | 4 | ||||
-rw-r--r-- | lib/Basic/SourceManager.cpp | 302 | ||||
-rw-r--r-- | lib/Basic/TargetInfo.cpp | 57 | ||||
-rw-r--r-- | lib/Basic/Targets.cpp | 1092 | ||||
-rw-r--r-- | lib/Basic/Version.cpp | 49 |
12 files changed, 1544 insertions, 873 deletions
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp index 6cb5dab53df24..1a3293775ed61 100644 --- a/lib/Basic/Builtins.cpp +++ b/lib/Basic/Builtins.cpp @@ -34,7 +34,7 @@ Builtin::Context::Context(const TargetInfo &Target) { // Get the target specific builtins from the target. TSRecords = 0; NumTSRecords = 0; - Target.getTargetBuiltins(TSRecords, NumTSRecords); + Target.getTargetBuiltins(TSRecords, NumTSRecords); } /// InitializeBuiltins - Mark the identifiers for all the builtins with their @@ -51,13 +51,13 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table, // Step #2: Register target-specific builtins. for (unsigned i = 0, e = NumTSRecords; i != e; ++i) if (!TSRecords[i].Suppressed && - (!NoBuiltins || - (TSRecords[i].Attributes && + (!NoBuiltins || + (TSRecords[i].Attributes && !strchr(TSRecords[i].Attributes, 'f')))) Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin); } -void +void Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names, bool NoBuiltins) { // Final all target-independent names @@ -65,18 +65,18 @@ Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names, if (!BuiltinInfo[i].Suppressed && (!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f'))) Names.push_back(BuiltinInfo[i].Name); - + // Find target-specific names. for (unsigned i = 0, e = NumTSRecords; i != e; ++i) if (!TSRecords[i].Suppressed && - (!NoBuiltins || - (TSRecords[i].Attributes && + (!NoBuiltins || + (TSRecords[i].Attributes && !strchr(TSRecords[i].Attributes, 'f')))) Names.push_back(TSRecords[i].Name); } -bool -Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, +bool +Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg) { const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP"); if (!Printf) diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt index e0e9a10e51958..527ebf965934b 100644 --- a/lib/Basic/CMakeLists.txt +++ b/lib/Basic/CMakeLists.txt @@ -11,8 +11,19 @@ add_clang_library(clangBasic TargetInfo.cpp Targets.cpp TokenKinds.cpp + Version.cpp ) +# Determine Subversion revision. +# FIXME: This only gets updated when CMake is run, so this revision number +# may be out-of-date! +find_package(Subversion) +if (Subversion_FOUND) + Subversion_WC_INFO(${CLANG_SOURCE_DIR} CLANG) + set_source_files_properties(Version.cpp + PROPERTIES COMPILE_DEFINITIONS "SVN_REVISION=\"${CLANG_WC_REVISION}\"") +endif() + add_dependencies(clangBasic ClangDiagnosticAnalysis ClangDiagnosticAST diff --git a/lib/Basic/ConvertUTF.c b/lib/Basic/ConvertUTF.c index e5dd3e6bf5706..124e386c55265 100644 --- a/lib/Basic/ConvertUTF.c +++ b/lib/Basic/ConvertUTF.c @@ -34,10 +34,10 @@ Author: Mark E. Davis, 1994. Rev History: Rick McGowan, fixes & updates May 2001. Sept 2001: fixed const & error conditions per - mods suggested by S. Parent & A. Lillich. + mods suggested by S. Parent & A. Lillich. June 2002: Tim Dodd added detection and handling of incomplete - source sequences, enhanced error detection, added casts - to eliminate compiler warnings. + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. July 2003: slight mods to back out aggressive FFFE detection. Jan 2004: updated switches in from-UTF8 conversions. Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. @@ -61,8 +61,8 @@ static const UTF32 halfMask = 0x3FFUL; #define UNI_SUR_HIGH_END (UTF32)0xDBFF #define UNI_SUR_LOW_START (UTF32)0xDC00 #define UNI_SUR_LOW_END (UTF32)0xDFFF -#define false 0 -#define true 1 +#define false 0 +#define true 1 /* --------------------------------------------------------------------- */ @@ -90,7 +90,7 @@ static const char trailingBytesForUTF8[256] = { * in a UTF-8 sequence. */ static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; /* * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed @@ -116,46 +116,46 @@ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF32toUTF16 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF32* source = *sourceStart; UTF16* target = *targetStart; while (source < sourceEnd) { - UTF32 ch; - if (target >= targetEnd) { - result = targetExhausted; break; - } - ch = *source++; - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_LEGAL_UTF32) { - if (flags == strictConversion) { - result = sourceIllegal; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - --source; /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } } *sourceStart = source; *targetStart = target; @@ -165,48 +165,48 @@ ConversionResult ConvertUTF32toUTF16 ( /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF16toUTF32 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF32* target = *targetStart; UTF32 ch, ch2; while (source < sourceEnd) { - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - if (target >= targetEnd) { - source = oldSource; /* Back up source pointer! */ - result = targetExhausted; break; - } - *target++ = ch; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; break; + } + *target++ = ch; } *sourceStart = source; *targetStart = target; @@ -219,67 +219,67 @@ if (result == sourceIllegal) { return result; } ConversionResult ConvertUTF16toUTF8 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - UTF32 ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; } *sourceStart = source; *targetStart = target; @@ -289,50 +289,50 @@ ConversionResult ConvertUTF16toUTF8 ( /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF32toUTF8 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF32* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - if (flags == strictConversion ) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* - * Figure out how many bytes the result will require. Turn any - * illegally large UTF32 things (> Plane 17) into replacement chars. - */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - result = sourceIllegal; - } - - target += bytesToWrite; - if (target > targetEnd) { - --source; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion ) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; } *sourceStart = source; *targetStart = target; @@ -342,59 +342,59 @@ ConversionResult ConvertUTF32toUTF8 ( /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF32* target = *targetStart; while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (!isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; - case 4: ch += *source++; ch <<= 6; - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up the source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_LEGAL_UTF32) { - /* - * UTF-16 surrogate values are illegal in UTF-32, and anything - * over Plane 17 (> 0x10FFFF) is illegal. - */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = ch; - } - } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ - result = sourceIllegal; - *target++ = UNI_REPLACEMENT_CHAR; - } + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; + case 4: ch += *source++; ch <<= 6; + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up the source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } } *sourceStart = source; *targetStart = target; @@ -420,19 +420,19 @@ static Boolean isLegalUTF8(const UTF8 *source, int length) { const UTF8 *srcptr = source+length; switch (length) { default: return false; - /* Everything else falls through when "true"... */ + /* Everything else falls through when "true"... */ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 2: if ((a = (*--srcptr)) > 0xBF) return false; - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return false; break; - case 0xED: if (a > 0x9F) return false; break; - case 0xF0: if (a < 0x90) return false; break; - case 0xF4: if (a > 0x8F) return false; break; - default: if (a < 0x80) return false; - } + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xED: if (a > 0x9F) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } case 1: if (*source >= 0x80 && *source < 0xC2) return false; } @@ -449,7 +449,7 @@ static Boolean isLegalUTF8(const UTF8 *source, int length) { Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { int length = trailingBytesForUTF8[*source]+1; if (source+length > sourceEnd) { - return false; + return false; } return isLegalUTF8(source, length); } @@ -457,70 +457,70 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF8toUTF16 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF16* target = *targetStart; while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (!isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - source -= (extraBytesToRead+1); /* return to the start */ - break; /* Bail out; shouldn't continue */ - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } } *sourceStart = source; *targetStart = target; @@ -533,14 +533,14 @@ ConversionResult ConvertUTF8toUTF16 ( The fall-through switches in UTF-8 reading code save a temp variable, some decrements & conditionals. The switches are equivalent to the following loop: - { - int tmpBytesToRead = extraBytesToRead+1; - do { - ch += *source++; - --tmpBytesToRead; - if (tmpBytesToRead) ch <<= 6; - } while (tmpBytesToRead > 0); - } + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } In UTF-8 writing code, the switches on "bytesToWrite" are similarly unrolled loops. diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 78b8b0a855977..4a29997a2ccc3 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -49,7 +49,7 @@ struct StaticDiagInfoRec { bool SFINAE : 1; const char *Description; const char *OptionGroup; - + bool operator<(const StaticDiagInfoRec &RHS) const { return DiagID < RHS.DiagID; } @@ -88,16 +88,16 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { IsFirst = false; } #endif - + // Search the diagnostic table with a binary search. StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 }; - + const StaticDiagInfoRec *Found = std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find); if (Found == StaticDiagInfo + NumDiagEntries || Found->DiagID != DiagID) return 0; - + return Found; } @@ -141,7 +141,7 @@ namespace clang { 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 { @@ -149,14 +149,14 @@ namespace clang { "Invalid diagnosic ID"); return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str(); } - + /// getLevel - Return the level of the specified custom diagnostic. Diagnostic::Level getLevel(unsigned DiagID) const { assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && "Invalid diagnosic ID"); return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; } - + unsigned getOrCreateDiagID(Diagnostic::Level L, const char *Message, Diagnostic &Diags) { DiagDesc D(L, Message); @@ -164,7 +164,7 @@ namespace clang { 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_UPPER_LIMIT; DiagIDs.insert(std::make_pair(D, ID)); @@ -172,9 +172,9 @@ namespace clang { return ID; } }; - - } // end diag namespace -} // end clang namespace + + } // end diag namespace +} // end clang namespace //===----------------------------------------------------------------------===// @@ -196,32 +196,48 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) { IgnoreAllWarnings = false; WarningsAsErrors = false; SuppressSystemWarnings = false; + SuppressAllDiagnostics = false; ExtBehavior = Ext_Ignore; - + ErrorOccurred = false; FatalErrorOccurred = false; NumDiagnostics = 0; + NumErrors = 0; CustomDiagInfo = 0; CurDiagID = ~0U; LastDiagLevel = Ignored; - + ArgToStringFn = DummyArgToStringFn; ArgToStringCookie = 0; - + // Set all mappings to 'unset'. - memset(DiagMappings, 0, sizeof(DiagMappings)); + DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0); + DiagMappingsStack.push_back(BlankDiags); } Diagnostic::~Diagnostic() { delete CustomDiagInfo; } + +void Diagnostic::pushMappings() { + DiagMappingsStack.push_back(DiagMappingsStack.back()); +} + +bool Diagnostic::popMappings() { + if (DiagMappingsStack.size() == 1) + return false; + + DiagMappingsStack.pop_back(); + return true; +} + /// 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) + if (CustomDiagInfo == 0) CustomDiagInfo = new diag::CustomDiagInfo(); return CustomDiagInfo->getOrCreateDiagID(L, Message, *this); } @@ -267,7 +283,7 @@ Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const { // Handle custom diagnostics, which cannot be mapped. if (DiagID >= diag::DIAG_UPPER_LIMIT) return CustomDiagInfo->getLevel(DiagID); - + unsigned DiagClass = getBuiltinDiagClass(DiagID); assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!"); return getDiagnosticLevel(DiagID, DiagClass); @@ -281,14 +297,14 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const { // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. Diagnostic::Level Result = Diagnostic::Fatal; - + // Get the mapping information, if unset, compute it lazily. unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID); if (MappingInfo == 0) { MappingInfo = GetDefaultDiagMapping(DiagID); setDiagnosticMappingInternal(DiagID, MappingInfo, false); } - + switch (MappingInfo & 7) { default: assert(0 && "Unknown mapping!"); case diag::MAP_IGNORE: @@ -311,29 +327,29 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const { // If warnings are globally mapped to ignore or error, do it. if (IgnoreAllWarnings) return Diagnostic::Ignored; - + Result = Diagnostic::Warning; - + // If this is an extension diagnostic and we're in -pedantic-error mode, and // if the user didn't explicitly map it, upgrade to an error. if (ExtBehavior == Ext_Error && (MappingInfo & 8) == 0 && isBuiltinExtensionDiag(DiagID)) Result = Diagnostic::Error; - + if (WarningsAsErrors) Result = Diagnostic::Error; break; - + case diag::MAP_WARNING_NO_WERROR: // Diagnostics specified with -Wno-error=foo should be set to warnings, but // not be adjusted by -Werror or -pedantic-errors. Result = Diagnostic::Warning; - + // If warnings are globally mapped to ignore or error, do it. if (IgnoreAllWarnings) return Diagnostic::Ignored; - + break; } @@ -342,7 +358,7 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const { // block, silence it. if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID)) return Diagnostic::Ignored; - + return Result; } @@ -377,7 +393,7 @@ static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, for (; *Member != -1; ++Member) Diags.setDiagnosticMapping(*Member, Mapping); } - + // Enable/disable all subgroups along with this one. if (const char *SubGroups = Group->SubGroups) { for (; *SubGroups != (char)-1; ++SubGroups) @@ -390,7 +406,7 @@ static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, /// ignores the request if "Group" was unknown, false otherwise. bool Diagnostic::setDiagnosticGroupMapping(const char *Group, diag::Mapping Map) { - + WarningOption Key = { Group, 0, 0 }; const WarningOption *Found = std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, @@ -398,7 +414,7 @@ bool Diagnostic::setDiagnosticGroupMapping(const char *Group, if (Found == OptionTable + OptionTableSize || strcmp(Found->Name, Group) != 0) return true; // Option not found. - + MapGroupMembers(Found, Map, *this); return false; } @@ -408,19 +424,22 @@ bool Diagnostic::setDiagnosticGroupMapping(const char *Group, /// finally fully formed. bool Diagnostic::ProcessDiag() { DiagnosticInfo Info(this); - + + if (SuppressAllDiagnostics) + return false; + // Figure out the diagnostic level of this message. Diagnostic::Level DiagLevel; unsigned DiagID = Info.getID(); - + // ShouldEmitInSystemHeader - True if this diagnostic should be produced even // in a system header. bool ShouldEmitInSystemHeader; - + if (DiagID >= diag::DIAG_UPPER_LIMIT) { // Handle custom diagnostics, which cannot be mapped. DiagLevel = CustomDiagInfo->getLevel(DiagID); - + // Custom diagnostics always are emitted in system headers. ShouldEmitInSystemHeader = true; } else { @@ -432,12 +451,12 @@ bool Diagnostic::ProcessDiag() { DiagLevel = Diagnostic::Note; ShouldEmitInSystemHeader = false; // extra consideration is needed } else { - // If this is not an error and we are in a system header, we ignore it. + // If this is not an error and we are in a system header, we ignore it. // Check the original Diag ID here, because we also want to ignore // extensions and warnings in -Werror and -pedantic-errors modes, which // *map* warnings/extensions to errors. ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR; - + DiagLevel = getDiagnosticLevel(DiagID, DiagClass); } } @@ -451,7 +470,7 @@ bool Diagnostic::ProcessDiag() { FatalErrorOccurred = true; LastDiagLevel = DiagLevel; - } + } // If a fatal error has already been emitted, silence all subsequent // diagnostics. @@ -478,7 +497,7 @@ bool Diagnostic::ProcessDiag() { ErrorOccurred = true; ++NumErrors; } - + // Finally, report it. Client->HandleDiagnostic(DiagLevel, Info); if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics; @@ -508,7 +527,7 @@ static void HandleSelectModifier(unsigned ValNo, const char *Argument, unsigned ArgumentLen, llvm::SmallVectorImpl<char> &OutStr) { const char *ArgumentEnd = Argument+ArgumentLen; - + // Skip over 'ValNo' |'s. while (ValNo) { const char *NextVal = std::find(Argument, ArgumentEnd, '|'); @@ -517,7 +536,7 @@ static void HandleSelectModifier(unsigned ValNo, Argument = NextVal+1; // Skip this string. --ValNo; } - + // Get the end of the value. This is either the } or the |. const char *EndPtr = std::find(Argument, ArgumentEnd, '|'); // Add the value to the output string. @@ -590,7 +609,7 @@ static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) { // Scan for next or-expr part. Start = std::find(Start, End, ','); - if(Start == End) + if (Start == End) break; ++Start; } @@ -659,7 +678,7 @@ void DiagnosticInfo:: FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { const char *DiagStr = getDiags()->getDescription(getID()); const char *DiagEnd = DiagStr+strlen(DiagStr); - + while (DiagStr != DiagEnd) { if (DiagStr[0] != '%') { // Append non-%0 substrings to Str if we have one. @@ -672,10 +691,10 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { DiagStr += 2; continue; } - + // Skip the %. ++DiagStr; - + // This must be a placeholder for a diagnostic argument. The format for a // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0". // The digit is a number from 0-9 indicating which argument this comes from. @@ -683,7 +702,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { // brace enclosed string. const char *Modifier = 0, *Argument = 0; unsigned ModifierLen = 0, ArgumentLen = 0; - + // Check to see if we have a modifier. If so eat it. if (!isdigit(DiagStr[0])) { Modifier = DiagStr; @@ -696,14 +715,14 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { if (DiagStr[0] == '{') { ++DiagStr; // Skip {. Argument = DiagStr; - + for (; DiagStr[0] != '}'; ++DiagStr) assert(DiagStr[0] && "Mismatched {}'s in diagnostic string!"); ArgumentLen = DiagStr-Argument; ++DiagStr; // Skip }. } } - + assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic"); unsigned ArgNo = *DiagStr++ - '0'; @@ -722,14 +741,14 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { // Don't crash if get passed a null pointer by accident. if (!S) S = "(null)"; - + OutStr.append(S, S + strlen(S)); break; } // ---- INTEGERS ---- case Diagnostic::ak_sint: { int Val = getArgSInt(ArgNo); - + if (ModifierIs(Modifier, ModifierLen, "select")) { HandleSelectModifier((unsigned)Val, Argument, ArgumentLen, OutStr); } else if (ModifierIs(Modifier, ModifierLen, "s")) { @@ -746,7 +765,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { } case Diagnostic::ak_uint: { unsigned Val = getArgUInt(ArgNo); - + if (ModifierIs(Modifier, ModifierLen, "select")) { HandleSelectModifier(Val, Argument, ArgumentLen, OutStr); } else if (ModifierIs(Modifier, ModifierLen, "s")) { @@ -755,7 +774,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr); } else { assert(ModifierLen == 0 && "Unknown integer modifier"); - + // FIXME: Optimize std::string S = llvm::utostr_32(Val); OutStr.append(S.begin(), S.end()); @@ -782,6 +801,8 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { case Diagnostic::ak_qualtype: case Diagnostic::ak_declarationname: case Diagnostic::ak_nameddecl: + case Diagnostic::ak_nestednamespec: + case Diagnostic::ak_declcontext: getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo), Modifier, ModifierLen, Argument, ArgumentLen, OutStr); diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index cc25d33051586..df86f9d04702e 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -19,9 +19,12 @@ #include "clang/Basic/FileManager.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" -#include "llvm/Support/Streams.h" #include "llvm/Config/config.h" +#include <map> +#include <set> +#include <string> using namespace clang; // FIXME: Enhance libsystem to support inode and other fields. @@ -44,8 +47,7 @@ using namespace clang; #define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\') namespace { - static std::string GetFullPath(const char *relPath) - { + static std::string GetFullPath(const char *relPath) { char *absPathStrPtr = _fullpath(NULL, relPath, 0); assert(absPathStrPtr && "_fullpath() returned NULL!"); @@ -59,7 +61,7 @@ namespace { class FileManager::UniqueDirContainer { /// UniqueDirs - Cache from full path to existing directories/files. /// - llvm::StringMap<DirectoryEntry> UniqueDirs; + llvm::StringMap<DirectoryEntry> UniqueDirs; public: DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { @@ -69,7 +71,7 @@ public: FullPath.c_str() + FullPath.size() ).getValue(); } - + size_t size() { return UniqueDirs.size(); } }; @@ -101,7 +103,7 @@ public: class FileManager::UniqueDirContainer { /// UniqueDirs - Cache from ID's to existing directories/files. /// - std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; + std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; public: DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { @@ -149,27 +151,27 @@ FileManager::~FileManager() { /// 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_cached(InterndDirName, &StatBuf) || // Error stat'ing. @@ -177,13 +179,13 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart, 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. + // 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; @@ -196,11 +198,11 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart, /// 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); @@ -209,7 +211,7 @@ const FileEntry *FileManager::getFile(const char *NameStart, if (NamedFileEnt.getValue()) return NamedFileEnt.getValue() == NON_EXISTENT_FILE ? 0 : NamedFileEnt.getValue(); - + ++NumFileCacheMisses; // By default, initialize it to invalid. @@ -221,7 +223,10 @@ const FileEntry *FileManager::getFile(const char *NameStart, const char *SlashPos = NameEnd-1; while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0])) --SlashPos; - + // Ignore duplicate //'s. + while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1])) + --SlashPos; + const DirectoryEntry *DirInfo; if (SlashPos < NameStart) { // Use the current directory if file has no path component. @@ -231,32 +236,32 @@ const FileEntry *FileManager::getFile(const char *NameStart, 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; + //llvm::errs() << "STATING: " << Filename; if (stat_cached(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"; + //llvm::errs() << ": Not existing\n"; return 0; } - //llvm::cerr << ": exists\n"; - + //llvm::errs() << ": 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; @@ -273,23 +278,24 @@ const FileEntry *FileManager::getFile(const char *NameStart, } 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; + llvm::errs() << "\n*** File Manager Stats:\n"; + llvm::errs() << UniqueFiles.size() << " files found, " + << UniqueDirs.size() << " dirs found.\n"; + llvm::errs() << NumDirLookups << " dir lookups, " + << NumDirCacheMisses << " dir cache misses.\n"; + llvm::errs() << NumFileLookups << " file lookups, " + << NumFileCacheMisses << " file cache misses.\n"; + + //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; } int MemorizeStatCalls::stat(const char *path, struct stat *buf) { int result = ::stat(path, buf); - - if (result != 0) { + + if (result != 0) { // Cache failed 'stat' results. struct stat empty; + memset(&empty, 0, sizeof(empty)); StatCalls[path] = StatResult(result, empty); } else if (!S_ISDIR(buf->st_mode) || llvm::sys::Path(path).isAbsolute()) { @@ -297,6 +303,6 @@ int MemorizeStatCalls::stat(const char *path, struct stat *buf) { // paths. StatCalls[path] = StatResult(result, *buf); } - - return result; + + return result; } diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 3810c49f71f31..93c260fdbe17a 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -109,9 +109,9 @@ static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen, Info.setIsCPlusPlusOperatorKeyword(); } -/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or +/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or /// "property". -static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID, +static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID, const char *Name, unsigned NameLen, IdentifierTable &Table) { Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID); @@ -144,13 +144,13 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { // 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(); @@ -179,7 +179,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { CASE( 8, 'u', 'a', unassert); CASE(12, 'i', 'c', include_next); - + CASE(16, '_', 'i', __include_macros); #undef CASE #undef HASH @@ -198,7 +198,7 @@ void IdentifierTable::PrintStats() const { 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) { @@ -207,7 +207,7 @@ void IdentifierTable::PrintStats() const { 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); @@ -216,7 +216,7 @@ void IdentifierTable::PrintStats() const { 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(); } @@ -232,42 +232,42 @@ unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) { namespace clang { /// 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 +/// to unique aggregate names (keyword selectors in ObjC parlance). Access to /// this class is provided strictly through Selector. -class MultiKeywordSelector +class MultiKeywordSelector : public DeclarationNameExtra, public llvm::FoldingSetNode { MultiKeywordSelector(unsigned nKeys) { ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys; } -public: +public: // Constructor for keyword selectors. MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) { assert((nKeys > 1) && "not a multi-keyword selector"); ExtraKindOrNumArgs = NUM_EXTRA_KINDS + 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 ExtraKindOrNumArgs - NUM_EXTRA_KINDS; } - + 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()+getNumArgs(); + keyword_iterator keyword_end() const { + return keyword_begin()+getNumArgs(); } IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const { assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index"); return keyword_begin()[i]; } - static void Profile(llvm::FoldingSetNodeID &ID, + static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys, unsigned NumArgs) { ID.AddInteger(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) @@ -287,7 +287,7 @@ unsigned Selector::getNumArgs() const { return 1; // We point to a MultiKeywordSelector (pointer doesn't contain any flags). MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr); - return SI->getNumArgs(); + return SI->getNumArgs(); } IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const { @@ -308,16 +308,16 @@ std::string MultiKeywordSelector::getName() const { 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; } @@ -327,7 +327,7 @@ std::string Selector::getAsString() const { if (InfoPtr & ArgFlags) { IdentifierInfo *II = getAsIdentifierInfo(); - + // If the number of arguments is 0 then II is guaranteed to not be null. if (getNumArgs() == 0) return II->getName(); @@ -336,7 +336,7 @@ std::string Selector::getAsString() const { Res += ":"; return Res; } - + // We have a multiple keyword selector (no embedded flags). return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName(); } @@ -357,9 +357,9 @@ static SelectorTableImpl &getSelectorTableImpl(void *P) { Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) { if (nKeys < 2) return Selector(IIV[0], nKeys); - + SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl); - + // Unique selector, to guarantee there is one per name. llvm::FoldingSetNodeID ID; MultiKeywordSelector::Profile(ID, IIV, nKeys); @@ -368,12 +368,12 @@ Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) { if (MultiKeywordSelector *SI = SelTabImpl.Table.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. unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *); MultiKeywordSelector *SI = - (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size, + (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size, llvm::alignof<MultiKeywordSelector>()); new (SI) MultiKeywordSelector(nKeys, IIV); SelTabImpl.Table.InsertNode(SI, InsertPos); diff --git a/lib/Basic/Makefile b/lib/Basic/Makefile index 3fd6c2c153842..5bd4314f45cdc 100644 --- a/lib/Basic/Makefile +++ b/lib/Basic/Makefile @@ -20,3 +20,14 @@ CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include include $(LEVEL)/Makefile.common +SVN_REVISION := $(shell cd $(PROJ_SRC_DIR)/../.. && svnversion) + +CPP.Defines += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include \ + -DSVN_REVISION='"$(SVN_REVISION)"' + +$(ObjDir)/.ver-svn .ver: $(ObjDir)/.dir + @if [ '$(SVN_REVISION)' != '$(shell cat $(ObjDir)/.ver-svn 2>/dev/null)' ]; then\ + echo '$(SVN_REVISION)' > $(ObjDir)/.ver-svn; \ + fi +$(ObjDir)/.ver-svn: .ver +$(ObjDir)/Version.o: $(ObjDir)/.ver-svn diff --git a/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp index f21ec8b1e9d7e..578a4eb34bab5 100644 --- a/lib/Basic/SourceLocation.cpp +++ b/lib/Basic/SourceLocation.cpp @@ -40,7 +40,7 @@ void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{ OS << "<invalid loc>"; return; } - + if (isFileID()) { PresumedLoc PLoc = SM.getPresumedLoc(*this); // The instantiation and spelling pos is identical for file locs. @@ -48,7 +48,7 @@ void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{ << ':' << PLoc.getColumn(); return; } - + SM.getInstantiationLoc(*this).print(OS, SM); OS << " <Spelling="; diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 6640c61ff3b79..962cb4c42a8ab 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -16,10 +16,9 @@ #include "clang/Basic/FileManager.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" -#include "llvm/Support/Streams.h" #include <algorithm> -#include <iostream> using namespace clang; using namespace SrcMgr; using llvm::MemoryBuffer; @@ -42,29 +41,74 @@ unsigned ContentCache::getSizeBytesMapped() const { /// getSize - Returns the size of the content encapsulated by this ContentCache. /// This can be the size of the source file or the size of an arbitrary /// scratch buffer. If the ContentCache encapsulates a source file, that -/// file is not lazily brought in from disk to satisfy this query. +/// file is not lazily brought in from disk to satisfy this query unless it +/// needs to be truncated due to a truncateAt() call. unsigned ContentCache::getSize() const { - return Entry ? Entry->getSize() : Buffer->getBufferSize(); + return Buffer ? Buffer->getBufferSize() : Entry->getSize(); } -const llvm::MemoryBuffer *ContentCache::getBuffer() const { +const llvm::MemoryBuffer *ContentCache::getBuffer() const { // Lazily create the Buffer for ContentCaches that wrap files. if (!Buffer && Entry) { // FIXME: Should we support a way to not have to do this check over // and over if we cannot open the file? Buffer = MemoryBuffer::getFile(Entry->getName(), 0, Entry->getSize()); + if (isTruncated()) + const_cast<ContentCache *>(this)->truncateAt(TruncateAtLine, + TruncateAtColumn); } return Buffer; } +void ContentCache::truncateAt(unsigned Line, unsigned Column) { + TruncateAtLine = Line; + TruncateAtColumn = Column; + + if (!isTruncated() || !Buffer) + return; + + // Find the byte position of the truncation point. + const char *Position = Buffer->getBufferStart(); + for (unsigned Line = 1; Line < TruncateAtLine; ++Line) { + for (; *Position; ++Position) { + if (*Position != '\r' && *Position != '\n') + continue; + + // Eat \r\n or \n\r as a single line. + if ((Position[1] == '\r' || Position[1] == '\n') && + Position[0] != Position[1]) + ++Position; + ++Position; + break; + } + } + + for (unsigned Column = 1; Column < TruncateAtColumn; ++Column, ++Position) { + if (!*Position) + break; + + if (*Position == '\t') + Column += 7; + } + + // Truncate the buffer. + if (Position != Buffer->getBufferEnd()) { + MemoryBuffer *TruncatedBuffer + = MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position, + Buffer->getBufferIdentifier()); + delete Buffer; + Buffer = TruncatedBuffer; + } +} + unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) { // Look up the filename in the string table, returning the pre-existing value // if it exists. - llvm::StringMapEntry<unsigned> &Entry = + llvm::StringMapEntry<unsigned> &Entry = FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U); if (Entry.getValue() != ~0U) return Entry.getValue(); - + // Otherwise, assign this the next available ID. Entry.setValue(FilenamesByID.size()); FilenamesByID.push_back(&Entry); @@ -77,25 +121,25 @@ unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) { void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, unsigned LineNo, int FilenameID) { std::vector<LineEntry> &Entries = LineEntries[FID]; - + assert((Entries.empty() || Entries.back().FileOffset < Offset) && "Adding line entries out of order!"); - + SrcMgr::CharacteristicKind Kind = SrcMgr::C_User; unsigned IncludeOffset = 0; - + if (!Entries.empty()) { // If this is a '#line 4' after '#line 42 "foo.h"', make sure to remember // that we are still in "foo.h". if (FilenameID == -1) FilenameID = Entries.back().FilenameID; - + // If we are after a line marker that switched us to system header mode, or // that set #include information, preserve it. Kind = Entries.back().FileKind; IncludeOffset = Entries.back().IncludeOffset; } - + Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind, IncludeOffset)); } @@ -110,9 +154,9 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind) { assert(FilenameID != -1 && "Unspecified filename should use other accessor"); - + std::vector<LineEntry> &Entries = LineEntries[FID]; - + assert((Entries.empty() || Entries.back().FileOffset < Offset) && "Adding line entries out of order!"); @@ -124,14 +168,14 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, } else if (EntryExit == 2) { assert(!Entries.empty() && Entries.back().IncludeOffset && "PPDirectives should have caught case when popping empty include stack"); - + // Get the include loc of the last entries' include loc as our include loc. IncludeOffset = 0; if (const LineEntry *PrevEntry = FindNearestLineEntry(FID, Entries.back().IncludeOffset)) IncludeOffset = PrevEntry->IncludeOffset; } - + Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind, IncludeOffset)); } @@ -139,7 +183,7 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, /// FindNearestLineEntry - Find the line entry nearest to FID that is before /// it. If there is no line entry before Offset in FID, return null. -const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID, +const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID, unsigned Offset) { const std::vector<LineEntry> &Entries = LineEntries[FID]; assert(!Entries.empty() && "No #line entries for this FID after all!"); @@ -158,13 +202,13 @@ const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID, /// \brief Add a new line entry that has already been encoded into /// the internal representation of the line table. -void LineTableInfo::AddEntry(unsigned FID, +void LineTableInfo::AddEntry(unsigned FID, const std::vector<LineEntry> &Entries) { LineEntries[FID] = Entries; } /// getLineTableFilenameID - Return the uniqued ID for the specified filename. -/// +/// unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) { if (LineTable == 0) LineTable = new LineTableInfo(); @@ -178,12 +222,12 @@ unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) { void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID) { std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); - + const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile(); // Remember that this file has #line directives now if it doesn't already. const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); - + if (LineTable == 0) LineTable = new LineTableInfo(); LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID); @@ -201,16 +245,16 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, "Can't set flags without setting the filename!"); return AddLineNote(Loc, LineNo, FilenameID); } - + std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile(); - + // Remember that this file has #line directives now if it doesn't already. const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); - + if (LineTable == 0) LineTable = new LineTableInfo(); - + SrcMgr::CharacteristicKind FileKind; if (IsExternCHeader) FileKind = SrcMgr::C_ExternCSystem; @@ -218,13 +262,13 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, FileKind = SrcMgr::C_System; else FileKind = SrcMgr::C_User; - + unsigned EntryExit = 0; if (IsFileEntry) EntryExit = 1; else if (IsFileExit) EntryExit = 2; - + LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID, EntryExit, FileKind); } @@ -241,7 +285,7 @@ LineTableInfo &SourceManager::getLineTable() { SourceManager::~SourceManager() { delete LineTable; - + // Delete FileEntry objects corresponding to content caches. Since the actual // content cache objects are bump pointer allocated, we just have to run the // dtors, but we call the deallocate method for completeness. @@ -262,10 +306,10 @@ void SourceManager::clearIDTables() { LastLineNoFileIDQuery = FileID(); LastLineNoContentCache = 0; LastFileIDLookup = FileID(); - + if (LineTable) LineTable->clear(); - + // Use up FileID #0 as an invalid instantiation. NextOffset = 0; createInstantiationLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); @@ -276,11 +320,11 @@ void SourceManager::clearIDTables() { const ContentCache * SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) { assert(FileEnt && "Didn't specify a file entry to use?"); - + // Do we already have information about this file? ContentCache *&Entry = FileInfos[FileEnt]; if (Entry) return Entry; - + // Nope, create a new Cache entry. Make sure it is at least 8-byte aligned // so that FileInfo can use the low 3 bits of the pointer for its own // nefarious purposes. @@ -288,6 +332,16 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) { EntryAlign = std::max(8U, EntryAlign); Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign); new (Entry) ContentCache(FileEnt); + + if (FileEnt == TruncateFile) { + // If we had queued up a file truncation request, perform the truncation + // now. + Entry->truncateAt(TruncateAtLine, TruncateAtColumn); + TruncateFile = 0; + TruncateAtLine = 0; + TruncateAtColumn = 0; + } + return Entry; } @@ -350,12 +404,12 @@ FileID SourceManager::createFileID(const ContentCache *File, if (PreallocatedID) { // If we're filling in a preallocated ID, just load in the file // entry and return. - assert(PreallocatedID < SLocEntryLoaded.size() && + assert(PreallocatedID < SLocEntryLoaded.size() && "Preallocate ID out-of-range"); - assert(!SLocEntryLoaded[PreallocatedID] && + assert(!SLocEntryLoaded[PreallocatedID] && "Source location entry already loaded"); assert(Offset && "Preallocate source location cannot have zero offset"); - SLocEntryTable[PreallocatedID] + SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter)); SLocEntryLoaded[PreallocatedID] = true; FileID FID = FileID::get(PreallocatedID); @@ -364,13 +418,13 @@ FileID SourceManager::createFileID(const ContentCache *File, return LastFileIDLookup = FID; } - SLocEntryTable.push_back(SLocEntry::get(NextOffset, + SLocEntryTable.push_back(SLocEntry::get(NextOffset, FileInfo::get(IncludePos, File, FileCharacter))); unsigned FileSize = File->getSize(); assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!"); NextOffset += FileSize+1; - + // Set LastFileIDLookup to the newly created file. The next getFileID call is // almost guaranteed to be from that file. FileID FID = FileID::get(SLocEntryTable.size()-1); @@ -392,9 +446,9 @@ SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc, if (PreallocatedID) { // If we're filling in a preallocated ID, just load in the // instantiation entry and return. - assert(PreallocatedID < SLocEntryLoaded.size() && + assert(PreallocatedID < SLocEntryLoaded.size() && "Preallocate ID out-of-range"); - assert(!SLocEntryLoaded[PreallocatedID] && + assert(!SLocEntryLoaded[PreallocatedID] && "Source location entry already loaded"); assert(Offset && "Preallocate source location cannot have zero offset"); SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, II); @@ -427,7 +481,7 @@ SourceManager::getBufferData(FileID FID) const { /// FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { assert(SLocOffset && "Invalid FileID"); - + // After the first and second level caches, I see two common sorts of // behavior: 1) a lot of searched FileID's are "near" the cached file location // or are "near" the cached instantiation location. 2) others are just @@ -436,11 +490,11 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { // To handle this, we do a linear search for up to 8 steps to catch #1 quickly // then we fall back to a less cache efficient, but more scalable, binary // search to find the location. - + // See if this is near the file point - worst case we start scanning from the // most newly created FileID. std::vector<SrcMgr::SLocEntry>::const_iterator I; - + if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) { // Neither loc prunes our search. I = SLocEntryTable.end(); @@ -475,7 +529,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { if (++NumProbes == 8) break; } - + // Convert "I" back into an index. We know that it is an entry whose index is // larger than the offset we are looking for. unsigned GreaterIndex = I-SLocEntryTable.begin(); @@ -487,16 +541,16 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { while (1) { unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex)).getOffset(); - + ++NumProbes; - + // If the offset of the midpoint is too large, chop the high side of the // range to the midpoint. if (MidOffset > SLocOffset) { GreaterIndex = MiddleIndex; continue; } - + // If the middle index contains the value, succeed and return. if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) { #if 0 @@ -514,7 +568,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { NumBinaryProbes += NumProbes; return Res; } - + // Otherwise, move the low-side up to the middle index. LessIndex = MiddleIndex; } @@ -551,12 +605,12 @@ SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E, SourceLocation Loc; do { Loc = E->getInstantiation().getInstantiationLocStart(); - + FID = getFileID(Loc); E = &getSLocEntry(FID); Offset += Loc.getOffset()-E->getOffset(); } while (!Loc.isFileID()); - + return std::make_pair(FID, Offset); } @@ -569,12 +623,12 @@ SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, SourceLocation Loc; do { Loc = E->getInstantiation().getSpellingLoc(); - + FID = getFileID(Loc); E = &getSLocEntry(FID); Offset += Loc.getOffset()-E->getOffset(); } while (!Loc.isFileID()); - + return std::make_pair(FID, Offset); } @@ -604,10 +658,10 @@ SourceManager::getImmediateInstantiationRange(SourceLocation Loc) const { std::pair<SourceLocation,SourceLocation> SourceManager::getInstantiationRange(SourceLocation Loc) const { if (Loc.isFileID()) return std::make_pair(Loc, Loc); - + std::pair<SourceLocation,SourceLocation> Res = getImmediateInstantiationRange(Loc); - + // Fully resolve the start and end locations to their ultimate instantiation // points. while (!Res.first.isFileID()) @@ -629,7 +683,7 @@ 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. std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL); - + // Note that calling 'getBuffer()' may lazily page in a source file. return getSLocEntry(LocInfo.first).getFile().getContentCache() ->getBuffer()->getBufferStart() + LocInfo.second; @@ -640,7 +694,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const { /// this is significantly cheaper to compute than the line number. unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos) const { const char *Buf = getBuffer(FID)->getBufferStart(); - + unsigned LineStart = FilePos; while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r') --LineStart; @@ -663,17 +717,17 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc) const { static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE; -static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ +static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ // Note that calling 'getBuffer()' may lazily page in the file. const MemoryBuffer *Buffer = FI->getBuffer(); - + // 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; @@ -686,7 +740,7 @@ static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ ++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]) @@ -700,7 +754,7 @@ static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ ++Offs, ++Buf; } } - + // Copy the offsets into the FileInfo structure. FI->NumLines = LineOffsets.size(); FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size()); @@ -718,7 +772,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { else Content = const_cast<ContentCache*>(getSLocEntry(FID) .getFile().getContentCache()); - + // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) @@ -729,11 +783,11 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { unsigned *SourceLineCache = Content->SourceLineCache; unsigned *SourceLineCacheStart = SourceLineCache; unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines; - + unsigned QueriedFilePos = FilePos+1; // FIXME: I would like to be convinced that this code is worth being as - // complicated as it is, binary search isn't that slow. + // complicated as it is, binary search isn't that slow. // // If it is worth being optimized, then in my opinion it could be more // performant, simpler, and more obviously correct by just "galloping" outward @@ -749,7 +803,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { if (QueriedFilePos >= LastLineNoFilePos) { // FIXME: Potential overflow? 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 @@ -771,17 +825,17 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { 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); @@ -790,17 +844,17 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { 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 = FID; LastLineNoContentCache = Content; LastLineNoFilePos = QueriedFilePos; @@ -820,14 +874,14 @@ unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc) const { } /// getFileCharacteristic - return the file characteristic of the specified -/// source location, indicating whether this is a normal file, a system +/// source location, indicating whether this is a normal file, a system /// header, or an "implicit extern C" system header. /// /// This state can be modified with flags on GNU linemarker directives like: /// # 4 "foo.h" 3 /// which changes all source locations in the current file after that to be /// considered to be from a system header. -SrcMgr::CharacteristicKind +SrcMgr::CharacteristicKind SourceManager::getFileCharacteristic(SourceLocation Loc) const { assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!"); std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); @@ -837,12 +891,12 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const { // state. if (!FI.hasLineDirectives()) return FI.getFileCharacteristic(); - + assert(LineTable && "Can't have linetable entries without a LineTable!"); // See if there is a #line directive before the location. const LineEntry *Entry = LineTable->FindNearestLineEntry(LocInfo.first.ID, LocInfo.second); - + // If this is before the first line marker, use the file characteristic. if (!Entry) return FI.getFileCharacteristic(); @@ -855,7 +909,7 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const { /// for normal clients. const char *SourceManager::getBufferName(SourceLocation Loc) const { if (Loc.isInvalid()) return "<invalid loc>"; - + return getBuffer(getFileID(Loc))->getBufferIdentifier(); } @@ -869,22 +923,22 @@ const char *SourceManager::getBufferName(SourceLocation Loc) const { /// of an instantiation location, not at the spelling location. PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { if (Loc.isInvalid()) return PresumedLoc(); - + // Presumed locations are always for instantiation points. std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); - + const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile(); const SrcMgr::ContentCache *C = FI.getContentCache(); - + // To get the source name, first consult the FileEntry (if one exists) // before the MemBuffer as this will avoid unnecessarily paging in the // MemBuffer. - const char *Filename = + const char *Filename = C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier(); unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second); unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second); SourceLocation IncludeLoc = FI.getIncludeLoc(); - + // If we have #line directives in this file, update and overwrite the physical // location info if appropriate. if (FI.hasLineDirectives()) { @@ -902,9 +956,9 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { // total. unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset); LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1); - + // Note that column numbers are not molested by line markers. - + // Handle virtual #include manipulation. if (Entry->IncludeOffset) { IncludeLoc = getLocForStartOfFile(LocInfo.first); @@ -933,7 +987,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, if (FI == FileInfos.end()) return SourceLocation(); ContentCache *Content = FI->second; - + // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) @@ -941,7 +995,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, if (Line > Content->NumLines) return SourceLocation(); - + unsigned FilePos = Content->SourceLineCache[Line - 1]; const char *Buf = Content->getBuffer()->getBufferStart() + FilePos; unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf; @@ -952,7 +1006,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, ++i; if (i < Col-1) return SourceLocation(); - + return getLocForStartOfFile(Content->FirstFID). getFileLocWithOffset(FilePos + Col - 1); } @@ -965,24 +1019,24 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!"); if (LHS == RHS) return false; - + std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS); std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS); - + // If the source locations are in the same file, just compare offsets. if (LOffs.first == ROffs.first) return LOffs.second < ROffs.second; // If we are comparing a source location with multiple locations in the same // file, we get a big win by caching the result. - + if (LastLFIDForBeforeTUCheck == LOffs.first && LastRFIDForBeforeTUCheck == ROffs.first) return LastResForBeforeTUCheck; - + LastLFIDForBeforeTUCheck = LOffs.first; LastRFIDForBeforeTUCheck = ROffs.first; - + // "Traverse" the include/instantiation stacks of both locations and try to // find a common "ancestor". // @@ -1000,15 +1054,15 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, UpperLoc = Entry.getInstantiation().getInstantiationLocStart(); else UpperLoc = Entry.getFile().getIncludeLoc(); - + if (UpperLoc.isInvalid()) break; // We reached the top. - + ROffs = getDecomposedLoc(UpperLoc); - + if (LOffs.first == ROffs.first) return LastResForBeforeTUCheck = LOffs.second < ROffs.second; - + ROffsMap[ROffs.first] = ROffs.second; } @@ -1022,33 +1076,33 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, UpperLoc = Entry.getInstantiation().getInstantiationLocStart(); else UpperLoc = Entry.getFile().getIncludeLoc(); - + if (UpperLoc.isInvalid()) break; // We reached the top. - + LOffs = getDecomposedLoc(UpperLoc); - + std::map<FileID, unsigned>::iterator I = ROffsMap.find(LOffs.first); if (I != ROffsMap.end()) return LastResForBeforeTUCheck = LOffs.second < I->second; } - + // No common ancestor. // Now we are getting into murky waters. Most probably this is because one // location is in the predefines buffer. - + const FileEntry *LEntry = getSLocEntry(LOffs.first).getFile().getContentCache()->Entry; const FileEntry *REntry = getSLocEntry(ROffs.first).getFile().getContentCache()->Entry; - + // If the locations are in two memory buffers we give up, we can't answer // which one should be considered first. // FIXME: Should there be a way to "include" memory buffers in the translation // unit ? assert((LEntry != 0 || REntry != 0) && "Locations in memory buffers."); (void) REntry; - + // Consider the memory buffer as coming before the file in the translation // unit. if (LEntry == 0) @@ -1059,26 +1113,48 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, } } +void SourceManager::truncateFileAt(const FileEntry *Entry, unsigned Line, + unsigned Column) { + llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator FI + = FileInfos.find(Entry); + if (FI != FileInfos.end()) { + FI->second->truncateAt(Line, Column); + return; + } + + // We cannot perform the truncation until we actually see the file, so + // save the truncation information. + assert(TruncateFile == 0 && "Can't queue up multiple file truncations!"); + TruncateFile = Entry; + TruncateAtLine = Line; + TruncateAtColumn = Column; +} + +/// \brief Determine whether this file was truncated. +bool SourceManager::isTruncatedFile(FileID FID) const { + return getSLocEntry(FID).getFile().getContentCache()->isTruncated(); +} + /// 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.\n"; - llvm::cerr << SLocEntryTable.size() << " SLocEntry's allocated, " - << NextOffset << "B of Sloc address space used.\n"; - + llvm::errs() << "\n*** Source Manager Stats:\n"; + llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size() + << " mem buffers mapped.\n"; + llvm::errs() << SLocEntryTable.size() << " SLocEntry's allocated, " + << NextOffset << "B of Sloc address space used.\n"; + unsigned NumLineNumsComputed = 0; unsigned NumFileBytesMapped = 0; for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){ NumLineNumsComputed += I->second->SourceLineCache != 0; NumFileBytesMapped += I->second->getSizeBytesMapped(); } - - llvm::cerr << NumFileBytesMapped << " bytes of files mapped, " - << NumLineNumsComputed << " files with line #'s computed.\n"; - llvm::cerr << "FileID scans: " << NumLinearScans << " linear, " - << NumBinaryProbes << " binary.\n"; + + llvm::errs() << NumFileBytesMapped << " bytes of files mapped, " + << NumLineNumsComputed << " files with line #'s computed.\n"; + llvm::errs() << "FileID scans: " << NumLinearScans << " linear, " + << NumBinaryProbes << " binary.\n"; } ExternalSLocEntrySource::~ExternalSLocEntrySource() { } diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index ba7f190408b29..9cd12493e7a49 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -25,6 +25,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { TLSSupported = true; PointerWidth = PointerAlign = 32; WCharWidth = WCharAlign = 32; + Char16Width = Char16Align = 16; + Char32Width = Char32Align = 32; IntWidth = IntAlign = 32; LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; @@ -41,6 +43,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { UIntMaxType = UnsignedLongLong; IntPtrType = SignedLong; WCharType = SignedInt; + Char16Type = UnsignedShort; + Char32Type = UnsignedInt; Int64Type = SignedLongLong; FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEdouble; @@ -83,17 +87,17 @@ static void removeGCCRegisterPrefix(const char *&Name) { 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; @@ -107,11 +111,11 @@ bool TargetInfo::isValidGCCRegisterName(const char *Name) const { 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++) { @@ -121,15 +125,15 @@ bool TargetInfo::isValidGCCRegisterName(const char *Name) const { 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; @@ -140,16 +144,16 @@ const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const { char *End; int n = (int)strtol(Name, &End, 0); if (*End == 0) { - assert(n >= 0 && (unsigned)n < NumNames && + 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++) { @@ -159,7 +163,7 @@ const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const { return Aliases[i].Register; } } - + return Name; } @@ -184,6 +188,9 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { } case '&': // early clobber. break; + case '%': // commutative. + // FIXME: Check that there is a another register after this one. + break; case 'r': // general register. Info.setAllowsRegister(); break; @@ -196,10 +203,10 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { Info.setAllowsMemory(); break; } - + Name++; } - + return true; } @@ -212,14 +219,14 @@ bool TargetInfo::resolveSymbolicName(const char *&Name, const char *Start = Name; while (*Name && *Name != ']') Name++; - + if (!*Name) { // Missing ']' return false; } - + std::string SymbolicName(Start, Name - Start); - + for (Index = 0; Index != NumOutputs; ++Index) if (SymbolicName == OutputConstraints[Index].getName()) return true; @@ -238,12 +245,12 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, // 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; - - // The constraint should have the same info as the respective + + // The constraint should have the same info as the respective // output constraint. Info.setTiedOperand(i, OutputConstraints[i]); } else if (!validateAsmConstraint(Name, Info)) { @@ -257,9 +264,9 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, unsigned Index = 0; if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index)) return false; - + break; - } + } case '%': // commutative // FIXME: Fail if % is used with the last operand. break; @@ -287,9 +294,9 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, Info.setAllowsMemory(); break; } - + Name++; } - + return true; } diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 3f7d9a31c61e9..1d4d1235c9634 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -16,22 +16,25 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/LangOptions.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCSectionMachO.h" using namespace clang; //===----------------------------------------------------------------------===// // Common code shared among targets. //===----------------------------------------------------------------------===// -static void Define(std::vector<char> &Buf, const char *Macro, - const char *Val = "1") { +static void Define(std::vector<char> &Buf, const llvm::StringRef &Macro, + const llvm::StringRef &Val = "1") { const char *Def = "#define "; Buf.insert(Buf.end(), Def, Def+strlen(Def)); - Buf.insert(Buf.end(), Macro, Macro+strlen(Macro)); + Buf.insert(Buf.end(), Macro.begin(), Macro.end()); Buf.push_back(' '); - Buf.insert(Buf.end(), Val, Val+strlen(Val)); + Buf.insert(Buf.end(), Val.begin(), Val.end()); Buf.push_back('\n'); } @@ -51,91 +54,34 @@ static void DefineStd(std::vector<char> &Buf, const char *MacroName, llvm::SmallString<20> TmpStr; TmpStr = "__"; TmpStr += MacroName; - Define(Buf, TmpStr.c_str()); + Define(Buf, TmpStr.str()); // Define __unix__. TmpStr += "__"; - Define(Buf, TmpStr.c_str()); + Define(Buf, TmpStr.str()); } //===----------------------------------------------------------------------===// // Defines specific to certain operating systems. //===----------------------------------------------------------------------===// + namespace { template<typename TgtInfo> class OSTargetInfo : public TgtInfo { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defines) const=0; public: OSTargetInfo(const std::string& triple) : TgtInfo(triple) {} virtual void getTargetDefines(const LangOptions &Opts, std::vector<char> &Defines) const { TgtInfo::getTargetDefines(Opts, Defines); - getOSDefines(Opts, TgtInfo::getTargetTriple(), Defines); + getOSDefines(Opts, TgtInfo::getTriple(), Defines); } }; -} - -namespace { -/// getDarwinNumber - Parse the 'darwin number' out of the specific targe -/// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is -/// not defined, return 0's. Return true if we have -darwin in the string or -/// false otherwise. -static bool getDarwinNumber(const char *Triple, unsigned &Maj, unsigned &Min, unsigned &Revision) { - Maj = Min = Revision = 0; - const char *Darwin = strstr(Triple, "-darwin"); - if (Darwin == 0) return false; - - Darwin += strlen("-darwin"); - if (Darwin[0] < '0' || Darwin[0] > '9') - return true; - - Maj = Darwin[0]-'0'; - ++Darwin; - - // Handle "darwin11". - if (Maj == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') { - Maj = Maj*10 + (Darwin[0] - '0'); - ++Darwin; - } - - // Handle minor version: 10.4.9 -> darwin8.9 -> "1049" - if (Darwin[0] != '.') - return true; - - ++Darwin; - if (Darwin[0] < '0' || Darwin[0] > '9') - return true; - - Min = Darwin[0]-'0'; - ++Darwin; - - // Handle 10.4.11 -> darwin8.11 - if (Min == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') { - Min = Min*10 + (Darwin[0] - '0'); - ++Darwin; - } - - // Handle revision darwin8.9.1 - if (Darwin[0] != '.') - return true; - - ++Darwin; - if (Darwin[0] < '0' || Darwin[0] > '9') - return true; - - Revision = Darwin[0]-'0'; - ++Darwin; - - if (Revision == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') { - Revision = Revision*10 + (Darwin[0] - '0'); - ++Darwin; - } +} // end anonymous namespace - return true; -} static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts) { Define(Defs, "__APPLE_CC__", "5621"); @@ -156,81 +102,94 @@ static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts) { Define(Defs, "__STATIC__"); else Define(Defs, "__DYNAMIC__"); + + if (Opts.POSIXThreads) + Define(Defs, "_REENTRANT", "1"); } -static void getDarwinOSXDefines(std::vector<char> &Defs, const char *Triple) { +static void getDarwinOSXDefines(std::vector<char> &Defs, + const llvm::Triple &Triple) { + if (Triple.getOS() != llvm::Triple::Darwin) + return; + // Figure out which "darwin number" the target triple is. "darwin9" -> 10.5. unsigned Maj, Min, Rev; - if (getDarwinNumber(Triple, Maj, Min, Rev)) { - char MacOSXStr[] = "1000"; - if (Maj >= 4 && Maj <= 13) { // 10.0-10.9 - // darwin7 -> 1030, darwin8 -> 1040, darwin9 -> 1050, etc. - MacOSXStr[2] = '0' + Maj-4; - } + Triple.getDarwinNumber(Maj, Min, Rev); - // Handle minor version: 10.4.9 -> darwin8.9 -> "1049" - // Cap 10.4.11 -> darwin8.11 -> "1049" - MacOSXStr[3] = std::min(Min, 9U)+'0'; - Define(Defs, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", MacOSXStr); + char MacOSXStr[] = "1000"; + if (Maj >= 4 && Maj <= 13) { // 10.0-10.9 + // darwin7 -> 1030, darwin8 -> 1040, darwin9 -> 1050, etc. + MacOSXStr[2] = '0' + Maj-4; } + + // Handle minor version: 10.4.9 -> darwin8.9 -> "1049" + // Cap 10.4.11 -> darwin8.11 -> "1049" + MacOSXStr[3] = std::min(Min, 9U)+'0'; + Define(Defs, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", MacOSXStr); } static void getDarwinIPhoneOSDefines(std::vector<char> &Defs, - const char *Triple) { + const llvm::Triple &Triple) { + if (Triple.getOS() != llvm::Triple::Darwin) + return; + // Figure out which "darwin number" the target triple is. "darwin9" -> 10.5. unsigned Maj, Min, Rev; - if (getDarwinNumber(Triple, Maj, Min, Rev)) { - // When targetting iPhone OS, interpret the minor version and - // revision as the iPhone OS version - char iPhoneOSStr[] = "10000"; - if (Min >= 2 && Min <= 9) { // iPhone OS 2.0-9.0 - // darwin9.2.0 -> 20000, darwin9.3.0 -> 30000, etc. - iPhoneOSStr[0] = '0' + Min; - } + Triple.getDarwinNumber(Maj, Min, Rev); - // Handle minor version: 2.2 -> darwin9.2.2 -> 20200 - iPhoneOSStr[2] = std::min(Rev, 9U)+'0'; - Define(Defs, "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", - iPhoneOSStr); + // When targetting iPhone OS, interpret the minor version and + // revision as the iPhone OS version + char iPhoneOSStr[] = "10000"; + if (Min >= 2 && Min <= 9) { // iPhone OS 2.0-9.0 + // darwin9.2.0 -> 20000, darwin9.3.0 -> 30000, etc. + iPhoneOSStr[0] = '0' + Min; } + + // Handle minor version: 2.2 -> darwin9.2.2 -> 20200 + iPhoneOSStr[2] = std::min(Rev, 9U)+'0'; + Define(Defs, "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", + iPhoneOSStr); } /// GetDarwinLanguageOptions - Set the default language options for darwin. static void GetDarwinLanguageOptions(LangOptions &Opts, - const char *Triple) { + const llvm::Triple &Triple) { Opts.NeXTRuntime = true; - unsigned Maj, Min, Rev; - if (!getDarwinNumber(Triple, Maj, Min, Rev)) + if (Triple.getOS() != llvm::Triple::Darwin) return; + unsigned MajorVersion = Triple.getDarwinMajorNumber(); + // Blocks and stack protectors default to on for 10.6 (darwin10) and beyond. - if (Maj > 9) { + if (MajorVersion > 9) { Opts.Blocks = 1; Opts.setStackProtectorMode(LangOptions::SSPOn); } // Non-fragile ABI (in 64-bit mode) default to on for 10.5 (darwin9) and // beyond. - if (Maj >= 9 && Opts.ObjC1 && !strncmp(Triple, "x86_64", 6)) + if (MajorVersion >= 9 && Opts.ObjC1 && + Triple.getArch() == llvm::Triple::x86_64) Opts.ObjCNonFragileABI = 1; } +namespace { template<typename Target> class DarwinTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defines) const { getDarwinDefines(Defines, Opts); getDarwinOSXDefines(Defines, Triple); } - + /// getDefaultLangOptions - Allow the target to specify default settings for /// various language options. These may be overridden by command line /// options. virtual void getDefaultLangOptions(LangOptions &Opts) { TargetInfo::getDefaultLangOptions(Opts); - GetDarwinLanguageOptions(Opts, TargetInfo::getTargetTriple()); + GetDarwinLanguageOptions(Opts, TargetInfo::getTriple()); } public: DarwinTargetInfo(const std::string& triple) : @@ -238,28 +197,25 @@ public: this->TLSSupported = false; } - virtual const char *getCFStringSymbolPrefix() const { - return "\01L_unnamed_cfstring_"; - } - - virtual const char *getStringSymbolPrefix(bool IsConstant) const { - return IsConstant ? "\01LC" : "\01lC"; - } - - virtual const char *getUnicodeStringSymbolPrefix() const { - return "__utf16_string_"; - } - virtual const char *getUnicodeStringSection() const { return "__TEXT,__ustring"; } + + virtual std::string isValidSectionSpecifier(const llvm::StringRef &SR) const { + // Let MCSectionMachO validate this. + llvm::StringRef Segment, Section; + unsigned TAA, StubSize; + return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section, + TAA, StubSize); + } }; + // DragonFlyBSD Target template<typename Target> class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defs) const { // DragonFly defines; list based off of gcc output Define(Defs, "__DragonFly__"); @@ -270,7 +226,7 @@ protected: DefineStd(Defs, "unix", Opts); } public: - DragonFlyBSDTargetInfo(const std::string &triple) + DragonFlyBSDTargetInfo(const std::string &triple) : OSTargetInfo<Target>(triple) {} }; @@ -278,11 +234,13 @@ public: template<typename Target> class FreeBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defs) const { // FreeBSD defines; list based off of gcc output - const char *FreeBSD = strstr(Triple, "-freebsd"); + // FIXME: Move version number handling to llvm::Triple. + const char *FreeBSD = strstr(Triple.getTriple().c_str(), + "-freebsd"); FreeBSD += strlen("-freebsd"); char release[] = "X"; release[0] = FreeBSD[0]; @@ -296,43 +254,69 @@ protected: Define(Defs, "__ELF__", "1"); } public: - FreeBSDTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) {} + FreeBSDTargetInfo(const std::string &triple) + : OSTargetInfo<Target>(triple) { + this->UserLabelPrefix = ""; + } }; // Linux target template<typename Target> class LinuxTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defs) const { // Linux defines; list based off of gcc output DefineStd(Defs, "unix", Opts); DefineStd(Defs, "linux", Opts); Define(Defs, "__gnu_linux__"); Define(Defs, "__ELF__", "1"); + if (Opts.POSIXThreads) + Define(Defs, "_REENTRANT", "1"); } public: - LinuxTargetInfo(const std::string& triple) + LinuxTargetInfo(const std::string& triple) : OSTargetInfo<Target>(triple) { this->UserLabelPrefix = ""; } }; +// NetBSD Target +template<typename Target> +class NetBSDTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + std::vector<char> &Defs) const { + // NetBSD defines; list based off of gcc output + Define(Defs, "__NetBSD__", "1"); + Define(Defs, "__unix__", "1"); + Define(Defs, "__ELF__", "1"); + if (Opts.POSIXThreads) + Define(Defs, "_POSIX_THREADS", "1"); + } +public: + NetBSDTargetInfo(const std::string &triple) + : OSTargetInfo<Target>(triple) { + this->UserLabelPrefix = ""; + } +}; + // OpenBSD Target template<typename Target> class OpenBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defs) const { // OpenBSD defines; list based off of gcc output Define(Defs, "__OpenBSD__", "1"); DefineStd(Defs, "unix", Opts); Define(Defs, "__ELF__", "1"); + if (Opts.POSIXThreads) + Define(Defs, "_POSIX_THREADS", "1"); } public: - OpenBSDTargetInfo(const std::string &triple) + OpenBSDTargetInfo(const std::string &triple) : OSTargetInfo<Target>(triple) {} }; @@ -340,7 +324,7 @@ public: template<typename Target> class SolarisTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defs) const { DefineStd(Defs, "sun", Opts); DefineStd(Defs, "unix", Opts); @@ -349,20 +333,14 @@ protected: Define(Defs, "__SVR4"); } public: - SolarisTargetInfo(const std::string& triple) + SolarisTargetInfo(const std::string& triple) : OSTargetInfo<Target>(triple) { this->UserLabelPrefix = ""; this->WCharType = this->SignedLong; // FIXME: WIntType should be SignedLong } }; -} // end anonymous namespace. - -/// GetWindowsLanguageOptions - Set the default language options for Windows. -static void GetWindowsLanguageOptions(LangOptions &Opts, - const char *Triple) { - Opts.Microsoft = true; -} +} // end anonymous namespace. //===----------------------------------------------------------------------===// // Specific target implementations. @@ -398,9 +376,6 @@ public: " void* reg_save_area;" "} __builtin_va_list[1];";*/ } - virtual const char *getTargetPrefix() const { - return "ppc"; - } virtual void getGCCRegNames(const char * const *&Names, unsigned &NumNames) const; virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, @@ -464,21 +439,21 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, const char * const PPCTargetInfo::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", + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "mq", "lr", "ctr", "ap", - "0", "1", "2", "3", "4", "5", "6", "7", + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "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", + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", "vrsave", "vscr", "spe_acc", "spefscr", "sfp" @@ -493,38 +468,71 @@ void PPCTargetInfo::getGCCRegNames(const char * const *&Names, const TargetInfo::GCCRegAlias PPCTargetInfo::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" }, + { { "0" }, "r0" }, + { { "1"}, "r1" }, + { { "2" }, "r2" }, + { { "3" }, "r3" }, + { { "4" }, "r4" }, + { { "5" }, "r5" }, + { { "6" }, "r6" }, + { { "7" }, "r7" }, + { { "8" }, "r8" }, + { { "9" }, "r9" }, + { { "10" }, "r10" }, + { { "11" }, "r11" }, + { { "12" }, "r12" }, + { { "13" }, "r13" }, + { { "14" }, "r14" }, + { { "15" }, "r15" }, + { { "16" }, "r16" }, + { { "17" }, "r17" }, + { { "18" }, "r18" }, + { { "19" }, "r19" }, + { { "20" }, "r20" }, + { { "21" }, "r21" }, + { { "22" }, "r22" }, + { { "23" }, "r23" }, + { { "24" }, "r24" }, + { { "25" }, "r25" }, + { { "26" }, "r26" }, + { { "27" }, "r27" }, + { { "28" }, "r28" }, + { { "29" }, "r29" }, + { { "30" }, "r30" }, + { { "31" }, "r31" }, + { { "fr0" }, "f0" }, + { { "fr1" }, "f1" }, + { { "fr2" }, "f2" }, + { { "fr3" }, "f3" }, + { { "fr4" }, "f4" }, + { { "fr5" }, "f5" }, + { { "fr6" }, "f6" }, + { { "fr7" }, "f7" }, + { { "fr8" }, "f8" }, + { { "fr9" }, "f9" }, + { { "fr10" }, "f10" }, + { { "fr11" }, "f11" }, + { { "fr12" }, "f12" }, + { { "fr13" }, "f13" }, + { { "fr14" }, "f14" }, + { { "fr15" }, "f15" }, + { { "fr16" }, "f16" }, + { { "fr17" }, "f17" }, + { { "fr18" }, "f18" }, + { { "fr19" }, "f19" }, + { { "fr20" }, "f20" }, + { { "fr21" }, "f21" }, + { { "fr22" }, "f22" }, + { { "fr23" }, "f23" }, + { { "fr24" }, "f24" }, + { { "fr25" }, "f25" }, + { { "fr26" }, "f26" }, + { { "fr27" }, "f27" }, + { { "fr28" }, "f28" }, + { { "fr29" }, "f29" }, + { { "fr30" }, "f30" }, + { { "fr31" }, "f31" }, + { { "cc" }, "cr0" }, }; void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, @@ -603,9 +611,6 @@ public: Records = BuiltinInfo; NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin; } - virtual const char *getTargetPrefix() const { - return "x86"; - } virtual void getGCCRegNames(const char * const *&Names, unsigned &NumNames) const { Names = GCCRegNames; @@ -627,12 +632,12 @@ public: virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, const std::string &Name, bool Enabled) const; - virtual void getDefaultFeatures(const std::string &CPU, + virtual void getDefaultFeatures(const std::string &CPU, llvm::StringMap<bool> &Features) const; virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features); }; -void X86TargetInfo::getDefaultFeatures(const std::string &CPU, +void X86TargetInfo::getDefaultFeatures(const std::string &CPU, llvm::StringMap<bool> &Features) const { // FIXME: This should not be here. Features["3dnow"] = false; @@ -676,7 +681,7 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, setFeatureEnabled(Features, "sse4", true); else if (CPU == "k6" || CPU == "winchip-c6") setFeatureEnabled(Features, "mmx", true); - else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" || + else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" || CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") { setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "3dnow", true); @@ -685,14 +690,14 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, setFeatureEnabled(Features, "3dnowa", true); } else if (CPU == "k8" || CPU == "opteron" || CPU == "athlon64" || CPU == "athlon-fx") { - setFeatureEnabled(Features, "sse2", true); + setFeatureEnabled(Features, "sse2", true); setFeatureEnabled(Features, "3dnowa", true); } else if (CPU == "c3-2") setFeatureEnabled(Features, "sse", true); } bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, - const std::string &Name, + const std::string &Name, bool Enabled) const { // FIXME: This *really* should not be here. if (!Features.count(Name) && Name != "sse4") @@ -706,13 +711,13 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, else if (Name == "sse2") Features["mmx"] = Features["sse"] = Features["sse2"] = true; else if (Name == "sse3") - Features["mmx"] = Features["sse"] = Features["sse2"] = + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = true; else if (Name == "ssse3") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = true; else if (Name == "sse4") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = true; else if (Name == "3dnow") Features["3dnowa"] = true; @@ -720,16 +725,16 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, Features["3dnow"] = Features["3dnowa"] = true; } else { if (Name == "mmx") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; else if (Name == "sse") - Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; else if (Name == "sse2") - Features["sse2"] = Features["sse3"] = Features["ssse3"] = + Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; else if (Name == "sse3") - Features["sse3"] = Features["ssse3"] = Features["sse41"] = + Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; else if (Name == "ssse3") Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; @@ -885,6 +890,24 @@ public: virtual const char *getVAListDeclaration() const { return "typedef char* __builtin_va_list;"; } + + int getEHDataRegisterNumber(unsigned RegNo) const { + if (RegNo == 0) return 0; + if (RegNo == 1) return 2; + return -1; + } +}; +} // end anonymous namespace + +namespace { +class OpenBSDI386TargetInfo : public OpenBSDTargetInfo<X86_32TargetInfo> { +public: + OpenBSDI386TargetInfo(const std::string& triple) : + OpenBSDTargetInfo<X86_32TargetInfo>(triple) { + SizeType = UnsignedLong; + IntPtrType = SignedLong; + PtrDiffType = SignedLong; + } }; } // end anonymous namespace @@ -927,12 +950,75 @@ public: DefineStd(Defines, "WIN32", Opts); DefineStd(Defines, "WINNT", Opts); Define(Defines, "_X86_"); - Define(Defines, "__MSVCRT__"); } +}; +} // end anonymous namespace +namespace { + +/// GetWindowsVisualStudioLanguageOptions - Set the default language options for Windows. +static void GetWindowsVisualStudioLanguageOptions(LangOptions &Opts) { + Opts.Microsoft = true; +} + +// x86-32 Windows Visual Studio target +class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo { +public: + VisualStudioWindowsX86_32TargetInfo(const std::string& triple) + : WindowsX86_32TargetInfo(triple) { + } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + WindowsX86_32TargetInfo::getTargetDefines(Opts, Defines); + // The value of the following reflects processor type. + // 300=386, 400=486, 500=Pentium, 600=Blend (default) + // We lost the original triple, so we use the default. + Define(Defines, "_M_IX86", "600"); + } virtual void getDefaultLangOptions(LangOptions &Opts) { - X86_32TargetInfo::getDefaultLangOptions(Opts); - GetWindowsLanguageOptions(Opts, getTargetTriple()); + WindowsX86_32TargetInfo::getDefaultLangOptions(Opts); + GetWindowsVisualStudioLanguageOptions(Opts); + } +}; +} // end anonymous namespace + +namespace { +// x86-32 MinGW target +class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo { +public: + MinGWX86_32TargetInfo(const std::string& triple) + : WindowsX86_32TargetInfo(triple) { + } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + WindowsX86_32TargetInfo::getTargetDefines(Opts, Defines); + Define(Defines, "__MSVCRT__"); + Define(Defines, "__MINGW32__"); + Define(Defines, "__declspec", "__declspec"); + } +}; +} // end anonymous namespace + +namespace { +// x86-32 Cygwin target +class CygwinX86_32TargetInfo : public X86_32TargetInfo { +public: + CygwinX86_32TargetInfo(const std::string& triple) + : X86_32TargetInfo(triple) { + TLSSupported = false; + WCharType = UnsignedShort; + WCharWidth = WCharAlign = 16; + DoubleAlign = LongLongAlign = 64; + DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" + "a0:0:64-f80:32:32"; + } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + X86_32TargetInfo::getTargetDefines(Opts, Defines); + Define(Defines, "__CYGWIN__"); + Define(Defines, "__CYGWIN32__"); + DefineStd(Defines, "unix", Opts); } }; } // end anonymous namespace @@ -963,13 +1049,75 @@ public: "} __va_list_tag;" "typedef __va_list_tag __builtin_va_list[1];"; } + + int getEHDataRegisterNumber(unsigned RegNo) const { + if (RegNo == 0) return 0; + if (RegNo == 1) return 1; + return -1; + } +}; +} // end anonymous namespace + +namespace { +// x86-64 Windows target +class WindowsX86_64TargetInfo : public X86_64TargetInfo { +public: + WindowsX86_64TargetInfo(const std::string& triple) + : X86_64TargetInfo(triple) { + TLSSupported = false; + WCharType = UnsignedShort; + WCharWidth = WCharAlign = 16; + LongWidth = LongAlign = 32; + DoubleAlign = LongLongAlign = 64; + } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + X86_64TargetInfo::getTargetDefines(Opts, Defines); + Define(Defines, "_WIN64"); + DefineStd(Defines, "WIN64", Opts); + } +}; +} // end anonymous namespace + +namespace { +// x86-64 Windows Visual Studio target +class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo { +public: + VisualStudioWindowsX86_64TargetInfo(const std::string& triple) + : WindowsX86_64TargetInfo(triple) { + } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + WindowsX86_64TargetInfo::getTargetDefines(Opts, Defines); + Define(Defines, "_M_X64"); + } + virtual const char *getVAListDeclaration() const { + return "typedef char* va_list;"; + } +}; +} // end anonymous namespace + +namespace { +// x86-64 MinGW target +class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo { +public: + MinGWX86_64TargetInfo(const std::string& triple) + : WindowsX86_64TargetInfo(triple) { + } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + WindowsX86_64TargetInfo::getTargetDefines(Opts, Defines); + Define(Defines, "__MSVCRT__"); + Define(Defines, "__MINGW64__"); + Define(Defines, "__declspec"); + } }; } // end anonymous namespace namespace { class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> { public: - DarwinX86_64TargetInfo(const std::string& triple) + DarwinX86_64TargetInfo(const std::string& triple) : DarwinTargetInfo<X86_64TargetInfo>(triple) { Int64Type = SignedLongLong; } @@ -977,33 +1125,107 @@ public: } // end anonymous namespace namespace { +class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo<X86_64TargetInfo> { +public: + OpenBSDX86_64TargetInfo(const std::string& triple) + : OpenBSDTargetInfo<X86_64TargetInfo>(triple) { + IntMaxType = SignedLongLong; + UIntMaxType = UnsignedLongLong; + Int64Type = SignedLongLong; + } +}; +} // end anonymous namespace + +namespace { class ARMTargetInfo : public TargetInfo { enum { Armv4t, Armv5, Armv6, + Armv7a, XScale } ArmArch; + + static const TargetInfo::GCCRegAlias GCCRegAliases[]; + static const char * const GCCRegNames[]; + + std::string ABI; + bool IsThumb; + public: - ARMTargetInfo(const std::string& triple) : TargetInfo(triple) { - // FIXME: Are the defaults correct for ARM? - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:64"; - if (triple.find("arm-") == 0 || triple.find("armv6-") == 0) + ARMTargetInfo(const std::string &TripleStr) + : TargetInfo(TripleStr), ABI("aapcs-linux"), IsThumb(false) + { + llvm::Triple Triple(TripleStr); + + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + + // FIXME: This shouldn't be done this way, we should use features to + // indicate the arch. See lib/Driver/Tools.cpp. + llvm::StringRef Version(""), Arch = Triple.getArchName(); + if (Arch.startswith("arm")) + Version = Arch.substr(3); + else if (Arch.startswith("thumb")) + Version = Arch.substr(5); + if (Version == "v7") + ArmArch = Armv7a; + else if (Version.empty() || Version == "v6" || Version == "v6t2") ArmArch = Armv6; - else if (triple.find("armv5-") == 0) + else if (Version == "v5") ArmArch = Armv5; - else if (triple.find("armv4t-") == 0) + else if (Version == "v4t") ArmArch = Armv4t; - else if (triple.find("xscale-") == 0) + else if (Arch == "xscale" || Arch == "thumbv5e") ArmArch = XScale; - else if (triple.find("armv") == 0) { - // FIXME: fuzzy match for other random weird arm triples. This is useful - // for the static analyzer and other clients, but probably should be - // re-evaluated when codegen is brought up. + else ArmArch = Armv6; + + if (Arch.startswith("thumb")) + IsThumb = true; + + if (IsThumb) { + DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-" + "v64:64:64-v128:128:128-a0:0:32"); + } else { + DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-" + "v64:64:64-v128:128:128-a0:0:64"); } } + virtual const char *getABI() const { return ABI.c_str(); } + virtual bool setABI(const std::string &Name) { + ABI = Name; + + // The defaults (above) are for AAPCS, check if we need to change them. + // + // FIXME: We need support for -meabi... we could just mangle it into the + // name. + if (Name == "apcs-gnu") { + DoubleAlign = LongLongAlign = 32; + SizeType = UnsignedLong; + + if (IsThumb) { + DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-" + "i64:32:32-f32:32:32-f64:32:32-" + "v64:64:64-v128:128:128-a0:0:32"); + } else { + DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" + "i64:32:32-f32:32:32-f64:32:32-" + "v64:64:64-v128:128:128-a0:0:64"); + } + + // FIXME: Override "preferred align" for double and long long. + } else if (Name == "aapcs") { + // FIXME: Enumerated types are variable width in straight AAPCS. + } else if (Name == "aapcs-linux") { + ; + } else + return false; + + return true; + } virtual void getTargetDefines(const LangOptions &Opts, std::vector<char> &Defs) const { // Target identification. @@ -1014,7 +1236,13 @@ public: Define(Defs, "__LITTLE_ENDIAN__"); // Subtarget options. - if (ArmArch == Armv6) { + // + // FIXME: Neither THUMB_INTERWORK nor SOFTFP is not being set correctly + // here. + if (ArmArch == Armv7a) { + Define(Defs, "__ARM_ARCH_7A__"); + Define(Defs, "__THUMB_INTERWORK__"); + } else if (ArmArch == Armv6) { Define(Defs, "__ARM_ARCH_6K__"); Define(Defs, "__THUMB_INTERWORK__"); } else if (ArmArch == Armv5) { @@ -1029,9 +1257,22 @@ public: Define(Defs, "__XSCALE__"); Define(Defs, "__SOFTFP__"); } + Define(Defs, "__ARMEL__"); + + if (IsThumb) { + Define(Defs, "__THUMBEL__"); + Define(Defs, "__thumb__"); + if (ArmArch == Armv7a) + Define(Defs, "__thumb2__"); + } + + // Note, this is always on in gcc, even though it doesn't make sense. Define(Defs, "__APCS_32__"); + // FIXME: This should be conditional on VFP instruction support. Define(Defs, "__VFP_FP__"); + + Define(Defs, "__USING_SJLJ_EXCEPTIONS__"); } virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const { @@ -1042,21 +1283,10 @@ public: virtual const char *getVAListDeclaration() const { return "typedef char* __builtin_va_list;"; } - virtual const char *getTargetPrefix() const { - return "arm"; - } virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const { - // FIXME: Implement. - Names = 0; - NumNames = 0; - } + unsigned &NumNames) const; virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - // FIXME: Implement. - Aliases = 0; - NumAliases = 0; - } + unsigned &NumAliases) const; virtual bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const { // FIXME: Check if this is complete @@ -1076,21 +1306,58 @@ public: return ""; } }; + +const char * const ARMTargetInfo::GCCRegNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" +}; + +void ARMTargetInfo::getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const { + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); +} + +const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { + + { { "a1" }, "r0" }, + { { "a2" }, "r1" }, + { { "a3" }, "r2" }, + { { "a4" }, "r3" }, + { { "v1" }, "r4" }, + { { "v2" }, "r5" }, + { { "v3" }, "r6" }, + { { "v4" }, "r7" }, + { { "v5" }, "r8" }, + { { "v6", "rfp" }, "r9" }, + { { "sl" }, "r10" }, + { { "fp" }, "r11" }, + { { "ip" }, "r12" }, + { { "sp" }, "r13" }, + { { "lr" }, "r14" }, + { { "pc" }, "r15" }, +}; + +void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + Aliases = GCCRegAliases; + NumAliases = llvm::array_lengthof(GCCRegAliases); +} } // end anonymous namespace. namespace { -class DarwinARMTargetInfo : +class DarwinARMTargetInfo : public DarwinTargetInfo<ARMTargetInfo> { protected: - virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, std::vector<char> &Defines) const { getDarwinDefines(Defines, Opts); getDarwinIPhoneOSDefines(Defines, Triple); } public: - DarwinARMTargetInfo(const std::string& triple) + DarwinARMTargetInfo(const std::string& triple) : DarwinTargetInfo<ARMTargetInfo>(triple) {} }; } // end anonymous namespace. @@ -1118,9 +1385,6 @@ public: virtual const char *getVAListDeclaration() const { return "typedef void* __builtin_va_list;"; } - virtual const char *getTargetPrefix() const { - return "sparc"; - } virtual void getGCCRegNames(const char * const *&Names, unsigned &NumNames) const; virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, @@ -1236,12 +1500,25 @@ namespace { virtual void getTargetDefines(const LangOptions &Opts, std::vector<char> &Defines) const { Define(Defines, "__pic16"); + Define(Defines, "rom", "__attribute__((address_space(1)))"); + Define(Defines, "ram", "__attribute__((address_space(0)))"); + Define(Defines, "_section(SectName)", + "__attribute__((section(SectName)))"); + Define(Defines, "_address(Addr)", + "__attribute__((section(\"Address=\"#Addr)))"); + Define(Defines, "_CONFIG(conf)", "asm(\"CONFIG \"#conf)"); + Define(Defines, "_interrupt", + "__attribute__((section(\"interrupt=0x4\"))) \ + __attribute__((used))"); } virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const {} - virtual const char *getVAListDeclaration() const { return "";} - virtual const char *getClobbers() const {return "";} - virtual const char *getTargetPrefix() const {return "pic16";} + virtual const char *getVAListDeclaration() const { + return ""; + } + virtual const char *getClobbers() const { + return ""; + } virtual void getGCCRegNames(const char * const *&Names, unsigned &NumNames) const {} virtual bool validateAsmConstraint(const char *&Name, @@ -1286,9 +1563,6 @@ namespace { Records = 0; NumRecords = 0; } - virtual const char *getTargetPrefix() const { - return "msp430"; - } virtual void getGCCRegNames(const char * const *&Names, unsigned &NumNames) const; virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, @@ -1325,93 +1599,309 @@ namespace { } +namespace { + class SystemZTargetInfo : public TargetInfo { + static const char * const GCCRegNames[]; + public: + SystemZTargetInfo(const std::string& triple) : TargetInfo(triple) { + TLSSupported = false; + IntWidth = IntAlign = 32; + LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; + PointerWidth = PointerAlign = 64; + DescriptionString = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16"; + } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + Define(Defines, "__s390__"); + Define(Defines, "__s390x__"); + } + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const { + // FIXME: Implement. + Records = 0; + NumRecords = 0; + } + + virtual void getDefaultLangOptions(LangOptions &Opts) { + TargetInfo::getDefaultLangOptions(Opts); + Opts.CharIsSigned = false; + } + + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const; + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + // No aliases. + Aliases = 0; + NumAliases = 0; + } + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const { + // FIXME: implement + return true; + } + virtual const char *getClobbers() const { + // FIXME: Is this really right? + return ""; + } + virtual const char *getVAListDeclaration() const { + // FIXME: implement + return "typedef char* __builtin_va_list;"; + } + }; + + const char * const SystemZTargetInfo::GCCRegNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + }; + + void SystemZTargetInfo::getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const { + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); + } +} + +namespace { + class BlackfinTargetInfo : public TargetInfo { + static const char * const GCCRegNames[]; + public: + BlackfinTargetInfo(const std::string& triple) : TargetInfo(triple) { + TLSSupported = false; + DoubleAlign = 32; + LongLongAlign = 32; + LongDoubleAlign = 32; + DescriptionString = "e-p:32:32-i64:32-f64:32"; + } + + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + DefineStd(Defines, "bfin", Opts); + DefineStd(Defines, "BFIN", Opts); + Define(Defines, "__ADSPBLACKFIN__"); + // FIXME: This one is really dependent on -mcpu + Define(Defines, "__ADSPLPBLACKFIN__"); + // FIXME: Add cpu-dependent defines and __SILICON_REVISION__ + } + + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const { + // FIXME: Implement. + Records = 0; + NumRecords = 0; + } + + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const; + + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + // No aliases. + Aliases = 0; + NumAliases = 0; + } + + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const { + if (strchr("adzDWeABbvfcCtukxywZY", Name[0])) { + Info.setAllowsRegister(); + return true; + } + return false; + } + + virtual const char *getClobbers() const { + return ""; + } + + virtual const char *getVAListDeclaration() const { + return "typedef char* __builtin_va_list;"; + } + }; + + const char * const BlackfinTargetInfo::GCCRegNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "p0", "p1", "p2", "p3", "p4", "p5", "sp", "fp", + "i0", "i1", "i2", "i3", "b0", "b1", "b2", "b3", + "l0", "l1", "l2", "l3", "m0", "m1", "m2", "m3", + "a0", "a1", "cc", + "rets", "reti", "retx", "retn", "rete", "astat", "seqstat", "usp", + "argp", "lt0", "lt1", "lc0", "lc1", "lb0", "lb1" + }; + + void BlackfinTargetInfo::getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const { + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); + } +} + +namespace { + + // LLVM and Clang cannot be used directly to output native binaries for + // target, but is used to compile C code to llvm bitcode with correct + // type and alignment information. + // + // TCE uses the llvm bitcode as input and uses it for generating customized + // target processor and program binary. TCE co-design environment is + // publicly available in http://tce.cs.tut.fi + + class TCETargetInfo : public TargetInfo{ + public: + TCETargetInfo(const std::string& triple) : TargetInfo(triple) { + TLSSupported = false; + IntWidth = 32; + LongWidth = LongLongWidth = 32; + IntMaxTWidth = 32; + PointerWidth = 32; + IntAlign = 32; + LongAlign = LongLongAlign = 32; + PointerAlign = 32; + SizeType = UnsignedInt; + IntMaxType = SignedLong; + UIntMaxType = UnsignedLong; + IntPtrType = SignedInt; + PtrDiffType = SignedInt; + FloatWidth = 32; + FloatAlign = 32; + DoubleWidth = 32; + DoubleAlign = 32; + LongDoubleWidth = 32; + LongDoubleAlign = 32; + FloatFormat = &llvm::APFloat::IEEEsingle; + DoubleFormat = &llvm::APFloat::IEEEsingle; + LongDoubleFormat = &llvm::APFloat::IEEEsingle; + DescriptionString = "E-p:32:32:32-a0:32:32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64" + "-f32:32:32-f64:32:64"; + } + + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + DefineStd(Defines, "tce", Opts); + Define(Defines, "__TCE__"); + Define(Defines, "__TCE_V1__"); + } + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const {} + virtual const char *getClobbers() const { + return ""; + } + virtual const char *getVAListDeclaration() const { + return "typedef void* __builtin_va_list;"; + } + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const {} + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const { + return true; + } + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const {} + }; +} + //===----------------------------------------------------------------------===// // 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) { - // OS detection; this isn't really anywhere near complete. - // Additions and corrections are welcome. - bool isDarwin = T.find("-darwin") != std::string::npos; - bool isDragonFly = T.find("-dragonfly") != std::string::npos; - bool isOpenBSD = T.find("-openbsd") != std::string::npos; - bool isFreeBSD = T.find("-freebsd") != std::string::npos; - bool isSolaris = T.find("-solaris") != std::string::npos; - bool isLinux = T.find("-linux") != std::string::npos; - bool isWindows = T.find("-windows") != std::string::npos || - T.find("-win32") != std::string::npos || - T.find("-mingw") != std::string::npos; - - if (T.find("ppc-") == 0 || T.find("powerpc-") == 0) { - if (isDarwin) + llvm::Triple Triple(T); + llvm::Triple::OSType os = Triple.getOS(); + + switch (Triple.getArch()) { + default: + return NULL; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + switch (os) { + case llvm::Triple::Darwin: + return new DarwinARMTargetInfo(T); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<ARMTargetInfo>(T); + default: + return new ARMTargetInfo(T); + } + + case llvm::Triple::bfin: + return new BlackfinTargetInfo(T); + + case llvm::Triple::msp430: + return new MSP430TargetInfo(T); + + case llvm::Triple::pic16: + return new PIC16TargetInfo(T); + + case llvm::Triple::ppc: + if (os == llvm::Triple::Darwin) return new DarwinTargetInfo<PPCTargetInfo>(T); return new PPC32TargetInfo(T); - } - if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) { - if (isDarwin) + case llvm::Triple::ppc64: + if (os == llvm::Triple::Darwin) return new DarwinTargetInfo<PPC64TargetInfo>(T); return new PPC64TargetInfo(T); - } - - if (T.find("armv") == 0 || T.find("arm-") == 0 || T.find("xscale") == 0) { - if (isDarwin) - return new DarwinARMTargetInfo(T); - if (isFreeBSD) - return new FreeBSDTargetInfo<ARMTargetInfo>(T); - return new ARMTargetInfo(T); - } - if (T.find("sparc-") == 0) { - if (isSolaris) + case llvm::Triple::sparc: + if (os == llvm::Triple::Solaris) return new SolarisSparcV8TargetInfo(T); return new SparcV8TargetInfo(T); - } - - if (T.find("x86_64-") == 0 || T.find("amd64-") == 0) { - if (isDarwin) - return new DarwinX86_64TargetInfo(T); - if (isLinux) - return new LinuxTargetInfo<X86_64TargetInfo>(T); - if (isOpenBSD) - return new OpenBSDTargetInfo<X86_64TargetInfo>(T); - if (isFreeBSD) - return new FreeBSDTargetInfo<X86_64TargetInfo>(T); - if (isSolaris) - return new SolarisTargetInfo<X86_64TargetInfo>(T); - return new X86_64TargetInfo(T); - } - if (T.find("pic16-") == 0) - return new PIC16TargetInfo(T); + case llvm::Triple::systemz: + return new SystemZTargetInfo(T); - if (T.find("msp430-") == 0) - return new MSP430TargetInfo(T); + case llvm::Triple::tce: + return new TCETargetInfo(T); - if (IsX86(T)) { - if (isDarwin) + case llvm::Triple::x86: + switch (os) { + case llvm::Triple::Darwin: return new DarwinI386TargetInfo(T); - if (isLinux) + case llvm::Triple::Linux: return new LinuxTargetInfo<X86_32TargetInfo>(T); - if (isDragonFly) + case llvm::Triple::DragonFly: return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(T); - if (isOpenBSD) - return new OpenBSDTargetInfo<X86_32TargetInfo>(T); - if (isFreeBSD) + case llvm::Triple::NetBSD: + return new NetBSDTargetInfo<X86_32TargetInfo>(T); + case llvm::Triple::OpenBSD: + return new OpenBSDI386TargetInfo(T); + case llvm::Triple::FreeBSD: return new FreeBSDTargetInfo<X86_32TargetInfo>(T); - if (isSolaris) + case llvm::Triple::Solaris: return new SolarisTargetInfo<X86_32TargetInfo>(T); - if (isWindows) - return new WindowsX86_32TargetInfo(T); - return new X86_32TargetInfo(T); - } + case llvm::Triple::Cygwin: + return new CygwinX86_32TargetInfo(T); + case llvm::Triple::MinGW32: + return new MinGWX86_32TargetInfo(T); + case llvm::Triple::Win32: + return new VisualStudioWindowsX86_32TargetInfo(T); + default: + return new X86_32TargetInfo(T); + } - return NULL; + case llvm::Triple::x86_64: + switch (os) { + case llvm::Triple::Darwin: + return new DarwinX86_64TargetInfo(T); + case llvm::Triple::Linux: + return new LinuxTargetInfo<X86_64TargetInfo>(T); + case llvm::Triple::NetBSD: + return new NetBSDTargetInfo<X86_64TargetInfo>(T); + case llvm::Triple::OpenBSD: + return new OpenBSDX86_64TargetInfo(T); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<X86_64TargetInfo>(T); + case llvm::Triple::Solaris: + return new SolarisTargetInfo<X86_64TargetInfo>(T); + case llvm::Triple::MinGW64: + return new MinGWX86_64TargetInfo(T); + case llvm::Triple::Win32: // This is what Triple.h supports now. + return new VisualStudioWindowsX86_64TargetInfo(T); + default: + return new X86_64TargetInfo(T); + } + } } diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp new file mode 100644 index 0000000000000..30383f6251f64 --- /dev/null +++ b/lib/Basic/Version.cpp @@ -0,0 +1,49 @@ +//===- Version.cpp - Clang Version Number -----------------------*- 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 several version-related utility functions for Clang. +// +//===----------------------------------------------------------------------===// +#include <cstring> +#include <cstdlib> +using namespace std; + +namespace clang { + +const char *getClangSubversionPath() { + static const char *Path = 0; + if (Path) + return Path; + + static char URL[] = "$URL: http://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $"; + char *End = strstr(URL, "/lib/Basic"); + if (End) + *End = 0; + + char *Begin = strstr(URL, "cfe/"); + if (Begin) { + Path = Begin + 4; + return Path; + } + + Path = URL; + return Path; +} + + +unsigned getClangSubversionRevision() { +#ifndef SVN_REVISION + // Subversion was not available at build time? + return 0; +#else + return strtol(SVN_REVISION, 0, 10); +#endif +} + +} // end namespace clang |