aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Basic
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic')
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Attributes.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Builtins.cpp164
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/CharInfo.cpp81
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Cuda.cpp298
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp1142
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp744
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileManager.cpp557
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp129
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp722
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/MemoryBufferCache.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Module.cpp610
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp98
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp968
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp199
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp2286
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp795
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp658
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.h51
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp592
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h176
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp326
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h430
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp1102
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h264
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp312
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h185
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h99
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp175
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h130
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h94
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h64
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h92
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp239
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h401
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp234
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h140
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h151
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp139
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h745
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h87
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp445
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h429
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp104
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h114
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h132
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp251
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h233
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp152
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h149
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h123
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp118
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h154
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp1792
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/X86.h853
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h82
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Version.cpp151
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp2026
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Warnings.cpp230
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp69
76 files changed, 24117 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp
new file mode 100644
index 000000000000..b7570d03c85a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp
@@ -0,0 +1,28 @@
+#include "clang/Basic/Attributes.h"
+#include "clang/Basic/AttrSubjectMatchRules.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
+ const IdentifierInfo *Attr, const TargetInfo &Target,
+ const LangOptions &LangOpts) {
+ StringRef Name = Attr->getName();
+ // Normalize the attribute name, __foo__ becomes foo.
+ if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
+ Name = Name.substr(2, Name.size() - 4);
+
+#include "clang/Basic/AttrHasAttributeImpl.inc"
+
+ return 0;
+}
+
+const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
+ switch (Rule) {
+#define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \
+ case attr::NAME: \
+ return SPELLING;
+#include "clang/Basic/AttrSubMatchRulesList.inc"
+ }
+ llvm_unreachable("Invalid subject match rule");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
new file mode 100644
index 000000000000..a3210ba09068
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
@@ -0,0 +1,164 @@
+//===--- Builtins.cpp - Builtin function implementation -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements various things for builtin functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringRef.h"
+using namespace clang;
+
+static const Builtin::Info BuiltinInfo[] = {
+ { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES,nullptr},
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANGS) \
+ { #ID, TYPE, ATTRS, nullptr, LANGS, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, LANGS) \
+ { #ID, TYPE, ATTRS, HEADER, LANGS, nullptr },
+#include "clang/Basic/Builtins.def"
+};
+
+const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const {
+ if (ID < Builtin::FirstTSBuiltin)
+ return BuiltinInfo[ID];
+ assert(((ID - Builtin::FirstTSBuiltin) <
+ (TSRecords.size() + AuxTSRecords.size())) &&
+ "Invalid builtin ID!");
+ if (isAuxBuiltinID(ID))
+ return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin];
+ return TSRecords[ID - Builtin::FirstTSBuiltin];
+}
+
+void Builtin::Context::InitializeTarget(const TargetInfo &Target,
+ const TargetInfo *AuxTarget) {
+ assert(TSRecords.empty() && "Already initialized target?");
+ TSRecords = Target.getTargetBuiltins();
+ if (AuxTarget)
+ AuxTSRecords = AuxTarget->getTargetBuiltins();
+}
+
+bool Builtin::Context::isBuiltinFunc(const char *Name) {
+ StringRef FuncName(Name);
+ for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i)
+ if (FuncName.equals(BuiltinInfo[i].Name))
+ return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;
+
+ return false;
+}
+
+bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
+ const LangOptions &LangOpts) {
+ bool BuiltinsUnsupported =
+ (LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) &&
+ strchr(BuiltinInfo.Attributes, 'f');
+ bool MathBuiltinsUnsupported =
+ LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName &&
+ llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h");
+ bool GnuModeUnsupported = !LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG);
+ bool MSModeUnsupported =
+ !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
+ bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;
+ bool OclC1Unsupported = (LangOpts.OpenCLVersion / 100) != 1 &&
+ (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES ) == OCLC1X_LANG;
+ bool OclC2Unsupported = LangOpts.OpenCLVersion != 200 &&
+ (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES) == OCLC20_LANG;
+ bool OclCUnsupported = !LangOpts.OpenCL &&
+ (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES);
+ bool OpenMPUnsupported = !LangOpts.OpenMP && BuiltinInfo.Langs == OMP_LANG;
+ return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported &&
+ !OclC1Unsupported && !OclC2Unsupported && !OpenMPUnsupported &&
+ !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported;
+}
+
+/// initializeBuiltins - Mark the identifiers for all the builtins with their
+/// appropriate builtin ID # and mark any non-portable builtin identifiers as
+/// such.
+void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
+ const LangOptions& LangOpts) {
+ // Step #1: mark all target-independent builtins with their ID's.
+ for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
+ if (builtinIsSupported(BuiltinInfo[i], LangOpts)) {
+ Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
+ }
+
+ // Step #2: Register target-specific builtins.
+ for (unsigned i = 0, e = TSRecords.size(); i != e; ++i)
+ if (builtinIsSupported(TSRecords[i], LangOpts))
+ Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin);
+
+ // Step #3: Register target-specific builtins for AuxTarget.
+ for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i)
+ Table.get(AuxTSRecords[i].Name)
+ .setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size());
+}
+
+void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) {
+ Table.get(getRecord(ID).Name).setBuiltinID(0);
+}
+
+unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const {
+ const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V');
+ if (!WidthPos)
+ return 0;
+
+ ++WidthPos;
+ assert(*WidthPos == ':' &&
+ "Vector width specifier must be followed by a ':'");
+ ++WidthPos;
+
+ char *EndPos;
+ unsigned Width = ::strtol(WidthPos, &EndPos, 10);
+ assert(*EndPos == ':' && "Vector width specific must end with a ':'");
+ return Width;
+}
+
+bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
+ bool &HasVAListArg, const char *Fmt) const {
+ assert(Fmt && "Not passed a format string");
+ assert(::strlen(Fmt) == 2 &&
+ "Format string needs to be two characters long");
+ assert(::toupper(Fmt[0]) == Fmt[1] &&
+ "Format string is not in the form \"xX\"");
+
+ const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt);
+ if (!Like)
+ return false;
+
+ HasVAListArg = (*Like == Fmt[1]);
+
+ ++Like;
+ assert(*Like == ':' && "Format specifier must be followed by a ':'");
+ ++Like;
+
+ assert(::strchr(Like, ':') && "Format specifier must end with a ':'");
+ FormatIdx = ::strtol(Like, nullptr, 10);
+ return true;
+}
+
+bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
+ bool &HasVAListArg) {
+ return isLike(ID, FormatIdx, HasVAListArg, "pP");
+}
+
+bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
+ bool &HasVAListArg) {
+ return isLike(ID, FormatIdx, HasVAListArg, "sS");
+}
+
+bool Builtin::Context::canBeRedeclared(unsigned ID) const {
+ return ID == Builtin::NotBuiltin ||
+ ID == Builtin::BI__va_start ||
+ (!hasReferenceArgsOrResult(ID) &&
+ !hasCustomTypechecking(ID));
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/CharInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/CharInfo.cpp
new file mode 100644
index 000000000000..32b3277c927b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/CharInfo.cpp
@@ -0,0 +1,81 @@
+//===--- CharInfo.cpp - Static Data for Classifying ASCII Characters ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/CharInfo.h"
+
+using namespace clang::charinfo;
+
+// Statically initialize CharInfo table based on ASCII character set
+// Reference: FreeBSD 7.2 /usr/share/misc/ascii
+const uint16_t clang::charinfo::InfoTable[256] = {
+ // 0 NUL 1 SOH 2 STX 3 ETX
+ // 4 EOT 5 ENQ 6 ACK 7 BEL
+ 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+ // 8 BS 9 HT 10 NL 11 VT
+ //12 NP 13 CR 14 SO 15 SI
+ 0 , CHAR_HORZ_WS, CHAR_VERT_WS, CHAR_HORZ_WS,
+ CHAR_HORZ_WS, CHAR_VERT_WS, 0 , 0 ,
+ //16 DLE 17 DC1 18 DC2 19 DC3
+ //20 DC4 21 NAK 22 SYN 23 ETB
+ 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+ //24 CAN 25 EM 26 SUB 27 ESC
+ //28 FS 29 GS 30 RS 31 US
+ 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+ //32 SP 33 ! 34 " 35 #
+ //36 $ 37 % 38 & 39 '
+ CHAR_SPACE , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL ,
+ CHAR_PUNCT , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL ,
+ //40 ( 41 ) 42 * 43 +
+ //44 , 45 - 46 . 47 /
+ CHAR_PUNCT , CHAR_PUNCT , CHAR_RAWDEL , CHAR_RAWDEL ,
+ CHAR_RAWDEL , CHAR_RAWDEL , CHAR_PERIOD , CHAR_RAWDEL ,
+ //48 0 49 1 50 2 51 3
+ //52 4 53 5 54 6 55 7
+ CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT ,
+ CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT ,
+ //56 8 57 9 58 : 59 ;
+ //60 < 61 = 62 > 63 ?
+ CHAR_DIGIT , CHAR_DIGIT , CHAR_RAWDEL , CHAR_RAWDEL ,
+ CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL ,
+ //64 @ 65 A 66 B 67 C
+ //68 D 69 E 70 F 71 G
+ CHAR_PUNCT , CHAR_XUPPER , CHAR_XUPPER , CHAR_XUPPER ,
+ CHAR_XUPPER , CHAR_XUPPER , CHAR_XUPPER , CHAR_UPPER ,
+ //72 H 73 I 74 J 75 K
+ //76 L 77 M 78 N 79 O
+ CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_UPPER ,
+ CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_UPPER ,
+ //80 P 81 Q 82 R 83 S
+ //84 T 85 U 86 V 87 W
+ CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_UPPER ,
+ CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_UPPER ,
+ //88 X 89 Y 90 Z 91 [
+ //92 \ 93 ] 94 ^ 95 _
+ CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_RAWDEL ,
+ CHAR_PUNCT , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_UNDER ,
+ //96 ` 97 a 98 b 99 c
+ //100 d 101 e 102 f 103 g
+ CHAR_PUNCT , CHAR_XLOWER , CHAR_XLOWER , CHAR_XLOWER ,
+ CHAR_XLOWER , CHAR_XLOWER , CHAR_XLOWER , CHAR_LOWER ,
+ //104 h 105 i 106 j 107 k
+ //108 l 109 m 110 n 111 o
+ CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_LOWER ,
+ CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_LOWER ,
+ //112 p 113 q 114 r 115 s
+ //116 t 117 u 118 v 119 w
+ CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_LOWER ,
+ CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_LOWER ,
+ //120 x 121 y 122 z 123 {
+ //124 | 125 } 126 ~ 127 DEL
+ CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_RAWDEL ,
+ CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL , 0
+};
diff --git a/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp b/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
new file mode 100644
index 000000000000..dc7e61c02b24
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
@@ -0,0 +1,298 @@
+#include "clang/Basic/Cuda.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+const char *CudaVersionToString(CudaVersion V) {
+ switch (V) {
+ case CudaVersion::UNKNOWN:
+ return "unknown";
+ case CudaVersion::CUDA_70:
+ return "7.0";
+ case CudaVersion::CUDA_75:
+ return "7.5";
+ case CudaVersion::CUDA_80:
+ return "8.0";
+ case CudaVersion::CUDA_90:
+ return "9.0";
+ case CudaVersion::CUDA_91:
+ return "9.1";
+ case CudaVersion::CUDA_92:
+ return "9.2";
+ }
+ llvm_unreachable("invalid enum");
+}
+
+const char *CudaArchToString(CudaArch A) {
+ switch (A) {
+ case CudaArch::LAST:
+ break;
+ case CudaArch::UNKNOWN:
+ return "unknown";
+ case CudaArch::SM_20:
+ return "sm_20";
+ case CudaArch::SM_21:
+ return "sm_21";
+ case CudaArch::SM_30:
+ return "sm_30";
+ case CudaArch::SM_32:
+ return "sm_32";
+ case CudaArch::SM_35:
+ return "sm_35";
+ case CudaArch::SM_37:
+ return "sm_37";
+ case CudaArch::SM_50:
+ return "sm_50";
+ case CudaArch::SM_52:
+ return "sm_52";
+ case CudaArch::SM_53:
+ return "sm_53";
+ case CudaArch::SM_60:
+ return "sm_60";
+ case CudaArch::SM_61:
+ return "sm_61";
+ case CudaArch::SM_62:
+ return "sm_62";
+ case CudaArch::SM_70:
+ return "sm_70";
+ case CudaArch::SM_72:
+ return "sm_72";
+ case CudaArch::GFX600: // tahiti
+ return "gfx600";
+ case CudaArch::GFX601: // pitcairn, verde, oland,hainan
+ return "gfx601";
+ case CudaArch::GFX700: // kaveri
+ return "gfx700";
+ case CudaArch::GFX701: // hawaii
+ return "gfx701";
+ case CudaArch::GFX702: // 290,290x,R390,R390x
+ return "gfx702";
+ case CudaArch::GFX703: // kabini mullins
+ return "gfx703";
+ case CudaArch::GFX704: // bonaire
+ return "gfx704";
+ case CudaArch::GFX801: // carrizo
+ return "gfx801";
+ case CudaArch::GFX802: // tonga,iceland
+ return "gfx802";
+ case CudaArch::GFX803: // fiji,polaris10
+ return "gfx803";
+ case CudaArch::GFX810: // stoney
+ return "gfx810";
+ case CudaArch::GFX900: // vega, instinct
+ return "gfx900";
+ case CudaArch::GFX902: // TBA
+ return "gfx902";
+ }
+ llvm_unreachable("invalid enum");
+}
+
+CudaArch StringToCudaArch(llvm::StringRef S) {
+ return llvm::StringSwitch<CudaArch>(S)
+ .Case("sm_20", CudaArch::SM_20)
+ .Case("sm_21", CudaArch::SM_21)
+ .Case("sm_30", CudaArch::SM_30)
+ .Case("sm_32", CudaArch::SM_32)
+ .Case("sm_35", CudaArch::SM_35)
+ .Case("sm_37", CudaArch::SM_37)
+ .Case("sm_50", CudaArch::SM_50)
+ .Case("sm_52", CudaArch::SM_52)
+ .Case("sm_53", CudaArch::SM_53)
+ .Case("sm_60", CudaArch::SM_60)
+ .Case("sm_61", CudaArch::SM_61)
+ .Case("sm_62", CudaArch::SM_62)
+ .Case("sm_70", CudaArch::SM_70)
+ .Case("sm_72", CudaArch::SM_72)
+ .Case("gfx600", CudaArch::GFX600)
+ .Case("gfx601", CudaArch::GFX601)
+ .Case("gfx700", CudaArch::GFX700)
+ .Case("gfx701", CudaArch::GFX701)
+ .Case("gfx702", CudaArch::GFX702)
+ .Case("gfx703", CudaArch::GFX703)
+ .Case("gfx704", CudaArch::GFX704)
+ .Case("gfx801", CudaArch::GFX801)
+ .Case("gfx802", CudaArch::GFX802)
+ .Case("gfx803", CudaArch::GFX803)
+ .Case("gfx810", CudaArch::GFX810)
+ .Case("gfx900", CudaArch::GFX900)
+ .Case("gfx902", CudaArch::GFX902)
+ .Default(CudaArch::UNKNOWN);
+}
+
+const char *CudaVirtualArchToString(CudaVirtualArch A) {
+ switch (A) {
+ case CudaVirtualArch::UNKNOWN:
+ return "unknown";
+ case CudaVirtualArch::COMPUTE_20:
+ return "compute_20";
+ case CudaVirtualArch::COMPUTE_30:
+ return "compute_30";
+ case CudaVirtualArch::COMPUTE_32:
+ return "compute_32";
+ case CudaVirtualArch::COMPUTE_35:
+ return "compute_35";
+ case CudaVirtualArch::COMPUTE_37:
+ return "compute_37";
+ case CudaVirtualArch::COMPUTE_50:
+ return "compute_50";
+ case CudaVirtualArch::COMPUTE_52:
+ return "compute_52";
+ case CudaVirtualArch::COMPUTE_53:
+ return "compute_53";
+ case CudaVirtualArch::COMPUTE_60:
+ return "compute_60";
+ case CudaVirtualArch::COMPUTE_61:
+ return "compute_61";
+ case CudaVirtualArch::COMPUTE_62:
+ return "compute_62";
+ case CudaVirtualArch::COMPUTE_70:
+ return "compute_70";
+ case CudaVirtualArch::COMPUTE_72:
+ return "compute_72";
+ case CudaVirtualArch::COMPUTE_AMDGCN:
+ return "compute_amdgcn";
+ }
+ llvm_unreachable("invalid enum");
+}
+
+CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
+ return llvm::StringSwitch<CudaVirtualArch>(S)
+ .Case("compute_20", CudaVirtualArch::COMPUTE_20)
+ .Case("compute_30", CudaVirtualArch::COMPUTE_30)
+ .Case("compute_32", CudaVirtualArch::COMPUTE_32)
+ .Case("compute_35", CudaVirtualArch::COMPUTE_35)
+ .Case("compute_37", CudaVirtualArch::COMPUTE_37)
+ .Case("compute_50", CudaVirtualArch::COMPUTE_50)
+ .Case("compute_52", CudaVirtualArch::COMPUTE_52)
+ .Case("compute_53", CudaVirtualArch::COMPUTE_53)
+ .Case("compute_60", CudaVirtualArch::COMPUTE_60)
+ .Case("compute_61", CudaVirtualArch::COMPUTE_61)
+ .Case("compute_62", CudaVirtualArch::COMPUTE_62)
+ .Case("compute_70", CudaVirtualArch::COMPUTE_70)
+ .Case("compute_72", CudaVirtualArch::COMPUTE_72)
+ .Case("compute_amdgcn", CudaVirtualArch::COMPUTE_AMDGCN)
+ .Default(CudaVirtualArch::UNKNOWN);
+}
+
+CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
+ switch (A) {
+ case CudaArch::LAST:
+ break;
+ case CudaArch::UNKNOWN:
+ return CudaVirtualArch::UNKNOWN;
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ return CudaVirtualArch::COMPUTE_20;
+ case CudaArch::SM_30:
+ return CudaVirtualArch::COMPUTE_30;
+ case CudaArch::SM_32:
+ return CudaVirtualArch::COMPUTE_32;
+ case CudaArch::SM_35:
+ return CudaVirtualArch::COMPUTE_35;
+ case CudaArch::SM_37:
+ return CudaVirtualArch::COMPUTE_37;
+ case CudaArch::SM_50:
+ return CudaVirtualArch::COMPUTE_50;
+ case CudaArch::SM_52:
+ return CudaVirtualArch::COMPUTE_52;
+ case CudaArch::SM_53:
+ return CudaVirtualArch::COMPUTE_53;
+ case CudaArch::SM_60:
+ return CudaVirtualArch::COMPUTE_60;
+ case CudaArch::SM_61:
+ return CudaVirtualArch::COMPUTE_61;
+ case CudaArch::SM_62:
+ return CudaVirtualArch::COMPUTE_62;
+ case CudaArch::SM_70:
+ return CudaVirtualArch::COMPUTE_70;
+ case CudaArch::SM_72:
+ return CudaVirtualArch::COMPUTE_72;
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ return CudaVirtualArch::COMPUTE_AMDGCN;
+ }
+ llvm_unreachable("invalid enum");
+}
+
+CudaVersion MinVersionForCudaArch(CudaArch A) {
+ switch (A) {
+ case CudaArch::LAST:
+ break;
+ case CudaArch::UNKNOWN:
+ return CudaVersion::UNKNOWN;
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ case CudaArch::SM_30:
+ case CudaArch::SM_32:
+ case CudaArch::SM_35:
+ case CudaArch::SM_37:
+ case CudaArch::SM_50:
+ case CudaArch::SM_52:
+ case CudaArch::SM_53:
+ return CudaVersion::CUDA_70;
+ case CudaArch::SM_60:
+ case CudaArch::SM_61:
+ case CudaArch::SM_62:
+ return CudaVersion::CUDA_80;
+ case CudaArch::SM_70:
+ return CudaVersion::CUDA_90;
+ case CudaArch::SM_72:
+ return CudaVersion::CUDA_91;
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ return CudaVersion::CUDA_70;
+ }
+ llvm_unreachable("invalid enum");
+}
+
+CudaVersion MaxVersionForCudaArch(CudaArch A) {
+ switch (A) {
+ case CudaArch::UNKNOWN:
+ return CudaVersion::UNKNOWN;
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ return CudaVersion::CUDA_80;
+ default:
+ return CudaVersion::LATEST;
+ }
+}
+
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
new file mode 100644
index 000000000000..f1ebd9d38b9e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
@@ -0,0 +1,1142 @@
+//===- Diagnostic.cpp - C Language Family Diagnostic Handling -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Diagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/DiagnosticError.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Locale.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+
+const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
+ DiagNullabilityKind nullability) {
+ StringRef string;
+ switch (nullability.first) {
+ case NullabilityKind::NonNull:
+ string = nullability.second ? "'nonnull'" : "'_Nonnull'";
+ break;
+
+ case NullabilityKind::Nullable:
+ string = nullability.second ? "'nullable'" : "'_Nullable'";
+ break;
+
+ case NullabilityKind::Unspecified:
+ string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'";
+ break;
+ }
+
+ DB.AddString(string);
+ return DB;
+}
+
+static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
+ StringRef Modifier, StringRef Argument,
+ ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
+ SmallVectorImpl<char> &Output,
+ void *Cookie,
+ ArrayRef<intptr_t> QualTypeVals) {
+ StringRef Str = "<can't format argument>";
+ Output.append(Str.begin(), Str.end());
+}
+
+DiagnosticsEngine::DiagnosticsEngine(
+ IntrusiveRefCntPtr<DiagnosticIDs> diags,
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, DiagnosticConsumer *client,
+ bool ShouldOwnClient)
+ : Diags(std::move(diags)), DiagOpts(std::move(DiagOpts)) {
+ setClient(client, ShouldOwnClient);
+ ArgToStringFn = DummyArgToStringFn;
+
+ Reset();
+}
+
+DiagnosticsEngine::~DiagnosticsEngine() {
+ // If we own the diagnostic client, destroy it first so that it can access the
+ // engine from its destructor.
+ setClient(nullptr);
+}
+
+void DiagnosticsEngine::setClient(DiagnosticConsumer *client,
+ bool ShouldOwnClient) {
+ Owner.reset(ShouldOwnClient ? client : nullptr);
+ Client = client;
+}
+
+void DiagnosticsEngine::pushMappings(SourceLocation Loc) {
+ DiagStateOnPushStack.push_back(GetCurDiagState());
+}
+
+bool DiagnosticsEngine::popMappings(SourceLocation Loc) {
+ if (DiagStateOnPushStack.empty())
+ return false;
+
+ if (DiagStateOnPushStack.back() != GetCurDiagState()) {
+ // State changed at some point between push/pop.
+ PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
+ }
+ DiagStateOnPushStack.pop_back();
+ return true;
+}
+
+void DiagnosticsEngine::Reset() {
+ ErrorOccurred = false;
+ UncompilableErrorOccurred = false;
+ FatalErrorOccurred = false;
+ UnrecoverableErrorOccurred = false;
+
+ NumWarnings = 0;
+ NumErrors = 0;
+ TrapNumErrorsOccurred = 0;
+ TrapNumUnrecoverableErrorsOccurred = 0;
+
+ CurDiagID = std::numeric_limits<unsigned>::max();
+ LastDiagLevel = DiagnosticIDs::Ignored;
+ DelayedDiagID = 0;
+
+ // Clear state related to #pragma diagnostic.
+ DiagStates.clear();
+ DiagStatesByLoc.clear();
+ DiagStateOnPushStack.clear();
+
+ // Create a DiagState and DiagStatePoint representing diagnostic changes
+ // through command-line.
+ DiagStates.emplace_back();
+ DiagStatesByLoc.appendFirst(&DiagStates.back());
+}
+
+void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1,
+ StringRef Arg2) {
+ if (DelayedDiagID)
+ return;
+
+ DelayedDiagID = DiagID;
+ DelayedDiagArg1 = Arg1.str();
+ DelayedDiagArg2 = Arg2.str();
+}
+
+void DiagnosticsEngine::ReportDelayed() {
+ unsigned ID = DelayedDiagID;
+ DelayedDiagID = 0;
+ Report(ID) << DelayedDiagArg1 << DelayedDiagArg2;
+}
+
+void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
+ assert(Files.empty() && "not first");
+ FirstDiagState = CurDiagState = State;
+ CurDiagStateLoc = SourceLocation();
+}
+
+void DiagnosticsEngine::DiagStateMap::append(SourceManager &SrcMgr,
+ SourceLocation Loc,
+ DiagState *State) {
+ CurDiagState = State;
+ CurDiagStateLoc = Loc;
+
+ std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc);
+ unsigned Offset = Decomp.second;
+ for (File *F = getFile(SrcMgr, Decomp.first); F;
+ Offset = F->ParentOffset, F = F->Parent) {
+ F->HasLocalTransitions = true;
+ auto &Last = F->StateTransitions.back();
+ assert(Last.Offset <= Offset && "state transitions added out of order");
+
+ if (Last.Offset == Offset) {
+ if (Last.State == State)
+ break;
+ Last.State = State;
+ continue;
+ }
+
+ F->StateTransitions.push_back({State, Offset});
+ }
+}
+
+DiagnosticsEngine::DiagState *
+DiagnosticsEngine::DiagStateMap::lookup(SourceManager &SrcMgr,
+ SourceLocation Loc) const {
+ // Common case: we have not seen any diagnostic pragmas.
+ if (Files.empty())
+ return FirstDiagState;
+
+ std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc);
+ const File *F = getFile(SrcMgr, Decomp.first);
+ return F->lookup(Decomp.second);
+}
+
+DiagnosticsEngine::DiagState *
+DiagnosticsEngine::DiagStateMap::File::lookup(unsigned Offset) const {
+ auto OnePastIt = std::upper_bound(
+ StateTransitions.begin(), StateTransitions.end(), Offset,
+ [](unsigned Offset, const DiagStatePoint &P) {
+ return Offset < P.Offset;
+ });
+ assert(OnePastIt != StateTransitions.begin() && "missing initial state");
+ return OnePastIt[-1].State;
+}
+
+DiagnosticsEngine::DiagStateMap::File *
+DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr,
+ FileID ID) const {
+ // Get or insert the File for this ID.
+ auto Range = Files.equal_range(ID);
+ if (Range.first != Range.second)
+ return &Range.first->second;
+ auto &F = Files.insert(Range.first, std::make_pair(ID, File()))->second;
+
+ // We created a new File; look up the diagnostic state at the start of it and
+ // initialize it.
+ if (ID.isValid()) {
+ std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedIncludedLoc(ID);
+ F.Parent = getFile(SrcMgr, Decomp.first);
+ F.ParentOffset = Decomp.second;
+ F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
+ } else {
+ // This is the (imaginary) root file into which we pretend all top-level
+ // files are included; it descends from the initial state.
+ //
+ // FIXME: This doesn't guarantee that we use the same ordering as
+ // isBeforeInTranslationUnit in the cases where someone invented another
+ // top-level file and added diagnostic pragmas to it. See the code at the
+ // end of isBeforeInTranslationUnit for the quirks it deals with.
+ F.StateTransitions.push_back({FirstDiagState, 0});
+ }
+ return &F;
+}
+
+void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
+ StringRef DiagName) const {
+ llvm::errs() << "diagnostic state at ";
+ CurDiagStateLoc.dump(SrcMgr);
+ llvm::errs() << ": " << CurDiagState << "\n";
+
+ for (auto &F : Files) {
+ FileID ID = F.first;
+ File &File = F.second;
+
+ bool PrintedOuterHeading = false;
+ auto PrintOuterHeading = [&] {
+ if (PrintedOuterHeading) return;
+ PrintedOuterHeading = true;
+
+ llvm::errs() << "File " << &File << " <FileID " << ID.getHashValue()
+ << ">: " << SrcMgr.getBuffer(ID)->getBufferIdentifier();
+ if (F.second.Parent) {
+ std::pair<FileID, unsigned> Decomp =
+ SrcMgr.getDecomposedIncludedLoc(ID);
+ assert(File.ParentOffset == Decomp.second);
+ llvm::errs() << " parent " << File.Parent << " <FileID "
+ << Decomp.first.getHashValue() << "> ";
+ SrcMgr.getLocForStartOfFile(Decomp.first)
+ .getLocWithOffset(Decomp.second)
+ .dump(SrcMgr);
+ }
+ if (File.HasLocalTransitions)
+ llvm::errs() << " has_local_transitions";
+ llvm::errs() << "\n";
+ };
+
+ if (DiagName.empty())
+ PrintOuterHeading();
+
+ for (DiagStatePoint &Transition : File.StateTransitions) {
+ bool PrintedInnerHeading = false;
+ auto PrintInnerHeading = [&] {
+ if (PrintedInnerHeading) return;
+ PrintedInnerHeading = true;
+
+ PrintOuterHeading();
+ llvm::errs() << " ";
+ SrcMgr.getLocForStartOfFile(ID)
+ .getLocWithOffset(Transition.Offset)
+ .dump(SrcMgr);
+ llvm::errs() << ": state " << Transition.State << ":\n";
+ };
+
+ if (DiagName.empty())
+ PrintInnerHeading();
+
+ for (auto &Mapping : *Transition.State) {
+ StringRef Option =
+ DiagnosticIDs::getWarningOptionForDiag(Mapping.first);
+ if (!DiagName.empty() && DiagName != Option)
+ continue;
+
+ PrintInnerHeading();
+ llvm::errs() << " ";
+ if (Option.empty())
+ llvm::errs() << "<unknown " << Mapping.first << ">";
+ else
+ llvm::errs() << Option;
+ llvm::errs() << ": ";
+
+ switch (Mapping.second.getSeverity()) {
+ case diag::Severity::Ignored: llvm::errs() << "ignored"; break;
+ case diag::Severity::Remark: llvm::errs() << "remark"; break;
+ case diag::Severity::Warning: llvm::errs() << "warning"; break;
+ case diag::Severity::Error: llvm::errs() << "error"; break;
+ case diag::Severity::Fatal: llvm::errs() << "fatal"; break;
+ }
+
+ if (!Mapping.second.isUser())
+ llvm::errs() << " default";
+ if (Mapping.second.isPragma())
+ llvm::errs() << " pragma";
+ if (Mapping.second.hasNoWarningAsError())
+ llvm::errs() << " no-error";
+ if (Mapping.second.hasNoErrorAsFatal())
+ llvm::errs() << " no-fatal";
+ if (Mapping.second.wasUpgradedFromWarning())
+ llvm::errs() << " overruled";
+ llvm::errs() << "\n";
+ }
+ }
+ }
+}
+
+void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
+ SourceLocation Loc) {
+ assert(Loc.isValid() && "Adding invalid loc point");
+ DiagStatesByLoc.append(*SourceMgr, Loc, State);
+}
+
+void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
+ SourceLocation L) {
+ assert(Diag < diag::DIAG_UPPER_LIMIT &&
+ "Can only map builtin diagnostics");
+ assert((Diags->isBuiltinWarningOrExtension(Diag) ||
+ (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&
+ "Cannot map errors into warnings!");
+ assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location");
+
+ // Don't allow a mapping to a warning override an error/fatal mapping.
+ bool WasUpgradedFromWarning = false;
+ if (Map == diag::Severity::Warning) {
+ DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
+ if (Info.getSeverity() == diag::Severity::Error ||
+ Info.getSeverity() == diag::Severity::Fatal) {
+ Map = Info.getSeverity();
+ WasUpgradedFromWarning = true;
+ }
+ }
+ DiagnosticMapping Mapping = makeUserMapping(Map, L);
+ Mapping.setUpgradedFromWarning(WasUpgradedFromWarning);
+
+ // Common case; setting all the diagnostics of a group in one place.
+ if ((L.isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
+ DiagStatesByLoc.getCurDiagState()) {
+ // FIXME: This is theoretically wrong: if the current state is shared with
+ // some other location (via push/pop) we will change the state for that
+ // other location as well. This cannot currently happen, as we can't update
+ // the diagnostic state at the same location at which we pop.
+ DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping);
+ return;
+ }
+
+ // A diagnostic pragma occurred, create a new DiagState initialized with
+ // the current one and a new DiagStatePoint to record at which location
+ // the new state became active.
+ DiagStates.push_back(*GetCurDiagState());
+ DiagStates.back().setMapping(Diag, Mapping);
+ PushDiagStatePoint(&DiagStates.back(), L);
+}
+
+bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
+ StringRef Group, diag::Severity Map,
+ SourceLocation Loc) {
+ // Get the diagnostics in this group.
+ SmallVector<diag::kind, 256> GroupDiags;
+ if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
+ return true;
+
+ // Set the mapping.
+ for (diag::kind Diag : GroupDiags)
+ setSeverity(Diag, Map, Loc);
+
+ return false;
+}
+
+bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
+ bool Enabled) {
+ // If we are enabling this feature, just set the diagnostic mappings to map to
+ // errors.
+ if (Enabled)
+ return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
+ diag::Severity::Error);
+
+ // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
+ // potentially downgrade anything already mapped to be a warning.
+
+ // Get the diagnostics in this group.
+ SmallVector<diag::kind, 8> GroupDiags;
+ if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
+ GroupDiags))
+ return true;
+
+ // Perform the mapping change.
+ for (diag::kind Diag : GroupDiags) {
+ DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
+
+ if (Info.getSeverity() == diag::Severity::Error ||
+ Info.getSeverity() == diag::Severity::Fatal)
+ Info.setSeverity(diag::Severity::Warning);
+
+ Info.setNoWarningAsError(true);
+ }
+
+ return false;
+}
+
+bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
+ bool Enabled) {
+ // If we are enabling this feature, just set the diagnostic mappings to map to
+ // fatal errors.
+ if (Enabled)
+ return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
+ diag::Severity::Fatal);
+
+ // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit,
+ // and potentially downgrade anything already mapped to be a fatal error.
+
+ // Get the diagnostics in this group.
+ SmallVector<diag::kind, 8> GroupDiags;
+ if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
+ GroupDiags))
+ return true;
+
+ // Perform the mapping change.
+ for (diag::kind Diag : GroupDiags) {
+ DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
+
+ if (Info.getSeverity() == diag::Severity::Fatal)
+ Info.setSeverity(diag::Severity::Error);
+
+ Info.setNoErrorAsFatal(true);
+ }
+
+ return false;
+}
+
+void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
+ diag::Severity Map,
+ SourceLocation Loc) {
+ // Get all the diagnostics.
+ std::vector<diag::kind> AllDiags;
+ DiagnosticIDs::getAllDiagnostics(Flavor, AllDiags);
+
+ // Set the mapping.
+ for (diag::kind Diag : AllDiags)
+ if (Diags->isBuiltinWarningOrExtension(Diag))
+ setSeverity(Diag, Map, Loc);
+}
+
+void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
+ assert(CurDiagID == std::numeric_limits<unsigned>::max() &&
+ "Multiple diagnostics in flight at once!");
+
+ CurDiagLoc = storedDiag.getLocation();
+ CurDiagID = storedDiag.getID();
+ NumDiagArgs = 0;
+
+ DiagRanges.clear();
+ DiagRanges.append(storedDiag.range_begin(), storedDiag.range_end());
+
+ DiagFixItHints.clear();
+ DiagFixItHints.append(storedDiag.fixit_begin(), storedDiag.fixit_end());
+
+ assert(Client && "DiagnosticConsumer not set!");
+ Level DiagLevel = storedDiag.getLevel();
+ Diagnostic Info(this, storedDiag.getMessage());
+ Client->HandleDiagnostic(DiagLevel, Info);
+ if (Client->IncludeInDiagnosticCounts()) {
+ if (DiagLevel == DiagnosticsEngine::Warning)
+ ++NumWarnings;
+ }
+
+ CurDiagID = std::numeric_limits<unsigned>::max();
+}
+
+bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) {
+ assert(getClient() && "DiagnosticClient not set!");
+
+ bool Emitted;
+ if (Force) {
+ Diagnostic Info(this);
+
+ // Figure out the diagnostic level of this message.
+ DiagnosticIDs::Level DiagLevel
+ = Diags->getDiagnosticLevel(Info.getID(), Info.getLocation(), *this);
+
+ Emitted = (DiagLevel != DiagnosticIDs::Ignored);
+ if (Emitted) {
+ // Emit the diagnostic regardless of suppression level.
+ Diags->EmitDiag(*this, DiagLevel);
+ }
+ } else {
+ // Process the diagnostic, sending the accumulated information to the
+ // DiagnosticConsumer.
+ Emitted = ProcessDiag();
+ }
+
+ // Clear out the current diagnostic object.
+ Clear();
+
+ // If there was a delayed diagnostic, emit it now.
+ if (!Force && DelayedDiagID)
+ ReportDelayed();
+
+ return Emitted;
+}
+
+DiagnosticConsumer::~DiagnosticConsumer() = default;
+
+void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) {
+ if (!IncludeInDiagnosticCounts())
+ return;
+
+ if (DiagLevel == DiagnosticsEngine::Warning)
+ ++NumWarnings;
+ else if (DiagLevel >= DiagnosticsEngine::Error)
+ ++NumErrors;
+}
+
+/// ModifierIs - Return true if the specified modifier matches specified string.
+template <std::size_t StrLen>
+static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
+ const char (&Str)[StrLen]) {
+ return StrLen-1 == ModifierLen && memcmp(Modifier, Str, StrLen-1) == 0;
+}
+
+/// ScanForward - Scans forward, looking for the given character, skipping
+/// nested clauses and escaped characters.
+static const char *ScanFormat(const char *I, const char *E, char Target) {
+ unsigned Depth = 0;
+
+ for ( ; I != E; ++I) {
+ if (Depth == 0 && *I == Target) return I;
+ if (Depth != 0 && *I == '}') Depth--;
+
+ if (*I == '%') {
+ I++;
+ if (I == E) break;
+
+ // Escaped characters get implicitly skipped here.
+
+ // Format specifier.
+ if (!isDigit(*I) && !isPunctuation(*I)) {
+ for (I++; I != E && !isDigit(*I) && *I != '{'; I++) ;
+ if (I == E) break;
+ if (*I == '{')
+ Depth++;
+ }
+ }
+ }
+ return E;
+}
+
+/// HandleSelectModifier - Handle the integer 'select' modifier. This is used
+/// like this: %select{foo|bar|baz}2. This means that the integer argument
+/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
+/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'.
+/// This is very useful for certain classes of variant diagnostics.
+static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
+ const char *Argument, unsigned ArgumentLen,
+ SmallVectorImpl<char> &OutStr) {
+ const char *ArgumentEnd = Argument+ArgumentLen;
+
+ // Skip over 'ValNo' |'s.
+ while (ValNo) {
+ const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
+ assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
+ " larger than the number of options in the diagnostic string!");
+ Argument = NextVal+1; // Skip this string.
+ --ValNo;
+ }
+
+ // Get the end of the value. This is either the } or the |.
+ const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
+
+ // Recursively format the result of the select clause into the output string.
+ DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
+}
+
+/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
+/// letter 's' to the string if the value is not 1. This is used in cases like
+/// this: "you idiot, you have %4 parameter%s4!".
+static void HandleIntegerSModifier(unsigned ValNo,
+ SmallVectorImpl<char> &OutStr) {
+ if (ValNo != 1)
+ OutStr.push_back('s');
+}
+
+/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This
+/// prints the ordinal form of the given integer, with 1 corresponding
+/// to the first ordinal. Currently this is hard-coded to use the
+/// English form.
+static void HandleOrdinalModifier(unsigned ValNo,
+ SmallVectorImpl<char> &OutStr) {
+ assert(ValNo != 0 && "ValNo must be strictly positive!");
+
+ llvm::raw_svector_ostream Out(OutStr);
+
+ // We could use text forms for the first N ordinals, but the numeric
+ // forms are actually nicer in diagnostics because they stand out.
+ Out << ValNo << llvm::getOrdinalSuffix(ValNo);
+}
+
+/// PluralNumber - Parse an unsigned integer and advance Start.
+static unsigned PluralNumber(const char *&Start, const char *End) {
+ // Programming 101: Parse a decimal number :-)
+ unsigned Val = 0;
+ while (Start != End && *Start >= '0' && *Start <= '9') {
+ Val *= 10;
+ Val += *Start - '0';
+ ++Start;
+ }
+ return Val;
+}
+
+/// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
+static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
+ if (*Start != '[') {
+ unsigned Ref = PluralNumber(Start, End);
+ return Ref == Val;
+ }
+
+ ++Start;
+ unsigned Low = PluralNumber(Start, End);
+ assert(*Start == ',' && "Bad plural expression syntax: expected ,");
+ ++Start;
+ unsigned High = PluralNumber(Start, End);
+ assert(*Start == ']' && "Bad plural expression syntax: expected )");
+ ++Start;
+ return Low <= Val && Val <= High;
+}
+
+/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
+static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
+ // Empty condition?
+ if (*Start == ':')
+ return true;
+
+ while (true) {
+ char C = *Start;
+ if (C == '%') {
+ // Modulo expression
+ ++Start;
+ unsigned Arg = PluralNumber(Start, End);
+ assert(*Start == '=' && "Bad plural expression syntax: expected =");
+ ++Start;
+ unsigned ValMod = ValNo % Arg;
+ if (TestPluralRange(ValMod, Start, End))
+ return true;
+ } else {
+ assert((C == '[' || (C >= '0' && C <= '9')) &&
+ "Bad plural expression syntax: unexpected character");
+ // Range expression
+ if (TestPluralRange(ValNo, Start, End))
+ return true;
+ }
+
+ // Scan for next or-expr part.
+ Start = std::find(Start, End, ',');
+ if (Start == End)
+ break;
+ ++Start;
+ }
+ return false;
+}
+
+/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
+/// for complex plural forms, or in languages where all plurals are complex.
+/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
+/// conditions that are tested in order, the form corresponding to the first
+/// that applies being emitted. The empty condition is always true, making the
+/// last form a default case.
+/// Conditions are simple boolean expressions, where n is the number argument.
+/// Here are the rules.
+/// condition := expression | empty
+/// empty := -> always true
+/// expression := numeric [',' expression] -> logical or
+/// numeric := range -> true if n in range
+/// | '%' number '=' range -> true if n % number in range
+/// range := number
+/// | '[' number ',' number ']' -> ranges are inclusive both ends
+///
+/// Here are some examples from the GNU gettext manual written in this form:
+/// English:
+/// {1:form0|:form1}
+/// Latvian:
+/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
+/// Gaeilge:
+/// {1:form0|2:form1|:form2}
+/// Romanian:
+/// {1:form0|0,%100=[1,19]:form1|:form2}
+/// Lithuanian:
+/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
+/// Russian (requires repeated form):
+/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
+/// Slovak
+/// {1:form0|[2,4]:form1|:form2}
+/// Polish (requires repeated form):
+/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
+static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
+ const char *Argument, unsigned ArgumentLen,
+ SmallVectorImpl<char> &OutStr) {
+ const char *ArgumentEnd = Argument + ArgumentLen;
+ while (true) {
+ assert(Argument < ArgumentEnd && "Plural expression didn't match.");
+ const char *ExprEnd = Argument;
+ while (*ExprEnd != ':') {
+ assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
+ ++ExprEnd;
+ }
+ if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
+ Argument = ExprEnd + 1;
+ ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
+
+ // Recursively format the result of the plural clause into the
+ // output string.
+ DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
+ return;
+ }
+ Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
+ }
+}
+
+/// Returns the friendly description for a token kind that will appear
+/// without quotes in diagnostic messages. These strings may be translatable in
+/// future.
+static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) {
+ switch (Kind) {
+ case tok::identifier:
+ return "identifier";
+ default:
+ return nullptr;
+ }
+}
+
+/// FormatDiagnostic - Format this diagnostic into a string, substituting the
+/// formal arguments into the %0 slots. The result is appended onto the Str
+/// array.
+void Diagnostic::
+FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
+ if (!StoredDiagMessage.empty()) {
+ OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
+ return;
+ }
+
+ StringRef Diag =
+ getDiags()->getDiagnosticIDs()->getDescription(getID());
+
+ FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
+}
+
+void Diagnostic::
+FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
+ SmallVectorImpl<char> &OutStr) const {
+ // When the diagnostic string is only "%0", the entire string is being given
+ // by an outside source. Remove unprintable characters from this string
+ // and skip all the other string processing.
+ if (DiagEnd - DiagStr == 2 &&
+ StringRef(DiagStr, DiagEnd - DiagStr).equals("%0") &&
+ getArgKind(0) == DiagnosticsEngine::ak_std_string) {
+ const std::string &S = getArgStdStr(0);
+ for (char c : S) {
+ if (llvm::sys::locale::isPrint(c) || c == '\t') {
+ OutStr.push_back(c);
+ }
+ }
+ return;
+ }
+
+ /// FormattedArgs - Keep track of all of the arguments formatted by
+ /// ConvertArgToString and pass them into subsequent calls to
+ /// ConvertArgToString, allowing the implementation to avoid redundancies in
+ /// obvious cases.
+ SmallVector<DiagnosticsEngine::ArgumentValue, 8> FormattedArgs;
+
+ /// QualTypeVals - Pass a vector of arrays so that QualType names can be
+ /// compared to see if more information is needed to be printed.
+ SmallVector<intptr_t, 2> QualTypeVals;
+ SmallVector<char, 64> Tree;
+
+ for (unsigned i = 0, e = getNumArgs(); i < e; ++i)
+ if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)
+ QualTypeVals.push_back(getRawArg(i));
+
+ while (DiagStr != DiagEnd) {
+ if (DiagStr[0] != '%') {
+ // Append non-%0 substrings to Str if we have one.
+ const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
+ OutStr.append(DiagStr, StrEnd);
+ DiagStr = StrEnd;
+ continue;
+ } else if (isPunctuation(DiagStr[1])) {
+ OutStr.push_back(DiagStr[1]); // %% -> %.
+ 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.
+ // The modifier is a string of digits from the set [-a-z]+, arguments is a
+ // brace enclosed string.
+ const char *Modifier = nullptr, *Argument = nullptr;
+ unsigned ModifierLen = 0, ArgumentLen = 0;
+
+ // Check to see if we have a modifier. If so eat it.
+ if (!isDigit(DiagStr[0])) {
+ Modifier = DiagStr;
+ while (DiagStr[0] == '-' ||
+ (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
+ ++DiagStr;
+ ModifierLen = DiagStr-Modifier;
+
+ // If we have an argument, get it next.
+ if (DiagStr[0] == '{') {
+ ++DiagStr; // Skip {.
+ Argument = DiagStr;
+
+ DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
+ assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
+ ArgumentLen = DiagStr-Argument;
+ ++DiagStr; // Skip }.
+ }
+ }
+
+ assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic");
+ unsigned ArgNo = *DiagStr++ - '0';
+
+ // Only used for type diffing.
+ unsigned ArgNo2 = ArgNo;
+
+ DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
+ if (ModifierIs(Modifier, ModifierLen, "diff")) {
+ assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) &&
+ "Invalid format for diff modifier");
+ ++DiagStr; // Comma.
+ ArgNo2 = *DiagStr++ - '0';
+ DiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2);
+ if (Kind == DiagnosticsEngine::ak_qualtype &&
+ Kind2 == DiagnosticsEngine::ak_qualtype)
+ Kind = DiagnosticsEngine::ak_qualtype_pair;
+ else {
+ // %diff only supports QualTypes. For other kinds of arguments,
+ // use the default printing. For example, if the modifier is:
+ // "%diff{compare $ to $|other text}1,2"
+ // treat it as:
+ // "compare %1 to %2"
+ const char *ArgumentEnd = Argument + ArgumentLen;
+ const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
+ assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd &&
+ "Found too many '|'s in a %diff modifier!");
+ const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
+ const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
+ const char ArgStr1[] = { '%', static_cast<char>('0' + ArgNo) };
+ const char ArgStr2[] = { '%', static_cast<char>('0' + ArgNo2) };
+ FormatDiagnostic(Argument, FirstDollar, OutStr);
+ FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
+ FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
+ FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
+ FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
+ continue;
+ }
+ }
+
+ switch (Kind) {
+ // ---- STRINGS ----
+ case DiagnosticsEngine::ak_std_string: {
+ const std::string &S = getArgStdStr(ArgNo);
+ assert(ModifierLen == 0 && "No modifiers for strings yet");
+ OutStr.append(S.begin(), S.end());
+ break;
+ }
+ case DiagnosticsEngine::ak_c_string: {
+ const char *S = getArgCStr(ArgNo);
+ assert(ModifierLen == 0 && "No modifiers for strings yet");
+
+ // Don't crash if get passed a null pointer by accident.
+ if (!S)
+ S = "(null)";
+
+ OutStr.append(S, S + strlen(S));
+ break;
+ }
+ // ---- INTEGERS ----
+ case DiagnosticsEngine::ak_sint: {
+ int Val = getArgSInt(ArgNo);
+
+ if (ModifierIs(Modifier, ModifierLen, "select")) {
+ HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
+ OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "s")) {
+ HandleIntegerSModifier(Val, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
+ HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
+ OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
+ HandleOrdinalModifier((unsigned)Val, OutStr);
+ } else {
+ assert(ModifierLen == 0 && "Unknown integer modifier");
+ llvm::raw_svector_ostream(OutStr) << Val;
+ }
+ break;
+ }
+ case DiagnosticsEngine::ak_uint: {
+ unsigned Val = getArgUInt(ArgNo);
+
+ if (ModifierIs(Modifier, ModifierLen, "select")) {
+ HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "s")) {
+ HandleIntegerSModifier(Val, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
+ HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
+ OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
+ HandleOrdinalModifier(Val, OutStr);
+ } else {
+ assert(ModifierLen == 0 && "Unknown integer modifier");
+ llvm::raw_svector_ostream(OutStr) << Val;
+ }
+ break;
+ }
+ // ---- TOKEN SPELLINGS ----
+ case DiagnosticsEngine::ak_tokenkind: {
+ tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));
+ assert(ModifierLen == 0 && "No modifiers for token kinds yet");
+
+ llvm::raw_svector_ostream Out(OutStr);
+ if (const char *S = tok::getPunctuatorSpelling(Kind))
+ // Quoted token spelling for punctuators.
+ Out << '\'' << S << '\'';
+ else if (const char *S = tok::getKeywordSpelling(Kind))
+ // Unquoted token spelling for keywords.
+ Out << S;
+ else if (const char *S = getTokenDescForDiagnostic(Kind))
+ // Unquoted translatable token name.
+ Out << S;
+ else if (const char *S = tok::getTokenName(Kind))
+ // Debug name, shouldn't appear in user-facing diagnostics.
+ Out << '<' << S << '>';
+ else
+ Out << "(null)";
+ break;
+ }
+ // ---- NAMES and TYPES ----
+ case DiagnosticsEngine::ak_identifierinfo: {
+ const IdentifierInfo *II = getArgIdentifier(ArgNo);
+ assert(ModifierLen == 0 && "No modifiers for strings yet");
+
+ // Don't crash if get passed a null pointer by accident.
+ if (!II) {
+ const char *S = "(null)";
+ OutStr.append(S, S + strlen(S));
+ continue;
+ }
+
+ llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
+ break;
+ }
+ case DiagnosticsEngine::ak_qualtype:
+ case DiagnosticsEngine::ak_declarationname:
+ case DiagnosticsEngine::ak_nameddecl:
+ case DiagnosticsEngine::ak_nestednamespec:
+ case DiagnosticsEngine::ak_declcontext:
+ case DiagnosticsEngine::ak_attr:
+ getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
+ StringRef(Modifier, ModifierLen),
+ StringRef(Argument, ArgumentLen),
+ FormattedArgs,
+ OutStr, QualTypeVals);
+ break;
+ case DiagnosticsEngine::ak_qualtype_pair: {
+ // Create a struct with all the info needed for printing.
+ TemplateDiffTypes TDT;
+ TDT.FromType = getRawArg(ArgNo);
+ TDT.ToType = getRawArg(ArgNo2);
+ TDT.ElideType = getDiags()->ElideType;
+ TDT.ShowColors = getDiags()->ShowColors;
+ TDT.TemplateDiffUsed = false;
+ intptr_t val = reinterpret_cast<intptr_t>(&TDT);
+
+ const char *ArgumentEnd = Argument + ArgumentLen;
+ const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
+
+ // Print the tree. If this diagnostic already has a tree, skip the
+ // second tree.
+ if (getDiags()->PrintTemplateTree && Tree.empty()) {
+ TDT.PrintFromType = true;
+ TDT.PrintTree = true;
+ getDiags()->ConvertArgToString(Kind, val,
+ StringRef(Modifier, ModifierLen),
+ StringRef(Argument, ArgumentLen),
+ FormattedArgs,
+ Tree, QualTypeVals);
+ // If there is no tree information, fall back to regular printing.
+ if (!Tree.empty()) {
+ FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr);
+ break;
+ }
+ }
+
+ // Non-tree printing, also the fall-back when tree printing fails.
+ // The fall-back is triggered when the types compared are not templates.
+ const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$');
+ const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$');
+
+ // Append before text
+ FormatDiagnostic(Argument, FirstDollar, OutStr);
+
+ // Append first type
+ TDT.PrintTree = false;
+ TDT.PrintFromType = true;
+ getDiags()->ConvertArgToString(Kind, val,
+ StringRef(Modifier, ModifierLen),
+ StringRef(Argument, ArgumentLen),
+ FormattedArgs,
+ OutStr, QualTypeVals);
+ if (!TDT.TemplateDiffUsed)
+ FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
+ TDT.FromType));
+
+ // Append middle text
+ FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
+
+ // Append second type
+ TDT.PrintFromType = false;
+ getDiags()->ConvertArgToString(Kind, val,
+ StringRef(Modifier, ModifierLen),
+ StringRef(Argument, ArgumentLen),
+ FormattedArgs,
+ OutStr, QualTypeVals);
+ if (!TDT.TemplateDiffUsed)
+ FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
+ TDT.ToType));
+
+ // Append end text
+ FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
+ break;
+ }
+ }
+
+ // Remember this argument info for subsequent formatting operations. Turn
+ // std::strings into a null terminated string to make it be the same case as
+ // all the other ones.
+ if (Kind == DiagnosticsEngine::ak_qualtype_pair)
+ continue;
+ else if (Kind != DiagnosticsEngine::ak_std_string)
+ FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
+ else
+ FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,
+ (intptr_t)getArgStdStr(ArgNo).c_str()));
+ }
+
+ // Append the type tree to the end of the diagnostics.
+ OutStr.append(Tree.begin(), Tree.end());
+}
+
+StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
+ StringRef Message)
+ : ID(ID), Level(Level), Message(Message) {}
+
+StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
+ const Diagnostic &Info)
+ : ID(Info.getID()), Level(Level) {
+ assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
+ "Valid source location without setting a source manager for diagnostic");
+ if (Info.getLocation().isValid())
+ Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
+ SmallString<64> Message;
+ Info.FormatDiagnostic(Message);
+ this->Message.assign(Message.begin(), Message.end());
+ this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
+ this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
+}
+
+StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
+ StringRef Message, FullSourceLoc Loc,
+ ArrayRef<CharSourceRange> Ranges,
+ ArrayRef<FixItHint> FixIts)
+ : ID(ID), Level(Level), Loc(Loc), Message(Message),
+ Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
+{
+}
+
+/// IncludeInDiagnosticCounts - This method (whose default implementation
+/// returns true) indicates whether the diagnostics handled by this
+/// DiagnosticConsumer should be included in the number of diagnostics
+/// reported by DiagnosticsEngine.
+bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
+
+void IgnoringDiagConsumer::anchor() {}
+
+ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() = default;
+
+void ForwardingDiagnosticConsumer::HandleDiagnostic(
+ DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) {
+ Target.HandleDiagnostic(DiagLevel, Info);
+}
+
+void ForwardingDiagnosticConsumer::clear() {
+ DiagnosticConsumer::clear();
+ Target.clear();
+}
+
+bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const {
+ return Target.IncludeInDiagnosticCounts();
+}
+
+PartialDiagnostic::StorageAllocator::StorageAllocator() {
+ for (unsigned I = 0; I != NumCached; ++I)
+ FreeList[I] = Cached + I;
+ NumFreeListEntries = NumCached;
+}
+
+PartialDiagnostic::StorageAllocator::~StorageAllocator() {
+ // Don't assert if we are in a CrashRecovery context, as this invariant may
+ // be invalidated during a crash.
+ assert((NumFreeListEntries == NumCached ||
+ llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
+ "A partial is on the lam");
+}
+
+char DiagnosticError::ID;
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
new file mode 100644
index 000000000000..8f2c3d06a504
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -0,0 +1,744 @@
+//===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Diagnostic IDs-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/AllDiagnostics.h"
+#include "clang/Basic/DiagnosticCategories.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <map>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Builtin Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+// Diagnostic classes.
+enum {
+ CLASS_NOTE = 0x01,
+ CLASS_REMARK = 0x02,
+ CLASS_WARNING = 0x03,
+ CLASS_EXTENSION = 0x04,
+ CLASS_ERROR = 0x05
+};
+
+struct StaticDiagInfoRec {
+ uint16_t DiagID;
+ unsigned DefaultSeverity : 3;
+ unsigned Class : 3;
+ unsigned SFINAE : 2;
+ unsigned WarnNoWerror : 1;
+ unsigned WarnShowInSystemHeader : 1;
+ unsigned Category : 6;
+
+ uint16_t OptionGroupIndex;
+
+ uint16_t DescriptionLen;
+ const char *DescriptionStr;
+
+ unsigned getOptionGroupIndex() const {
+ return OptionGroupIndex;
+ }
+
+ StringRef getDescription() const {
+ return StringRef(DescriptionStr, DescriptionLen);
+ }
+
+ diag::Flavor getFlavor() const {
+ return Class == CLASS_REMARK ? diag::Flavor::Remark
+ : diag::Flavor::WarningOrError;
+ }
+
+ bool operator<(const StaticDiagInfoRec &RHS) const {
+ return DiagID < RHS.DiagID;
+ }
+};
+
+#define STRINGIFY_NAME(NAME) #NAME
+#define VALIDATE_DIAG_SIZE(NAME) \
+ static_assert( \
+ static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
+ static_cast<unsigned>(diag::DIAG_START_##NAME) + \
+ static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
+ STRINGIFY_NAME( \
+ DIAG_SIZE_##NAME) " is insufficient to contain all " \
+ "diagnostics, it may need to be made larger in " \
+ "DiagnosticIDs.h.");
+VALIDATE_DIAG_SIZE(COMMON)
+VALIDATE_DIAG_SIZE(DRIVER)
+VALIDATE_DIAG_SIZE(FRONTEND)
+VALIDATE_DIAG_SIZE(SERIALIZATION)
+VALIDATE_DIAG_SIZE(LEX)
+VALIDATE_DIAG_SIZE(PARSE)
+VALIDATE_DIAG_SIZE(AST)
+VALIDATE_DIAG_SIZE(COMMENT)
+VALIDATE_DIAG_SIZE(SEMA)
+VALIDATE_DIAG_SIZE(ANALYSIS)
+VALIDATE_DIAG_SIZE(REFACTORING)
+#undef VALIDATE_DIAG_SIZE
+#undef STRINGIFY_NAME
+
+} // namespace anonymous
+
+static const StaticDiagInfoRec StaticDiagInfo[] = {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ { \
+ diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \
+ } \
+ ,
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+#undef DIAG
+};
+
+static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo);
+
+/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
+/// or null if the ID is invalid.
+static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
+ // Out of bounds diag. Can't be in the table.
+ using namespace diag;
+ if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
+ return nullptr;
+
+ // Compute the index of the requested diagnostic in the static table.
+ // 1. Add the number of diagnostics in each category preceding the
+ // diagnostic and of the category the diagnostic is in. This gives us
+ // the offset of the category in the table.
+ // 2. Subtract the number of IDs in each category from our ID. This gives us
+ // the offset of the diagnostic in the category.
+ // This is cheaper than a binary search on the table as it doesn't touch
+ // memory at all.
+ unsigned Offset = 0;
+ unsigned ID = DiagID - DIAG_START_COMMON - 1;
+#define CATEGORY(NAME, PREV) \
+ if (DiagID > DIAG_START_##NAME) { \
+ Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
+ ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
+ }
+CATEGORY(DRIVER, COMMON)
+CATEGORY(FRONTEND, DRIVER)
+CATEGORY(SERIALIZATION, FRONTEND)
+CATEGORY(LEX, SERIALIZATION)
+CATEGORY(PARSE, LEX)
+CATEGORY(AST, PARSE)
+CATEGORY(COMMENT, AST)
+CATEGORY(CROSSTU, COMMENT)
+CATEGORY(SEMA, CROSSTU)
+CATEGORY(ANALYSIS, SEMA)
+CATEGORY(REFACTORING, ANALYSIS)
+#undef CATEGORY
+
+ // Avoid out of bounds reads.
+ if (ID + Offset >= StaticDiagInfoSize)
+ return nullptr;
+
+ assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
+
+ const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset];
+ // If the diag id doesn't match we found a different diag, abort. This can
+ // happen when this function is called with an ID that points into a hole in
+ // the diagID space.
+ if (Found->DiagID != DiagID)
+ return nullptr;
+ return Found;
+}
+
+static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) {
+ DiagnosticMapping Info = DiagnosticMapping::Make(
+ diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
+
+ if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
+ Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
+
+ if (StaticInfo->WarnNoWerror) {
+ assert(Info.getSeverity() == diag::Severity::Warning &&
+ "Unexpected mapping with no-Werror bit!");
+ Info.setNoWarningAsError(true);
+ }
+ }
+
+ return Info;
+}
+
+/// getCategoryNumberForDiag - Return the category number that a specified
+/// DiagID belongs to, or 0 if no category.
+unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Category;
+ return 0;
+}
+
+namespace {
+ // The diagnostic category names.
+ struct StaticDiagCategoryRec {
+ const char *NameStr;
+ uint8_t NameLen;
+
+ StringRef getName() const {
+ return StringRef(NameStr, NameLen);
+ }
+ };
+}
+
+// Unfortunately, the split between DiagnosticIDs and Diagnostic is not
+// particularly clean, but for now we just implement this method here so we can
+// access GetDefaultDiagMapping.
+DiagnosticMapping &
+DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
+ std::pair<iterator, bool> Result =
+ DiagMap.insert(std::make_pair(Diag, DiagnosticMapping()));
+
+ // Initialize the entry if we added it.
+ if (Result.second)
+ Result.first->second = GetDefaultDiagMapping(Diag);
+
+ return Result.first->second;
+}
+
+static const StaticDiagCategoryRec CategoryNameTable[] = {
+#define GET_CATEGORY_TABLE
+#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_CATEGORY_TABLE
+ { nullptr, 0 }
+};
+
+/// getNumberOfCategories - Return the number of categories
+unsigned DiagnosticIDs::getNumberOfCategories() {
+ return llvm::array_lengthof(CategoryNameTable) - 1;
+}
+
+/// getCategoryNameFromID - Given a category ID, return the name of the
+/// category, an empty string if CategoryID is zero, or null if CategoryID is
+/// invalid.
+StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
+ if (CategoryID >= getNumberOfCategories())
+ return StringRef();
+ return CategoryNameTable[CategoryID].getName();
+}
+
+
+
+DiagnosticIDs::SFINAEResponse
+DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE);
+ return SFINAE_Report;
+}
+
+/// getBuiltinDiagClass - Return the class field of the diagnostic.
+///
+static unsigned getBuiltinDiagClass(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Class;
+ return ~0U;
+}
+
+//===----------------------------------------------------------------------===//
+// Custom Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ namespace diag {
+ class CustomDiagInfo {
+ typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
+ std::vector<DiagDesc> DiagInfo;
+ std::map<DiagDesc, unsigned> DiagIDs;
+ public:
+
+ /// getDescription - Return the description of the specified custom
+ /// diagnostic.
+ StringRef getDescription(unsigned DiagID) const {
+ assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ "Invalid diagnostic ID");
+ return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
+ }
+
+ /// getLevel - Return the level of the specified custom diagnostic.
+ DiagnosticIDs::Level getLevel(unsigned DiagID) const {
+ assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ "Invalid diagnostic ID");
+ return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
+ }
+
+ unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
+ DiagnosticIDs &Diags) {
+ DiagDesc D(L, Message);
+ // Check to see if it already exists.
+ std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
+ if (I != DiagIDs.end() && I->first == D)
+ return I->second;
+
+ // If not, assign a new ID.
+ unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
+ DiagIDs.insert(std::make_pair(D, ID));
+ DiagInfo.push_back(D);
+ return ID;
+ }
+ };
+
+ } // end diag namespace
+} // end clang namespace
+
+
+//===----------------------------------------------------------------------===//
+// Common Diagnostic implementation
+//===----------------------------------------------------------------------===//
+
+DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; }
+
+DiagnosticIDs::~DiagnosticIDs() {
+ delete CustomDiagInfo;
+}
+
+/// getCustomDiagID - Return an ID for a diagnostic with the specified message
+/// and level. If this is the first request for this diagnostic, it is
+/// registered and created, otherwise the existing ID is returned.
+///
+/// \param FormatString A fixed diagnostic format string that will be hashed and
+/// mapped to a unique DiagID.
+unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
+ if (!CustomDiagInfo)
+ CustomDiagInfo = new diag::CustomDiagInfo();
+ return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
+}
+
+
+/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
+/// level of the specified diagnostic ID is a Warning or Extension.
+/// This only works on builtin diagnostics, not custom ones, and is not legal to
+/// call on NOTEs.
+bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) != CLASS_ERROR;
+}
+
+/// Determine whether the given built-in diagnostic ID is a
+/// Note.
+bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) == CLASS_NOTE;
+}
+
+/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+/// ID is for an extension of some sort. This also returns EnabledByDefault,
+/// which is set to indicate whether the diagnostic is ignored by default (in
+/// which case -pedantic enables it) or treated as a warning/error by default.
+///
+bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
+ bool &EnabledByDefault) {
+ if (DiagID >= diag::DIAG_UPPER_LIMIT ||
+ getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
+ return false;
+
+ EnabledByDefault =
+ GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored;
+ return true;
+}
+
+bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
+ if (DiagID >= diag::DIAG_UPPER_LIMIT)
+ return false;
+
+ return GetDefaultDiagMapping(DiagID).getSeverity() >= diag::Severity::Error;
+}
+
+/// getDescription - Given a diagnostic ID, return a description of the
+/// issue.
+StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->getDescription();
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+ return CustomDiagInfo->getDescription(DiagID);
+}
+
+static DiagnosticIDs::Level toLevel(diag::Severity SV) {
+ switch (SV) {
+ case diag::Severity::Ignored:
+ return DiagnosticIDs::Ignored;
+ case diag::Severity::Remark:
+ return DiagnosticIDs::Remark;
+ case diag::Severity::Warning:
+ return DiagnosticIDs::Warning;
+ case diag::Severity::Error:
+ return DiagnosticIDs::Error;
+ case diag::Severity::Fatal:
+ return DiagnosticIDs::Fatal;
+ }
+ llvm_unreachable("unexpected severity");
+}
+
+/// getDiagnosticLevel - Based on the way the client configured the
+/// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
+/// by consumable the DiagnosticClient.
+DiagnosticIDs::Level
+DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
+ const DiagnosticsEngine &Diag) const {
+ // Handle custom diagnostics, which cannot be mapped.
+ if (DiagID >= diag::DIAG_UPPER_LIMIT) {
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+ return CustomDiagInfo->getLevel(DiagID);
+ }
+
+ unsigned DiagClass = getBuiltinDiagClass(DiagID);
+ if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
+ return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
+}
+
+/// Based on the way the client configured the Diagnostic
+/// object, classify the specified diagnostic ID into a Level, consumable by
+/// the DiagnosticClient.
+///
+/// \param Loc The source location we are interested in finding out the
+/// diagnostic state. Can be null in order to query the latest state.
+diag::Severity
+DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
+ const DiagnosticsEngine &Diag) const {
+ assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE);
+
+ // Specific non-error diagnostics may be mapped to various levels from ignored
+ // to error. Errors can only be mapped to fatal.
+ diag::Severity Result = diag::Severity::Fatal;
+
+ // Get the mapping information, or compute it lazily.
+ DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
+ DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
+
+ // TODO: Can a null severity really get here?
+ if (Mapping.getSeverity() != diag::Severity())
+ Result = Mapping.getSeverity();
+
+ // Upgrade ignored diagnostics if -Weverything is enabled.
+ if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&
+ !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)
+ Result = diag::Severity::Warning;
+
+ // Ignore -pedantic diagnostics inside __extension__ blocks.
+ // (The diagnostics controlled by -pedantic are the extension diagnostics
+ // that are not enabled by default.)
+ bool EnabledByDefault = false;
+ bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
+ if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
+ return diag::Severity::Ignored;
+
+ // For extension diagnostics that haven't been explicitly mapped, check if we
+ // should upgrade the diagnostic.
+ if (IsExtensionDiag && !Mapping.isUser())
+ Result = std::max(Result, State->ExtBehavior);
+
+ // At this point, ignored errors can no longer be upgraded.
+ if (Result == diag::Severity::Ignored)
+ return Result;
+
+ // Honor -w, which is lower in priority than pedantic-errors, but higher than
+ // -Werror.
+ // FIXME: Under GCC, this also suppresses warnings that have been mapped to
+ // errors by -W flags and #pragma diagnostic.
+ if (Result == diag::Severity::Warning && State->IgnoreAllWarnings)
+ return diag::Severity::Ignored;
+
+ // If -Werror is enabled, map warnings to errors unless explicitly disabled.
+ if (Result == diag::Severity::Warning) {
+ if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError())
+ Result = diag::Severity::Error;
+ }
+
+ // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
+ // disabled.
+ if (Result == diag::Severity::Error) {
+ if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
+ Result = diag::Severity::Fatal;
+ }
+
+ // Custom diagnostics always are emitted in system headers.
+ bool ShowInSystemHeader =
+ !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
+
+ // If we are in a system header, we ignore it. We look at the diagnostic class
+ // because we also want to ignore extensions and warnings in -Werror and
+ // -pedantic-errors modes, which *map* warnings/extensions to errors.
+ if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
+ Diag.getSourceManager().isInSystemHeader(
+ Diag.getSourceManager().getExpansionLoc(Loc)))
+ return diag::Severity::Ignored;
+
+ return Result;
+}
+
+#define GET_DIAG_ARRAYS
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_ARRAYS
+
+namespace {
+ struct WarningOption {
+ uint16_t NameOffset;
+ uint16_t Members;
+ uint16_t SubGroups;
+
+ // String is stored with a pascal-style length byte.
+ StringRef getName() const {
+ return StringRef(DiagGroupNames + NameOffset + 1,
+ DiagGroupNames[NameOffset]);
+ }
+ };
+}
+
+// Second the table of options, sorted by name for fast binary lookup.
+static const WarningOption OptionTable[] = {
+#define GET_DIAG_TABLE
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_TABLE
+};
+
+/// getWarningOptionForDiag - Return the lowest-level warning option that
+/// enables the specified diagnostic. If there is no -Wfoo flag that controls
+/// the diagnostic, this returns null.
+StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return OptionTable[Info->getOptionGroupIndex()].getName();
+ return StringRef();
+}
+
+std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
+ std::vector<std::string> Res;
+ for (size_t I = 1; DiagGroupNames[I] != '\0';) {
+ std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
+ I += DiagGroupNames[I] + 1;
+ Res.push_back("-W" + Diag);
+ Res.push_back("-Wno-" + Diag);
+ }
+
+ return Res;
+}
+
+/// Return \c true if any diagnostics were found in this group, even if they
+/// were filtered out due to having the wrong flavor.
+static bool getDiagnosticsInGroup(diag::Flavor Flavor,
+ const WarningOption *Group,
+ SmallVectorImpl<diag::kind> &Diags) {
+ // An empty group is considered to be a warning group: we have empty groups
+ // for GCC compatibility, and GCC does not have remarks.
+ if (!Group->Members && !Group->SubGroups)
+ return Flavor == diag::Flavor::Remark;
+
+ bool NotFound = true;
+
+ // Add the members of the option diagnostic set.
+ const int16_t *Member = DiagArrays + Group->Members;
+ for (; *Member != -1; ++Member) {
+ if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
+ NotFound = false;
+ Diags.push_back(*Member);
+ }
+ }
+
+ // Add the members of the subgroups.
+ const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
+ for (; *SubGroups != (int16_t)-1; ++SubGroups)
+ NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
+ Diags);
+
+ return NotFound;
+}
+
+bool
+DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
+ SmallVectorImpl<diag::kind> &Diags) const {
+ auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable),
+ Group,
+ [](const WarningOption &LHS, StringRef RHS) {
+ return LHS.getName() < RHS;
+ });
+ if (Found == std::end(OptionTable) || Found->getName() != Group)
+ return true; // Option not found.
+
+ return ::getDiagnosticsInGroup(Flavor, Found, Diags);
+}
+
+void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
+ std::vector<diag::kind> &Diags) {
+ for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
+ if (StaticDiagInfo[i].getFlavor() == Flavor)
+ Diags.push_back(StaticDiagInfo[i].DiagID);
+}
+
+StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
+ StringRef Group) {
+ StringRef Best;
+ unsigned BestDistance = Group.size() + 1; // Sanity threshold.
+ for (const WarningOption &O : OptionTable) {
+ // Don't suggest ignored warning flags.
+ if (!O.Members && !O.SubGroups)
+ continue;
+
+ unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
+ if (Distance > BestDistance)
+ continue;
+
+ // Don't suggest groups that are not of this kind.
+ llvm::SmallVector<diag::kind, 8> Diags;
+ if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
+ continue;
+
+ if (Distance == BestDistance) {
+ // Two matches with the same distance, don't prefer one over the other.
+ Best = "";
+ } else if (Distance < BestDistance) {
+ // This is a better match.
+ Best = O.getName();
+ BestDistance = Distance;
+ }
+ }
+
+ return Best;
+}
+
+/// ProcessDiag - This is the method used to report a diagnostic that is
+/// finally fully formed.
+bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
+ Diagnostic Info(&Diag);
+
+ assert(Diag.getClient() && "DiagnosticClient not set!");
+
+ // Figure out the diagnostic level of this message.
+ unsigned DiagID = Info.getID();
+ DiagnosticIDs::Level DiagLevel
+ = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
+
+ // Update counts for DiagnosticErrorTrap even if a fatal error occurred
+ // or diagnostics are suppressed.
+ if (DiagLevel >= DiagnosticIDs::Error) {
+ ++Diag.TrapNumErrorsOccurred;
+ if (isUnrecoverable(DiagID))
+ ++Diag.TrapNumUnrecoverableErrorsOccurred;
+ }
+
+ if (Diag.SuppressAllDiagnostics)
+ return false;
+
+ if (DiagLevel != DiagnosticIDs::Note) {
+ // Record that a fatal error occurred only when we see a second
+ // non-note diagnostic. This allows notes to be attached to the
+ // fatal error, but suppresses any diagnostics that follow those
+ // notes.
+ if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
+ Diag.FatalErrorOccurred = true;
+
+ Diag.LastDiagLevel = DiagLevel;
+ }
+
+ // If a fatal error has already been emitted, silence all subsequent
+ // diagnostics.
+ if (Diag.FatalErrorOccurred && Diag.SuppressAfterFatalError) {
+ if (DiagLevel >= DiagnosticIDs::Error &&
+ Diag.Client->IncludeInDiagnosticCounts()) {
+ ++Diag.NumErrors;
+ }
+
+ return false;
+ }
+
+ // If the client doesn't care about this message, don't issue it. If this is
+ // a note and the last real diagnostic was ignored, ignore it too.
+ if (DiagLevel == DiagnosticIDs::Ignored ||
+ (DiagLevel == DiagnosticIDs::Note &&
+ Diag.LastDiagLevel == DiagnosticIDs::Ignored))
+ return false;
+
+ if (DiagLevel >= DiagnosticIDs::Error) {
+ if (isUnrecoverable(DiagID))
+ Diag.UnrecoverableErrorOccurred = true;
+
+ // Warnings which have been upgraded to errors do not prevent compilation.
+ if (isDefaultMappingAsError(DiagID))
+ Diag.UncompilableErrorOccurred = true;
+
+ Diag.ErrorOccurred = true;
+ if (Diag.Client->IncludeInDiagnosticCounts()) {
+ ++Diag.NumErrors;
+ }
+
+ // If we've emitted a lot of errors, emit a fatal error instead of it to
+ // stop a flood of bogus errors.
+ if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
+ DiagLevel == DiagnosticIDs::Error) {
+ Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
+ return false;
+ }
+ }
+
+ // Make sure we set FatalErrorOccurred to ensure that the notes from the
+ // diagnostic that caused `fatal_too_many_errors` won't be emitted.
+ if (Diag.CurDiagID == diag::fatal_too_many_errors)
+ Diag.FatalErrorOccurred = true;
+ // Finally, report it.
+ EmitDiag(Diag, DiagLevel);
+ return true;
+}
+
+void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
+ Diagnostic Info(&Diag);
+ assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
+
+ Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
+ if (Diag.Client->IncludeInDiagnosticCounts()) {
+ if (DiagLevel == DiagnosticIDs::Warning)
+ ++Diag.NumWarnings;
+ }
+
+ Diag.CurDiagID = ~0U;
+}
+
+bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
+ if (DiagID >= diag::DIAG_UPPER_LIMIT) {
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+ // Custom diagnostics.
+ return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
+ }
+
+ // Only errors may be unrecoverable.
+ if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
+ return false;
+
+ if (DiagID == diag::err_unavailable ||
+ DiagID == diag::err_unavailable_message)
+ return false;
+
+ // Currently we consider all ARC errors as recoverable.
+ if (isARCDiagnostic(DiagID))
+ return false;
+
+ return true;
+}
+
+bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
+ unsigned cat = getCategoryNumberForDiag(DiagID);
+ return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp
new file mode 100644
index 000000000000..ebd9bb45f380
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp
@@ -0,0 +1,25 @@
+//===- DiagnosticOptions.cpp - C Language Family Diagnostic Handling ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DiagnosticOptions related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/Support/raw_ostream.h"
+#include <type_traits>
+
+namespace clang {
+
+raw_ostream &operator<<(raw_ostream &Out, DiagnosticLevelMask M) {
+ using UT = std::underlying_type<DiagnosticLevelMask>::type;
+ return Out << static_cast<UT>(M);
+}
+
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
new file mode 100644
index 000000000000..d339b972ae8e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
@@ -0,0 +1,557 @@
+//===--- FileManager.cpp - File System Probing and Caching ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the FileManager interface.
+//
+//===----------------------------------------------------------------------===//
+//
+// TODO: This should index all interesting directories with dirent calls.
+// getdirentries ?
+// opendir/readdir_r/closedir ?
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <climits>
+#include <cstdint>
+#include <cstdlib>
+#include <string>
+#include <utility>
+
+using namespace clang;
+
+/// NON_EXISTENT_DIR - A special value distinct from null that is used to
+/// represent a dir name that doesn't exist on the disk.
+#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
+
+/// NON_EXISTENT_FILE - A special value distinct from null that is used to
+/// represent a filename that doesn't exist on the disk.
+#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
+
+//===----------------------------------------------------------------------===//
+// Common logic.
+//===----------------------------------------------------------------------===//
+
+FileManager::FileManager(const FileSystemOptions &FSO,
+ IntrusiveRefCntPtr<vfs::FileSystem> FS)
+ : FS(std::move(FS)), FileSystemOpts(FSO), SeenDirEntries(64),
+ SeenFileEntries(64), NextFileUID(0) {
+ NumDirLookups = NumFileLookups = 0;
+ NumDirCacheMisses = NumFileCacheMisses = 0;
+
+ // If the caller doesn't provide a virtual file system, just grab the real
+ // file system.
+ if (!this->FS)
+ this->FS = vfs::getRealFileSystem();
+}
+
+FileManager::~FileManager() = default;
+
+void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
+ bool AtBeginning) {
+ assert(statCache && "No stat cache provided?");
+ if (AtBeginning || !StatCache.get()) {
+ statCache->setNextStatCache(std::move(StatCache));
+ StatCache = std::move(statCache);
+ return;
+ }
+
+ FileSystemStatCache *LastCache = StatCache.get();
+ while (LastCache->getNextStatCache())
+ LastCache = LastCache->getNextStatCache();
+
+ LastCache->setNextStatCache(std::move(statCache));
+}
+
+void FileManager::removeStatCache(FileSystemStatCache *statCache) {
+ if (!statCache)
+ return;
+
+ if (StatCache.get() == statCache) {
+ // This is the first stat cache.
+ StatCache = StatCache->takeNextStatCache();
+ return;
+ }
+
+ // Find the stat cache in the list.
+ FileSystemStatCache *PrevCache = StatCache.get();
+ while (PrevCache && PrevCache->getNextStatCache() != statCache)
+ PrevCache = PrevCache->getNextStatCache();
+
+ assert(PrevCache && "Stat cache not found for removal");
+ PrevCache->setNextStatCache(statCache->takeNextStatCache());
+}
+
+void FileManager::clearStatCaches() {
+ StatCache.reset();
+}
+
+/// Retrieve the directory that the given file name resides in.
+/// Filename can point to either a real file or a virtual file.
+static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
+ StringRef Filename,
+ bool CacheFailure) {
+ if (Filename.empty())
+ return nullptr;
+
+ if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
+ return nullptr; // If Filename is a directory.
+
+ StringRef DirName = llvm::sys::path::parent_path(Filename);
+ // Use the current directory if file has no path component.
+ if (DirName.empty())
+ DirName = ".";
+
+ return FileMgr.getDirectory(DirName, CacheFailure);
+}
+
+/// Add all ancestors of the given path (pointing to either a file or
+/// a directory) as virtual directories.
+void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
+ StringRef DirName = llvm::sys::path::parent_path(Path);
+ if (DirName.empty())
+ DirName = ".";
+
+ auto &NamedDirEnt =
+ *SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first;
+
+ // When caching a virtual directory, we always cache its ancestors
+ // at the same time. Therefore, if DirName is already in the cache,
+ // we don't need to recurse as its ancestors must also already be in
+ // the cache.
+ if (NamedDirEnt.second && NamedDirEnt.second != NON_EXISTENT_DIR)
+ return;
+
+ // Add the virtual directory to the cache.
+ auto UDE = llvm::make_unique<DirectoryEntry>();
+ UDE->Name = NamedDirEnt.first();
+ NamedDirEnt.second = UDE.get();
+ VirtualDirectoryEntries.push_back(std::move(UDE));
+
+ // Recursively add the other ancestors.
+ addAncestorsAsVirtualDirs(DirName);
+}
+
+const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
+ bool CacheFailure) {
+ // stat doesn't like trailing separators except for root directory.
+ // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'.
+ // (though it can strip '\\')
+ if (DirName.size() > 1 &&
+ DirName != llvm::sys::path::root_path(DirName) &&
+ llvm::sys::path::is_separator(DirName.back()))
+ DirName = DirName.substr(0, DirName.size()-1);
+#ifdef _WIN32
+ // Fixing a problem with "clang C:test.c" on Windows.
+ // Stat("C:") does not recognize "C:" as a valid directory
+ std::string DirNameStr;
+ if (DirName.size() > 1 && DirName.back() == ':' &&
+ DirName.equals_lower(llvm::sys::path::root_name(DirName))) {
+ DirNameStr = DirName.str() + '.';
+ DirName = DirNameStr;
+ }
+#endif
+
+ ++NumDirLookups;
+ auto &NamedDirEnt =
+ *SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first;
+
+ // See if there was already an entry in the map. Note that the map
+ // contains both virtual and real directories.
+ if (NamedDirEnt.second)
+ return NamedDirEnt.second == NON_EXISTENT_DIR ? nullptr
+ : NamedDirEnt.second;
+
+ ++NumDirCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedDirEnt.second = NON_EXISTENT_DIR;
+
+ // Get the null-terminated directory name as stored as the key of the
+ // SeenDirEntries map.
+ StringRef InterndDirName = NamedDirEnt.first();
+
+ // Check to see if the directory exists.
+ FileData Data;
+ if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) {
+ // There's no real directory at the given path.
+ if (!CacheFailure)
+ SeenDirEntries.erase(DirName);
+ return nullptr;
+ }
+
+ // It exists. See if we have already opened a directory with the
+ // same inode (this occurs on Unix-like systems when one dir is
+ // symlinked to another, for example) or the same path (on
+ // Windows).
+ DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID];
+
+ NamedDirEnt.second = &UDE;
+ if (UDE.getName().empty()) {
+ // We don't have this directory yet, add it. We use the string
+ // key from the SeenDirEntries map as the string.
+ UDE.Name = InterndDirName;
+ }
+
+ return &UDE;
+}
+
+const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
+ bool CacheFailure) {
+ ++NumFileLookups;
+
+ // See if there is already an entry in the map.
+ auto &NamedFileEnt =
+ *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first;
+
+ // See if there is already an entry in the map.
+ if (NamedFileEnt.second)
+ return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr
+ : NamedFileEnt.second;
+
+ ++NumFileCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedFileEnt.second = NON_EXISTENT_FILE;
+
+ // Get the null-terminated file name as stored as the key of the
+ // SeenFileEntries map.
+ StringRef InterndFileName = NamedFileEnt.first();
+
+ // Look up the directory for the file. When looking up something like
+ // sys/foo.h we'll discover all of the search directories that have a 'sys'
+ // subdirectory. This will let us avoid having to waste time on known-to-fail
+ // searches when we go to find sys/bar.h, because all the search directories
+ // without a 'sys' subdir will get a cached failure result.
+ const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
+ CacheFailure);
+ if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist.
+ if (!CacheFailure)
+ SeenFileEntries.erase(Filename);
+
+ return nullptr;
+ }
+
+ // 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.
+ std::unique_ptr<vfs::File> F;
+ FileData Data;
+ if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) {
+ // There's no real file at the given path.
+ if (!CacheFailure)
+ SeenFileEntries.erase(Filename);
+
+ return nullptr;
+ }
+
+ assert((openFile || !F) && "undesired open file");
+
+ // 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 = UniqueRealFiles[Data.UniqueID];
+
+ NamedFileEnt.second = &UFE;
+
+ // If the name returned by getStatValue is different than Filename, re-intern
+ // the name.
+ if (Data.Name != Filename) {
+ auto &NamedFileEnt =
+ *SeenFileEntries.insert(std::make_pair(Data.Name, nullptr)).first;
+ if (!NamedFileEnt.second)
+ NamedFileEnt.second = &UFE;
+ else
+ assert(NamedFileEnt.second == &UFE &&
+ "filename from getStatValue() refers to wrong file");
+ InterndFileName = NamedFileEnt.first().data();
+ }
+
+ if (UFE.isValid()) { // Already have an entry with this inode, return it.
+
+ // FIXME: this hack ensures that if we look up a file by a virtual path in
+ // the VFS that the getDir() will have the virtual path, even if we found
+ // the file by a 'real' path first. This is required in order to find a
+ // module's structure when its headers/module map are mapped in the VFS.
+ // We should remove this as soon as we can properly support a file having
+ // multiple names.
+ if (DirInfo != UFE.Dir && Data.IsVFSMapped)
+ UFE.Dir = DirInfo;
+
+ // Always update the name to use the last name by which a file was accessed.
+ // FIXME: Neither this nor always using the first name is correct; we want
+ // to switch towards a design where we return a FileName object that
+ // encapsulates both the name by which the file was accessed and the
+ // corresponding FileEntry.
+ UFE.Name = InterndFileName;
+
+ return &UFE;
+ }
+
+ // Otherwise, we don't have this file yet, add it.
+ UFE.Name = InterndFileName;
+ UFE.Size = Data.Size;
+ UFE.ModTime = Data.ModTime;
+ UFE.Dir = DirInfo;
+ UFE.UID = NextFileUID++;
+ UFE.UniqueID = Data.UniqueID;
+ UFE.IsNamedPipe = Data.IsNamedPipe;
+ UFE.InPCH = Data.InPCH;
+ UFE.File = std::move(F);
+ UFE.IsValid = true;
+ if (UFE.File)
+ if (auto RealPathName = UFE.File->getName())
+ UFE.RealPathName = *RealPathName;
+ return &UFE;
+}
+
+const FileEntry *
+FileManager::getVirtualFile(StringRef Filename, off_t Size,
+ time_t ModificationTime) {
+ ++NumFileLookups;
+
+ // See if there is already an entry in the map.
+ auto &NamedFileEnt =
+ *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first;
+
+ // See if there is already an entry in the map.
+ if (NamedFileEnt.second && NamedFileEnt.second != NON_EXISTENT_FILE)
+ return NamedFileEnt.second;
+
+ ++NumFileCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedFileEnt.second = NON_EXISTENT_FILE;
+
+ addAncestorsAsVirtualDirs(Filename);
+ FileEntry *UFE = nullptr;
+
+ // Now that all ancestors of Filename are in the cache, the
+ // following call is guaranteed to find the DirectoryEntry from the
+ // cache.
+ const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
+ /*CacheFailure=*/true);
+ assert(DirInfo &&
+ "The directory of a virtual file should already be in the cache.");
+
+ // Check to see if the file exists. If so, drop the virtual file
+ FileData Data;
+ const char *InterndFileName = NamedFileEnt.first().data();
+ if (getStatValue(InterndFileName, Data, true, nullptr) == 0) {
+ Data.Size = Size;
+ Data.ModTime = ModificationTime;
+ UFE = &UniqueRealFiles[Data.UniqueID];
+
+ NamedFileEnt.second = UFE;
+
+ // If we had already opened this file, close it now so we don't
+ // leak the descriptor. We're not going to use the file
+ // descriptor anyway, since this is a virtual file.
+ if (UFE->File)
+ UFE->closeFile();
+
+ // If we already have an entry with this inode, return it.
+ if (UFE->isValid())
+ return UFE;
+
+ UFE->UniqueID = Data.UniqueID;
+ UFE->IsNamedPipe = Data.IsNamedPipe;
+ UFE->InPCH = Data.InPCH;
+ }
+
+ if (!UFE) {
+ VirtualFileEntries.push_back(llvm::make_unique<FileEntry>());
+ UFE = VirtualFileEntries.back().get();
+ NamedFileEnt.second = UFE;
+ }
+
+ UFE->Name = InterndFileName;
+ UFE->Size = Size;
+ UFE->ModTime = ModificationTime;
+ UFE->Dir = DirInfo;
+ UFE->UID = NextFileUID++;
+ UFE->IsValid = true;
+ UFE->File.reset();
+ return UFE;
+}
+
+bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
+ StringRef pathRef(path.data(), path.size());
+
+ if (FileSystemOpts.WorkingDir.empty()
+ || llvm::sys::path::is_absolute(pathRef))
+ return false;
+
+ SmallString<128> NewPath(FileSystemOpts.WorkingDir);
+ llvm::sys::path::append(NewPath, pathRef);
+ path = NewPath;
+ return true;
+}
+
+bool FileManager::makeAbsolutePath(SmallVectorImpl<char> &Path) const {
+ bool Changed = FixupRelativePath(Path);
+
+ if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
+ FS->makeAbsolute(Path);
+ Changed = true;
+ }
+
+ return Changed;
+}
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
+ bool ShouldCloseOpenFile) {
+ uint64_t FileSize = Entry->getSize();
+ // If there's a high enough chance that the file have changed since we
+ // got its size, force a stat before opening it.
+ if (isVolatile)
+ FileSize = -1;
+
+ StringRef Filename = Entry->getName();
+ // If the file is already open, use the open file descriptor.
+ if (Entry->File) {
+ auto Result =
+ Entry->File->getBuffer(Filename, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
+ // FIXME: we need a set of APIs that can make guarantees about whether a
+ // FileEntry is open or not.
+ if (ShouldCloseOpenFile)
+ Entry->closeFile();
+ return Result;
+ }
+
+ // Otherwise, open the file.
+
+ if (FileSystemOpts.WorkingDir.empty())
+ return FS->getBufferForFile(Filename, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
+
+ SmallString<128> FilePath(Entry->getName());
+ FixupRelativePath(FilePath);
+ return FS->getBufferForFile(FilePath, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
+}
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+FileManager::getBufferForFile(StringRef Filename, bool isVolatile) {
+ if (FileSystemOpts.WorkingDir.empty())
+ return FS->getBufferForFile(Filename, -1, true, isVolatile);
+
+ SmallString<128> FilePath(Filename);
+ FixupRelativePath(FilePath);
+ return FS->getBufferForFile(FilePath.c_str(), -1, true, isVolatile);
+}
+
+/// getStatValue - Get the 'stat' information for the specified path,
+/// using the cache to accelerate it if possible. This returns true
+/// if the path points to a virtual file or does not exist, or returns
+/// false if it's an existent real file. If FileDescriptor is NULL,
+/// do directory look-up instead of file look-up.
+bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F) {
+ // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
+ // absolute!
+ if (FileSystemOpts.WorkingDir.empty())
+ return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS);
+
+ SmallString<128> FilePath(Path);
+ FixupRelativePath(FilePath);
+
+ return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F,
+ StatCache.get(), *FS);
+}
+
+bool FileManager::getNoncachedStatValue(StringRef Path,
+ vfs::Status &Result) {
+ SmallString<128> FilePath(Path);
+ FixupRelativePath(FilePath);
+
+ llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str());
+ if (!S)
+ return true;
+ Result = *S;
+ return false;
+}
+
+void FileManager::invalidateCache(const FileEntry *Entry) {
+ assert(Entry && "Cannot invalidate a NULL FileEntry");
+
+ SeenFileEntries.erase(Entry->getName());
+
+ // FileEntry invalidation should not block future optimizations in the file
+ // caches. Possible alternatives are cache truncation (invalidate last N) or
+ // invalidation of the whole cache.
+ UniqueRealFiles.erase(Entry->getUniqueID());
+}
+
+void FileManager::GetUniqueIDMapping(
+ SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
+ UIDToFiles.clear();
+ UIDToFiles.resize(NextFileUID);
+
+ // Map file entries
+ for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
+ FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
+ FE != FEEnd; ++FE)
+ if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE)
+ UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
+
+ // Map virtual file entries
+ for (const auto &VFE : VirtualFileEntries)
+ if (VFE && VFE.get() != NON_EXISTENT_FILE)
+ UIDToFiles[VFE->getUID()] = VFE.get();
+}
+
+void FileManager::modifyFileEntry(FileEntry *File,
+ off_t Size, time_t ModificationTime) {
+ File->Size = Size;
+ File->ModTime = ModificationTime;
+}
+
+StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
+ // FIXME: use llvm::sys::fs::canonical() when it gets implemented
+ llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known
+ = CanonicalDirNames.find(Dir);
+ if (Known != CanonicalDirNames.end())
+ return Known->second;
+
+ StringRef CanonicalName(Dir->getName());
+
+ SmallString<4096> CanonicalNameBuf;
+ if (!FS->getRealPath(Dir->getName(), CanonicalNameBuf))
+ CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
+
+ CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
+ return CanonicalName;
+}
+
+void FileManager::PrintStats() const {
+ llvm::errs() << "\n*** File Manager Stats:\n";
+ llvm::errs() << UniqueRealFiles.size() << " real files found, "
+ << UniqueRealDirs.size() << " real dirs found.\n";
+ llvm::errs() << VirtualFileEntries.size() << " virtual files found, "
+ << VirtualDirectoryEntries.size() << " virtual 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;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
new file mode 100644
index 000000000000..f5856cb6542a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
@@ -0,0 +1,129 @@
+//===- FileSystemStatCache.cpp - Caching for 'stat' calls -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the FileSystemStatCache interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Path.h"
+#include <utility>
+
+using namespace clang;
+
+void FileSystemStatCache::anchor() {}
+
+static void copyStatusToFileData(const vfs::Status &Status,
+ FileData &Data) {
+ Data.Name = Status.getName();
+ Data.Size = Status.getSize();
+ Data.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
+ Data.UniqueID = Status.getUniqueID();
+ Data.IsDirectory = Status.isDirectory();
+ Data.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
+ Data.InPCH = false;
+ Data.IsVFSMapped = Status.IsVFSMapped;
+}
+
+/// FileSystemStatCache::get - Get the 'stat' information for the specified
+/// path, using the cache to accelerate it if possible. This returns true if
+/// the path does not exist or false if it exists.
+///
+/// If isFile is true, then this lookup should only return success for files
+/// (not directories). If it is false this lookup should only return
+/// success for directories (not files). On a successful file lookup, the
+/// implementation can optionally fill in FileDescriptor with a valid
+/// descriptor and the client guarantees that it will close it.
+bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F,
+ FileSystemStatCache *Cache, vfs::FileSystem &FS) {
+ LookupResult R;
+ bool isForDir = !isFile;
+
+ // If we have a cache, use it to resolve the stat query.
+ if (Cache)
+ R = Cache->getStat(Path, Data, isFile, F, FS);
+ else if (isForDir || !F) {
+ // If this is a directory or a file descriptor is not needed and we have
+ // no cache, just go to the file system.
+ llvm::ErrorOr<vfs::Status> Status = FS.status(Path);
+ if (!Status) {
+ R = CacheMissing;
+ } else {
+ R = CacheExists;
+ copyStatusToFileData(*Status, Data);
+ }
+ } else {
+ // Otherwise, we have to go to the filesystem. We can always just use
+ // 'stat' here, but (for files) the client is asking whether the file exists
+ // because it wants to turn around and *open* it. It is more efficient to
+ // do "open+fstat" on success than it is to do "stat+open".
+ //
+ // Because of this, check to see if the file exists with 'open'. If the
+ // open succeeds, use fstat to get the stat info.
+ auto OwnedFile = FS.openFileForRead(Path);
+
+ if (!OwnedFile) {
+ // If the open fails, our "stat" fails.
+ R = CacheMissing;
+ } else {
+ // Otherwise, the open succeeded. Do an fstat to get the information
+ // about the file. We'll end up returning the open file descriptor to the
+ // client to do what they please with it.
+ llvm::ErrorOr<vfs::Status> Status = (*OwnedFile)->status();
+ if (Status) {
+ R = CacheExists;
+ copyStatusToFileData(*Status, Data);
+ *F = std::move(*OwnedFile);
+ } else {
+ // fstat rarely fails. If it does, claim the initial open didn't
+ // succeed.
+ R = CacheMissing;
+ *F = nullptr;
+ }
+ }
+ }
+
+ // If the path doesn't exist, return failure.
+ if (R == CacheMissing) return true;
+
+ // If the path exists, make sure that its "directoryness" matches the clients
+ // demands.
+ if (Data.IsDirectory != isForDir) {
+ // If not, close the file if opened.
+ if (F)
+ *F = nullptr;
+
+ return true;
+ }
+
+ return false;
+}
+
+MemorizeStatCalls::LookupResult
+MemorizeStatCalls::getStat(StringRef Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
+ LookupResult Result = statChained(Path, Data, isFile, F, FS);
+
+ // Do not cache failed stats, it is easy to construct common inconsistent
+ // situations if we do, and they are not important for PCH performance (which
+ // currently only needs the stats to construct the initial FileManager
+ // entries).
+ if (Result == CacheMissing)
+ return Result;
+
+ // Cache file 'stat' results and directories with absolutely paths.
+ if (!Data.IsDirectory || llvm::sys::path::is_absolute(Path))
+ StatCalls[Path] = Data;
+
+ return Result;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
new file mode 100644
index 000000000000..7ec3cb7dd65b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -0,0 +1,722 @@
+//===- IdentifierTable.cpp - Hash table for identifier lookup -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IdentifierInfo, IdentifierVisitor, and
+// IdentifierTable interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdentifierInfo Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierInfo::IdentifierInfo() {
+ TokenID = tok::identifier;
+ ObjCOrBuiltinID = 0;
+ HasMacro = false;
+ HadMacro = false;
+ IsExtension = false;
+ IsFutureCompatKeyword = false;
+ IsPoisoned = false;
+ IsCPPOperatorKeyword = false;
+ NeedsHandleIdentifier = false;
+ IsFromAST = false;
+ ChangedAfterLoad = false;
+ FEChangedAfterLoad = false;
+ RevertedTokenID = false;
+ OutOfDate = false;
+ IsModulesImport = false;
+}
+
+//===----------------------------------------------------------------------===//
+// IdentifierTable Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierIterator::~IdentifierIterator() = default;
+
+IdentifierInfoLookup::~IdentifierInfoLookup() = default;
+
+namespace {
+
+/// A simple identifier lookup iterator that represents an
+/// empty sequence of identifiers.
+class EmptyLookupIterator : public IdentifierIterator
+{
+public:
+ StringRef Next() override { return StringRef(); }
+};
+
+} // namespace
+
+IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
+ return new EmptyLookupIterator();
+}
+
+IdentifierTable::IdentifierTable(IdentifierInfoLookup *ExternalLookup)
+ : HashTable(8192), // Start with space for 8K identifiers.
+ ExternalLookup(ExternalLookup) {}
+
+IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
+ IdentifierInfoLookup *ExternalLookup)
+ : IdentifierTable(ExternalLookup) {
+ // Populate the identifier table with info about keywords for the current
+ // language.
+ AddKeywords(LangOpts);
+}
+
+//===----------------------------------------------------------------------===//
+// Language Keyword Implementation
+//===----------------------------------------------------------------------===//
+
+// Constants for TokenKinds.def
+namespace {
+
+ enum {
+ KEYC99 = 0x1,
+ KEYCXX = 0x2,
+ KEYCXX11 = 0x4,
+ KEYGNU = 0x8,
+ KEYMS = 0x10,
+ BOOLSUPPORT = 0x20,
+ KEYALTIVEC = 0x40,
+ KEYNOCXX = 0x80,
+ KEYBORLAND = 0x100,
+ KEYOPENCLC = 0x200,
+ KEYC11 = 0x400,
+ KEYARC = 0x800,
+ KEYNOMS18 = 0x01000,
+ KEYNOOPENCL = 0x02000,
+ WCHARSUPPORT = 0x04000,
+ HALFSUPPORT = 0x08000,
+ CHAR8SUPPORT = 0x10000,
+ KEYCONCEPTS = 0x20000,
+ KEYOBJC2 = 0x40000,
+ KEYZVECTOR = 0x80000,
+ KEYCOROUTINES = 0x100000,
+ KEYMODULES = 0x200000,
+ KEYCXX2A = 0x400000,
+ KEYOPENCLCXX = 0x800000,
+ KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A,
+ KEYALL = (0xffffff & ~KEYNOMS18 &
+ ~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
+ };
+
+ /// How a keyword is treated in the selected standard.
+ enum KeywordStatus {
+ KS_Disabled, // Disabled
+ KS_Extension, // Is an extension
+ KS_Enabled, // Enabled
+ KS_Future // Is a keyword in future standard
+ };
+
+} // namespace
+
+/// Translates flags as specified in TokenKinds.def into keyword status
+/// in the given language standard.
+static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
+ unsigned Flags) {
+ if (Flags == KEYALL) return KS_Enabled;
+ if (LangOpts.CPlusPlus && (Flags & KEYCXX)) return KS_Enabled;
+ if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11)) return KS_Enabled;
+ if (LangOpts.CPlusPlus2a && (Flags & KEYCXX2A)) return KS_Enabled;
+ if (LangOpts.C99 && (Flags & KEYC99)) return KS_Enabled;
+ if (LangOpts.GNUKeywords && (Flags & KEYGNU)) return KS_Extension;
+ if (LangOpts.MicrosoftExt && (Flags & KEYMS)) return KS_Extension;
+ if (LangOpts.Borland && (Flags & KEYBORLAND)) return KS_Extension;
+ if (LangOpts.Bool && (Flags & BOOLSUPPORT)) return KS_Enabled;
+ if (LangOpts.Half && (Flags & HALFSUPPORT)) return KS_Enabled;
+ if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled;
+ if (LangOpts.Char8 && (Flags & CHAR8SUPPORT)) return KS_Enabled;
+ if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) return KS_Enabled;
+ if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLC))
+ return KS_Enabled;
+ if (LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLCXX)) return KS_Enabled;
+ if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) return KS_Enabled;
+ if (LangOpts.C11 && (Flags & KEYC11)) return KS_Enabled;
+ // We treat bridge casts as objective-C keywords so we can warn on them
+ // in non-arc mode.
+ if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
+ if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
+ if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
+ if (LangOpts.CoroutinesTS && (Flags & KEYCOROUTINES)) return KS_Enabled;
+ if (LangOpts.ModulesTS && (Flags & KEYMODULES)) return KS_Enabled;
+ if (LangOpts.CPlusPlus && (Flags & KEYALLCXX)) return KS_Future;
+ return KS_Disabled;
+}
+
+/// AddKeyword - This method is used to associate a token ID with specific
+/// identifiers because they are language keywords. This causes the lexer to
+/// automatically map matching identifiers to specialized token codes.
+static void AddKeyword(StringRef Keyword,
+ tok::TokenKind TokenCode, unsigned Flags,
+ const LangOptions &LangOpts, IdentifierTable &Table) {
+ KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
+
+ // Don't add this keyword under MSVCCompat.
+ if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
+ !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
+ return;
+
+ // Don't add this keyword under OpenCL.
+ if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
+ return;
+
+ // Don't add this keyword if disabled in this language.
+ if (AddResult == KS_Disabled) return;
+
+ IdentifierInfo &Info =
+ Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
+ Info.setIsExtensionToken(AddResult == KS_Extension);
+ Info.setIsFutureCompatKeyword(AddResult == KS_Future);
+}
+
+/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
+/// representations.
+static void AddCXXOperatorKeyword(StringRef Keyword,
+ tok::TokenKind TokenCode,
+ IdentifierTable &Table) {
+ IdentifierInfo &Info = Table.get(Keyword, TokenCode);
+ Info.setIsCPlusPlusOperatorKeyword();
+}
+
+/// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"
+/// or "property".
+static void AddObjCKeyword(StringRef Name,
+ tok::ObjCKeywordKind ObjCID,
+ IdentifierTable &Table) {
+ Table.get(Name).setObjCKeywordID(ObjCID);
+}
+
+/// AddKeywords - Add all keywords to the symbol table.
+///
+void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
+ // Add keywords and tokens for the current language.
+#define KEYWORD(NAME, FLAGS) \
+ AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
+ FLAGS, LangOpts, *this);
+#define ALIAS(NAME, TOK, FLAGS) \
+ AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
+ FLAGS, LangOpts, *this);
+#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
+ if (LangOpts.CXXOperatorNames) \
+ AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
+#define OBJC1_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC1) \
+ AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
+#define OBJC2_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC2) \
+ AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
+#define TESTING_KEYWORD(NAME, FLAGS)
+#include "clang/Basic/TokenKinds.def"
+
+ if (LangOpts.ParseUnknownAnytype)
+ AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
+ LangOpts, *this);
+
+ if (LangOpts.DeclSpecKeyword)
+ AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
+
+ // Add the '_experimental_modules_import' contextual keyword.
+ get("import").setModulesImport(true);
+}
+
+/// Checks if the specified token kind represents a keyword in the
+/// specified language.
+/// \returns Status of the keyword in the language.
+static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
+ tok::TokenKind K) {
+ switch (K) {
+#define KEYWORD(NAME, FLAGS) \
+ case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
+#include "clang/Basic/TokenKinds.def"
+ default: return KS_Disabled;
+ }
+}
+
+/// Returns true if the identifier represents a keyword in the
+/// specified language.
+bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
+ switch (getTokenKwStatus(LangOpts, getTokenID())) {
+ case KS_Enabled:
+ case KS_Extension:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/// Returns true if the identifier represents a C++ keyword in the
+/// specified language.
+bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {
+ if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
+ return false;
+ // This is a C++ keyword if this identifier is not a keyword when checked
+ // using LangOptions without C++ support.
+ LangOptions LangOptsNoCPP = LangOpts;
+ LangOptsNoCPP.CPlusPlus = false;
+ LangOptsNoCPP.CPlusPlus11 = false;
+ LangOptsNoCPP.CPlusPlus2a = false;
+ return !isKeyword(LangOptsNoCPP);
+}
+
+tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
+ // We use a perfect hash function here involving the length of the keyword,
+ // the first and third character. For preprocessor ID's there are no
+ // collisions (if there were, the switch below would complain about duplicate
+ // case values). Note that this depends on 'if' being null terminated.
+
+#define HASH(LEN, FIRST, THIRD) \
+ (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
+#define CASE(LEN, FIRST, THIRD, NAME) \
+ case HASH(LEN, FIRST, THIRD): \
+ return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
+
+ unsigned Len = getLength();
+ if (Len < 2) return tok::pp_not_keyword;
+ const char *Name = getNameStart();
+ switch (HASH(Len, Name[0], Name[2])) {
+ default: return tok::pp_not_keyword;
+ CASE( 2, 'i', '\0', if);
+ CASE( 4, 'e', 'i', elif);
+ CASE( 4, 'e', 's', else);
+ CASE( 4, 'l', 'n', line);
+ CASE( 4, 's', 'c', sccs);
+ CASE( 5, 'e', 'd', endif);
+ CASE( 5, 'e', 'r', error);
+ CASE( 5, 'i', 'e', ident);
+ CASE( 5, 'i', 'd', ifdef);
+ CASE( 5, 'u', 'd', undef);
+
+ CASE( 6, 'a', 's', assert);
+ CASE( 6, 'd', 'f', define);
+ CASE( 6, 'i', 'n', ifndef);
+ CASE( 6, 'i', 'p', import);
+ CASE( 6, 'p', 'a', pragma);
+
+ CASE( 7, 'd', 'f', defined);
+ CASE( 7, 'i', 'c', include);
+ CASE( 7, 'w', 'r', warning);
+
+ CASE( 8, 'u', 'a', unassert);
+ CASE(12, 'i', 'c', include_next);
+
+ CASE(14, '_', 'p', __public_macro);
+
+ CASE(15, '_', 'p', __private_macro);
+
+ CASE(16, '_', 'i', __include_macros);
+#undef CASE
+#undef HASH
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Stats Implementation
+//===----------------------------------------------------------------------===//
+
+/// PrintStats - Print statistics about how well the identifier table is doing
+/// at hashing identifiers.
+void IdentifierTable::PrintStats() const {
+ unsigned NumBuckets = HashTable.getNumBuckets();
+ unsigned NumIdentifiers = HashTable.getNumItems();
+ unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
+ unsigned AverageIdentifierSize = 0;
+ unsigned MaxIdentifierLength = 0;
+
+ // TODO: Figure out maximum times an identifier had to probe for -stats.
+ for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
+ I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
+ unsigned IdLen = I->getKeyLength();
+ AverageIdentifierSize += IdLen;
+ if (MaxIdentifierLength < IdLen)
+ MaxIdentifierLength = IdLen;
+ }
+
+ fprintf(stderr, "\n*** Identifier Table Stats:\n");
+ fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
+ fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
+ fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
+ NumIdentifiers/(double)NumBuckets);
+ fprintf(stderr, "Ave identifier length: %f\n",
+ (AverageIdentifierSize/(double)NumIdentifiers));
+ fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
+
+ // Compute statistics about the memory allocated for identifiers.
+ HashTable.getAllocator().PrintStats();
+}
+
+//===----------------------------------------------------------------------===//
+// SelectorTable Implementation
+//===----------------------------------------------------------------------===//
+
+unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
+ return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
+}
+
+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
+/// this class is provided strictly through Selector.
+class MultiKeywordSelector
+ : public DeclarationNameExtra, public llvm::FoldingSetNode {
+ MultiKeywordSelector(unsigned nKeys) {
+ ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
+ }
+
+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; }
+
+ using keyword_iterator = IdentifierInfo *const *;
+
+ keyword_iterator keyword_begin() const {
+ return reinterpret_cast<keyword_iterator>(this+1);
+ }
+
+ 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,
+ keyword_iterator ArgTys, unsigned NumArgs) {
+ ID.AddInteger(NumArgs);
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ID.AddPointer(ArgTys[i]);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, keyword_begin(), getNumArgs());
+ }
+};
+
+} // namespace clang.
+
+unsigned Selector::getNumArgs() const {
+ unsigned IIF = getIdentifierInfoFlag();
+ if (IIF <= ZeroArg)
+ return 0;
+ if (IIF == OneArg)
+ return 1;
+ // We point to a MultiKeywordSelector.
+ MultiKeywordSelector *SI = getMultiKeywordSelector();
+ return SI->getNumArgs();
+}
+
+IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
+ if (getIdentifierInfoFlag() < MultiArg) {
+ assert(argIndex == 0 && "illegal keyword index");
+ return getAsIdentifierInfo();
+ }
+
+ // We point to a MultiKeywordSelector.
+ MultiKeywordSelector *SI = getMultiKeywordSelector();
+ return SI->getIdentifierInfoForSlot(argIndex);
+}
+
+StringRef Selector::getNameForSlot(unsigned int argIndex) const {
+ IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
+ return II? II->getName() : StringRef();
+}
+
+std::string MultiKeywordSelector::getName() const {
+ SmallString<256> Str;
+ llvm::raw_svector_ostream OS(Str);
+ for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
+ if (*I)
+ OS << (*I)->getName();
+ OS << ':';
+ }
+
+ return OS.str();
+}
+
+std::string Selector::getAsString() const {
+ if (InfoPtr == 0)
+ return "<null selector>";
+
+ if (getIdentifierInfoFlag() < MultiArg) {
+ IdentifierInfo *II = getAsIdentifierInfo();
+
+ if (getNumArgs() == 0) {
+ assert(II && "If the number of arguments is 0 then II is guaranteed to "
+ "not be null.");
+ return II->getName();
+ }
+
+ if (!II)
+ return ":";
+
+ return II->getName().str() + ":";
+ }
+
+ // We have a multiple keyword selector.
+ return getMultiKeywordSelector()->getName();
+}
+
+void Selector::print(llvm::raw_ostream &OS) const {
+ OS << getAsString();
+}
+
+LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }
+
+/// Interpreting the given string using the normal CamelCase
+/// conventions, determine whether the given string starts with the
+/// given "word", which is assumed to end in a lowercase letter.
+static bool startsWithWord(StringRef name, StringRef word) {
+ if (name.size() < word.size()) return false;
+ return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
+ name.startswith(word));
+}
+
+ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
+ IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
+ if (!first) return OMF_None;
+
+ StringRef name = first->getName();
+ if (sel.isUnarySelector()) {
+ if (name == "autorelease") return OMF_autorelease;
+ if (name == "dealloc") return OMF_dealloc;
+ if (name == "finalize") return OMF_finalize;
+ if (name == "release") return OMF_release;
+ if (name == "retain") return OMF_retain;
+ if (name == "retainCount") return OMF_retainCount;
+ if (name == "self") return OMF_self;
+ if (name == "initialize") return OMF_initialize;
+ }
+
+ if (name == "performSelector" || name == "performSelectorInBackground" ||
+ name == "performSelectorOnMainThread")
+ return OMF_performSelector;
+
+ // The other method families may begin with a prefix of underscores.
+ while (!name.empty() && name.front() == '_')
+ name = name.substr(1);
+
+ if (name.empty()) return OMF_None;
+ switch (name.front()) {
+ case 'a':
+ if (startsWithWord(name, "alloc")) return OMF_alloc;
+ break;
+ case 'c':
+ if (startsWithWord(name, "copy")) return OMF_copy;
+ break;
+ case 'i':
+ if (startsWithWord(name, "init")) return OMF_init;
+ break;
+ case 'm':
+ if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
+ break;
+ case 'n':
+ if (startsWithWord(name, "new")) return OMF_new;
+ break;
+ default:
+ break;
+ }
+
+ return OMF_None;
+}
+
+ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
+ IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
+ if (!first) return OIT_None;
+
+ StringRef name = first->getName();
+
+ if (name.empty()) return OIT_None;
+ switch (name.front()) {
+ case 'a':
+ if (startsWithWord(name, "array")) return OIT_Array;
+ break;
+ case 'd':
+ if (startsWithWord(name, "default")) return OIT_ReturnsSelf;
+ if (startsWithWord(name, "dictionary")) return OIT_Dictionary;
+ break;
+ case 's':
+ if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;
+ if (startsWithWord(name, "standard")) return OIT_Singleton;
+ break;
+ case 'i':
+ if (startsWithWord(name, "init")) return OIT_Init;
+ default:
+ break;
+ }
+ return OIT_None;
+}
+
+ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
+ IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
+ if (!first) return SFF_None;
+
+ StringRef name = first->getName();
+
+ switch (name.front()) {
+ case 'a':
+ if (name == "appendFormat") return SFF_NSString;
+ break;
+
+ case 'i':
+ if (name == "initWithFormat") return SFF_NSString;
+ break;
+
+ case 'l':
+ if (name == "localizedStringWithFormat") return SFF_NSString;
+ break;
+
+ case 's':
+ if (name == "stringByAppendingFormat" ||
+ name == "stringWithFormat") return SFF_NSString;
+ break;
+ }
+ return SFF_None;
+}
+
+namespace {
+
+struct SelectorTableImpl {
+ llvm::FoldingSet<MultiKeywordSelector> Table;
+ llvm::BumpPtrAllocator Allocator;
+};
+
+} // namespace
+
+static SelectorTableImpl &getSelectorTableImpl(void *P) {
+ return *static_cast<SelectorTableImpl*>(P);
+}
+
+SmallString<64>
+SelectorTable::constructSetterName(StringRef Name) {
+ SmallString<64> SetterName("set");
+ SetterName += Name;
+ SetterName[3] = toUppercase(SetterName[3]);
+ return SetterName;
+}
+
+Selector
+SelectorTable::constructSetterSelector(IdentifierTable &Idents,
+ SelectorTable &SelTable,
+ const IdentifierInfo *Name) {
+ IdentifierInfo *SetterName =
+ &Idents.get(constructSetterName(Name->getName()));
+ return SelTable.getUnarySelector(SetterName);
+}
+
+std::string SelectorTable::getPropertyNameFromSetterSelector(Selector Sel) {
+ StringRef Name = Sel.getNameForSlot(0);
+ assert(Name.startswith("set") && "invalid setter name");
+ return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();
+}
+
+size_t SelectorTable::getTotalMemory() const {
+ SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
+ return SelTabImpl.Allocator.getTotalMemory();
+}
+
+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);
+
+ void *InsertPos = nullptr;
+ 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, alignof(MultiKeywordSelector));
+ new (SI) MultiKeywordSelector(nKeys, IIV);
+ SelTabImpl.Table.InsertNode(SI, InsertPos);
+ return Selector(SI);
+}
+
+SelectorTable::SelectorTable() {
+ Impl = new SelectorTableImpl();
+}
+
+SelectorTable::~SelectorTable() {
+ delete &getSelectorTableImpl(Impl);
+}
+
+const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
+ switch (Operator) {
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ return nullptr;
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case OO_##Name: return Spelling;
+#include "clang/Basic/OperatorKinds.def"
+ }
+
+ llvm_unreachable("Invalid OverloadedOperatorKind!");
+}
+
+StringRef clang::getNullabilitySpelling(NullabilityKind kind,
+ bool isContextSensitive) {
+ switch (kind) {
+ case NullabilityKind::NonNull:
+ return isContextSensitive ? "nonnull" : "_Nonnull";
+
+ case NullabilityKind::Nullable:
+ return isContextSensitive ? "nullable" : "_Nullable";
+
+ case NullabilityKind::Unspecified:
+ return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
+ }
+ llvm_unreachable("Unknown nullability kind.");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
new file mode 100644
index 000000000000..763ba33683bc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
@@ -0,0 +1,50 @@
+//===- LangOptions.cpp - C Language Family Language Options ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LangOptions class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/LangOptions.h"
+
+using namespace clang;
+
+LangOptions::LangOptions() {
+#define LANGOPT(Name, Bits, Default, Description) Name = Default;
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
+#include "clang/Basic/LangOptions.def"
+}
+
+void LangOptions::resetNonModularOptions() {
+#define LANGOPT(Name, Bits, Default, Description)
+#define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default;
+#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ Name = Default;
+#include "clang/Basic/LangOptions.def"
+
+ // These options do not affect AST generation.
+ SanitizerBlacklistFiles.clear();
+ XRayAlwaysInstrumentFiles.clear();
+ XRayNeverInstrumentFiles.clear();
+
+ CurrentModule.clear();
+ IsHeaderFile = false;
+}
+
+bool LangOptions::isNoBuiltinFunc(StringRef FuncName) const {
+ for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
+ if (FuncName.equals(NoBuiltinFuncs[i]))
+ return true;
+ return false;
+}
+
+VersionTuple LangOptions::getOpenCLVersionTuple() const {
+ const int Ver = OpenCLCPlusPlus ? OpenCLCPlusPlusVersion : OpenCLVersion;
+ return VersionTuple(Ver / 100, (Ver % 100) / 10);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/MemoryBufferCache.cpp b/contrib/llvm/tools/clang/lib/Basic/MemoryBufferCache.cpp
new file mode 100644
index 000000000000..c1fc571ec9b3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/MemoryBufferCache.cpp
@@ -0,0 +1,48 @@
+//===- MemoryBufferCache.cpp - Cache for loaded memory buffers ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/MemoryBufferCache.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace clang;
+
+llvm::MemoryBuffer &
+MemoryBufferCache::addBuffer(llvm::StringRef Filename,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ auto Insertion =
+ Buffers.insert({Filename, BufferEntry{std::move(Buffer), NextIndex++}});
+ assert(Insertion.second && "Already has a buffer");
+ return *Insertion.first->second.Buffer;
+}
+
+llvm::MemoryBuffer *MemoryBufferCache::lookupBuffer(llvm::StringRef Filename) {
+ auto I = Buffers.find(Filename);
+ if (I == Buffers.end())
+ return nullptr;
+ return I->second.Buffer.get();
+}
+
+bool MemoryBufferCache::isBufferFinal(llvm::StringRef Filename) {
+ auto I = Buffers.find(Filename);
+ if (I == Buffers.end())
+ return false;
+ return I->second.Index < FirstRemovableIndex;
+}
+
+bool MemoryBufferCache::tryToRemoveBuffer(llvm::StringRef Filename) {
+ auto I = Buffers.find(Filename);
+ assert(I != Buffers.end() && "No buffer to remove...");
+ if (I->second.Index < FirstRemovableIndex)
+ return true;
+
+ Buffers.erase(I);
+ return false;
+}
+
+void MemoryBufferCache::finalizeCurrentBuffers() { FirstRemovableIndex = NextIndex; }
diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
new file mode 100644
index 000000000000..1a0c19059058
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
@@ -0,0 +1,610 @@
+//===- Module.cpp - Describe a module -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Module class, which describes a module in the source
+// code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+
+Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
+ bool IsFramework, bool IsExplicit, unsigned VisibilityID)
+ : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
+ VisibilityID(VisibilityID), IsMissingRequirement(false),
+ HasIncompatibleModuleFile(false), IsAvailable(true),
+ IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit),
+ IsSystem(false), IsExternC(false), IsInferred(false),
+ InferSubmodules(false), InferExplicitSubmodules(false),
+ InferExportWildcard(false), ConfigMacrosExhaustive(false),
+ NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
+ NameVisibility(Hidden) {
+ if (Parent) {
+ if (!Parent->isAvailable())
+ IsAvailable = false;
+ if (Parent->IsSystem)
+ IsSystem = true;
+ if (Parent->IsExternC)
+ IsExternC = true;
+ if (Parent->NoUndeclaredIncludes)
+ NoUndeclaredIncludes = true;
+ if (Parent->ModuleMapIsPrivate)
+ ModuleMapIsPrivate = true;
+ IsMissingRequirement = Parent->IsMissingRequirement;
+
+ Parent->SubModuleIndex[Name] = Parent->SubModules.size();
+ Parent->SubModules.push_back(this);
+ }
+}
+
+Module::~Module() {
+ for (submodule_iterator I = submodule_begin(), IEnd = submodule_end();
+ I != IEnd; ++I) {
+ delete *I;
+ }
+}
+
+/// Determine whether a translation unit built using the current
+/// language options has the given feature.
+static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
+ const TargetInfo &Target) {
+ bool HasFeature = llvm::StringSwitch<bool>(Feature)
+ .Case("altivec", LangOpts.AltiVec)
+ .Case("blocks", LangOpts.Blocks)
+ .Case("coroutines", LangOpts.CoroutinesTS)
+ .Case("cplusplus", LangOpts.CPlusPlus)
+ .Case("cplusplus11", LangOpts.CPlusPlus11)
+ .Case("cplusplus14", LangOpts.CPlusPlus14)
+ .Case("cplusplus17", LangOpts.CPlusPlus17)
+ .Case("c99", LangOpts.C99)
+ .Case("c11", LangOpts.C11)
+ .Case("c17", LangOpts.C17)
+ .Case("freestanding", LangOpts.Freestanding)
+ .Case("gnuinlineasm", LangOpts.GNUAsm)
+ .Case("objc", LangOpts.ObjC1)
+ .Case("objc_arc", LangOpts.ObjCAutoRefCount)
+ .Case("opencl", LangOpts.OpenCL)
+ .Case("tls", Target.isTLSSupported())
+ .Case("zvector", LangOpts.ZVector)
+ .Default(Target.hasFeature(Feature));
+ if (!HasFeature)
+ HasFeature = std::find(LangOpts.ModuleFeatures.begin(),
+ LangOpts.ModuleFeatures.end(),
+ Feature) != LangOpts.ModuleFeatures.end();
+ return HasFeature;
+}
+
+bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
+ Requirement &Req,
+ UnresolvedHeaderDirective &MissingHeader,
+ Module *&ShadowingModule) const {
+ if (IsAvailable)
+ return true;
+
+ for (const Module *Current = this; Current; Current = Current->Parent) {
+ if (Current->ShadowingModule) {
+ ShadowingModule = Current->ShadowingModule;
+ return false;
+ }
+ for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
+ if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
+ Current->Requirements[I].second) {
+ Req = Current->Requirements[I];
+ return false;
+ }
+ }
+ if (!Current->MissingHeaders.empty()) {
+ MissingHeader = Current->MissingHeaders.front();
+ return false;
+ }
+ }
+
+ llvm_unreachable("could not find a reason why module is unavailable");
+}
+
+bool Module::isSubModuleOf(const Module *Other) const {
+ const Module *This = this;
+ do {
+ if (This == Other)
+ return true;
+
+ This = This->Parent;
+ } while (This);
+
+ return false;
+}
+
+const Module *Module::getTopLevelModule() const {
+ const Module *Result = this;
+ while (Result->Parent)
+ Result = Result->Parent;
+
+ return Result;
+}
+
+static StringRef getModuleNameFromComponent(
+ const std::pair<std::string, SourceLocation> &IdComponent) {
+ return IdComponent.first;
+}
+
+static StringRef getModuleNameFromComponent(StringRef R) { return R; }
+
+template<typename InputIter>
+static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End,
+ bool AllowStringLiterals = true) {
+ for (InputIter It = Begin; It != End; ++It) {
+ if (It != Begin)
+ OS << ".";
+
+ StringRef Name = getModuleNameFromComponent(*It);
+ if (!AllowStringLiterals || isValidIdentifier(Name))
+ OS << Name;
+ else {
+ OS << '"';
+ OS.write_escaped(Name);
+ OS << '"';
+ }
+ }
+}
+
+template<typename Container>
+static void printModuleId(raw_ostream &OS, const Container &C) {
+ return printModuleId(OS, C.begin(), C.end());
+}
+
+std::string Module::getFullModuleName(bool AllowStringLiterals) const {
+ SmallVector<StringRef, 2> Names;
+
+ // Build up the set of module names (from innermost to outermost).
+ for (const Module *M = this; M; M = M->Parent)
+ Names.push_back(M->Name);
+
+ std::string Result;
+
+ llvm::raw_string_ostream Out(Result);
+ printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);
+ Out.flush();
+
+ return Result;
+}
+
+bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {
+ for (const Module *M = this; M; M = M->Parent) {
+ if (nameParts.empty() || M->Name != nameParts.back())
+ return false;
+ nameParts = nameParts.drop_back();
+ }
+ return nameParts.empty();
+}
+
+Module::DirectoryName Module::getUmbrellaDir() const {
+ if (Header U = getUmbrellaHeader())
+ return {"", U.Entry->getDir()};
+
+ return {UmbrellaAsWritten, Umbrella.dyn_cast<const DirectoryEntry *>()};
+}
+
+ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) {
+ if (!TopHeaderNames.empty()) {
+ for (std::vector<std::string>::iterator
+ I = TopHeaderNames.begin(), E = TopHeaderNames.end(); I != E; ++I) {
+ if (const FileEntry *FE = FileMgr.getFile(*I))
+ TopHeaders.insert(FE);
+ }
+ TopHeaderNames.clear();
+ }
+
+ return llvm::makeArrayRef(TopHeaders.begin(), TopHeaders.end());
+}
+
+bool Module::directlyUses(const Module *Requested) const {
+ auto *Top = getTopLevelModule();
+
+ // A top-level module implicitly uses itself.
+ if (Requested->isSubModuleOf(Top))
+ return true;
+
+ for (auto *Use : Top->DirectUses)
+ if (Requested->isSubModuleOf(Use))
+ return true;
+
+ // Anyone is allowed to use our builtin stddef.h and its accompanying module.
+ if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t")
+ return true;
+
+ return false;
+}
+
+void Module::addRequirement(StringRef Feature, bool RequiredState,
+ const LangOptions &LangOpts,
+ const TargetInfo &Target) {
+ Requirements.push_back(Requirement(Feature, RequiredState));
+
+ // If this feature is currently available, we're done.
+ if (hasFeature(Feature, LangOpts, Target) == RequiredState)
+ return;
+
+ markUnavailable(/*MissingRequirement*/true);
+}
+
+void Module::markUnavailable(bool MissingRequirement) {
+ auto needUpdate = [MissingRequirement](Module *M) {
+ return M->IsAvailable || (!M->IsMissingRequirement && MissingRequirement);
+ };
+
+ if (!needUpdate(this))
+ return;
+
+ SmallVector<Module *, 2> Stack;
+ Stack.push_back(this);
+ while (!Stack.empty()) {
+ Module *Current = Stack.back();
+ Stack.pop_back();
+
+ if (!needUpdate(Current))
+ continue;
+
+ Current->IsAvailable = false;
+ Current->IsMissingRequirement |= MissingRequirement;
+ for (submodule_iterator Sub = Current->submodule_begin(),
+ SubEnd = Current->submodule_end();
+ Sub != SubEnd; ++Sub) {
+ if (needUpdate(*Sub))
+ Stack.push_back(*Sub);
+ }
+ }
+}
+
+Module *Module::findSubmodule(StringRef Name) const {
+ llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
+ if (Pos == SubModuleIndex.end())
+ return nullptr;
+
+ return SubModules[Pos->getValue()];
+}
+
+void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
+ // All non-explicit submodules are exported.
+ for (std::vector<Module *>::const_iterator I = SubModules.begin(),
+ E = SubModules.end();
+ I != E; ++I) {
+ Module *Mod = *I;
+ if (!Mod->IsExplicit)
+ Exported.push_back(Mod);
+ }
+
+ // Find re-exported modules by filtering the list of imported modules.
+ bool AnyWildcard = false;
+ bool UnrestrictedWildcard = false;
+ SmallVector<Module *, 4> WildcardRestrictions;
+ for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
+ Module *Mod = Exports[I].getPointer();
+ if (!Exports[I].getInt()) {
+ // Export a named module directly; no wildcards involved.
+ Exported.push_back(Mod);
+
+ continue;
+ }
+
+ // Wildcard export: export all of the imported modules that match
+ // the given pattern.
+ AnyWildcard = true;
+ if (UnrestrictedWildcard)
+ continue;
+
+ if (Module *Restriction = Exports[I].getPointer())
+ WildcardRestrictions.push_back(Restriction);
+ else {
+ WildcardRestrictions.clear();
+ UnrestrictedWildcard = true;
+ }
+ }
+
+ // If there were any wildcards, push any imported modules that were
+ // re-exported by the wildcard restriction.
+ if (!AnyWildcard)
+ return;
+
+ for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
+ Module *Mod = Imports[I];
+ bool Acceptable = UnrestrictedWildcard;
+ if (!Acceptable) {
+ // Check whether this module meets one of the restrictions.
+ for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
+ Module *Restriction = WildcardRestrictions[R];
+ if (Mod == Restriction || Mod->isSubModuleOf(Restriction)) {
+ Acceptable = true;
+ break;
+ }
+ }
+ }
+
+ if (!Acceptable)
+ continue;
+
+ Exported.push_back(Mod);
+ }
+}
+
+void Module::buildVisibleModulesCache() const {
+ assert(VisibleModulesCache.empty() && "cache does not need building");
+
+ // This module is visible to itself.
+ VisibleModulesCache.insert(this);
+
+ // Every imported module is visible.
+ SmallVector<Module *, 16> Stack(Imports.begin(), Imports.end());
+ while (!Stack.empty()) {
+ Module *CurrModule = Stack.pop_back_val();
+
+ // Every module transitively exported by an imported module is visible.
+ if (VisibleModulesCache.insert(CurrModule).second)
+ CurrModule->getExportedModules(Stack);
+ }
+}
+
+void Module::print(raw_ostream &OS, unsigned Indent) const {
+ OS.indent(Indent);
+ if (IsFramework)
+ OS << "framework ";
+ if (IsExplicit)
+ OS << "explicit ";
+ OS << "module ";
+ printModuleId(OS, &Name, &Name + 1);
+
+ if (IsSystem || IsExternC) {
+ OS.indent(Indent + 2);
+ if (IsSystem)
+ OS << " [system]";
+ if (IsExternC)
+ OS << " [extern_c]";
+ }
+
+ OS << " {\n";
+
+ if (!Requirements.empty()) {
+ OS.indent(Indent + 2);
+ OS << "requires ";
+ for (unsigned I = 0, N = Requirements.size(); I != N; ++I) {
+ if (I)
+ OS << ", ";
+ if (!Requirements[I].second)
+ OS << "!";
+ OS << Requirements[I].first;
+ }
+ OS << "\n";
+ }
+
+ if (Header H = getUmbrellaHeader()) {
+ OS.indent(Indent + 2);
+ OS << "umbrella header \"";
+ OS.write_escaped(H.NameAsWritten);
+ OS << "\"\n";
+ } else if (DirectoryName D = getUmbrellaDir()) {
+ OS.indent(Indent + 2);
+ OS << "umbrella \"";
+ OS.write_escaped(D.NameAsWritten);
+ OS << "\"\n";
+ }
+
+ if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {
+ OS.indent(Indent + 2);
+ OS << "config_macros ";
+ if (ConfigMacrosExhaustive)
+ OS << "[exhaustive]";
+ for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) {
+ if (I)
+ OS << ", ";
+ OS << ConfigMacros[I];
+ }
+ OS << "\n";
+ }
+
+ struct {
+ StringRef Prefix;
+ HeaderKind Kind;
+ } Kinds[] = {{"", HK_Normal},
+ {"textual ", HK_Textual},
+ {"private ", HK_Private},
+ {"private textual ", HK_PrivateTextual},
+ {"exclude ", HK_Excluded}};
+
+ for (auto &K : Kinds) {
+ assert(&K == &Kinds[K.Kind] && "kinds in wrong order");
+ for (auto &H : Headers[K.Kind]) {
+ OS.indent(Indent + 2);
+ OS << K.Prefix << "header \"";
+ OS.write_escaped(H.NameAsWritten);
+ OS << "\" { size " << H.Entry->getSize()
+ << " mtime " << H.Entry->getModificationTime() << " }\n";
+ }
+ }
+ for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) {
+ for (auto &U : *Unresolved) {
+ OS.indent(Indent + 2);
+ OS << Kinds[U.Kind].Prefix << "header \"";
+ OS.write_escaped(U.FileName);
+ OS << "\"";
+ if (U.Size || U.ModTime) {
+ OS << " {";
+ if (U.Size)
+ OS << " size " << *U.Size;
+ if (U.ModTime)
+ OS << " mtime " << *U.ModTime;
+ OS << " }";
+ }
+ OS << "\n";
+ }
+ }
+
+ if (!ExportAsModule.empty()) {
+ OS.indent(Indent + 2);
+ OS << "export_as" << ExportAsModule << "\n";
+ }
+
+ for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end();
+ MI != MIEnd; ++MI)
+ // Print inferred subframework modules so that we don't need to re-infer
+ // them (requires expensive directory iteration + stat calls) when we build
+ // the module. Regular inferred submodules are OK, as we need to look at all
+ // those header files anyway.
+ if (!(*MI)->IsInferred || (*MI)->IsFramework)
+ (*MI)->print(OS, Indent + 2);
+
+ for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "export ";
+ if (Module *Restriction = Exports[I].getPointer()) {
+ OS << Restriction->getFullModuleName(true);
+ if (Exports[I].getInt())
+ OS << ".*";
+ } else {
+ OS << "*";
+ }
+ OS << "\n";
+ }
+
+ for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "export ";
+ printModuleId(OS, UnresolvedExports[I].Id);
+ if (UnresolvedExports[I].Wildcard)
+ OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*");
+ OS << "\n";
+ }
+
+ for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "use ";
+ OS << DirectUses[I]->getFullModuleName(true);
+ OS << "\n";
+ }
+
+ for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "use ";
+ printModuleId(OS, UnresolvedDirectUses[I]);
+ OS << "\n";
+ }
+
+ for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "link ";
+ if (LinkLibraries[I].IsFramework)
+ OS << "framework ";
+ OS << "\"";
+ OS.write_escaped(LinkLibraries[I].Library);
+ OS << "\"";
+ }
+
+ for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "conflict ";
+ printModuleId(OS, UnresolvedConflicts[I].Id);
+ OS << ", \"";
+ OS.write_escaped(UnresolvedConflicts[I].Message);
+ OS << "\"\n";
+ }
+
+ for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "conflict ";
+ OS << Conflicts[I].Other->getFullModuleName(true);
+ OS << ", \"";
+ OS.write_escaped(Conflicts[I].Message);
+ OS << "\"\n";
+ }
+
+ if (InferSubmodules) {
+ OS.indent(Indent + 2);
+ if (InferExplicitSubmodules)
+ OS << "explicit ";
+ OS << "module * {\n";
+ if (InferExportWildcard) {
+ OS.indent(Indent + 4);
+ OS << "export *\n";
+ }
+ OS.indent(Indent + 2);
+ OS << "}\n";
+ }
+
+ OS.indent(Indent);
+ OS << "}\n";
+}
+
+LLVM_DUMP_METHOD void Module::dump() const {
+ print(llvm::errs());
+}
+
+void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
+ VisibleCallback Vis, ConflictCallback Cb) {
+ assert(Loc.isValid() && "setVisible expects a valid import location");
+ if (isVisible(M))
+ return;
+
+ ++Generation;
+
+ struct Visiting {
+ Module *M;
+ Visiting *ExportedBy;
+ };
+
+ std::function<void(Visiting)> VisitModule = [&](Visiting V) {
+ // Modules that aren't available cannot be made visible.
+ if (!V.M->isAvailable())
+ return;
+
+ // Nothing to do for a module that's already visible.
+ unsigned ID = V.M->getVisibilityID();
+ if (ImportLocs.size() <= ID)
+ ImportLocs.resize(ID + 1);
+ else if (ImportLocs[ID].isValid())
+ return;
+
+ ImportLocs[ID] = Loc;
+ Vis(M);
+
+ // Make any exported modules visible.
+ SmallVector<Module *, 16> Exports;
+ V.M->getExportedModules(Exports);
+ for (Module *E : Exports)
+ VisitModule({E, &V});
+
+ for (auto &C : V.M->Conflicts) {
+ if (isVisible(C.Other)) {
+ llvm::SmallVector<Module*, 8> Path;
+ for (Visiting *I = &V; I; I = I->ExportedBy)
+ Path.push_back(I->M);
+ Cb(Path, C.Other, C.Message);
+ }
+ }
+ };
+ VisitModule({M, nullptr});
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
new file mode 100644
index 000000000000..311bd067261a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
@@ -0,0 +1,98 @@
+//===- ObjCRuntime.cpp - Objective-C Runtime Handling ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ObjCRuntime class, which represents the
+// target Objective-C runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/ObjCRuntime.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <string>
+
+using namespace clang;
+
+std::string ObjCRuntime::getAsString() const {
+ std::string Result;
+ {
+ llvm::raw_string_ostream Out(Result);
+ Out << *this;
+ }
+ return Result;
+}
+
+raw_ostream &clang::operator<<(raw_ostream &out, const ObjCRuntime &value) {
+ switch (value.getKind()) {
+ case ObjCRuntime::MacOSX: out << "macosx"; break;
+ case ObjCRuntime::FragileMacOSX: out << "macosx-fragile"; break;
+ case ObjCRuntime::iOS: out << "ios"; break;
+ case ObjCRuntime::WatchOS: out << "watchos"; break;
+ case ObjCRuntime::GNUstep: out << "gnustep"; break;
+ case ObjCRuntime::GCC: out << "gcc"; break;
+ case ObjCRuntime::ObjFW: out << "objfw"; break;
+ }
+ if (value.getVersion() > VersionTuple(0)) {
+ out << '-' << value.getVersion();
+ }
+ return out;
+}
+
+bool ObjCRuntime::tryParse(StringRef input) {
+ // Look for the last dash.
+ std::size_t dash = input.rfind('-');
+
+ // We permit dashes in the runtime name, and we also permit the
+ // version to be omitted, so if we see a dash not followed by a
+ // digit then we need to ignore it.
+ if (dash != StringRef::npos && dash + 1 != input.size() &&
+ (input[dash+1] < '0' || input[dash+1] > '9')) {
+ dash = StringRef::npos;
+ }
+
+ // Everything prior to that must be a valid string name.
+ Kind kind;
+ StringRef runtimeName = input.substr(0, dash);
+ Version = VersionTuple(0);
+ if (runtimeName == "macosx") {
+ kind = ObjCRuntime::MacOSX;
+ } else if (runtimeName == "macosx-fragile") {
+ kind = ObjCRuntime::FragileMacOSX;
+ } else if (runtimeName == "ios") {
+ kind = ObjCRuntime::iOS;
+ } else if (runtimeName == "watchos") {
+ kind = ObjCRuntime::WatchOS;
+ } else if (runtimeName == "gnustep") {
+ // If no version is specified then default to the most recent one that we
+ // know about.
+ Version = VersionTuple(1, 6);
+ kind = ObjCRuntime::GNUstep;
+ } else if (runtimeName == "gcc") {
+ kind = ObjCRuntime::GCC;
+ } else if (runtimeName == "objfw") {
+ kind = ObjCRuntime::ObjFW;
+ Version = VersionTuple(0, 8);
+ } else {
+ return true;
+ }
+ TheKind = kind;
+
+ if (dash != StringRef::npos) {
+ StringRef verString = input.substr(dash + 1);
+ if (Version.tryParse(verString))
+ return true;
+ }
+
+ if (kind == ObjCRuntime::ObjFW && Version > VersionTuple(0, 8))
+ Version = VersionTuple(0, 8);
+
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
new file mode 100644
index 000000000000..67b7d91e6292
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
@@ -0,0 +1,968 @@
+//===--- OpenMPKinds.cpp - Token Kinds Support ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements the OpenMP enum and support functions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+
+using namespace clang;
+
+OpenMPDirectiveKind clang::getOpenMPDirectiveKind(StringRef Str) {
+ return llvm::StringSwitch<OpenMPDirectiveKind>(Str)
+#define OPENMP_DIRECTIVE(Name) .Case(#Name, OMPD_##Name)
+#define OPENMP_DIRECTIVE_EXT(Name, Str) .Case(Str, OMPD_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPD_unknown);
+}
+
+const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
+ assert(Kind <= OMPD_unknown);
+ switch (Kind) {
+ case OMPD_unknown:
+ return "unknown";
+#define OPENMP_DIRECTIVE(Name) \
+ case OMPD_##Name: \
+ return #Name;
+#define OPENMP_DIRECTIVE_EXT(Name, Str) \
+ case OMPD_##Name: \
+ return Str;
+#include "clang/Basic/OpenMPKinds.def"
+ break;
+ }
+ llvm_unreachable("Invalid OpenMP directive kind");
+}
+
+OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) {
+ // 'flush' clause cannot be specified explicitly, because this is an implicit
+ // clause for 'flush' directive. If the 'flush' clause is explicitly specified
+ // the Parser should generate a warning about extra tokens at the end of the
+ // directive.
+ if (Str == "flush")
+ return OMPC_unknown;
+ return llvm::StringSwitch<OpenMPClauseKind>(Str)
+#define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Case("uniform", OMPC_uniform)
+ .Default(OMPC_unknown);
+}
+
+const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) {
+ assert(Kind <= OMPC_unknown);
+ switch (Kind) {
+ case OMPC_unknown:
+ return "unknown";
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ case OMPC_uniform:
+ return "uniform";
+ case OMPC_threadprivate:
+ return "threadprivate or thread local";
+ }
+ llvm_unreachable("Invalid OpenMP clause kind");
+}
+
+unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
+ StringRef Str) {
+ switch (Kind) {
+ case OMPC_default:
+ return llvm::StringSwitch<OpenMPDefaultClauseKind>(Str)
+#define OPENMP_DEFAULT_KIND(Name) .Case(#Name, OMPC_DEFAULT_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DEFAULT_unknown);
+ case OMPC_proc_bind:
+ return llvm::StringSwitch<OpenMPProcBindClauseKind>(Str)
+#define OPENMP_PROC_BIND_KIND(Name) .Case(#Name, OMPC_PROC_BIND_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_PROC_BIND_unknown);
+ case OMPC_schedule:
+ return llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_SCHEDULE_KIND(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_##Name))
+#define OPENMP_SCHEDULE_MODIFIER(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_MODIFIER_##Name))
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_SCHEDULE_unknown);
+ case OMPC_depend:
+ return llvm::StringSwitch<OpenMPDependClauseKind>(Str)
+#define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DEPEND_unknown);
+ case OMPC_linear:
+ return llvm::StringSwitch<OpenMPLinearClauseKind>(Str)
+#define OPENMP_LINEAR_KIND(Name) .Case(#Name, OMPC_LINEAR_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_LINEAR_unknown);
+ case OMPC_map:
+ return llvm::StringSwitch<OpenMPMapClauseKind>(Str)
+#define OPENMP_MAP_KIND(Name) .Case(#Name, OMPC_MAP_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_MAP_unknown);
+ case OMPC_dist_schedule:
+ return llvm::StringSwitch<OpenMPDistScheduleClauseKind>(Str)
+#define OPENMP_DIST_SCHEDULE_KIND(Name) .Case(#Name, OMPC_DIST_SCHEDULE_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DIST_SCHEDULE_unknown);
+ case OMPC_defaultmap:
+ return llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_DEFAULTMAP_KIND(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_##Name))
+#define OPENMP_DEFAULTMAP_MODIFIER(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_MODIFIER_##Name))
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DEFAULTMAP_unknown);
+ case OMPC_unknown:
+ case OMPC_threadprivate:
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_simdlen:
+ case OMPC_collapse:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_lastprivate:
+ case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_task_reduction:
+ case OMPC_in_reduction:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
+ case OMPC_flush:
+ case OMPC_read:
+ case OMPC_write:
+ case OMPC_update:
+ case OMPC_capture:
+ case OMPC_seq_cst:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
+ case OMPC_uniform:
+ case OMPC_to:
+ case OMPC_from:
+ case OMPC_use_device_ptr:
+ case OMPC_is_device_ptr:
+ break;
+ }
+ llvm_unreachable("Invalid OpenMP simple clause kind");
+}
+
+const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
+ unsigned Type) {
+ switch (Kind) {
+ case OMPC_default:
+ switch (Type) {
+ case OMPC_DEFAULT_unknown:
+ return "unknown";
+#define OPENMP_DEFAULT_KIND(Name) \
+ case OMPC_DEFAULT_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'default' clause type");
+ case OMPC_proc_bind:
+ switch (Type) {
+ case OMPC_PROC_BIND_unknown:
+ return "unknown";
+#define OPENMP_PROC_BIND_KIND(Name) \
+ case OMPC_PROC_BIND_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'proc_bind' clause type");
+ case OMPC_schedule:
+ switch (Type) {
+ case OMPC_SCHEDULE_unknown:
+ case OMPC_SCHEDULE_MODIFIER_last:
+ return "unknown";
+#define OPENMP_SCHEDULE_KIND(Name) \
+ case OMPC_SCHEDULE_##Name: \
+ return #Name;
+#define OPENMP_SCHEDULE_MODIFIER(Name) \
+ case OMPC_SCHEDULE_MODIFIER_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'schedule' clause type");
+ case OMPC_depend:
+ switch (Type) {
+ case OMPC_DEPEND_unknown:
+ return "unknown";
+#define OPENMP_DEPEND_KIND(Name) \
+ case OMPC_DEPEND_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'depend' clause type");
+ case OMPC_linear:
+ switch (Type) {
+ case OMPC_LINEAR_unknown:
+ return "unknown";
+#define OPENMP_LINEAR_KIND(Name) \
+ case OMPC_LINEAR_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'linear' clause type");
+ case OMPC_map:
+ switch (Type) {
+ case OMPC_MAP_unknown:
+ return "unknown";
+#define OPENMP_MAP_KIND(Name) \
+ case OMPC_MAP_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ llvm_unreachable("Invalid OpenMP 'map' clause type");
+ case OMPC_dist_schedule:
+ switch (Type) {
+ case OMPC_DIST_SCHEDULE_unknown:
+ return "unknown";
+#define OPENMP_DIST_SCHEDULE_KIND(Name) \
+ case OMPC_DIST_SCHEDULE_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'dist_schedule' clause type");
+ case OMPC_defaultmap:
+ switch (Type) {
+ case OMPC_DEFAULTMAP_unknown:
+ case OMPC_DEFAULTMAP_MODIFIER_last:
+ return "unknown";
+#define OPENMP_DEFAULTMAP_KIND(Name) \
+ case OMPC_DEFAULTMAP_##Name: \
+ return #Name;
+#define OPENMP_DEFAULTMAP_MODIFIER(Name) \
+ case OMPC_DEFAULTMAP_MODIFIER_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'schedule' clause type");
+ case OMPC_unknown:
+ case OMPC_threadprivate:
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_simdlen:
+ case OMPC_collapse:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_lastprivate:
+ case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_task_reduction:
+ case OMPC_in_reduction:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
+ case OMPC_flush:
+ case OMPC_read:
+ case OMPC_write:
+ case OMPC_update:
+ case OMPC_capture:
+ case OMPC_seq_cst:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
+ case OMPC_uniform:
+ case OMPC_to:
+ case OMPC_from:
+ case OMPC_use_device_ptr:
+ case OMPC_is_device_ptr:
+ break;
+ }
+ llvm_unreachable("Invalid OpenMP simple clause kind");
+}
+
+bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind) {
+ assert(DKind <= OMPD_unknown);
+ assert(CKind <= OMPC_unknown);
+ switch (DKind) {
+ case OMPD_parallel:
+ switch (CKind) {
+#define OPENMP_PARALLEL_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_simd:
+ switch (CKind) {
+#define OPENMP_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_for:
+ switch (CKind) {
+#define OPENMP_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_for_simd:
+ switch (CKind) {
+#define OPENMP_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_sections:
+ switch (CKind) {
+#define OPENMP_SECTIONS_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_single:
+ switch (CKind) {
+#define OPENMP_SINGLE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_parallel_for:
+ switch (CKind) {
+#define OPENMP_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_parallel_sections:
+ switch (CKind) {
+#define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_task:
+ switch (CKind) {
+#define OPENMP_TASK_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_flush:
+ return CKind == OMPC_flush;
+ break;
+ case OMPD_atomic:
+ switch (CKind) {
+#define OPENMP_ATOMIC_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target:
+ switch (CKind) {
+#define OPENMP_TARGET_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_data:
+ switch (CKind) {
+#define OPENMP_TARGET_DATA_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_enter_data:
+ switch (CKind) {
+#define OPENMP_TARGET_ENTER_DATA_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_exit_data:
+ switch (CKind) {
+#define OPENMP_TARGET_EXIT_DATA_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_parallel:
+ switch (CKind) {
+#define OPENMP_TARGET_PARALLEL_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_parallel_for:
+ switch (CKind) {
+#define OPENMP_TARGET_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_update:
+ switch (CKind) {
+#define OPENMP_TARGET_UPDATE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams:
+ switch (CKind) {
+#define OPENMP_TEAMS_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_declare_simd:
+ break;
+ case OMPD_cancel:
+ switch (CKind) {
+#define OPENMP_CANCEL_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_ordered:
+ switch (CKind) {
+#define OPENMP_ORDERED_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_taskloop:
+ switch (CKind) {
+#define OPENMP_TASKLOOP_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_taskloop_simd:
+ switch (CKind) {
+#define OPENMP_TASKLOOP_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_critical:
+ switch (CKind) {
+#define OPENMP_CRITICAL_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_distribute:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_distribute_parallel_for:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_distribute_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_distribute_simd:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_simd:
+ switch (CKind) {
+#define OPENMP_TARGET_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute_simd:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute_parallel_for:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams_distribute:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams_distribute_parallel_for:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams_distribute_simd:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_taskgroup:
+ switch (CKind) {
+#define OPENMP_TASKGROUP_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_unknown:
+ case OMPD_threadprivate:
+ case OMPD_section:
+ case OMPD_master:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_declare_reduction:
+ break;
+ }
+ return false;
+}
+
+bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd ||
+ DKind == OMPD_parallel_for || DKind == OMPD_parallel_for_simd ||
+ DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
+ DKind == OMPD_distribute || DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_distribute_parallel_for ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_distribute_simd ||
+ DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
+ DKind == OMPD_teams_distribute ||
+ DKind == OMPD_teams_distribute_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute ||
+ DKind == OMPD_target_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_simd;
+}
+
+bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_for || DKind == OMPD_for_simd ||
+ DKind == OMPD_sections || DKind == OMPD_section ||
+ DKind == OMPD_single || DKind == OMPD_parallel_for ||
+ DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
+ DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_distribute_parallel_for ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_target_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute_parallel_for_simd;
+}
+
+bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd;
+}
+
+bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_parallel || DKind == OMPD_parallel_for ||
+ DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
+ DKind == OMPD_target_parallel || DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_distribute_parallel_for ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_target_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute_parallel_for_simd;
+}
+
+bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_target || DKind == OMPD_target_parallel ||
+ DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
+ DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
+ DKind == OMPD_target_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_simd;
+}
+
+bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_target_data || DKind == OMPD_target_enter_data ||
+ DKind == OMPD_target_exit_data || DKind == OMPD_target_update;
+}
+
+bool clang::isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_teams || DKind == OMPD_teams_distribute ||
+ DKind == OMPD_teams_distribute_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for;
+}
+
+bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
+ return isOpenMPNestingTeamsDirective(DKind) ||
+ DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
+ DKind == OMPD_target_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_simd;
+}
+
+bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_simd || DKind == OMPD_for_simd ||
+ DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop_simd ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_distribute_simd || DKind == OMPD_target_simd ||
+ DKind == OMPD_teams_distribute_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_simd ||
+ DKind == OMPD_target_parallel_for_simd;
+}
+
+bool clang::isOpenMPNestingDistributeDirective(OpenMPDirectiveKind Kind) {
+ return Kind == OMPD_distribute || Kind == OMPD_distribute_parallel_for ||
+ Kind == OMPD_distribute_parallel_for_simd ||
+ Kind == OMPD_distribute_simd;
+ // TODO add next directives.
+}
+
+bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
+ return isOpenMPNestingDistributeDirective(Kind) ||
+ Kind == OMPD_teams_distribute || Kind == OMPD_teams_distribute_simd ||
+ Kind == OMPD_teams_distribute_parallel_for_simd ||
+ Kind == OMPD_teams_distribute_parallel_for ||
+ Kind == OMPD_target_teams_distribute ||
+ Kind == OMPD_target_teams_distribute_parallel_for ||
+ Kind == OMPD_target_teams_distribute_parallel_for_simd ||
+ Kind == OMPD_target_teams_distribute_simd;
+}
+
+bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
+ return Kind == OMPC_private || Kind == OMPC_firstprivate ||
+ Kind == OMPC_lastprivate || Kind == OMPC_linear ||
+ Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
+ Kind == OMPC_in_reduction; // TODO add next clauses like 'reduction'.
+}
+
+bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
+ return Kind == OMPC_threadprivate || Kind == OMPC_copyin;
+}
+
+bool clang::isOpenMPTaskingDirective(OpenMPDirectiveKind Kind) {
+ return Kind == OMPD_task || isOpenMPTaskLoopDirective(Kind);
+}
+
+bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) {
+ return Kind == OMPD_distribute_parallel_for ||
+ Kind == OMPD_distribute_parallel_for_simd ||
+ Kind == OMPD_teams_distribute_parallel_for_simd ||
+ Kind == OMPD_teams_distribute_parallel_for ||
+ Kind == OMPD_target_teams_distribute_parallel_for ||
+ Kind == OMPD_target_teams_distribute_parallel_for_simd;
+}
+
+void clang::getOpenMPCaptureRegions(
+ SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions,
+ OpenMPDirectiveKind DKind) {
+ assert(DKind <= OMPD_unknown);
+ switch (DKind) {
+ case OMPD_parallel:
+ case OMPD_parallel_for:
+ case OMPD_parallel_for_simd:
+ case OMPD_parallel_sections:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_parallel);
+ break;
+ case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ CaptureRegions.push_back(OMPD_task);
+ CaptureRegions.push_back(OMPD_target);
+ CaptureRegions.push_back(OMPD_teams);
+ break;
+ case OMPD_teams:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ CaptureRegions.push_back(OMPD_teams);
+ break;
+ case OMPD_target:
+ case OMPD_target_simd:
+ CaptureRegions.push_back(OMPD_task);
+ CaptureRegions.push_back(OMPD_target);
+ break;
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_teams);
+ CaptureRegions.push_back(OMPD_parallel);
+ break;
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_task);
+ CaptureRegions.push_back(OMPD_target);
+ CaptureRegions.push_back(OMPD_parallel);
+ break;
+ case OMPD_task:
+ case OMPD_target_enter_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_update:
+ CaptureRegions.push_back(OMPD_task);
+ break;
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ CaptureRegions.push_back(OMPD_taskloop);
+ break;
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_task);
+ CaptureRegions.push_back(OMPD_target);
+ CaptureRegions.push_back(OMPD_teams);
+ CaptureRegions.push_back(OMPD_parallel);
+ break;
+ case OMPD_simd:
+ case OMPD_for:
+ case OMPD_for_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskgroup:
+ case OMPD_distribute:
+ case OMPD_ordered:
+ case OMPD_atomic:
+ case OMPD_target_data:
+ case OMPD_distribute_simd:
+ CaptureRegions.push_back(OMPD_unknown);
+ break;
+ case OMPD_threadprivate:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_cancel:
+ case OMPD_flush:
+ case OMPD_declare_reduction:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ llvm_unreachable("OpenMP Directive is not allowed");
+ case OMPD_unknown:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp b/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
new file mode 100644
index 000000000000..bf805fc7deb1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
@@ -0,0 +1,78 @@
+//===--- OperatorPrecedence.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Defines and computes precedence levels for binary/ternary operators.
+///
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/OperatorPrecedence.h"
+
+namespace clang {
+
+prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator,
+ bool CPlusPlus11) {
+ switch (Kind) {
+ case tok::greater:
+ // C++ [temp.names]p3:
+ // [...] When parsing a template-argument-list, the first
+ // non-nested > is taken as the ending delimiter rather than a
+ // greater-than operator. [...]
+ if (GreaterThanIsOperator)
+ return prec::Relational;
+ return prec::Unknown;
+
+ case tok::greatergreater:
+ // C++11 [temp.names]p3:
+ //
+ // [...] Similarly, the first non-nested >> is treated as two
+ // consecutive but distinct > tokens, the first of which is
+ // taken as the end of the template-argument-list and completes
+ // the template-id. [...]
+ if (GreaterThanIsOperator || !CPlusPlus11)
+ return prec::Shift;
+ return prec::Unknown;
+
+ default: return prec::Unknown;
+ case tok::comma: return prec::Comma;
+ case tok::equal:
+ case tok::starequal:
+ case tok::slashequal:
+ case tok::percentequal:
+ case tok::plusequal:
+ case tok::minusequal:
+ case tok::lesslessequal:
+ case tok::greatergreaterequal:
+ case tok::ampequal:
+ case tok::caretequal:
+ case tok::pipeequal: return prec::Assignment;
+ case tok::question: return prec::Conditional;
+ case tok::pipepipe: return prec::LogicalOr;
+ case tok::caretcaret:
+ case tok::ampamp: return prec::LogicalAnd;
+ case tok::pipe: return prec::InclusiveOr;
+ case tok::caret: return prec::ExclusiveOr;
+ case tok::amp: return prec::And;
+ case tok::exclaimequal:
+ case tok::equalequal: return prec::Equality;
+ case tok::lessequal:
+ case tok::less:
+ case tok::greaterequal: return prec::Relational;
+ case tok::spaceship: return prec::Spaceship;
+ case tok::lessless: return prec::Shift;
+ case tok::plus:
+ case tok::minus: return prec::Additive;
+ case tok::percent:
+ case tok::slash:
+ case tok::star: return prec::Multiplicative;
+ case tok::periodstar:
+ case tok::arrowstar: return prec::PointerToMember;
+ }
+}
+
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
new file mode 100644
index 000000000000..199ded1f317a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
@@ -0,0 +1,51 @@
+//===--- SanitizerBlacklist.cpp - Blacklist for sanitizers ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided blacklist used to disable/alter instrumentation done in
+// sanitizers.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/SanitizerBlacklist.h"
+
+using namespace clang;
+
+SanitizerBlacklist::SanitizerBlacklist(
+ const std::vector<std::string> &BlacklistPaths, SourceManager &SM)
+ : SSCL(SanitizerSpecialCaseList::createOrDie(BlacklistPaths)), SM(SM) {}
+
+bool SanitizerBlacklist::isBlacklistedGlobal(SanitizerMask Mask,
+ StringRef GlobalName,
+ StringRef Category) const {
+ return SSCL->inSection(Mask, "global", GlobalName, Category);
+}
+
+bool SanitizerBlacklist::isBlacklistedType(SanitizerMask Mask,
+ StringRef MangledTypeName,
+ StringRef Category) const {
+ return SSCL->inSection(Mask, "type", MangledTypeName, Category);
+}
+
+bool SanitizerBlacklist::isBlacklistedFunction(SanitizerMask Mask,
+ StringRef FunctionName) const {
+ return SSCL->inSection(Mask, "fun", FunctionName);
+}
+
+bool SanitizerBlacklist::isBlacklistedFile(SanitizerMask Mask,
+ StringRef FileName,
+ StringRef Category) const {
+ return SSCL->inSection(Mask, "src", FileName, Category);
+}
+
+bool SanitizerBlacklist::isBlacklistedLocation(SanitizerMask Mask,
+ SourceLocation Loc,
+ StringRef Category) const {
+ return Loc.isValid() &&
+ isBlacklistedFile(Mask, SM.getFilename(SM.getFileLoc(Loc)), Category);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp b/contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp
new file mode 100644
index 000000000000..ee8feecbce65
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp
@@ -0,0 +1,64 @@
+//===--- SanitizerSpecialCaseList.cpp - SCL for sanitizers ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// An extension of SpecialCaseList to allowing querying sections by
+// SanitizerMask.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/SanitizerSpecialCaseList.h"
+
+using namespace clang;
+
+std::unique_ptr<SanitizerSpecialCaseList>
+SanitizerSpecialCaseList::create(const std::vector<std::string> &Paths,
+ std::string &Error) {
+ std::unique_ptr<clang::SanitizerSpecialCaseList> SSCL(
+ new SanitizerSpecialCaseList());
+ if (SSCL->createInternal(Paths, Error)) {
+ SSCL->createSanitizerSections();
+ return SSCL;
+ }
+ return nullptr;
+}
+
+std::unique_ptr<SanitizerSpecialCaseList>
+SanitizerSpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
+ std::string Error;
+ if (auto SSCL = create(Paths, Error))
+ return SSCL;
+ llvm::report_fatal_error(Error);
+}
+
+void SanitizerSpecialCaseList::createSanitizerSections() {
+ for (auto &S : Sections) {
+ SanitizerMask Mask = 0;
+
+#define SANITIZER(NAME, ID) \
+ if (S.SectionMatcher->match(NAME)) \
+ Mask |= SanitizerKind::ID;
+#define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID)
+
+#include "clang/Basic/Sanitizers.def"
+#undef SANITIZER
+#undef SANITIZER_GROUP
+
+ SanitizerSections.emplace_back(Mask, S.Entries);
+ }
+}
+
+bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
+ StringRef Query,
+ StringRef Category) const {
+ for (auto &S : SanitizerSections)
+ if ((S.Mask & Mask) &&
+ SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category))
+ return true;
+
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
new file mode 100644
index 000000000000..8faf17b8f22e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
@@ -0,0 +1,36 @@
+//===- Sanitizers.cpp - C Language Family Language Options ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the classes from Sanitizers.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Sanitizers.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+
+SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) {
+ SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
+#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : 0)
+#include "clang/Basic/Sanitizers.def"
+ .Default(0);
+ return ParsedKind;
+}
+
+SanitizerMask clang::expandSanitizerGroups(SanitizerMask Kinds) {
+#define SANITIZER(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ if (Kinds & SanitizerKind::ID##Group) \
+ Kinds |= SanitizerKind::ID;
+#include "clang/Basic/Sanitizers.def"
+ return Kinds;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
new file mode 100644
index 000000000000..eb916ec76fdc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
@@ -0,0 +1,199 @@
+//===- SourceLocation.cpp - Compact identifier for Source Files -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines accessor methods for the FullSourceLoc class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+#include <utility>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// PrettyStackTraceLoc
+//===----------------------------------------------------------------------===//
+
+void PrettyStackTraceLoc::print(raw_ostream &OS) const {
+ if (Loc.isValid()) {
+ Loc.print(OS, SM);
+ OS << ": ";
+ }
+ OS << Message << '\n';
+}
+
+//===----------------------------------------------------------------------===//
+// SourceLocation
+//===----------------------------------------------------------------------===//
+
+void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{
+ if (!isValid()) {
+ OS << "<invalid loc>";
+ return;
+ }
+
+ if (isFileID()) {
+ PresumedLoc PLoc = SM.getPresumedLoc(*this);
+
+ if (PLoc.isInvalid()) {
+ OS << "<invalid>";
+ return;
+ }
+ // The macro expansion and spelling pos is identical for file locs.
+ OS << PLoc.getFilename() << ':' << PLoc.getLine()
+ << ':' << PLoc.getColumn();
+ return;
+ }
+
+ SM.getExpansionLoc(*this).print(OS, SM);
+
+ OS << " <Spelling=";
+ SM.getSpellingLoc(*this).print(OS, SM);
+ OS << '>';
+}
+
+LLVM_DUMP_METHOD std::string
+SourceLocation::printToString(const SourceManager &SM) const {
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ print(OS, SM);
+ return OS.str();
+}
+
+LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const {
+ print(llvm::errs(), SM);
+}
+
+//===----------------------------------------------------------------------===//
+// FullSourceLoc
+//===----------------------------------------------------------------------===//
+
+FileID FullSourceLoc::getFileID() const {
+ assert(isValid());
+ return SrcMgr->getFileID(*this);
+}
+
+FullSourceLoc FullSourceLoc::getExpansionLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr);
+}
+
+FullSourceLoc FullSourceLoc::getSpellingLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);
+}
+
+FullSourceLoc FullSourceLoc::getFileLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
+}
+
+PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
+ if (!isValid())
+ return PresumedLoc();
+
+ return SrcMgr->getPresumedLoc(*this, UseLineDirectives);
+}
+
+bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const {
+ assert(isValid());
+ return SrcMgr->isMacroArgExpansion(*this, StartLoc);
+}
+
+FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr);
+}
+
+std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const {
+ if (!isValid())
+ return std::make_pair(FullSourceLoc(), StringRef());
+
+ std::pair<SourceLocation, StringRef> ImportLoc =
+ SrcMgr->getModuleImportLoc(*this);
+ return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr),
+ ImportLoc.second);
+}
+
+unsigned FullSourceLoc::getFileOffset() const {
+ assert(isValid());
+ return SrcMgr->getFileOffset(*this);
+}
+
+unsigned FullSourceLoc::getLineNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid);
+}
+
+unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
+}
+
+const FileEntry *FullSourceLoc::getFileEntry() const {
+ assert(isValid());
+ return SrcMgr->getFileEntryForID(getFileID());
+}
+
+unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getExpansionLineNumber(*this, Invalid);
+}
+
+unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getExpansionColumnNumber(*this, Invalid);
+}
+
+unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getSpellingLineNumber(*this, Invalid);
+}
+
+unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getSpellingColumnNumber(*this, Invalid);
+}
+
+bool FullSourceLoc::isInSystemHeader() const {
+ assert(isValid());
+ return SrcMgr->isInSystemHeader(*this);
+}
+
+bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const {
+ assert(isValid());
+ return SrcMgr->isBeforeInTranslationUnit(*this, Loc);
+}
+
+LLVM_DUMP_METHOD void FullSourceLoc::dump() const {
+ SourceLocation::dump(*SrcMgr);
+}
+
+const char *FullSourceLoc::getCharacterData(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getCharacterData(*this, Invalid);
+}
+
+StringRef FullSourceLoc::getBufferData(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer();
+}
+
+std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
+ return SrcMgr->getDecomposedLoc(*this);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
new file mode 100644
index 000000000000..efa6ad2493b2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -0,0 +1,2286 @@
+//===- SourceManager.cpp - Track and cache source files -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SourceManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Capacity.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace SrcMgr;
+using llvm::MemoryBuffer;
+
+//===----------------------------------------------------------------------===//
+// SourceManager Helper Classes
+//===----------------------------------------------------------------------===//
+
+ContentCache::~ContentCache() {
+ if (shouldFreeBuffer())
+ delete Buffer.getPointer();
+}
+
+/// getSizeBytesMapped - Returns the number of bytes actually mapped for this
+/// ContentCache. This can be 0 if the MemBuffer was not actually expanded.
+unsigned ContentCache::getSizeBytesMapped() const {
+ return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
+}
+
+/// Returns the kind of memory used to back the memory buffer for
+/// this content cache. This is used for performance analysis.
+llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const {
+ assert(Buffer.getPointer());
+
+ // Should be unreachable, but keep for sanity.
+ if (!Buffer.getPointer())
+ return llvm::MemoryBuffer::MemoryBuffer_Malloc;
+
+ llvm::MemoryBuffer *buf = Buffer.getPointer();
+ return buf->getBufferKind();
+}
+
+/// 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.
+unsigned ContentCache::getSize() const {
+ return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
+ : (unsigned) ContentsEntry->getSize();
+}
+
+void ContentCache::replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree) {
+ if (B && B == Buffer.getPointer()) {
+ assert(0 && "Replacing with the same buffer");
+ Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
+ return;
+ }
+
+ if (shouldFreeBuffer())
+ delete Buffer.getPointer();
+ Buffer.setPointer(B);
+ Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0);
+}
+
+llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
+ const SourceManager &SM,
+ SourceLocation Loc,
+ bool *Invalid) const {
+ // Lazily create the Buffer for ContentCaches that wrap files. If we already
+ // computed it, just return what we have.
+ if (Buffer.getPointer() || !ContentsEntry) {
+ if (Invalid)
+ *Invalid = isBufferInvalid();
+
+ return Buffer.getPointer();
+ }
+
+ bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile;
+ auto BufferOrError =
+ SM.getFileManager().getBufferForFile(ContentsEntry, isVolatile);
+
+ // If we were unable to open the file, then we are in an inconsistent
+ // situation where the content cache referenced a file which no longer
+ // exists. Most likely, we were using a stat cache with an invalid entry but
+ // the file could also have been removed during processing. Since we can't
+ // really deal with this situation, just create an empty buffer.
+ //
+ // FIXME: This is definitely not ideal, but our immediate clients can't
+ // currently handle returning a null entry here. Ideally we should detect
+ // that we are in an inconsistent situation and error out as quickly as
+ // possible.
+ if (!BufferOrError) {
+ StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
+ auto BackupBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
+ ContentsEntry->getSize(), "<invalid>");
+ char *Ptr = BackupBuffer->getBufferStart();
+ for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
+ Ptr[i] = FillStr[i % FillStr.size()];
+ Buffer.setPointer(BackupBuffer.release());
+
+ if (Diag.isDiagnosticInFlight())
+ Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
+ ContentsEntry->getName(),
+ BufferOrError.getError().message());
+ else
+ Diag.Report(Loc, diag::err_cannot_open_file)
+ << ContentsEntry->getName() << BufferOrError.getError().message();
+
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
+
+ if (Invalid) *Invalid = true;
+ return Buffer.getPointer();
+ }
+
+ Buffer.setPointer(BufferOrError->release());
+
+ // Check that the file's size is the same as in the file entry (which may
+ // have come from a stat cache).
+ if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) {
+ if (Diag.isDiagnosticInFlight())
+ Diag.SetDelayedDiagnostic(diag::err_file_modified,
+ ContentsEntry->getName());
+ else
+ Diag.Report(Loc, diag::err_file_modified)
+ << ContentsEntry->getName();
+
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
+ if (Invalid) *Invalid = true;
+ return Buffer.getPointer();
+ }
+
+ // If the buffer is valid, check to see if it has a UTF Byte Order Mark
+ // (BOM). We only support UTF-8 with and without a BOM right now. See
+ // http://en.wikipedia.org/wiki/Byte_order_mark for more information.
+ StringRef BufStr = Buffer.getPointer()->getBuffer();
+ const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr)
+ .StartsWith("\xFE\xFF", "UTF-16 (BE)")
+ .StartsWith("\xFF\xFE", "UTF-16 (LE)")
+ .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"),
+ "UTF-32 (BE)")
+ .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"),
+ "UTF-32 (LE)")
+ .StartsWith("\x2B\x2F\x76", "UTF-7")
+ .StartsWith("\xF7\x64\x4C", "UTF-1")
+ .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC")
+ .StartsWith("\x0E\xFE\xFF", "SDSU")
+ .StartsWith("\xFB\xEE\x28", "BOCU-1")
+ .StartsWith("\x84\x31\x95\x33", "GB-18030")
+ .Default(nullptr);
+
+ if (InvalidBOM) {
+ Diag.Report(Loc, diag::err_unsupported_bom)
+ << InvalidBOM << ContentsEntry->getName();
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
+ }
+
+ if (Invalid)
+ *Invalid = isBufferInvalid();
+
+ return Buffer.getPointer();
+}
+
+unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
+ auto IterBool =
+ FilenameIDs.insert(std::make_pair(Name, FilenamesByID.size()));
+ if (IterBool.second)
+ FilenamesByID.push_back(&*IterBool.first);
+ return IterBool.first->second;
+}
+
+/// Add a line note to the line table that indicates that there is a \#line or
+/// GNU line marker at the specified FID/Offset location which changes the
+/// presumed location to LineNo/FilenameID. If EntryExit is 0, then this doesn't
+/// change the presumed \#include stack. If it is 1, this is a file entry, if
+/// it is 2 then this is a file exit. FileKind specifies whether this is a
+/// system header or extern C system header.
+void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo,
+ int FilenameID, unsigned EntryExit,
+ SrcMgr::CharacteristicKind FileKind) {
+ std::vector<LineEntry> &Entries = LineEntries[FID];
+
+ // An unspecified FilenameID means use the last filename if available, or the
+ // main source file otherwise.
+ if (FilenameID == -1 && !Entries.empty())
+ FilenameID = Entries.back().FilenameID;
+
+ assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
+ "Adding line entries out of order!");
+
+ unsigned IncludeOffset = 0;
+ if (EntryExit == 0) { // No #include stack change.
+ IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset;
+ } else if (EntryExit == 1) {
+ IncludeOffset = Offset-1;
+ } 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));
+}
+
+/// 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(FileID FID,
+ unsigned Offset) {
+ const std::vector<LineEntry> &Entries = LineEntries[FID];
+ assert(!Entries.empty() && "No #line entries for this FID after all!");
+
+ // It is very common for the query to be after the last #line, check this
+ // first.
+ if (Entries.back().FileOffset <= Offset)
+ return &Entries.back();
+
+ // Do a binary search to find the maximal element that is still before Offset.
+ std::vector<LineEntry>::const_iterator I =
+ std::upper_bound(Entries.begin(), Entries.end(), Offset);
+ if (I == Entries.begin()) return nullptr;
+ return &*--I;
+}
+
+/// Add a new line entry that has already been encoded into
+/// the internal representation of the line table.
+void LineTableInfo::AddEntry(FileID FID,
+ const std::vector<LineEntry> &Entries) {
+ LineEntries[FID] = Entries;
+}
+
+/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+unsigned SourceManager::getLineTableFilenameID(StringRef Name) {
+ return getLineTable().getLineTableFilenameID(Name);
+}
+
+/// AddLineNote - Add a line note to the line table for the FileID and offset
+/// specified by Loc. If FilenameID is -1, it is considered to be
+/// unspecified.
+void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
+ int FilenameID, bool IsFileEntry,
+ bool IsFileExit,
+ SrcMgr::CharacteristicKind FileKind) {
+ std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
+
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
+ if (!Entry.isFile() || Invalid)
+ return;
+
+ const SrcMgr::FileInfo &FileInfo = Entry.getFile();
+
+ // Remember that this file has #line directives now if it doesn't already.
+ const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
+
+ (void) getLineTable();
+
+ unsigned EntryExit = 0;
+ if (IsFileEntry)
+ EntryExit = 1;
+ else if (IsFileExit)
+ EntryExit = 2;
+
+ LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
+ EntryExit, FileKind);
+}
+
+LineTableInfo &SourceManager::getLineTable() {
+ if (!LineTable)
+ LineTable = new LineTableInfo();
+ return *LineTable;
+}
+
+//===----------------------------------------------------------------------===//
+// Private 'Create' methods.
+//===----------------------------------------------------------------------===//
+
+SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
+ bool UserFilesAreVolatile)
+ : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
+ clearIDTables();
+ Diag.setSourceManager(this);
+}
+
+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.
+ for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
+ if (MemBufferInfos[i]) {
+ MemBufferInfos[i]->~ContentCache();
+ ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
+ }
+ }
+ for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
+ I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
+ if (I->second) {
+ I->second->~ContentCache();
+ ContentCacheAlloc.Deallocate(I->second);
+ }
+ }
+}
+
+void SourceManager::clearIDTables() {
+ MainFileID = FileID();
+ LocalSLocEntryTable.clear();
+ LoadedSLocEntryTable.clear();
+ SLocEntryLoaded.clear();
+ LastLineNoFileIDQuery = FileID();
+ LastLineNoContentCache = nullptr;
+ LastFileIDLookup = FileID();
+
+ if (LineTable)
+ LineTable->clear();
+
+ // Use up FileID #0 as an invalid expansion.
+ NextLocalOffset = 0;
+ CurrentLoadedOffset = MaxLoadedOffset;
+ createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
+}
+
+void SourceManager::initializeForReplay(const SourceManager &Old) {
+ assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");
+
+ auto CloneContentCache = [&](const ContentCache *Cache) -> ContentCache * {
+ auto *Clone = new (ContentCacheAlloc.Allocate<ContentCache>()) ContentCache;
+ Clone->OrigEntry = Cache->OrigEntry;
+ Clone->ContentsEntry = Cache->ContentsEntry;
+ Clone->BufferOverridden = Cache->BufferOverridden;
+ Clone->IsSystemFile = Cache->IsSystemFile;
+ Clone->IsTransient = Cache->IsTransient;
+ Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true);
+ return Clone;
+ };
+
+ // Ensure all SLocEntries are loaded from the external source.
+ for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
+ if (!Old.SLocEntryLoaded[I])
+ Old.loadSLocEntry(I, nullptr);
+
+ // Inherit any content cache data from the old source manager.
+ for (auto &FileInfo : Old.FileInfos) {
+ SrcMgr::ContentCache *&Slot = FileInfos[FileInfo.first];
+ if (Slot)
+ continue;
+ Slot = CloneContentCache(FileInfo.second);
+ }
+}
+
+/// getOrCreateContentCache - Create or return a cached ContentCache for the
+/// specified file.
+const ContentCache *
+SourceManager::getOrCreateContentCache(const FileEntry *FileEnt,
+ bool isSystemFile) {
+ 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.
+ Entry = ContentCacheAlloc.Allocate<ContentCache>();
+
+ if (OverriddenFilesInfo) {
+ // If the file contents are overridden with contents from another file,
+ // pass that file to ContentCache.
+ llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
+ overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
+ if (overI == OverriddenFilesInfo->OverriddenFiles.end())
+ new (Entry) ContentCache(FileEnt);
+ else
+ new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
+ : overI->second,
+ overI->second);
+ } else {
+ new (Entry) ContentCache(FileEnt);
+ }
+
+ Entry->IsSystemFile = isSystemFile;
+ Entry->IsTransient = FilesAreTransient;
+
+ return Entry;
+}
+
+/// Create a new ContentCache for the specified memory buffer.
+/// This does no caching.
+const ContentCache *
+SourceManager::createMemBufferContentCache(llvm::MemoryBuffer *Buffer,
+ bool DoNotFree) {
+ // Add a new ContentCache to the MemBufferInfos list and return it.
+ ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
+ new (Entry) ContentCache();
+ MemBufferInfos.push_back(Entry);
+ Entry->replaceBuffer(Buffer, DoNotFree);
+ return Entry;
+}
+
+const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index,
+ bool *Invalid) const {
+ assert(!SLocEntryLoaded[Index]);
+ if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
+ if (Invalid)
+ *Invalid = true;
+ // If the file of the SLocEntry changed we could still have loaded it.
+ if (!SLocEntryLoaded[Index]) {
+ // Try to recover; create a SLocEntry so the rest of clang can handle it.
+ LoadedSLocEntryTable[Index] = SLocEntry::get(0,
+ FileInfo::get(SourceLocation(),
+ getFakeContentCacheForRecovery(),
+ SrcMgr::C_User));
+ }
+ }
+
+ return LoadedSLocEntryTable[Index];
+}
+
+std::pair<int, unsigned>
+SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
+ unsigned TotalSize) {
+ assert(ExternalSLocEntries && "Don't have an external sloc source");
+ // Make sure we're not about to run out of source locations.
+ if (CurrentLoadedOffset - TotalSize < NextLocalOffset)
+ return std::make_pair(0, 0);
+ LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
+ SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
+ CurrentLoadedOffset -= TotalSize;
+ int ID = LoadedSLocEntryTable.size();
+ return std::make_pair(-ID - 1, CurrentLoadedOffset);
+}
+
+/// As part of recovering from missing or changed content, produce a
+/// fake, non-empty buffer.
+llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
+ if (!FakeBufferForRecovery)
+ FakeBufferForRecovery =
+ llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>");
+
+ return FakeBufferForRecovery.get();
+}
+
+/// As part of recovering from missing or changed content, produce a
+/// fake content cache.
+const SrcMgr::ContentCache *
+SourceManager::getFakeContentCacheForRecovery() const {
+ if (!FakeContentCacheForRecovery) {
+ FakeContentCacheForRecovery = llvm::make_unique<SrcMgr::ContentCache>();
+ FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(),
+ /*DoNotFree=*/true);
+ }
+ return FakeContentCacheForRecovery.get();
+}
+
+/// Returns the previous in-order FileID or an invalid FileID if there
+/// is no previous one.
+FileID SourceManager::getPreviousFileID(FileID FID) const {
+ if (FID.isInvalid())
+ return FileID();
+
+ int ID = FID.ID;
+ if (ID == -1)
+ return FileID();
+
+ if (ID > 0) {
+ if (ID-1 == 0)
+ return FileID();
+ } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
+ return FileID();
+ }
+
+ return FileID::get(ID-1);
+}
+
+/// Returns the next in-order FileID or an invalid FileID if there is
+/// no next one.
+FileID SourceManager::getNextFileID(FileID FID) const {
+ if (FID.isInvalid())
+ return FileID();
+
+ int ID = FID.ID;
+ if (ID > 0) {
+ if (unsigned(ID+1) >= local_sloc_entry_size())
+ return FileID();
+ } else if (ID+1 >= -1) {
+ return FileID();
+ }
+
+ return FileID::get(ID+1);
+}
+
+//===----------------------------------------------------------------------===//
+// Methods to create new FileID's and macro expansions.
+//===----------------------------------------------------------------------===//
+
+/// createFileID - Create a new FileID for the specified ContentCache and
+/// include position. This works regardless of whether the ContentCache
+/// corresponds to a file or some other input source.
+FileID SourceManager::createFileID(const ContentCache *File,
+ SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter,
+ int LoadedID, unsigned LoadedOffset) {
+ if (LoadedID < 0) {
+ assert(LoadedID != -1 && "Loading sentinel FileID");
+ unsigned Index = unsigned(-LoadedID) - 2;
+ assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
+ assert(!SLocEntryLoaded[Index] && "FileID already loaded");
+ LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset,
+ FileInfo::get(IncludePos, File, FileCharacter));
+ SLocEntryLoaded[Index] = true;
+ return FileID::get(LoadedID);
+ }
+ LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset,
+ FileInfo::get(IncludePos, File,
+ FileCharacter)));
+ unsigned FileSize = File->getSize();
+ assert(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
+ NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset &&
+ "Ran out of source locations!");
+ // We do a +1 here because we want a SourceLocation that means "the end of the
+ // file", e.g. for the "no newline at the end of the file" diagnostic.
+ NextLocalOffset += 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(LocalSLocEntryTable.size()-1);
+ return LastFileIDLookup = FID;
+}
+
+SourceLocation
+SourceManager::createMacroArgExpansionLoc(SourceLocation SpellingLoc,
+ SourceLocation ExpansionLoc,
+ unsigned TokLength) {
+ ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc,
+ ExpansionLoc);
+ return createExpansionLocImpl(Info, TokLength);
+}
+
+SourceLocation
+SourceManager::createExpansionLoc(SourceLocation SpellingLoc,
+ SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd,
+ unsigned TokLength,
+ bool ExpansionIsTokenRange,
+ int LoadedID,
+ unsigned LoadedOffset) {
+ ExpansionInfo Info = ExpansionInfo::create(
+ SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
+ return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
+}
+
+SourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling,
+ SourceLocation TokenStart,
+ SourceLocation TokenEnd) {
+ assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
+ "token spans multiple files");
+ return createExpansionLocImpl(
+ ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
+ TokenEnd.getOffset() - TokenStart.getOffset());
+}
+
+SourceLocation
+SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
+ unsigned TokLength,
+ int LoadedID,
+ unsigned LoadedOffset) {
+ if (LoadedID < 0) {
+ assert(LoadedID != -1 && "Loading sentinel FileID");
+ unsigned Index = unsigned(-LoadedID) - 2;
+ assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
+ assert(!SLocEntryLoaded[Index] && "FileID already loaded");
+ LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
+ SLocEntryLoaded[Index] = true;
+ return SourceLocation::getMacroLoc(LoadedOffset);
+ }
+ LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
+ assert(NextLocalOffset + TokLength + 1 > NextLocalOffset &&
+ NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset &&
+ "Ran out of source locations!");
+ // See createFileID for that +1.
+ NextLocalOffset += TokLength + 1;
+ return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1));
+}
+
+llvm::MemoryBuffer *SourceManager::getMemoryBufferForFile(const FileEntry *File,
+ bool *Invalid) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
+ return IR->getBuffer(Diag, *this, SourceLocation(), Invalid);
+}
+
+void SourceManager::overrideFileContents(const FileEntry *SourceFile,
+ llvm::MemoryBuffer *Buffer,
+ bool DoNotFree) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
+
+ const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
+ const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true;
+
+ getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
+}
+
+void SourceManager::overrideFileContents(const FileEntry *SourceFile,
+ const FileEntry *NewFile) {
+ assert(SourceFile->getSize() == NewFile->getSize() &&
+ "Different sizes, use the FileManager to create a virtual file with "
+ "the correct size");
+ assert(FileInfos.count(SourceFile) == 0 &&
+ "This function should be called at the initialization stage, before "
+ "any parsing occurs.");
+ getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile;
+}
+
+void SourceManager::disableFileContentsOverride(const FileEntry *File) {
+ if (!isFileOverridden(File))
+ return;
+
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
+ const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(nullptr);
+ const_cast<SrcMgr::ContentCache *>(IR)->ContentsEntry = IR->OrigEntry;
+
+ assert(OverriddenFilesInfo);
+ OverriddenFilesInfo->OverriddenFiles.erase(File);
+ OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File);
+}
+
+void SourceManager::setFileIsTransient(const FileEntry *File) {
+ const SrcMgr::ContentCache *CC = getOrCreateContentCache(File);
+ const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true;
+}
+
+StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
+ bool MyInvalid = false;
+ const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid);
+ if (!SLoc.isFile() || MyInvalid) {
+ if (Invalid)
+ *Invalid = true;
+ return "<<<<<INVALID SOURCE LOCATION>>>>>";
+ }
+
+ llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer(
+ Diag, *this, SourceLocation(), &MyInvalid);
+ if (Invalid)
+ *Invalid = MyInvalid;
+
+ if (MyInvalid)
+ return "<<<<<INVALID SOURCE LOCATION>>>>>";
+
+ return Buf->getBuffer();
+}
+
+//===----------------------------------------------------------------------===//
+// SourceLocation manipulation methods.
+//===----------------------------------------------------------------------===//
+
+/// Return the FileID for a SourceLocation.
+///
+/// This is the cache-miss path of getFileID. Not as hot as that function, but
+/// still very important. It is responsible for finding the entry in the
+/// SLocEntry tables that contains the specified location.
+FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
+ if (!SLocOffset)
+ return FileID::get(0);
+
+ // Now it is time to search for the correct file. See where the SLocOffset
+ // sits in the global view and consult local or loaded buffers for it.
+ if (SLocOffset < NextLocalOffset)
+ return getFileIDLocal(SLocOffset);
+ return getFileIDLoaded(SLocOffset);
+}
+
+/// Return the FileID for a SourceLocation with a low offset.
+///
+/// This function knows that the SourceLocation is in a local buffer, not a
+/// loaded one.
+FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
+ assert(SLocOffset < NextLocalOffset && "Bad function choice");
+
+ // 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 expansion location. 2) others are just
+ // completely random and may be a very long way away.
+ //
+ // 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.
+ const SrcMgr::SLocEntry *I;
+
+ if (LastFileIDLookup.ID < 0 ||
+ LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
+ // Neither loc prunes our search.
+ I = LocalSLocEntryTable.end();
+ } else {
+ // Perhaps it is near the file point.
+ I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID;
+ }
+
+ // Find the FileID that contains this. "I" is an iterator that points to a
+ // FileID whose offset is known to be larger than SLocOffset.
+ unsigned NumProbes = 0;
+ while (true) {
+ --I;
+ if (I->getOffset() <= SLocOffset) {
+ FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin()));
+
+ // If this isn't an expansion, remember it. We have good locality across
+ // FileID lookups.
+ if (!I->isExpansion())
+ LastFileIDLookup = Res;
+ NumLinearScans += NumProbes+1;
+ return Res;
+ }
+ 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 - LocalSLocEntryTable.begin();
+ // LessIndex - This is the lower bound of the range that we're searching.
+ // We know that the offset corresponding to the FileID is is less than
+ // SLocOffset.
+ unsigned LessIndex = 0;
+ NumProbes = 0;
+ while (true) {
+ bool Invalid = false;
+ unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
+ unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset();
+ if (Invalid)
+ return FileID::get(0);
+
+ ++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.
+ // FIXME: This could be made faster by using a function that's aware of
+ // being in the local area.
+ if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
+ FileID Res = FileID::get(MiddleIndex);
+
+ // If this isn't a macro expansion, remember it. We have good locality
+ // across FileID lookups.
+ if (!LocalSLocEntryTable[MiddleIndex].isExpansion())
+ LastFileIDLookup = Res;
+ NumBinaryProbes += NumProbes;
+ return Res;
+ }
+
+ // Otherwise, move the low-side up to the middle index.
+ LessIndex = MiddleIndex;
+ }
+}
+
+/// Return the FileID for a SourceLocation with a high offset.
+///
+/// This function knows that the SourceLocation is in a loaded buffer, not a
+/// local one.
+FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const {
+ // Sanity checking, otherwise a bug may lead to hanging in release build.
+ if (SLocOffset < CurrentLoadedOffset) {
+ assert(0 && "Invalid SLocOffset or bad function choice");
+ return FileID();
+ }
+
+ // Essentially the same as the local case, but the loaded array is sorted
+ // in the other direction.
+
+ // First do a linear scan from the last lookup position, if possible.
+ unsigned I;
+ int LastID = LastFileIDLookup.ID;
+ if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset)
+ I = 0;
+ else
+ I = (-LastID - 2) + 1;
+
+ unsigned NumProbes;
+ for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) {
+ // Make sure the entry is loaded!
+ const SrcMgr::SLocEntry &E = getLoadedSLocEntry(I);
+ if (E.getOffset() <= SLocOffset) {
+ FileID Res = FileID::get(-int(I) - 2);
+
+ if (!E.isExpansion())
+ LastFileIDLookup = Res;
+ NumLinearScans += NumProbes + 1;
+ return Res;
+ }
+ }
+
+ // Linear scan failed. Do the binary search. Note the reverse sorting of the
+ // table: GreaterIndex is the one where the offset is greater, which is
+ // actually a lower index!
+ unsigned GreaterIndex = I;
+ unsigned LessIndex = LoadedSLocEntryTable.size();
+ NumProbes = 0;
+ while (true) {
+ ++NumProbes;
+ unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
+ const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex);
+ if (E.getOffset() == 0)
+ return FileID(); // invalid entry.
+
+ ++NumProbes;
+
+ if (E.getOffset() > SLocOffset) {
+ // Sanity checking, otherwise a bug may lead to hanging in release build.
+ if (GreaterIndex == MiddleIndex) {
+ assert(0 && "binary search missed the entry");
+ return FileID();
+ }
+ GreaterIndex = MiddleIndex;
+ continue;
+ }
+
+ if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) {
+ FileID Res = FileID::get(-int(MiddleIndex) - 2);
+ if (!E.isExpansion())
+ LastFileIDLookup = Res;
+ NumBinaryProbes += NumProbes;
+ return Res;
+ }
+
+ // Sanity checking, otherwise a bug may lead to hanging in release build.
+ if (LessIndex == MiddleIndex) {
+ assert(0 && "binary search missed the entry");
+ return FileID();
+ }
+ LessIndex = MiddleIndex;
+ }
+}
+
+SourceLocation SourceManager::
+getExpansionLocSlowCase(SourceLocation Loc) const {
+ do {
+ // Note: If Loc indicates an offset into a token that came from a macro
+ // expansion (e.g. the 5th character of the token) we do not want to add
+ // this offset when going to the expansion location. The expansion
+ // location is the macro invocation, which the offset has nothing to do
+ // with. This is unlike when we get the spelling loc, because the offset
+ // directly correspond to the token whose spelling we're inspecting.
+ Loc = getSLocEntry(getFileID(Loc)).getExpansion().getExpansionLocStart();
+ } while (!Loc.isFileID());
+
+ return Loc;
+}
+
+SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
+ do {
+ std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
+ Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
+ Loc = Loc.getLocWithOffset(LocInfo.second);
+ } while (!Loc.isFileID());
+ return Loc;
+}
+
+SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
+ do {
+ if (isMacroArgExpansion(Loc))
+ Loc = getImmediateSpellingLoc(Loc);
+ else
+ Loc = getImmediateExpansionRange(Loc).getBegin();
+ } while (!Loc.isFileID());
+ return Loc;
+}
+
+
+std::pair<FileID, unsigned>
+SourceManager::getDecomposedExpansionLocSlowCase(
+ const SrcMgr::SLocEntry *E) const {
+ // If this is an expansion record, walk through all the expansion points.
+ FileID FID;
+ SourceLocation Loc;
+ unsigned Offset;
+ do {
+ Loc = E->getExpansion().getExpansionLocStart();
+
+ FID = getFileID(Loc);
+ E = &getSLocEntry(FID);
+ Offset = Loc.getOffset()-E->getOffset();
+ } while (!Loc.isFileID());
+
+ return std::make_pair(FID, Offset);
+}
+
+std::pair<FileID, unsigned>
+SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const {
+ // If this is an expansion record, walk through all the expansion points.
+ FileID FID;
+ SourceLocation Loc;
+ do {
+ Loc = E->getExpansion().getSpellingLoc();
+ Loc = Loc.getLocWithOffset(Offset);
+
+ FID = getFileID(Loc);
+ E = &getSLocEntry(FID);
+ Offset = Loc.getOffset()-E->getOffset();
+ } while (!Loc.isFileID());
+
+ return std::make_pair(FID, Offset);
+}
+
+/// getImmediateSpellingLoc - Given a SourceLocation object, return the
+/// spelling location referenced by the ID. This is the first level down
+/// towards the place where the characters that make up the lexed token can be
+/// found. This should not generally be used by clients.
+SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
+ if (Loc.isFileID()) return Loc;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
+ Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
+ return Loc.getLocWithOffset(LocInfo.second);
+}
+
+/// getImmediateExpansionRange - Loc is required to be an expansion location.
+/// Return the start/end of the expansion information.
+CharSourceRange
+SourceManager::getImmediateExpansionRange(SourceLocation Loc) const {
+ assert(Loc.isMacroID() && "Not a macro expansion loc!");
+ const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
+ return Expansion.getExpansionLocRange();
+}
+
+SourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const {
+ while (isMacroArgExpansion(Loc))
+ Loc = getImmediateSpellingLoc(Loc);
+ return Loc;
+}
+
+/// getExpansionRange - Given a SourceLocation object, return the range of
+/// tokens covered by the expansion in the ultimate file.
+CharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const {
+ if (Loc.isFileID())
+ return CharSourceRange(SourceRange(Loc, Loc), true);
+
+ CharSourceRange Res = getImmediateExpansionRange(Loc);
+
+ // Fully resolve the start and end locations to their ultimate expansion
+ // points.
+ while (!Res.getBegin().isFileID())
+ Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin());
+ while (!Res.getEnd().isFileID()) {
+ CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd());
+ Res.setEnd(EndRange.getEnd());
+ Res.setTokenRange(EndRange.isTokenRange());
+ }
+ return Res;
+}
+
+bool SourceManager::isMacroArgExpansion(SourceLocation Loc,
+ SourceLocation *StartLoc) const {
+ if (!Loc.isMacroID()) return false;
+
+ FileID FID = getFileID(Loc);
+ const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
+ if (!Expansion.isMacroArgExpansion()) return false;
+
+ if (StartLoc)
+ *StartLoc = Expansion.getExpansionLocStart();
+ return true;
+}
+
+bool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const {
+ if (!Loc.isMacroID()) return false;
+
+ FileID FID = getFileID(Loc);
+ const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
+ return Expansion.isMacroBodyExpansion();
+}
+
+bool SourceManager::isAtStartOfImmediateMacroExpansion(SourceLocation Loc,
+ SourceLocation *MacroBegin) const {
+ assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
+
+ std::pair<FileID, unsigned> DecompLoc = getDecomposedLoc(Loc);
+ if (DecompLoc.second > 0)
+ return false; // Does not point at the start of expansion range.
+
+ bool Invalid = false;
+ const SrcMgr::ExpansionInfo &ExpInfo =
+ getSLocEntry(DecompLoc.first, &Invalid).getExpansion();
+ if (Invalid)
+ return false;
+ SourceLocation ExpLoc = ExpInfo.getExpansionLocStart();
+
+ if (ExpInfo.isMacroArgExpansion()) {
+ // For macro argument expansions, check if the previous FileID is part of
+ // the same argument expansion, in which case this Loc is not at the
+ // beginning of the expansion.
+ FileID PrevFID = getPreviousFileID(DecompLoc.first);
+ if (!PrevFID.isInvalid()) {
+ const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid);
+ if (Invalid)
+ return false;
+ if (PrevEntry.isExpansion() &&
+ PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc)
+ return false;
+ }
+ }
+
+ if (MacroBegin)
+ *MacroBegin = ExpLoc;
+ return true;
+}
+
+bool SourceManager::isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
+ SourceLocation *MacroEnd) const {
+ assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
+
+ FileID FID = getFileID(Loc);
+ SourceLocation NextLoc = Loc.getLocWithOffset(1);
+ if (isInFileID(NextLoc, FID))
+ return false; // Does not point at the end of expansion range.
+
+ bool Invalid = false;
+ const SrcMgr::ExpansionInfo &ExpInfo =
+ getSLocEntry(FID, &Invalid).getExpansion();
+ if (Invalid)
+ return false;
+
+ if (ExpInfo.isMacroArgExpansion()) {
+ // For macro argument expansions, check if the next FileID is part of the
+ // same argument expansion, in which case this Loc is not at the end of the
+ // expansion.
+ FileID NextFID = getNextFileID(FID);
+ if (!NextFID.isInvalid()) {
+ const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid);
+ if (Invalid)
+ return false;
+ if (NextEntry.isExpansion() &&
+ NextEntry.getExpansion().getExpansionLocStart() ==
+ ExpInfo.getExpansionLocStart())
+ return false;
+ }
+ }
+
+ if (MacroEnd)
+ *MacroEnd = ExpInfo.getExpansionLocEnd();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Queries about the code at a SourceLocation.
+//===----------------------------------------------------------------------===//
+
+/// getCharacterData - Return a pointer to the start of the specified location
+/// in the appropriate MemoryBuffer.
+const char *SourceManager::getCharacterData(SourceLocation SL,
+ bool *Invalid) 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.
+ bool CharDataInvalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
+ if (CharDataInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+
+ return "<<<<INVALID BUFFER>>>>";
+ }
+ llvm::MemoryBuffer *Buffer = Entry.getFile().getContentCache()->getBuffer(
+ Diag, *this, SourceLocation(), &CharDataInvalid);
+ if (Invalid)
+ *Invalid = CharDataInvalid;
+ return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
+}
+
+/// getColumnNumber - Return the column # for the specified file position.
+/// this is significantly cheaper to compute than the line number.
+unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
+ bool *Invalid) const {
+ bool MyInvalid = false;
+ llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid);
+ if (Invalid)
+ *Invalid = MyInvalid;
+
+ if (MyInvalid)
+ return 1;
+
+ // It is okay to request a position just past the end of the buffer.
+ if (FilePos > MemBuf->getBufferSize()) {
+ if (Invalid)
+ *Invalid = true;
+ return 1;
+ }
+
+ const char *Buf = MemBuf->getBufferStart();
+ // See if we just calculated the line number for this FilePos and can use
+ // that to lookup the start of the line instead of searching for it.
+ if (LastLineNoFileIDQuery == FID &&
+ LastLineNoContentCache->SourceLineCache != nullptr &&
+ LastLineNoResult < LastLineNoContentCache->NumLines) {
+ unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache;
+ unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
+ unsigned LineEnd = SourceLineCache[LastLineNoResult];
+ if (FilePos >= LineStart && FilePos < LineEnd) {
+ // LineEnd is the LineStart of the next line.
+ // A line ends with separator LF or CR+LF on Windows.
+ // FilePos might point to the last separator,
+ // but we need a column number at most 1 + the last column.
+ if (FilePos + 1 == LineEnd && FilePos > LineStart) {
+ if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
+ --FilePos;
+ }
+ return FilePos - LineStart + 1;
+ }
+ }
+
+ unsigned LineStart = FilePos;
+ while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
+ --LineStart;
+ return FilePos-LineStart+1;
+}
+
+// isInvalid - Return the result of calling loc.isInvalid(), and
+// if Invalid is not null, set its value to same.
+template<typename LocType>
+static bool isInvalid(LocType Loc, bool *Invalid) {
+ bool MyInvalid = Loc.isInvalid();
+ if (Invalid)
+ *Invalid = MyInvalid;
+ return MyInvalid;
+}
+
+unsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
+ return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
+}
+
+unsigned SourceManager::getExpansionColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
+ return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
+}
+
+unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ PresumedLoc PLoc = getPresumedLoc(Loc);
+ if (isInvalid(PLoc, Invalid)) return 0;
+ return PLoc.getColumn();
+}
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+static LLVM_ATTRIBUTE_NOINLINE void
+ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
+ llvm::BumpPtrAllocator &Alloc,
+ const SourceManager &SM, bool &Invalid);
+static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
+ llvm::BumpPtrAllocator &Alloc,
+ const SourceManager &SM, bool &Invalid) {
+ // Note that calling 'getBuffer()' may lazily page in the file.
+ MemoryBuffer *Buffer = FI->getBuffer(Diag, SM, SourceLocation(), &Invalid);
+ if (Invalid)
+ return;
+
+ // Find the file offsets of all of the *physical* source lines. This does
+ // not look at trigraphs, escaped newlines, or anything else tricky.
+ SmallVector<unsigned, 256> LineOffsets;
+
+ // Line #1 starts at char 0.
+ LineOffsets.push_back(0);
+
+ const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
+ const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
+ unsigned Offs = 0;
+ while (true) {
+ // Skip over the contents of the line.
+ const unsigned char *NextBuf = (const unsigned char *)Buf;
+
+#ifdef __SSE2__
+ // Try to skip to the next newline using SSE instructions. This is very
+ // performance sensitive for programs with lots of diagnostics and in -E
+ // mode.
+ __m128i CRs = _mm_set1_epi8('\r');
+ __m128i LFs = _mm_set1_epi8('\n');
+
+ // First fix up the alignment to 16 bytes.
+ while (((uintptr_t)NextBuf & 0xF) != 0) {
+ if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0')
+ goto FoundSpecialChar;
+ ++NextBuf;
+ }
+
+ // Scan 16 byte chunks for '\r' and '\n'. Ignore '\0'.
+ while (NextBuf+16 <= End) {
+ const __m128i Chunk = *(const __m128i*)NextBuf;
+ __m128i Cmp = _mm_or_si128(_mm_cmpeq_epi8(Chunk, CRs),
+ _mm_cmpeq_epi8(Chunk, LFs));
+ unsigned Mask = _mm_movemask_epi8(Cmp);
+
+ // If we found a newline, adjust the pointer and jump to the handling code.
+ if (Mask != 0) {
+ NextBuf += llvm::countTrailingZeros(Mask);
+ goto FoundSpecialChar;
+ }
+ NextBuf += 16;
+ }
+#endif
+
+ while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
+ ++NextBuf;
+
+#ifdef __SSE2__
+FoundSpecialChar:
+#endif
+ Offs += NextBuf-Buf;
+ Buf = NextBuf;
+
+ if (Buf[0] == '\n' || Buf[0] == '\r') {
+ // If this is \n\r or \r\n, skip both characters.
+ if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1]) {
+ ++Offs;
+ ++Buf;
+ }
+ ++Offs;
+ ++Buf;
+ LineOffsets.push_back(Offs);
+ } else {
+ // Otherwise, this is a null. If end of file, exit.
+ if (Buf == End) break;
+ // Otherwise, skip the null.
+ ++Offs;
+ ++Buf;
+ }
+ }
+
+ // Copy the offsets into the FileInfo structure.
+ FI->NumLines = LineOffsets.size();
+ FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
+ std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
+}
+
+/// getLineNumber - Given a SourceLocation, return the spelling line number
+/// for the position indicated. This requires building and caching a table of
+/// line offsets for the MemoryBuffer, so this is not cheap: use only when
+/// about to emit a diagnostic.
+unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
+ bool *Invalid) const {
+ if (FID.isInvalid()) {
+ if (Invalid)
+ *Invalid = true;
+ return 1;
+ }
+
+ ContentCache *Content;
+ if (LastLineNoFileIDQuery == FID)
+ Content = LastLineNoContentCache;
+ else {
+ bool MyInvalid = false;
+ const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
+ if (MyInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+ return 1;
+ }
+
+ Content = const_cast<ContentCache*>(Entry.getFile().getContentCache());
+ }
+
+ // If this is the first use of line information for this buffer, compute the
+ /// SourceLineCache for it on demand.
+ if (!Content->SourceLineCache) {
+ bool MyInvalid = false;
+ ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
+ if (Invalid)
+ *Invalid = MyInvalid;
+ if (MyInvalid)
+ return 1;
+ } else if (Invalid)
+ *Invalid = false;
+
+ // Okay, we know we have a line number table. Do a binary search to find the
+ // line number that this character position lands on.
+ unsigned *SourceLineCache = Content->SourceLineCache;
+ unsigned *SourceLineCacheStart = SourceLineCache;
+ unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
+
+ unsigned QueriedFilePos = 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.
+ //
+ // If it is worth being optimized, then in my opinion it could be more
+ // performant, simpler, and more obviously correct by just "galloping" outward
+ // from the queried file position. In fact, this could be incorporated into a
+ // generic algorithm such as lower_bound_with_hint.
+ //
+ // If someone gives me a test case where this matters, and I will do it! - DWD
+
+ // If the previous query was to the same file, we know both the file pos from
+ // that query and the line number returned. This allows us to narrow the
+ // search space from the entire file to something near the match.
+ if (LastLineNoFileIDQuery == FID) {
+ 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
+ // contribute no tokens.
+ if (SourceLineCache+5 < SourceLineCacheEnd) {
+ if (SourceLineCache[5] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+5;
+ else if (SourceLineCache+10 < SourceLineCacheEnd) {
+ if (SourceLineCache[10] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+10;
+ else if (SourceLineCache+20 < SourceLineCacheEnd) {
+ if (SourceLineCache[20] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+20;
+ }
+ }
+ }
+ } else {
+ if (LastLineNoResult < Content->NumLines)
+ SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
+ }
+ }
+
+ unsigned *Pos
+ = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
+ unsigned LineNo = Pos-SourceLineCacheStart;
+
+ LastLineNoFileIDQuery = FID;
+ LastLineNoContentCache = Content;
+ LastLineNoFilePos = QueriedFilePos;
+ LastLineNoResult = LineNo;
+ return LineNo;
+}
+
+unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
+ return getLineNumber(LocInfo.first, LocInfo.second);
+}
+unsigned SourceManager::getExpansionLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
+ return getLineNumber(LocInfo.first, LocInfo.second);
+}
+unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ PresumedLoc PLoc = getPresumedLoc(Loc);
+ if (isInvalid(PLoc, Invalid)) return 0;
+ return PLoc.getLine();
+}
+
+/// getFileCharacteristic - return the file characteristic of the specified
+/// 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
+SourceManager::getFileCharacteristic(SourceLocation Loc) const {
+ assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
+ std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
+ bool Invalid = false;
+ const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid);
+ if (Invalid || !SEntry.isFile())
+ return C_User;
+
+ const SrcMgr::FileInfo &FI = SEntry.getFile();
+
+ // If there are no #line directives in this file, just return the whole-file
+ // 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, LocInfo.second);
+
+ // If this is before the first line marker, use the file characteristic.
+ if (!Entry)
+ return FI.getFileCharacteristic();
+
+ return Entry->FileKind;
+}
+
+/// Return the filename or buffer identifier of the buffer the location is in.
+/// Note that this name does not respect \#line directives. Use getPresumedLoc
+/// for normal clients.
+StringRef SourceManager::getBufferName(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return "<invalid loc>";
+
+ return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier();
+}
+
+/// getPresumedLoc - This method returns the "presumed" location of a
+/// SourceLocation specifies. A "presumed location" can be modified by \#line
+/// or GNU line marker directives. This provides a view on the data that a
+/// user should see in diagnostics, for example.
+///
+/// Note that a presumed location is always given as the expansion point of an
+/// expansion location, not at the spelling location.
+PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
+ bool UseLineDirectives) const {
+ if (Loc.isInvalid()) return PresumedLoc();
+
+ // Presumed locations are always for expansion points.
+ std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
+
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return PresumedLoc();
+
+ const SrcMgr::FileInfo &FI = Entry.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.
+ StringRef Filename;
+ if (C->OrigEntry)
+ Filename = C->OrigEntry->getName();
+ else
+ Filename = C->getBuffer(Diag, *this)->getBufferIdentifier();
+
+ unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
+ if (Invalid)
+ return PresumedLoc();
+ unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
+ if (Invalid)
+ return PresumedLoc();
+
+ SourceLocation IncludeLoc = FI.getIncludeLoc();
+
+ // If we have #line directives in this file, update and overwrite the physical
+ // location info if appropriate.
+ if (UseLineDirectives && FI.hasLineDirectives()) {
+ assert(LineTable && "Can't have linetable entries without a LineTable!");
+ // See if there is a #line directive before this. If so, get it.
+ if (const LineEntry *Entry =
+ LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
+ // If the LineEntry indicates a filename, use it.
+ if (Entry->FilenameID != -1)
+ Filename = LineTable->getFilename(Entry->FilenameID);
+
+ // Use the line number specified by the LineEntry. This line number may
+ // be multiple lines down from the line entry. Add the difference in
+ // physical line numbers from the query point and the line marker to the
+ // 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);
+ IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
+ }
+ }
+ }
+
+ return PresumedLoc(Filename.data(), LineNo, ColNo, IncludeLoc);
+}
+
+/// Returns whether the PresumedLoc for a given SourceLocation is
+/// in the main file.
+///
+/// This computes the "presumed" location for a SourceLocation, then checks
+/// whether it came from a file other than the main file. This is different
+/// from isWrittenInMainFile() because it takes line marker directives into
+/// account.
+bool SourceManager::isInMainFile(SourceLocation Loc) const {
+ if (Loc.isInvalid()) return false;
+
+ // Presumed locations are always for expansion points.
+ std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
+
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return false;
+
+ const SrcMgr::FileInfo &FI = Entry.getFile();
+
+ // Check if there is a line directive for this location.
+ if (FI.hasLineDirectives())
+ if (const LineEntry *Entry =
+ LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
+ if (Entry->IncludeOffset)
+ return false;
+
+ return FI.getIncludeLoc().isInvalid();
+}
+
+/// The size of the SLocEntry that \p FID represents.
+unsigned SourceManager::getFileIDSize(FileID FID) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return 0;
+
+ int ID = FID.ID;
+ unsigned NextOffset;
+ if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))
+ NextOffset = getNextLocalOffset();
+ else if (ID+1 == -1)
+ NextOffset = MaxLoadedOffset;
+ else
+ NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
+
+ return NextOffset - Entry.getOffset() - 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Other miscellaneous methods.
+//===----------------------------------------------------------------------===//
+
+/// Retrieve the inode for the given file entry, if possible.
+///
+/// This routine involves a system call, and therefore should only be used
+/// in non-performance-critical code.
+static Optional<llvm::sys::fs::UniqueID>
+getActualFileUID(const FileEntry *File) {
+ if (!File)
+ return None;
+
+ llvm::sys::fs::UniqueID ID;
+ if (llvm::sys::fs::getUniqueID(File->getName(), ID))
+ return None;
+
+ return ID;
+}
+
+/// Get the source location for the given file:line:col triplet.
+///
+/// If the source file is included multiple times, the source location will
+/// be based upon an arbitrary inclusion.
+SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile,
+ unsigned Line,
+ unsigned Col) const {
+ assert(SourceFile && "Null source file!");
+ assert(Line && Col && "Line and column should start from 1!");
+
+ FileID FirstFID = translateFile(SourceFile);
+ return translateLineCol(FirstFID, Line, Col);
+}
+
+/// Get the FileID for the given file.
+///
+/// If the source file is included multiple times, the FileID will be the
+/// first inclusion.
+FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
+ assert(SourceFile && "Null source file!");
+
+ // Find the first file ID that corresponds to the given file.
+ FileID FirstFID;
+
+ // First, check the main file ID, since it is common to look for a
+ // location in the main file.
+ Optional<llvm::sys::fs::UniqueID> SourceFileUID;
+ Optional<StringRef> SourceFileName;
+ if (MainFileID.isValid()) {
+ bool Invalid = false;
+ const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
+ if (Invalid)
+ return FileID();
+
+ if (MainSLoc.isFile()) {
+ const ContentCache *MainContentCache
+ = MainSLoc.getFile().getContentCache();
+ if (!MainContentCache) {
+ // Can't do anything
+ } else if (MainContentCache->OrigEntry == SourceFile) {
+ FirstFID = MainFileID;
+ } else {
+ // Fall back: check whether we have the same base name and inode
+ // as the main file.
+ const FileEntry *MainFile = MainContentCache->OrigEntry;
+ SourceFileName = llvm::sys::path::filename(SourceFile->getName());
+ if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) {
+ SourceFileUID = getActualFileUID(SourceFile);
+ if (SourceFileUID) {
+ if (Optional<llvm::sys::fs::UniqueID> MainFileUID =
+ getActualFileUID(MainFile)) {
+ if (*SourceFileUID == *MainFileUID) {
+ FirstFID = MainFileID;
+ SourceFile = MainFile;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (FirstFID.isInvalid()) {
+ // The location we're looking for isn't in the main file; look
+ // through all of the local source locations.
+ for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
+ bool Invalid = false;
+ const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid);
+ if (Invalid)
+ return FileID();
+
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache() &&
+ SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
+ FirstFID = FileID::get(I);
+ break;
+ }
+ }
+ // If that still didn't help, try the modules.
+ if (FirstFID.isInvalid()) {
+ for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getLoadedSLocEntry(I);
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache() &&
+ SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
+ FirstFID = FileID::get(-int(I) - 2);
+ break;
+ }
+ }
+ }
+ }
+
+ // If we haven't found what we want yet, try again, but this time stat()
+ // each of the files in case the files have changed since we originally
+ // parsed the file.
+ if (FirstFID.isInvalid() &&
+ (SourceFileName ||
+ (SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) &&
+ (SourceFileUID || (SourceFileUID = getActualFileUID(SourceFile)))) {
+ bool Invalid = false;
+ for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
+ FileID IFileID;
+ IFileID.ID = I;
+ const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid);
+ if (Invalid)
+ return FileID();
+
+ if (SLoc.isFile()) {
+ const ContentCache *FileContentCache
+ = SLoc.getFile().getContentCache();
+ const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry
+ : nullptr;
+ if (Entry &&
+ *SourceFileName == llvm::sys::path::filename(Entry->getName())) {
+ if (Optional<llvm::sys::fs::UniqueID> EntryUID =
+ getActualFileUID(Entry)) {
+ if (*SourceFileUID == *EntryUID) {
+ FirstFID = FileID::get(I);
+ SourceFile = Entry;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ (void) SourceFile;
+ return FirstFID;
+}
+
+/// Get the source location in \arg FID for the given line:col.
+/// Returns null location if \arg FID is not a file SLocEntry.
+SourceLocation SourceManager::translateLineCol(FileID FID,
+ unsigned Line,
+ unsigned Col) const {
+ // Lines are used as a one-based index into a zero-based array. This assert
+ // checks for possible buffer underruns.
+ assert(Line && Col && "Line and column should start from 1!");
+
+ if (FID.isInvalid())
+ return SourceLocation();
+
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return SourceLocation();
+
+ if (!Entry.isFile())
+ return SourceLocation();
+
+ SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset());
+
+ if (Line == 1 && Col == 1)
+ return FileLoc;
+
+ ContentCache *Content
+ = const_cast<ContentCache *>(Entry.getFile().getContentCache());
+ if (!Content)
+ return SourceLocation();
+
+ // If this is the first use of line information for this buffer, compute the
+ // SourceLineCache for it on demand.
+ if (!Content->SourceLineCache) {
+ bool MyInvalid = false;
+ ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
+ if (MyInvalid)
+ return SourceLocation();
+ }
+
+ if (Line > Content->NumLines) {
+ unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize();
+ if (Size > 0)
+ --Size;
+ return FileLoc.getLocWithOffset(Size);
+ }
+
+ llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *this);
+ unsigned FilePos = Content->SourceLineCache[Line - 1];
+ const char *Buf = Buffer->getBufferStart() + FilePos;
+ unsigned BufLength = Buffer->getBufferSize() - FilePos;
+ if (BufLength == 0)
+ return FileLoc.getLocWithOffset(FilePos);
+
+ unsigned i = 0;
+
+ // Check that the given column is valid.
+ while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
+ ++i;
+ return FileLoc.getLocWithOffset(FilePos + i);
+}
+
+/// Compute a map of macro argument chunks to their expanded source
+/// location. Chunks that are not part of a macro argument will map to an
+/// invalid source location. e.g. if a file contains one macro argument at
+/// offset 100 with length 10, this is how the map will be formed:
+/// 0 -> SourceLocation()
+/// 100 -> Expanded macro arg location
+/// 110 -> SourceLocation()
+void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
+ FileID FID) const {
+ assert(FID.isValid());
+
+ // Initially no macro argument chunk is present.
+ MacroArgsCache.insert(std::make_pair(0, SourceLocation()));
+
+ int ID = FID.ID;
+ while (true) {
+ ++ID;
+ // Stop if there are no more FileIDs to check.
+ if (ID > 0) {
+ if (unsigned(ID) >= local_sloc_entry_size())
+ return;
+ } else if (ID == -1) {
+ return;
+ }
+
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
+ if (Invalid)
+ return;
+ if (Entry.isFile()) {
+ SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc();
+ if (IncludeLoc.isInvalid())
+ continue;
+ if (!isInFileID(IncludeLoc, FID))
+ return; // No more files/macros that may be "contained" in this file.
+
+ // Skip the files/macros of the #include'd file, we only care about macros
+ // that lexed macro arguments from our file.
+ if (Entry.getFile().NumCreatedFIDs)
+ ID += Entry.getFile().NumCreatedFIDs - 1/*because of next ++ID*/;
+ continue;
+ }
+
+ const ExpansionInfo &ExpInfo = Entry.getExpansion();
+
+ if (ExpInfo.getExpansionLocStart().isFileID()) {
+ if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
+ return; // No more files/macros that may be "contained" in this file.
+ }
+
+ if (!ExpInfo.isMacroArgExpansion())
+ continue;
+
+ associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
+ ExpInfo.getSpellingLoc(),
+ SourceLocation::getMacroLoc(Entry.getOffset()),
+ getFileIDSize(FileID::get(ID)));
+ }
+}
+
+void SourceManager::associateFileChunkWithMacroArgExp(
+ MacroArgsMap &MacroArgsCache,
+ FileID FID,
+ SourceLocation SpellLoc,
+ SourceLocation ExpansionLoc,
+ unsigned ExpansionLength) const {
+ if (!SpellLoc.isFileID()) {
+ unsigned SpellBeginOffs = SpellLoc.getOffset();
+ unsigned SpellEndOffs = SpellBeginOffs + ExpansionLength;
+
+ // The spelling range for this macro argument expansion can span multiple
+ // consecutive FileID entries. Go through each entry contained in the
+ // spelling range and if one is itself a macro argument expansion, recurse
+ // and associate the file chunk that it represents.
+
+ FileID SpellFID; // Current FileID in the spelling range.
+ unsigned SpellRelativeOffs;
+ std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
+ while (true) {
+ const SLocEntry &Entry = getSLocEntry(SpellFID);
+ unsigned SpellFIDBeginOffs = Entry.getOffset();
+ unsigned SpellFIDSize = getFileIDSize(SpellFID);
+ unsigned SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
+ const ExpansionInfo &Info = Entry.getExpansion();
+ if (Info.isMacroArgExpansion()) {
+ unsigned CurrSpellLength;
+ if (SpellFIDEndOffs < SpellEndOffs)
+ CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
+ else
+ CurrSpellLength = ExpansionLength;
+ associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
+ Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs),
+ ExpansionLoc, CurrSpellLength);
+ }
+
+ if (SpellFIDEndOffs >= SpellEndOffs)
+ return; // we covered all FileID entries in the spelling range.
+
+ // Move to the next FileID entry in the spelling range.
+ unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
+ ExpansionLoc = ExpansionLoc.getLocWithOffset(advance);
+ ExpansionLength -= advance;
+ ++SpellFID.ID;
+ SpellRelativeOffs = 0;
+ }
+ }
+
+ assert(SpellLoc.isFileID());
+
+ unsigned BeginOffs;
+ if (!isInFileID(SpellLoc, FID, &BeginOffs))
+ return;
+
+ unsigned EndOffs = BeginOffs + ExpansionLength;
+
+ // Add a new chunk for this macro argument. A previous macro argument chunk
+ // may have been lexed again, so e.g. if the map is
+ // 0 -> SourceLocation()
+ // 100 -> Expanded loc #1
+ // 110 -> SourceLocation()
+ // and we found a new macro FileID that lexed from offset 105 with length 3,
+ // the new map will be:
+ // 0 -> SourceLocation()
+ // 100 -> Expanded loc #1
+ // 105 -> Expanded loc #2
+ // 108 -> Expanded loc #1
+ // 110 -> SourceLocation()
+ //
+ // Since re-lexed macro chunks will always be the same size or less of
+ // previous chunks, we only need to find where the ending of the new macro
+ // chunk is mapped to and update the map with new begin/end mappings.
+
+ MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
+ --I;
+ SourceLocation EndOffsMappedLoc = I->second;
+ MacroArgsCache[BeginOffs] = ExpansionLoc;
+ MacroArgsCache[EndOffs] = EndOffsMappedLoc;
+}
+
+/// If \arg Loc points inside a function macro argument, the returned
+/// location will be the macro location in which the argument was expanded.
+/// If a macro argument is used multiple times, the expanded location will
+/// be at the first expansion of the argument.
+/// e.g.
+/// MY_MACRO(foo);
+/// ^
+/// Passing a file location pointing at 'foo', will yield a macro location
+/// where 'foo' was expanded into.
+SourceLocation
+SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
+ if (Loc.isInvalid() || !Loc.isFileID())
+ return Loc;
+
+ FileID FID;
+ unsigned Offset;
+ std::tie(FID, Offset) = getDecomposedLoc(Loc);
+ if (FID.isInvalid())
+ return Loc;
+
+ std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
+ if (!MacroArgsCache) {
+ MacroArgsCache = llvm::make_unique<MacroArgsMap>();
+ computeMacroArgsCache(*MacroArgsCache, FID);
+ }
+
+ assert(!MacroArgsCache->empty());
+ MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
+ --I;
+
+ unsigned MacroArgBeginOffs = I->first;
+ SourceLocation MacroArgExpandedLoc = I->second;
+ if (MacroArgExpandedLoc.isValid())
+ return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
+
+ return Loc;
+}
+
+std::pair<FileID, unsigned>
+SourceManager::getDecomposedIncludedLoc(FileID FID) const {
+ if (FID.isInvalid())
+ return std::make_pair(FileID(), 0);
+
+ // Uses IncludedLocMap to retrieve/cache the decomposed loc.
+
+ using DecompTy = std::pair<FileID, unsigned>;
+ using MapTy = llvm::DenseMap<FileID, DecompTy>;
+ std::pair<MapTy::iterator, bool>
+ InsertOp = IncludedLocMap.insert(std::make_pair(FID, DecompTy()));
+ DecompTy &DecompLoc = InsertOp.first->second;
+ if (!InsertOp.second)
+ return DecompLoc; // already in map.
+
+ SourceLocation UpperLoc;
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (!Invalid) {
+ if (Entry.isExpansion())
+ UpperLoc = Entry.getExpansion().getExpansionLocStart();
+ else
+ UpperLoc = Entry.getFile().getIncludeLoc();
+ }
+
+ if (UpperLoc.isValid())
+ DecompLoc = getDecomposedLoc(UpperLoc);
+
+ return DecompLoc;
+}
+
+/// Given a decomposed source location, move it up the include/expansion stack
+/// to the parent source location. If this is possible, return the decomposed
+/// version of the parent in Loc and return false. If Loc is the top-level
+/// entry, return true and don't modify it.
+static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
+ const SourceManager &SM) {
+ std::pair<FileID, unsigned> UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
+ if (UpperLoc.first.isInvalid())
+ return true; // We reached the top.
+
+ Loc = UpperLoc;
+ return false;
+}
+
+/// Return the cache entry for comparing the given file IDs
+/// for isBeforeInTranslationUnit.
+InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
+ FileID RFID) const {
+ // This is a magic number for limiting the cache size. It was experimentally
+ // derived from a small Objective-C project (where the cache filled
+ // out to ~250 items). We can make it larger if necessary.
+ enum { MagicCacheSize = 300 };
+ IsBeforeInTUCacheKey Key(LFID, RFID);
+
+ // If the cache size isn't too large, do a lookup and if necessary default
+ // construct an entry. We can then return it to the caller for direct
+ // use. When they update the value, the cache will get automatically
+ // updated as well.
+ if (IBTUCache.size() < MagicCacheSize)
+ return IBTUCache[Key];
+
+ // Otherwise, do a lookup that will not construct a new value.
+ InBeforeInTUCache::iterator I = IBTUCache.find(Key);
+ if (I != IBTUCache.end())
+ return I->second;
+
+ // Fall back to the overflow value.
+ return IBTUCacheOverflow;
+}
+
+/// Determines the order of 2 source locations in the translation unit.
+///
+/// \returns true if LHS source location comes before RHS, false otherwise.
+bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
+ SourceLocation RHS) const {
+ 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);
+
+ // getDecomposedLoc may have failed to return a valid FileID because, e.g. it
+ // is a serialized one referring to a file that was removed after we loaded
+ // the PCH.
+ if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
+ return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
+
+ std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
+ if (InSameTU.first)
+ return InSameTU.second;
+
+ // If we arrived here, the location is either in a built-ins buffer or
+ // associated with global inline asm. PR5662 and PR22576 are examples.
+
+ StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier();
+ StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier();
+ bool LIsBuiltins = LB == "<built-in>";
+ bool RIsBuiltins = RB == "<built-in>";
+ // Sort built-in before non-built-in.
+ if (LIsBuiltins || RIsBuiltins) {
+ if (LIsBuiltins != RIsBuiltins)
+ return LIsBuiltins;
+ // Both are in built-in buffers, but from different files. We just claim that
+ // lower IDs come first.
+ return LOffs.first < ROffs.first;
+ }
+ bool LIsAsm = LB == "<inline asm>";
+ bool RIsAsm = RB == "<inline asm>";
+ // Sort assembler after built-ins, but before the rest.
+ if (LIsAsm || RIsAsm) {
+ if (LIsAsm != RIsAsm)
+ return RIsAsm;
+ assert(LOffs.first == ROffs.first);
+ return false;
+ }
+ bool LIsScratch = LB == "<scratch space>";
+ bool RIsScratch = RB == "<scratch space>";
+ // Sort scratch after inline asm, but before the rest.
+ if (LIsScratch || RIsScratch) {
+ if (LIsScratch != RIsScratch)
+ return LIsScratch;
+ return LOffs.second < ROffs.second;
+ }
+ llvm_unreachable("Unsortable locations found");
+}
+
+std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
+ std::pair<FileID, unsigned> &LOffs,
+ std::pair<FileID, unsigned> &ROffs) const {
+ // If the source locations are in the same file, just compare offsets.
+ if (LOffs.first == ROffs.first)
+ return std::make_pair(true, 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.
+ InBeforeInTUCacheEntry &IsBeforeInTUCache =
+ getInBeforeInTUCache(LOffs.first, ROffs.first);
+
+ // If we are comparing a source location with multiple locations in the same
+ // file, we get a big win by caching the result.
+ if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
+ return std::make_pair(
+ true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
+
+ // Okay, we missed in the cache, start updating the cache for this query.
+ IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first,
+ /*isLFIDBeforeRFID=*/LOffs.first.ID < ROffs.first.ID);
+
+ // We need to find the common ancestor. The only way of doing this is to
+ // build the complete include chain for one and then walking up the chain
+ // of the other looking for a match.
+ // We use a map from FileID to Offset to store the chain. Easier than writing
+ // a custom set hash info that only depends on the first part of a pair.
+ using LocSet = llvm::SmallDenseMap<FileID, unsigned, 16>;
+ LocSet LChain;
+ do {
+ LChain.insert(LOffs);
+ // We catch the case where LOffs is in a file included by ROffs and
+ // quit early. The other way round unfortunately remains suboptimal.
+ } while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this));
+ LocSet::iterator I;
+ while((I = LChain.find(ROffs.first)) == LChain.end()) {
+ if (MoveUpIncludeHierarchy(ROffs, *this))
+ break; // Met at topmost file.
+ }
+ if (I != LChain.end())
+ LOffs = *I;
+
+ // If we exited because we found a nearest common ancestor, compare the
+ // locations within the common file and cache them.
+ if (LOffs.first == ROffs.first) {
+ IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
+ return std::make_pair(
+ true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
+ }
+ // Clear the lookup cache, it depends on a common location.
+ IsBeforeInTUCache.clear();
+ return std::make_pair(false, false);
+}
+
+void SourceManager::PrintStats() const {
+ llvm::errs() << "\n*** Source Manager Stats:\n";
+ llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
+ << " mem buffers mapped.\n";
+ llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntry's allocated ("
+ << llvm::capacity_in_bytes(LocalSLocEntryTable)
+ << " bytes of capacity), "
+ << NextLocalOffset << "B of Sloc address space used.\n";
+ llvm::errs() << LoadedSLocEntryTable.size()
+ << " loaded SLocEntries allocated, "
+ << MaxLoadedOffset - CurrentLoadedOffset
+ << "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 != nullptr;
+ NumFileBytesMapped += I->second->getSizeBytesMapped();
+ }
+ unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
+
+ llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
+ << NumLineNumsComputed << " files with line #'s computed, "
+ << NumMacroArgsComputed << " files with macro args computed.\n";
+ llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
+ << NumBinaryProbes << " binary.\n";
+}
+
+LLVM_DUMP_METHOD void SourceManager::dump() const {
+ llvm::raw_ostream &out = llvm::errs();
+
+ auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
+ llvm::Optional<unsigned> NextStart) {
+ out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
+ << " <SourceLocation " << Entry.getOffset() << ":";
+ if (NextStart)
+ out << *NextStart << ">\n";
+ else
+ out << "???\?>\n";
+ if (Entry.isFile()) {
+ auto &FI = Entry.getFile();
+ if (FI.NumCreatedFIDs)
+ out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
+ << ">\n";
+ if (FI.getIncludeLoc().isValid())
+ out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
+ if (auto *CC = FI.getContentCache()) {
+ out << " for " << (CC->OrigEntry ? CC->OrigEntry->getName() : "<none>")
+ << "\n";
+ if (CC->BufferOverridden)
+ out << " contents overridden\n";
+ if (CC->ContentsEntry != CC->OrigEntry) {
+ out << " contents from "
+ << (CC->ContentsEntry ? CC->ContentsEntry->getName() : "<none>")
+ << "\n";
+ }
+ }
+ } else {
+ auto &EI = Entry.getExpansion();
+ out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
+ out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
+ << " range <" << EI.getExpansionLocStart().getOffset() << ":"
+ << EI.getExpansionLocEnd().getOffset() << ">\n";
+ }
+ };
+
+ // Dump local SLocEntries.
+ for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
+ DumpSLocEntry(ID, LocalSLocEntryTable[ID],
+ ID == NumIDs - 1 ? NextLocalOffset
+ : LocalSLocEntryTable[ID + 1].getOffset());
+ }
+ // Dump loaded SLocEntries.
+ llvm::Optional<unsigned> NextStart;
+ for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
+ int ID = -(int)Index - 2;
+ if (SLocEntryLoaded[Index]) {
+ DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
+ NextStart = LoadedSLocEntryTable[Index].getOffset();
+ } else {
+ NextStart = None;
+ }
+ }
+}
+
+ExternalSLocEntrySource::~ExternalSLocEntrySource() = default;
+
+/// Return the amount of memory used by memory buffers, breaking down
+/// by heap-backed versus mmap'ed memory.
+SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const {
+ size_t malloc_bytes = 0;
+ size_t mmap_bytes = 0;
+
+ for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
+ if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
+ switch (MemBufferInfos[i]->getMemoryBufferKind()) {
+ case llvm::MemoryBuffer::MemoryBuffer_MMap:
+ mmap_bytes += sized_mapped;
+ break;
+ case llvm::MemoryBuffer::MemoryBuffer_Malloc:
+ malloc_bytes += sized_mapped;
+ break;
+ }
+
+ return MemoryBufferSizes(malloc_bytes, mmap_bytes);
+}
+
+size_t SourceManager::getDataStructureSizes() const {
+ size_t size = llvm::capacity_in_bytes(MemBufferInfos)
+ + llvm::capacity_in_bytes(LocalSLocEntryTable)
+ + llvm::capacity_in_bytes(LoadedSLocEntryTable)
+ + llvm::capacity_in_bytes(SLocEntryLoaded)
+ + llvm::capacity_in_bytes(FileInfos);
+
+ if (OverriddenFilesInfo)
+ size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
+
+ return size;
+}
+
+SourceManagerForFile::SourceManagerForFile(StringRef FileName,
+ StringRef Content) {
+ // This is referenced by `FileMgr` and will be released by `FileMgr` when it
+ // is deleted.
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ InMemoryFileSystem->addFile(
+ FileName, 0,
+ llvm::MemoryBuffer::getMemBuffer(Content, FileName,
+ /*RequiresNullTerminator=*/false));
+ // This is passed to `SM` as reference, so the pointer has to be referenced
+ // in `Environment` so that `FileMgr` can out-live this function scope.
+ FileMgr =
+ llvm::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem);
+ // This is passed to `SM` as reference, so the pointer has to be referenced
+ // by `Environment` due to the same reason above.
+ Diagnostics = llvm::make_unique<DiagnosticsEngine>(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+ new DiagnosticOptions);
+ SourceMgr = llvm::make_unique<SourceManager>(*Diagnostics, *FileMgr);
+ FileID ID = SourceMgr->createFileID(FileMgr->getFile(FileName),
+ SourceLocation(), clang::SrcMgr::C_User);
+ assert(ID.isValid());
+ SourceMgr->setMainFileID(ID);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
new file mode 100644
index 000000000000..3400c8721f7a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
@@ -0,0 +1,795 @@
+//===--- TargetInfo.cpp - Information about Target machine ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TargetInfo and TargetInfoImpl interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetParser.h"
+#include <cstdlib>
+using namespace clang;
+
+static const LangASMap DefaultAddrSpaceMap = {0};
+
+// TargetInfo Constructor.
+TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
+ // Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
+ // SPARC. These should be overridden by concrete targets as needed.
+ BigEndian = !T.isLittleEndian();
+ TLSSupported = true;
+ VLASupported = true;
+ NoAsmVariants = false;
+ HasLegalHalfType = false;
+ HasFloat128 = false;
+ PointerWidth = PointerAlign = 32;
+ BoolWidth = BoolAlign = 8;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongAlign = 32;
+ LongLongWidth = LongLongAlign = 64;
+
+ // Fixed point default bit widths
+ ShortAccumWidth = ShortAccumAlign = 16;
+ AccumWidth = AccumAlign = 32;
+ LongAccumWidth = LongAccumAlign = 64;
+ ShortFractWidth = ShortFractAlign = 8;
+ FractWidth = FractAlign = 16;
+ LongFractWidth = LongFractAlign = 32;
+
+ // Fixed point default integral and fractional bit sizes
+ // We give the _Accum 1 fewer fractional bits than their corresponding _Fract
+ // types by default to have the same number of fractional bits between _Accum
+ // and _Fract types.
+ PaddingOnUnsignedFixedPoint = false;
+ ShortAccumScale = 7;
+ AccumScale = 15;
+ LongAccumScale = 31;
+
+ SuitableAlign = 64;
+ DefaultAlignForAttributeAligned = 128;
+ MinGlobalAlign = 0;
+ // From the glibc documentation, on GNU systems, malloc guarantees 16-byte
+ // alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
+ // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html
+ if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment())
+ NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
+ else
+ NewAlign = 0; // Infer from basic type alignment.
+ HalfWidth = 16;
+ HalfAlign = 16;
+ FloatWidth = 32;
+ FloatAlign = 32;
+ DoubleWidth = 64;
+ DoubleAlign = 64;
+ LongDoubleWidth = 64;
+ LongDoubleAlign = 64;
+ Float128Align = 128;
+ LargeArrayMinWidth = 0;
+ LargeArrayAlign = 0;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
+ MaxVectorAlign = 0;
+ MaxTLSAlign = 0;
+ SimdDefaultAlign = 0;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntMaxType = SignedLongLong;
+ IntPtrType = SignedLong;
+ WCharType = SignedInt;
+ WIntType = SignedInt;
+ Char16Type = UnsignedShort;
+ Char32Type = UnsignedInt;
+ Int64Type = SignedLongLong;
+ SigAtomicType = SignedInt;
+ ProcessIDType = SignedInt;
+ UseSignedCharForObjCBool = true;
+ UseBitFieldTypeAlignment = true;
+ UseZeroLengthBitfieldAlignment = false;
+ UseExplicitBitFieldAlignment = true;
+ ZeroLengthBitfieldBoundary = 0;
+ HalfFormat = &llvm::APFloat::IEEEhalf();
+ FloatFormat = &llvm::APFloat::IEEEsingle();
+ DoubleFormat = &llvm::APFloat::IEEEdouble();
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ Float128Format = &llvm::APFloat::IEEEquad();
+ MCountName = "mcount";
+ RegParmMax = 0;
+ SSERegParmMax = 0;
+ HasAlignMac68kSupport = false;
+ HasBuiltinMSVaList = false;
+ IsRenderScriptTarget = false;
+
+ // Default to no types using fpret.
+ RealTypeUsesObjCFPRet = 0;
+
+ // Default to not using fp2ret for __Complex long double
+ ComplexLongDoubleUsesFP2Ret = false;
+
+ // Set the C++ ABI based on the triple.
+ TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment()
+ ? TargetCXXABI::Microsoft
+ : TargetCXXABI::GenericItanium);
+
+ // Default to an empty address space map.
+ AddrSpaceMap = &DefaultAddrSpaceMap;
+ UseAddrSpaceMapMangling = false;
+
+ // Default to an unknown platform name.
+ PlatformName = "unknown";
+ PlatformMinVersion = VersionTuple();
+}
+
+// Out of line virtual dtor for TargetInfo.
+TargetInfo::~TargetInfo() {}
+
+bool
+TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
+ Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch";
+ return false;
+}
+
+bool
+TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const {
+ Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return";
+ return false;
+}
+
+/// getTypeName - Return the user string for the specified integer type enum.
+/// For example, SignedShort -> "short".
+const char *TargetInfo::getTypeName(IntType T) {
+ switch (T) {
+ default: llvm_unreachable("not an integer!");
+ case SignedChar: return "signed char";
+ case UnsignedChar: return "unsigned char";
+ case SignedShort: return "short";
+ case UnsignedShort: return "unsigned short";
+ case SignedInt: return "int";
+ case UnsignedInt: return "unsigned int";
+ case SignedLong: return "long int";
+ case UnsignedLong: return "long unsigned int";
+ case SignedLongLong: return "long long int";
+ case UnsignedLongLong: return "long long unsigned int";
+ }
+}
+
+/// getTypeConstantSuffix - Return the constant suffix for the specified
+/// integer type enum. For example, SignedLong -> "L".
+const char *TargetInfo::getTypeConstantSuffix(IntType T) const {
+ switch (T) {
+ default: llvm_unreachable("not an integer!");
+ case SignedChar:
+ case SignedShort:
+ case SignedInt: return "";
+ case SignedLong: return "L";
+ case SignedLongLong: return "LL";
+ case UnsignedChar:
+ if (getCharWidth() < getIntWidth())
+ return "";
+ LLVM_FALLTHROUGH;
+ case UnsignedShort:
+ if (getShortWidth() < getIntWidth())
+ return "";
+ LLVM_FALLTHROUGH;
+ case UnsignedInt: return "U";
+ case UnsignedLong: return "UL";
+ case UnsignedLongLong: return "ULL";
+ }
+}
+
+/// getTypeFormatModifier - Return the printf format modifier for the
+/// specified integer type enum. For example, SignedLong -> "l".
+
+const char *TargetInfo::getTypeFormatModifier(IntType T) {
+ switch (T) {
+ default: llvm_unreachable("not an integer!");
+ case SignedChar:
+ case UnsignedChar: return "hh";
+ case SignedShort:
+ case UnsignedShort: return "h";
+ case SignedInt:
+ case UnsignedInt: return "";
+ case SignedLong:
+ case UnsignedLong: return "l";
+ case SignedLongLong:
+ case UnsignedLongLong: return "ll";
+ }
+}
+
+/// getTypeWidth - Return the width (in bits) of the specified integer type
+/// enum. For example, SignedInt -> getIntWidth().
+unsigned TargetInfo::getTypeWidth(IntType T) const {
+ switch (T) {
+ default: llvm_unreachable("not an integer!");
+ case SignedChar:
+ case UnsignedChar: return getCharWidth();
+ case SignedShort:
+ case UnsignedShort: return getShortWidth();
+ case SignedInt:
+ case UnsignedInt: return getIntWidth();
+ case SignedLong:
+ case UnsignedLong: return getLongWidth();
+ case SignedLongLong:
+ case UnsignedLongLong: return getLongLongWidth();
+ };
+}
+
+TargetInfo::IntType TargetInfo::getIntTypeByWidth(
+ unsigned BitWidth, bool IsSigned) const {
+ if (getCharWidth() == BitWidth)
+ return IsSigned ? SignedChar : UnsignedChar;
+ if (getShortWidth() == BitWidth)
+ return IsSigned ? SignedShort : UnsignedShort;
+ if (getIntWidth() == BitWidth)
+ return IsSigned ? SignedInt : UnsignedInt;
+ if (getLongWidth() == BitWidth)
+ return IsSigned ? SignedLong : UnsignedLong;
+ if (getLongLongWidth() == BitWidth)
+ return IsSigned ? SignedLongLong : UnsignedLongLong;
+ return NoInt;
+}
+
+TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth,
+ bool IsSigned) const {
+ if (getCharWidth() >= BitWidth)
+ return IsSigned ? SignedChar : UnsignedChar;
+ if (getShortWidth() >= BitWidth)
+ return IsSigned ? SignedShort : UnsignedShort;
+ if (getIntWidth() >= BitWidth)
+ return IsSigned ? SignedInt : UnsignedInt;
+ if (getLongWidth() >= BitWidth)
+ return IsSigned ? SignedLong : UnsignedLong;
+ if (getLongLongWidth() >= BitWidth)
+ return IsSigned ? SignedLongLong : UnsignedLongLong;
+ return NoInt;
+}
+
+TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
+ if (getFloatWidth() == BitWidth)
+ return Float;
+ if (getDoubleWidth() == BitWidth)
+ return Double;
+
+ switch (BitWidth) {
+ case 96:
+ if (&getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended())
+ return LongDouble;
+ break;
+ case 128:
+ if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble() ||
+ &getLongDoubleFormat() == &llvm::APFloat::IEEEquad())
+ return LongDouble;
+ if (hasFloat128Type())
+ return Float128;
+ break;
+ }
+
+ return NoFloat;
+}
+
+/// getTypeAlign - Return the alignment (in bits) of the specified integer type
+/// enum. For example, SignedInt -> getIntAlign().
+unsigned TargetInfo::getTypeAlign(IntType T) const {
+ switch (T) {
+ default: llvm_unreachable("not an integer!");
+ case SignedChar:
+ case UnsignedChar: return getCharAlign();
+ case SignedShort:
+ case UnsignedShort: return getShortAlign();
+ case SignedInt:
+ case UnsignedInt: return getIntAlign();
+ case SignedLong:
+ case UnsignedLong: return getLongAlign();
+ case SignedLongLong:
+ case UnsignedLongLong: return getLongLongAlign();
+ };
+}
+
+/// isTypeSigned - Return whether an integer types is signed. Returns true if
+/// the type is signed; false otherwise.
+bool TargetInfo::isTypeSigned(IntType T) {
+ switch (T) {
+ default: llvm_unreachable("not an integer!");
+ case SignedChar:
+ case SignedShort:
+ case SignedInt:
+ case SignedLong:
+ case SignedLongLong:
+ return true;
+ case UnsignedChar:
+ case UnsignedShort:
+ case UnsignedInt:
+ case UnsignedLong:
+ case UnsignedLongLong:
+ return false;
+ };
+}
+
+/// adjust - Set forced language options.
+/// Apply changes to the target information with respect to certain
+/// language options which change the target configuration and adjust
+/// the language based on the target options where applicable.
+void TargetInfo::adjust(LangOptions &Opts) {
+ if (Opts.NoBitFieldTypeAlign)
+ UseBitFieldTypeAlignment = false;
+
+ switch (Opts.WCharSize) {
+ default: llvm_unreachable("invalid wchar_t width");
+ case 0: break;
+ case 1: WCharType = Opts.WCharIsSigned ? SignedChar : UnsignedChar; break;
+ case 2: WCharType = Opts.WCharIsSigned ? SignedShort : UnsignedShort; break;
+ case 4: WCharType = Opts.WCharIsSigned ? SignedInt : UnsignedInt; break;
+ }
+
+ if (Opts.AlignDouble) {
+ DoubleAlign = LongLongAlign = 64;
+ LongDoubleAlign = 64;
+ }
+
+ if (Opts.OpenCL) {
+ // OpenCL C requires specific widths for types, irrespective of
+ // what these normally are for the target.
+ // We also define long long and long double here, although the
+ // OpenCL standard only mentions these as "reserved".
+ IntWidth = IntAlign = 32;
+ LongWidth = LongAlign = 64;
+ LongLongWidth = LongLongAlign = 128;
+ HalfWidth = HalfAlign = 16;
+ FloatWidth = FloatAlign = 32;
+
+ // Embedded 32-bit targets (OpenCL EP) might have double C type
+ // defined as float. Let's not override this as it might lead
+ // to generating illegal code that uses 64bit doubles.
+ if (DoubleWidth != FloatWidth) {
+ DoubleWidth = DoubleAlign = 64;
+ DoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+ LongDoubleWidth = LongDoubleAlign = 128;
+
+ unsigned MaxPointerWidth = getMaxPointerWidth();
+ assert(MaxPointerWidth == 32 || MaxPointerWidth == 64);
+ bool Is32BitArch = MaxPointerWidth == 32;
+ SizeType = Is32BitArch ? UnsignedInt : UnsignedLong;
+ PtrDiffType = Is32BitArch ? SignedInt : SignedLong;
+ IntPtrType = Is32BitArch ? SignedInt : SignedLong;
+
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLong;
+
+ HalfFormat = &llvm::APFloat::IEEEhalf();
+ FloatFormat = &llvm::APFloat::IEEEsingle();
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ }
+
+ if (Opts.NewAlignOverride)
+ NewAlign = Opts.NewAlignOverride * getCharWidth();
+
+ // Each unsigned fixed point type has the same number of fractional bits as
+ // its corresponding signed type.
+ PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint;
+ CheckFixedPointBits();
+}
+
+bool TargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const {
+ for (const auto &F : FeatureVec) {
+ StringRef Name = F;
+ // Apply the feature via the target.
+ bool Enabled = Name[0] == '+';
+ setFeatureEnabled(Features, Name.substr(1), Enabled);
+ }
+ return true;
+}
+
+TargetInfo::CallingConvKind
+TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
+ if (getCXXABI() != TargetCXXABI::Microsoft &&
+ (ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4))
+ return CCK_ClangABI4OrPS4;
+ return CCK_Default;
+}
+
+LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const {
+ switch (TK) {
+ case OCLTK_Image:
+ case OCLTK_Pipe:
+ return LangAS::opencl_global;
+
+ case OCLTK_Sampler:
+ return LangAS::opencl_constant;
+
+ default:
+ return LangAS::Default;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+
+
+static StringRef removeGCCRegisterPrefix(StringRef Name) {
+ if (Name[0] == '%' || Name[0] == '#')
+ Name = Name.substr(1);
+
+ return Name;
+}
+
+/// isValidClobber - Returns whether the passed in string is
+/// a valid clobber in an inline asm statement. This is used by
+/// Sema.
+bool TargetInfo::isValidClobber(StringRef Name) const {
+ return (isValidGCCRegisterName(Name) ||
+ Name == "memory" || Name == "cc");
+}
+
+/// isValidGCCRegisterName - Returns whether the passed in string
+/// is a valid register name according to GCC. This is used by Sema for
+/// inline asm statements.
+bool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
+ if (Name.empty())
+ return false;
+
+ // Get rid of any register prefix.
+ Name = removeGCCRegisterPrefix(Name);
+ if (Name.empty())
+ return false;
+
+ ArrayRef<const char *> Names = getGCCRegNames();
+
+ // If we have a number it maps to an entry in the register name array.
+ if (isDigit(Name[0])) {
+ unsigned n;
+ if (!Name.getAsInteger(0, n))
+ return n < Names.size();
+ }
+
+ // Check register names.
+ if (std::find(Names.begin(), Names.end(), Name) != Names.end())
+ return true;
+
+ // Check any additional names that we have.
+ for (const AddlRegName &ARN : getGCCAddlRegNames())
+ for (const char *AN : ARN.Names) {
+ if (!AN)
+ break;
+ // Make sure the register that the additional name is for is within
+ // the bounds of the register names from above.
+ if (AN == Name && ARN.RegNum < Names.size())
+ return true;
+ }
+
+ // Now check aliases.
+ for (const GCCRegAlias &GRA : getGCCRegAliases())
+ for (const char *A : GRA.Aliases) {
+ if (!A)
+ break;
+ if (A == Name)
+ return true;
+ }
+
+ return false;
+}
+
+StringRef TargetInfo::getNormalizedGCCRegisterName(StringRef Name,
+ bool ReturnCanonical) const {
+ assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
+
+ // Get rid of any register prefix.
+ Name = removeGCCRegisterPrefix(Name);
+
+ ArrayRef<const char *> Names = getGCCRegNames();
+
+ // First, check if we have a number.
+ if (isDigit(Name[0])) {
+ unsigned n;
+ if (!Name.getAsInteger(0, n)) {
+ assert(n < Names.size() && "Out of bounds register number!");
+ return Names[n];
+ }
+ }
+
+ // Check any additional names that we have.
+ for (const AddlRegName &ARN : getGCCAddlRegNames())
+ for (const char *AN : ARN.Names) {
+ if (!AN)
+ break;
+ // Make sure the register that the additional name is for is within
+ // the bounds of the register names from above.
+ if (AN == Name && ARN.RegNum < Names.size())
+ return ReturnCanonical ? Names[ARN.RegNum] : Name;
+ }
+
+ // Now check aliases.
+ for (const GCCRegAlias &RA : getGCCRegAliases())
+ for (const char *A : RA.Aliases) {
+ if (!A)
+ break;
+ if (A == Name)
+ return RA.Register;
+ }
+
+ return Name;
+}
+
+bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
+ const char *Name = Info.getConstraintStr().c_str();
+ // An output constraint must start with '=' or '+'
+ if (*Name != '=' && *Name != '+')
+ return false;
+
+ if (*Name == '+')
+ Info.setIsReadWrite();
+
+ Name++;
+ while (*Name) {
+ switch (*Name) {
+ default:
+ if (!validateAsmConstraint(Name, Info)) {
+ // FIXME: We temporarily return false
+ // so we can add more constraints as we hit it.
+ // Eventually, an unknown constraint should just be treated as 'g'.
+ return false;
+ }
+ break;
+ case '&': // early clobber.
+ Info.setEarlyClobber();
+ break;
+ case '%': // commutative.
+ // FIXME: Check that there is a another register after this one.
+ break;
+ case 'r': // general register.
+ Info.setAllowsRegister();
+ break;
+ case 'm': // memory operand.
+ case 'o': // offsetable memory operand.
+ case 'V': // non-offsetable memory operand.
+ case '<': // autodecrement memory operand.
+ case '>': // autoincrement memory operand.
+ Info.setAllowsMemory();
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ case 'X': // any operand.
+ Info.setAllowsRegister();
+ Info.setAllowsMemory();
+ break;
+ case ',': // multiple alternative constraint. Pass it.
+ // Handle additional optional '=' or '+' modifiers.
+ if (Name[1] == '=' || Name[1] == '+')
+ Name++;
+ break;
+ case '#': // Ignore as constraint.
+ while (Name[1] && Name[1] != ',')
+ Name++;
+ break;
+ case '?': // Disparage slightly code.
+ case '!': // Disparage severely.
+ case '*': // Ignore for choosing register preferences.
+ case 'i': // Ignore i,n,E,F as output constraints (match from the other
+ // chars)
+ case 'n':
+ case 'E':
+ case 'F':
+ break; // Pass them.
+ }
+
+ Name++;
+ }
+
+ // Early clobber with a read-write constraint which doesn't permit registers
+ // is invalid.
+ if (Info.earlyClobber() && Info.isReadWrite() && !Info.allowsRegister())
+ return false;
+
+ // If a constraint allows neither memory nor register operands it contains
+ // only modifiers. Reject it.
+ return Info.allowsMemory() || Info.allowsRegister();
+}
+
+bool TargetInfo::resolveSymbolicName(const char *&Name,
+ ArrayRef<ConstraintInfo> OutputConstraints,
+ unsigned &Index) const {
+ assert(*Name == '[' && "Symbolic name did not start with '['");
+ Name++;
+ const char *Start = Name;
+ while (*Name && *Name != ']')
+ Name++;
+
+ if (!*Name) {
+ // Missing ']'
+ return false;
+ }
+
+ std::string SymbolicName(Start, Name - Start);
+
+ for (Index = 0; Index != OutputConstraints.size(); ++Index)
+ if (SymbolicName == OutputConstraints[Index].getName())
+ return true;
+
+ return false;
+}
+
+bool TargetInfo::validateInputConstraint(
+ MutableArrayRef<ConstraintInfo> OutputConstraints,
+ ConstraintInfo &Info) const {
+ const char *Name = Info.ConstraintStr.c_str();
+
+ if (!*Name)
+ return false;
+
+ while (*Name) {
+ switch (*Name) {
+ default:
+ // Check if we have a matching constraint
+ if (*Name >= '0' && *Name <= '9') {
+ const char *DigitStart = Name;
+ while (Name[1] >= '0' && Name[1] <= '9')
+ Name++;
+ const char *DigitEnd = Name;
+ unsigned i;
+ if (StringRef(DigitStart, DigitEnd - DigitStart + 1)
+ .getAsInteger(10, i))
+ return false;
+
+ // Check if matching constraint is out of bounds.
+ if (i >= OutputConstraints.size()) return false;
+
+ // A number must refer to an output only operand.
+ if (OutputConstraints[i].isReadWrite())
+ return false;
+
+ // If the constraint is already tied, it must be tied to the
+ // same operand referenced to by the number.
+ if (Info.hasTiedOperand() && Info.getTiedOperand() != i)
+ return false;
+
+ // The constraint should have the same info as the respective
+ // output constraint.
+ Info.setTiedOperand(i, OutputConstraints[i]);
+ } else if (!validateAsmConstraint(Name, Info)) {
+ // FIXME: This error return is in place temporarily so we can
+ // add more constraints as we hit it. Eventually, an unknown
+ // constraint should just be treated as 'g'.
+ return false;
+ }
+ break;
+ case '[': {
+ unsigned Index = 0;
+ if (!resolveSymbolicName(Name, OutputConstraints, Index))
+ return false;
+
+ // If the constraint is already tied, it must be tied to the
+ // same operand referenced to by the number.
+ if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
+ return false;
+
+ // A number must refer to an output only operand.
+ if (OutputConstraints[Index].isReadWrite())
+ return false;
+
+ Info.setTiedOperand(Index, OutputConstraints[Index]);
+ break;
+ }
+ case '%': // commutative
+ // FIXME: Fail if % is used with the last operand.
+ break;
+ case 'i': // immediate integer.
+ case 'n': // immediate integer with a known value.
+ break;
+ case 'I': // Various constant constraints with target-specific meanings.
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ if (!validateAsmConstraint(Name, Info))
+ return false;
+ break;
+ case 'r': // general register.
+ Info.setAllowsRegister();
+ break;
+ case 'm': // memory operand.
+ case 'o': // offsettable memory operand.
+ case 'V': // non-offsettable memory operand.
+ case '<': // autodecrement memory operand.
+ case '>': // autoincrement memory operand.
+ Info.setAllowsMemory();
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ case 'X': // any operand.
+ Info.setAllowsRegister();
+ Info.setAllowsMemory();
+ break;
+ case 'E': // immediate floating point.
+ case 'F': // immediate floating point.
+ case 'p': // address operand.
+ break;
+ case ',': // multiple alternative constraint. Ignore comma.
+ break;
+ case '#': // Ignore as constraint.
+ while (Name[1] && Name[1] != ',')
+ Name++;
+ break;
+ case '?': // Disparage slightly code.
+ case '!': // Disparage severely.
+ case '*': // Ignore for choosing register preferences.
+ break; // Pass them.
+ }
+
+ Name++;
+ }
+
+ return true;
+}
+
+void TargetInfo::CheckFixedPointBits() const {
+ // Check that the number of fractional and integral bits (and maybe sign) can
+ // fit into the bits given for a fixed point type.
+ assert(ShortAccumScale + getShortAccumIBits() + 1 <= ShortAccumWidth);
+ assert(AccumScale + getAccumIBits() + 1 <= AccumWidth);
+ assert(LongAccumScale + getLongAccumIBits() + 1 <= LongAccumWidth);
+ assert(getUnsignedShortAccumScale() + getUnsignedShortAccumIBits() <=
+ ShortAccumWidth);
+ assert(getUnsignedAccumScale() + getUnsignedAccumIBits() <= AccumWidth);
+ assert(getUnsignedLongAccumScale() + getUnsignedLongAccumIBits() <=
+ LongAccumWidth);
+
+ assert(getShortFractScale() + 1 <= ShortFractWidth);
+ assert(getFractScale() + 1 <= FractWidth);
+ assert(getLongFractScale() + 1 <= LongFractWidth);
+ assert(getUnsignedShortFractScale() <= ShortFractWidth);
+ assert(getUnsignedFractScale() <= FractWidth);
+ assert(getUnsignedLongFractScale() <= LongFractWidth);
+
+ // Each unsigned fract type has either the same number of fractional bits
+ // as, or one more fractional bit than, its corresponding signed fract type.
+ assert(getShortFractScale() == getUnsignedShortFractScale() ||
+ getShortFractScale() == getUnsignedShortFractScale() - 1);
+ assert(getFractScale() == getUnsignedFractScale() ||
+ getFractScale() == getUnsignedFractScale() - 1);
+ assert(getLongFractScale() == getUnsignedLongFractScale() ||
+ getLongFractScale() == getUnsignedLongFractScale() - 1);
+
+ // When arranged in order of increasing rank (see 6.3.1.3a), the number of
+ // fractional bits is nondecreasing for each of the following sets of
+ // fixed-point types:
+ // - signed fract types
+ // - unsigned fract types
+ // - signed accum types
+ // - unsigned accum types.
+ assert(getLongFractScale() >= getFractScale() &&
+ getFractScale() >= getShortFractScale());
+ assert(getUnsignedLongFractScale() >= getUnsignedFractScale() &&
+ getUnsignedFractScale() >= getUnsignedShortFractScale());
+ assert(LongAccumScale >= AccumScale && AccumScale >= ShortAccumScale);
+ assert(getUnsignedLongAccumScale() >= getUnsignedAccumScale() &&
+ getUnsignedAccumScale() >= getUnsignedShortAccumScale());
+
+ // When arranged in order of increasing rank (see 6.3.1.3a), the number of
+ // integral bits is nondecreasing for each of the following sets of
+ // fixed-point types:
+ // - signed accum types
+ // - unsigned accum types
+ assert(getLongAccumIBits() >= getAccumIBits() &&
+ getAccumIBits() >= getShortAccumIBits());
+ assert(getUnsignedLongAccumIBits() >= getUnsignedAccumIBits() &&
+ getUnsignedAccumIBits() >= getUnsignedShortAccumIBits());
+
+ // Each signed accum type has at least as many integral bits as its
+ // corresponding unsigned accum type.
+ assert(getShortAccumIBits() >= getUnsignedShortAccumIBits());
+ assert(getAccumIBits() >= getUnsignedAccumIBits());
+ assert(getLongAccumIBits() >= getUnsignedLongAccumIBits());
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
new file mode 100644
index 000000000000..1ef2fe3b8141
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -0,0 +1,658 @@
+//===--- Targets.cpp - Implement target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements construction of a TargetInfo object from a
+// target triple.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Targets.h"
+
+#include "Targets/AArch64.h"
+#include "Targets/AMDGPU.h"
+#include "Targets/ARM.h"
+#include "Targets/AVR.h"
+#include "Targets/BPF.h"
+#include "Targets/Hexagon.h"
+#include "Targets/Lanai.h"
+#include "Targets/Le64.h"
+#include "Targets/MSP430.h"
+#include "Targets/Mips.h"
+#include "Targets/NVPTX.h"
+#include "Targets/Nios2.h"
+#include "Targets/OSTargets.h"
+#include "Targets/PNaCl.h"
+#include "Targets/PPC.h"
+#include "Targets/RISCV.h"
+#include "Targets/SPIR.h"
+#include "Targets/Sparc.h"
+#include "Targets/SystemZ.h"
+#include "Targets/TCE.h"
+#include "Targets/WebAssembly.h"
+#include "Targets/X86.h"
+#include "Targets/XCore.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang;
+
+namespace clang {
+namespace targets {
+//===----------------------------------------------------------------------===//
+// Common code shared among targets.
+//===----------------------------------------------------------------------===//
+
+/// DefineStd - Define a macro name and standard variants. For example if
+/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
+/// when in GNU mode.
+void DefineStd(MacroBuilder &Builder, StringRef MacroName,
+ const LangOptions &Opts) {
+ assert(MacroName[0] != '_' && "Identifier should be in the user's namespace");
+
+ // If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier
+ // in the user's namespace.
+ if (Opts.GNUMode)
+ Builder.defineMacro(MacroName);
+
+ // Define __unix.
+ Builder.defineMacro("__" + MacroName);
+
+ // Define __unix__.
+ Builder.defineMacro("__" + MacroName + "__");
+}
+
+void defineCPUMacros(MacroBuilder &Builder, StringRef CPUName, bool Tuning) {
+ Builder.defineMacro("__" + CPUName);
+ Builder.defineMacro("__" + CPUName + "__");
+ if (Tuning)
+ Builder.defineMacro("__tune_" + CPUName + "__");
+}
+
+void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
+ // Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang
+ // supports __declspec natively under -fms-extensions, but we define a no-op
+ // __declspec macro anyway for pre-processor compatibility.
+ if (Opts.MicrosoftExt)
+ Builder.defineMacro("__declspec", "__declspec");
+ else
+ Builder.defineMacro("__declspec(a)", "__attribute__((a))");
+
+ if (!Opts.MicrosoftExt) {
+ // Provide macros for all the calling convention keywords. Provide both
+ // single and double underscore prefixed variants. These are available on
+ // x64 as well as x86, even though they have no effect.
+ const char *CCs[] = {"cdecl", "stdcall", "fastcall", "thiscall", "pascal"};
+ for (const char *CC : CCs) {
+ std::string GCCSpelling = "__attribute__((__";
+ GCCSpelling += CC;
+ GCCSpelling += "__))";
+ Builder.defineMacro(Twine("_") + CC, GCCSpelling);
+ Builder.defineMacro(Twine("__") + CC, GCCSpelling);
+ }
+ }
+}
+
+void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts,
+ MacroBuilder &Builder) {
+ DefineStd(Builder, "WIN32", Opts);
+ DefineStd(Builder, "WINNT", Opts);
+ if (Triple.isArch64Bit()) {
+ DefineStd(Builder, "WIN64", Opts);
+ Builder.defineMacro("__MINGW64__");
+ }
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW32__");
+ addCygMingDefines(Opts, Builder);
+}
+
+//===----------------------------------------------------------------------===//
+// Driver code
+//===----------------------------------------------------------------------===//
+
+TargetInfo *AllocateTarget(const llvm::Triple &Triple,
+ const TargetOptions &Opts) {
+ llvm::Triple::OSType os = Triple.getOS();
+
+ switch (Triple.getArch()) {
+ default:
+ return nullptr;
+
+ case llvm::Triple::xcore:
+ return new XCoreTargetInfo(Triple, Opts);
+
+ case llvm::Triple::hexagon:
+ return new HexagonTargetInfo(Triple, Opts);
+
+ case llvm::Triple::lanai:
+ return new LanaiTargetInfo(Triple, Opts);
+
+ case llvm::Triple::aarch64:
+ if (Triple.isOSDarwin())
+ return new DarwinAArch64TargetInfo(Triple, Opts);
+
+ switch (os) {
+ case llvm::Triple::CloudABI:
+ return new CloudABITargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::Win32:
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::GNU:
+ return new MinGWARM64TargetInfo(Triple, Opts);
+ case llvm::Triple::MSVC:
+ default: // Assume MSVC for unknown environments
+ return new MicrosoftARM64TargetInfo(Triple, Opts);
+ }
+ default:
+ return new AArch64leTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::aarch64_be:
+ switch (os) {
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<AArch64beTargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<AArch64beTargetInfo>(Triple, Opts);
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<AArch64beTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<AArch64beTargetInfo>(Triple, Opts);
+ default:
+ return new AArch64beTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (Triple.isOSBinFormatMachO())
+ return new DarwinARMTargetInfo(Triple, Opts);
+
+ switch (os) {
+ case llvm::Triple::CloudABI:
+ return new CloudABITargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::NaCl:
+ return new NaClTargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::Win32:
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::Cygnus:
+ return new CygwinARMTargetInfo(Triple, Opts);
+ case llvm::Triple::GNU:
+ return new MinGWARMTargetInfo(Triple, Opts);
+ case llvm::Triple::Itanium:
+ return new ItaniumWindowsARMleTargetInfo(Triple, Opts);
+ case llvm::Triple::MSVC:
+ default: // Assume MSVC for unknown environments
+ return new MicrosoftARMleTargetInfo(Triple, Opts);
+ }
+ default:
+ return new ARMleTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ if (Triple.isOSDarwin())
+ return new DarwinARMTargetInfo(Triple, Opts);
+
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<ARMbeTargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<ARMbeTargetInfo>(Triple, Opts);
+ case llvm::Triple::NaCl:
+ return new NaClTargetInfo<ARMbeTargetInfo>(Triple, Opts);
+ default:
+ return new ARMbeTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::avr:
+ return new AVRTargetInfo(Triple, Opts);
+ case llvm::Triple::bpfeb:
+ case llvm::Triple::bpfel:
+ return new BPFTargetInfo(Triple, Opts);
+
+ case llvm::Triple::msp430:
+ return new MSP430TargetInfo(Triple, Opts);
+
+ case llvm::Triple::nios2:
+ return new LinuxTargetInfo<Nios2TargetInfo>(Triple, Opts);
+
+ case llvm::Triple::mips:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ default:
+ return new MipsTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::mipsel:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::NaCl:
+ return new NaClTargetInfo<NaClMips32TargetInfo>(Triple, Opts);
+ default:
+ return new MipsTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::mips64:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ default:
+ return new MipsTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::mips64el:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
+ default:
+ return new MipsTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::le32:
+ switch (os) {
+ case llvm::Triple::NaCl:
+ return new NaClTargetInfo<PNaClTargetInfo>(Triple, Opts);
+ default:
+ return nullptr;
+ }
+
+ case llvm::Triple::le64:
+ return new Le64TargetInfo(Triple, Opts);
+
+ case llvm::Triple::ppc:
+ if (Triple.isOSDarwin())
+ return new DarwinPPC32TargetInfo(Triple, Opts);
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<PPC32TargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<PPC32TargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<PPC32TargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<PPC32TargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<PPC32TargetInfo>(Triple, Opts);
+ default:
+ return new PPC32TargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::ppc64:
+ if (Triple.isOSDarwin())
+ return new DarwinPPC64TargetInfo(Triple, Opts);
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<PPC64TargetInfo>(Triple, Opts);
+ case llvm::Triple::Lv2:
+ return new PS3PPUTargetInfo<PPC64TargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
+ default:
+ return new PPC64TargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::ppc64le:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<PPC64TargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
+ default:
+ return new PPC64TargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::nvptx:
+ return new NVPTXTargetInfo(Triple, Opts, /*TargetPointerWidth=*/32);
+ case llvm::Triple::nvptx64:
+ return new NVPTXTargetInfo(Triple, Opts, /*TargetPointerWidth=*/64);
+
+ case llvm::Triple::amdgcn:
+ case llvm::Triple::r600:
+ return new AMDGPUTargetInfo(Triple, Opts);
+
+ case llvm::Triple::riscv32:
+ // TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<RISCV32TargetInfo>(Triple, Opts);
+ return new RISCV32TargetInfo(Triple, Opts);
+ case llvm::Triple::riscv64:
+ // TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<RISCV64TargetInfo>(Triple, Opts);
+ return new RISCV64TargetInfo(Triple, Opts);
+
+ case llvm::Triple::sparc:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<SparcV8TargetInfo>(Triple, Opts);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<SparcV8TargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<SparcV8TargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<SparcV8TargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<SparcV8TargetInfo>(Triple, Opts);
+ default:
+ return new SparcV8TargetInfo(Triple, Opts);
+ }
+
+ // The 'sparcel' architecture copies all the above cases except for Solaris.
+ case llvm::Triple::sparcel:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
+ default:
+ return new SparcV8elTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::sparcv9:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<SparcV9TargetInfo>(Triple, Opts);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<SparcV9TargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<SparcV9TargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<SparcV9TargetInfo>(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<SparcV9TargetInfo>(Triple, Opts);
+ default:
+ return new SparcV9TargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::systemz:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<SystemZTargetInfo>(Triple, Opts);
+ default:
+ return new SystemZTargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::tce:
+ return new TCETargetInfo(Triple, Opts);
+
+ case llvm::Triple::tcele:
+ return new TCELETargetInfo(Triple, Opts);
+
+ case llvm::Triple::x86:
+ if (Triple.isOSDarwin())
+ return new DarwinI386TargetInfo(Triple, Opts);
+
+ switch (os) {
+ case llvm::Triple::Ananas:
+ return new AnanasTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::CloudABI:
+ return new CloudABITargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::Linux: {
+ switch (Triple.getEnvironment()) {
+ default:
+ return new LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::Android:
+ return new AndroidX86_32TargetInfo(Triple, Opts);
+ }
+ }
+ case llvm::Triple::DragonFly:
+ return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDI386TargetInfo(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDI386TargetInfo(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::KFreeBSD:
+ return new KFreeBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::Minix:
+ return new MinixTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::Win32: {
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::Cygnus:
+ return new CygwinX86_32TargetInfo(Triple, Opts);
+ case llvm::Triple::GNU:
+ return new MinGWX86_32TargetInfo(Triple, Opts);
+ case llvm::Triple::Itanium:
+ case llvm::Triple::MSVC:
+ default: // Assume MSVC for unknown environments
+ return new MicrosoftX86_32TargetInfo(Triple, Opts);
+ }
+ }
+ case llvm::Triple::Haiku:
+ return new HaikuX86_32TargetInfo(Triple, Opts);
+ case llvm::Triple::RTEMS:
+ return new RTEMSX86_32TargetInfo(Triple, Opts);
+ case llvm::Triple::NaCl:
+ return new NaClTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::ELFIAMCU:
+ return new MCUX86_32TargetInfo(Triple, Opts);
+ default:
+ return new X86_32TargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::x86_64:
+ if (Triple.isOSDarwin() || Triple.isOSBinFormatMachO())
+ return new DarwinX86_64TargetInfo(Triple, Opts);
+
+ switch (os) {
+ case llvm::Triple::Ananas:
+ return new AnanasTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::CloudABI:
+ return new CloudABITargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::Linux: {
+ switch (Triple.getEnvironment()) {
+ default:
+ return new LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::Android:
+ return new AndroidX86_64TargetInfo(Triple, Opts);
+ }
+ }
+ case llvm::Triple::DragonFly:
+ return new DragonFlyBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDX86_64TargetInfo(Triple, Opts);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::KFreeBSD:
+ return new KFreeBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::Win32: {
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::Cygnus:
+ return new CygwinX86_64TargetInfo(Triple, Opts);
+ case llvm::Triple::GNU:
+ return new MinGWX86_64TargetInfo(Triple, Opts);
+ case llvm::Triple::MSVC:
+ default: // Assume MSVC for unknown environments
+ return new MicrosoftX86_64TargetInfo(Triple, Opts);
+ }
+ }
+ case llvm::Triple::Haiku:
+ return new HaikuTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::NaCl:
+ return new NaClTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::PS4:
+ return new PS4OSTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ default:
+ return new X86_64TargetInfo(Triple, Opts);
+ }
+
+ case llvm::Triple::spir: {
+ if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
+ return nullptr;
+ return new SPIR32TargetInfo(Triple, Opts);
+ }
+ case llvm::Triple::spir64: {
+ if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
+ return nullptr;
+ return new SPIR64TargetInfo(Triple, Opts);
+ }
+ case llvm::Triple::wasm32:
+ if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
+ Triple.getVendor() != llvm::Triple::UnknownVendor ||
+ Triple.getOS() != llvm::Triple::UnknownOS ||
+ Triple.getEnvironment() != llvm::Triple::UnknownEnvironment ||
+ !(Triple.isOSBinFormatELF() || Triple.isOSBinFormatWasm()))
+ return nullptr;
+ return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
+ case llvm::Triple::wasm64:
+ if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
+ Triple.getVendor() != llvm::Triple::UnknownVendor ||
+ Triple.getOS() != llvm::Triple::UnknownOS ||
+ Triple.getEnvironment() != llvm::Triple::UnknownEnvironment ||
+ !(Triple.isOSBinFormatELF() || Triple.isOSBinFormatWasm()))
+ return nullptr;
+ return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
+
+ case llvm::Triple::renderscript32:
+ return new LinuxTargetInfo<RenderScript32TargetInfo>(Triple, Opts);
+ case llvm::Triple::renderscript64:
+ return new LinuxTargetInfo<RenderScript64TargetInfo>(Triple, Opts);
+ }
+}
+} // namespace targets
+} // namespace clang
+
+using namespace clang::targets;
+/// CreateTargetInfo - Return the target info object for the specified target
+/// options.
+TargetInfo *
+TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
+ const std::shared_ptr<TargetOptions> &Opts) {
+ llvm::Triple Triple(Opts->Triple);
+
+ // Construct the target
+ std::unique_ptr<TargetInfo> Target(AllocateTarget(Triple, *Opts));
+ if (!Target) {
+ Diags.Report(diag::err_target_unknown_triple) << Triple.str();
+ return nullptr;
+ }
+ Target->TargetOpts = Opts;
+
+ // Set the target CPU if specified.
+ if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) {
+ Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU;
+ SmallVector<StringRef, 32> ValidList;
+ Target->fillValidCPUList(ValidList);
+ if (!ValidList.empty())
+ Diags.Report(diag::note_valid_options) << llvm::join(ValidList, ", ");
+ return nullptr;
+ }
+
+ // Set the target ABI if specified.
+ if (!Opts->ABI.empty() && !Target->setABI(Opts->ABI)) {
+ Diags.Report(diag::err_target_unknown_abi) << Opts->ABI;
+ return nullptr;
+ }
+
+ // Set the fp math unit.
+ if (!Opts->FPMath.empty() && !Target->setFPMath(Opts->FPMath)) {
+ Diags.Report(diag::err_target_unknown_fpmath) << Opts->FPMath;
+ return nullptr;
+ }
+
+ // Compute the default target features, we need the target to handle this
+ // because features may have dependencies on one another.
+ llvm::StringMap<bool> Features;
+ if (!Target->initFeatureMap(Features, Diags, Opts->CPU,
+ Opts->FeaturesAsWritten))
+ return nullptr;
+
+ // Add the features to the compile options.
+ Opts->Features.clear();
+ for (const auto &F : Features)
+ Opts->Features.push_back((F.getValue() ? "+" : "-") + F.getKey().str());
+ // Sort here, so we handle the features in a predictable order. (This matters
+ // when we're dealing with features that overlap.)
+ llvm::sort(Opts->Features.begin(), Opts->Features.end());
+
+ if (!Target->handleTargetFeatures(Opts->Features, Diags))
+ return nullptr;
+
+ Target->setSupportedOpenCLOpts();
+ Target->setOpenCLExtensionOpts();
+ Target->setMaxAtomicWidth();
+
+ if (!Target->validateTarget(Diags))
+ return nullptr;
+
+ Target->CheckFixedPointBits();
+
+ return Target.release();
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.h b/contrib/llvm/tools/clang/lib/Basic/Targets.h
new file mode 100644
index 000000000000..d450aa3f37ed
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.h
@@ -0,0 +1,51 @@
+//===------- Targets.h - Declare target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares things required for construction of a TargetInfo object
+// from a target triple. Typically individual targets will need to include from
+// here in order to get these functions if required.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace targets {
+
+LLVM_LIBRARY_VISIBILITY
+clang::TargetInfo *AllocateTarget(const llvm::Triple &Triple,
+ const clang::TargetOptions &Opts);
+
+/// DefineStd - Define a macro name and standard variants. For example if
+/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
+/// when in GNU mode.
+LLVM_LIBRARY_VISIBILITY
+void DefineStd(clang::MacroBuilder &Builder, llvm::StringRef MacroName,
+ const clang::LangOptions &Opts);
+
+LLVM_LIBRARY_VISIBILITY
+void defineCPUMacros(clang::MacroBuilder &Builder, llvm::StringRef CPUName,
+ bool Tuning = true);
+
+LLVM_LIBRARY_VISIBILITY
+void addMinGWDefines(const llvm::Triple &Triple, const clang::LangOptions &Opts,
+ clang::MacroBuilder &Builder);
+
+LLVM_LIBRARY_VISIBILITY
+void addCygMingDefines(const clang::LangOptions &Opts,
+ clang::MacroBuilder &Builder);
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
new file mode 100644
index 000000000000..3444591ac593
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
@@ -0,0 +1,592 @@
+//===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AArch64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsNEON.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
+ {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsAArch64.def"
+};
+
+AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : TargetInfo(Triple), ABI("aapcs") {
+ if (getTriple().getOS() == llvm::Triple::OpenBSD) {
+ Int64Type = SignedLongLong;
+ IntMaxType = SignedLongLong;
+ } else {
+ if (!getTriple().isOSDarwin() && getTriple().getOS() != llvm::Triple::NetBSD)
+ WCharType = UnsignedInt;
+
+ Int64Type = SignedLong;
+ IntMaxType = SignedLong;
+ }
+
+ // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
+ HasLegalHalfType = true;
+
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ MaxVectorAlign = 128;
+ MaxAtomicInlineWidth = 128;
+ MaxAtomicPromoteWidth = 128;
+
+ LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+
+ // Make __builtin_ms_va_list available.
+ HasBuiltinMSVaList = true;
+
+ // {} in inline assembly are neon specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
+ // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
+ // contributes to the alignment of the containing aggregate in the same way
+ // a plain (non bit-field) member of that type would, without exception for
+ // zero-sized or anonymous bit-fields."
+ assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
+ UseZeroLengthBitfieldAlignment = true;
+
+ // AArch64 targets default to using the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::GenericAArch64);
+
+ if (Triple.getOS() == llvm::Triple::Linux)
+ this->MCountName = "\01_mcount";
+ else if (Triple.getOS() == llvm::Triple::UnknownOS)
+ this->MCountName =
+ Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
+}
+
+StringRef AArch64TargetInfo::getABI() const { return ABI; }
+
+bool AArch64TargetInfo::setABI(const std::string &Name) {
+ if (Name != "aapcs" && Name != "darwinpcs")
+ return false;
+
+ ABI = Name;
+ return true;
+}
+
+bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
+ return Name == "generic" ||
+ llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
+}
+
+bool AArch64TargetInfo::setCPU(const std::string &Name) {
+ return isValidCPUName(Name);
+}
+
+void AArch64TargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ llvm::AArch64::fillValidCPUArchList(Values);
+}
+
+void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+}
+
+void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Also include the ARMv8.1 defines
+ getTargetDefinesARMV81A(Opts, Builder);
+}
+
+void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__aarch64__");
+ // For bare-metal none-eabi.
+ if (getTriple().getOS() == llvm::Triple::UnknownOS &&
+ (getTriple().getEnvironment() == llvm::Triple::EABI ||
+ getTriple().getEnvironment() == llvm::Triple::EABIHF))
+ Builder.defineMacro("__ELF__");
+
+ // Target properties.
+ if (!getTriple().isOSWindows()) {
+ Builder.defineMacro("_LP64");
+ Builder.defineMacro("__LP64__");
+ }
+
+ // ACLE predefines. Many can only have one possible value on v8 AArch64.
+ Builder.defineMacro("__ARM_ACLE", "200");
+ Builder.defineMacro("__ARM_ARCH", "8");
+ Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
+
+ Builder.defineMacro("__ARM_64BIT_STATE", "1");
+ Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
+ Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
+
+ Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
+ Builder.defineMacro("__ARM_FEATURE_FMA", "1");
+ Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
+ Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
+ Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
+ Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
+ Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
+
+ Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
+
+ // 0xe implies support for half, single and double precision operations.
+ Builder.defineMacro("__ARM_FP", "0xE");
+
+ // PCS specifies this for SysV variants, which is all we support. Other ABIs
+ // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
+ Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+ Builder.defineMacro("__ARM_FP16_ARGS", "1");
+
+ if (Opts.UnsafeFPMath)
+ Builder.defineMacro("__ARM_FP_FAST", "1");
+
+ Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
+ Twine(Opts.WCharSize ? Opts.WCharSize : 4));
+
+ Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
+
+ if (FPU & NeonMode) {
+ Builder.defineMacro("__ARM_NEON", "1");
+ // 64-bit NEON supports half, single and double precision operations.
+ Builder.defineMacro("__ARM_NEON_FP", "0xE");
+ }
+
+ if (FPU & SveMode)
+ Builder.defineMacro("__ARM_FEATURE_SVE", "1");
+
+ if (CRC)
+ Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
+
+ if (Crypto)
+ Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+
+ if (Unaligned)
+ Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+
+ if ((FPU & NeonMode) && HasFullFP16)
+ Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+ if (HasFullFP16)
+ Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
+
+ if (HasDotProd)
+ Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
+
+ switch (ArchKind) {
+ default:
+ break;
+ case llvm::AArch64::ArchKind::ARMV8_1A:
+ getTargetDefinesARMV81A(Opts, Builder);
+ break;
+ case llvm::AArch64::ArchKind::ARMV8_2A:
+ getTargetDefinesARMV82A(Opts, Builder);
+ break;
+ }
+
+ // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+}
+
+ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
+ return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
+ (Feature == "neon" && (FPU & NeonMode)) ||
+ (Feature == "sve" && (FPU & SveMode));
+}
+
+bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ FPU = FPUMode;
+ CRC = 0;
+ Crypto = 0;
+ Unaligned = 1;
+ HasFullFP16 = 0;
+ HasDotProd = 0;
+ ArchKind = llvm::AArch64::ArchKind::ARMV8A;
+
+ for (const auto &Feature : Features) {
+ if (Feature == "+neon")
+ FPU |= NeonMode;
+ if (Feature == "+sve")
+ FPU |= SveMode;
+ if (Feature == "+crc")
+ CRC = 1;
+ if (Feature == "+crypto")
+ Crypto = 1;
+ if (Feature == "+strict-align")
+ Unaligned = 0;
+ if (Feature == "+v8.1a")
+ ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
+ if (Feature == "+v8.2a")
+ ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
+ if (Feature == "+fullfp16")
+ HasFullFP16 = 1;
+ if (Feature == "+dotprod")
+ HasDotProd = 1;
+ }
+
+ setDataLayout();
+
+ return true;
+}
+
+TargetInfo::CallingConvCheckResult
+AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_C:
+ case CC_Swift:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_OpenCLKernel:
+ case CC_Win64:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
+
+TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::AArch64ABIBuiltinVaList;
+}
+
+const char *const AArch64TargetInfo::GCCRegNames[] = {
+ // 32-bit Integer registers
+ "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
+ "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
+ "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
+
+ // 64-bit Integer registers
+ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
+ "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
+ "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
+
+ // 32-bit floating point regsisters
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
+ "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
+ "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+
+ // 64-bit floating point regsisters
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
+ "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
+ "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+
+ // Vector registers
+ "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"
+};
+
+ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
+ {{"w31"}, "wsp"},
+ {{"x31"}, "sp"},
+ // GCC rN registers are aliases of xN registers.
+ {{"r0"}, "x0"},
+ {{"r1"}, "x1"},
+ {{"r2"}, "x2"},
+ {{"r3"}, "x3"},
+ {{"r4"}, "x4"},
+ {{"r5"}, "x5"},
+ {{"r6"}, "x6"},
+ {{"r7"}, "x7"},
+ {{"r8"}, "x8"},
+ {{"r9"}, "x9"},
+ {{"r10"}, "x10"},
+ {{"r11"}, "x11"},
+ {{"r12"}, "x12"},
+ {{"r13"}, "x13"},
+ {{"r14"}, "x14"},
+ {{"r15"}, "x15"},
+ {{"r16"}, "x16"},
+ {{"r17"}, "x17"},
+ {{"r18"}, "x18"},
+ {{"r19"}, "x19"},
+ {{"r20"}, "x20"},
+ {{"r21"}, "x21"},
+ {{"r22"}, "x22"},
+ {{"r23"}, "x23"},
+ {{"r24"}, "x24"},
+ {{"r25"}, "x25"},
+ {{"r26"}, "x26"},
+ {{"r27"}, "x27"},
+ {{"r28"}, "x28"},
+ {{"r29", "x29"}, "fp"},
+ {{"r30", "x30"}, "lr"},
+ // The S/D/Q and W/X registers overlap, but aren't really aliases; we
+ // don't want to substitute one of these for a different-sized one.
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool AArch64TargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+ case 'w': // Floating point and SIMD registers (V0-V31)
+ Info.setAllowsRegister();
+ return true;
+ case 'I': // Constant that can be used with an ADD instruction
+ case 'J': // Constant that can be used with a SUB instruction
+ case 'K': // Constant that can be used with a 32-bit logical instruction
+ case 'L': // Constant that can be used with a 64-bit logical instruction
+ case 'M': // Constant that can be used as a 32-bit MOV immediate
+ case 'N': // Constant that can be used as a 64-bit MOV immediate
+ case 'Y': // Floating point constant zero
+ case 'Z': // Integer constant zero
+ return true;
+ case 'Q': // A memory reference with base register and no offset
+ Info.setAllowsMemory();
+ return true;
+ case 'S': // A symbolic address
+ Info.setAllowsRegister();
+ return true;
+ case 'U':
+ // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
+ // Utf: A memory address suitable for ldp/stp in TF mode.
+ // Usa: An absolute symbolic address.
+ // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
+ llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
+ case 'z': // Zero register, wzr or xzr
+ Info.setAllowsRegister();
+ return true;
+ case 'x': // Floating point and SIMD registers (V0-V15)
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
+}
+
+bool AArch64TargetInfo::validateConstraintModifier(
+ StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const {
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ switch (Constraint[0]) {
+ default:
+ return true;
+ case 'z':
+ case 'r': {
+ switch (Modifier) {
+ case 'x':
+ case 'w':
+ // For now assume that the person knows what they're
+ // doing with the modifier.
+ return true;
+ default:
+ // By default an 'r' constraint will be in the 'x'
+ // registers.
+ if (Size == 64)
+ return true;
+
+ SuggestedModifier = "w";
+ return false;
+ }
+ }
+ }
+}
+
+const char *AArch64TargetInfo::getClobbers() const { return ""; }
+
+int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 1;
+ return -1;
+}
+
+AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : AArch64TargetInfo(Triple, Opts) {}
+
+void AArch64leTargetInfo::setDataLayout() {
+ if (getTriple().isOSBinFormatMachO())
+ resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
+ else
+ resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
+}
+
+void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__AARCH64EL__");
+ AArch64TargetInfo::getTargetDefines(Opts, Builder);
+}
+
+AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : AArch64TargetInfo(Triple, Opts) {}
+
+void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__AARCH64EB__");
+ Builder.defineMacro("__AARCH_BIG_ENDIAN");
+ Builder.defineMacro("__ARM_BIG_ENDIAN");
+ AArch64TargetInfo::getTargetDefines(Opts, Builder);
+}
+
+void AArch64beTargetInfo::setDataLayout() {
+ assert(!getTriple().isOSBinFormatMachO());
+ resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
+}
+
+WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
+
+ // This is an LLP64 platform.
+ // int:4, long:4, long long:8, long double:8.
+ IntWidth = IntAlign = 32;
+ LongWidth = LongAlign = 32;
+ DoubleAlign = LongLongAlign = 64;
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLongLong;
+ SizeType = UnsignedLongLong;
+ PtrDiffType = SignedLongLong;
+ IntPtrType = SignedLongLong;
+}
+
+void WindowsARM64TargetInfo::setDataLayout() {
+ resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
+}
+
+TargetInfo::BuiltinVaListKind
+WindowsARM64TargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::CharPtrBuiltinVaList;
+}
+
+TargetInfo::CallingConvCheckResult
+WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ case CC_X86VectorCall:
+ return CCCR_Ignore;
+ case CC_C:
+ case CC_OpenCLKernel:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_Win64:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARM64TargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::Microsoft);
+}
+
+void MicrosoftARM64TargetInfo::getVisualStudioDefines(
+ const LangOptions &Opts, MacroBuilder &Builder) const {
+ WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
+ Builder.defineMacro("_M_ARM64", "1");
+}
+
+void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo::getTargetDefines(Opts, Builder);
+ getVisualStudioDefines(Opts, Builder);
+}
+
+TargetInfo::CallingConvKind
+MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
+ return CCK_MicrosoftWin64;
+}
+
+MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARM64TargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::GenericAArch64);
+}
+
+DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
+ Int64Type = SignedLongLong;
+ UseSignedCharForObjCBool = false;
+
+ LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+
+ TheCXXABI.set(TargetCXXABI::iOS64);
+}
+
+void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
+ const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__AARCH64_SIMD__");
+ Builder.defineMacro("__ARM64_ARCH_8__");
+ Builder.defineMacro("__ARM_NEON__");
+ Builder.defineMacro("__LITTLE_ENDIAN__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+ Builder.defineMacro("__arm64", "1");
+ Builder.defineMacro("__arm64__", "1");
+
+ getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+}
+
+TargetInfo::BuiltinVaListKind
+DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::CharPtrBuiltinVaList;
+}
+
+// 64-bit RenderScript is aarch64
+RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
+ Triple.getOSName(),
+ Triple.getEnvironmentName()),
+ Opts) {
+ IsRenderScriptTarget = true;
+}
+
+void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__RENDERSCRIPT__");
+ AArch64leTargetInfo::getTargetDefines(Opts, Builder);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h
new file mode 100644
index 000000000000..a9df895e4dad
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h
@@ -0,0 +1,176 @@
+//===--- AArch64.h - Declare AArch64 target feature support -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares AArch64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AARCH64_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_AARCH64_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/Support/TargetParser.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
+ virtual void setDataLayout() = 0;
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+
+ enum FPUModeEnum { FPUMode, NeonMode = (1 << 0), SveMode = (1 << 1) };
+
+ unsigned FPU;
+ unsigned CRC;
+ unsigned Crypto;
+ unsigned Unaligned;
+ unsigned HasFullFP16;
+ unsigned HasDotProd;
+ llvm::AArch64::ArchKind ArchKind;
+
+ static const Builtin::Info BuiltinInfo[];
+
+ std::string ABI;
+
+public:
+ AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ StringRef getABI() const override;
+ bool setABI(const std::string &Name) override;
+
+ bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+ bool setCPU(const std::string &Name) override;
+
+ bool useFP16ConversionIntrinsics() const override {
+ return false;
+ }
+
+ void getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool hasFeature(StringRef Feature) const override;
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+
+ bool isCLZForZeroUndef() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override;
+ bool
+ validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const override;
+ const char *getClobbers() const override;
+
+ StringRef getConstraintRegister(StringRef Constraint,
+ StringRef Expression) const override {
+ return Expression;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
+public:
+ AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+private:
+ void setDataLayout() override;
+};
+
+class LLVM_LIBRARY_VISIBILITY WindowsARM64TargetInfo
+ : public WindowsTargetInfo<AArch64leTargetInfo> {
+ const llvm::Triple Triple;
+
+public:
+ WindowsARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void setDataLayout() override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+};
+
+// Windows ARM, MS (C++) ABI
+class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo
+ : public WindowsARM64TargetInfo {
+public:
+ MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+ TargetInfo::CallingConvKind
+ getCallingConvKind(bool ClangABICompat4) const override;
+};
+
+// ARM64 MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWARM64TargetInfo
+ : public WindowsARM64TargetInfo {
+public:
+ MinGWARM64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+};
+
+class LLVM_LIBRARY_VISIBILITY AArch64beTargetInfo : public AArch64TargetInfo {
+public:
+ AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+private:
+ void setDataLayout() override;
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinAArch64TargetInfo
+ : public DarwinTargetInfo<AArch64leTargetInfo> {
+public:
+ DarwinAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override;
+};
+
+// 64-bit RenderScript is aarch64
+class LLVM_LIBRARY_VISIBILITY RenderScript64TargetInfo
+ : public AArch64leTargetInfo {
+public:
+ RenderScript64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AARCH64_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp
new file mode 100644
index 000000000000..b6b9aa2f1244
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -0,0 +1,326 @@
+//===--- AMDGPU.cpp - Implement AMDGPU target feature support -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AMDGPU TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPU.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+namespace clang {
+namespace targets {
+
+// If you edit the description strings, make sure you update
+// getPointerWidthV().
+
+static const char *const DataLayoutStringR600 =
+ "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5";
+
+static const char *const DataLayoutStringAMDGCN =
+ "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32"
+ "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5";
+
+const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = {
+ Generic, // Default
+ Global, // opencl_global
+ Local, // opencl_local
+ Constant, // opencl_constant
+ Private, // opencl_private
+ Generic, // opencl_generic
+ Global, // cuda_device
+ Constant, // cuda_constant
+ Local // cuda_shared
+};
+
+const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
+ Private, // Default
+ Global, // opencl_global
+ Local, // opencl_local
+ Constant, // opencl_constant
+ Private, // opencl_private
+ Generic, // opencl_generic
+ Global, // cuda_device
+ Constant, // cuda_constant
+ Local // cuda_shared
+};
+} // namespace targets
+} // namespace clang
+
+const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsAMDGPU.def"
+};
+
+const char *const AMDGPUTargetInfo::GCCRegNames[] = {
+ "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", "v32", "v33", "v34", "v35",
+ "v36", "v37", "v38", "v39", "v40", "v41", "v42", "v43", "v44",
+ "v45", "v46", "v47", "v48", "v49", "v50", "v51", "v52", "v53",
+ "v54", "v55", "v56", "v57", "v58", "v59", "v60", "v61", "v62",
+ "v63", "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71",
+ "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79", "v80",
+ "v81", "v82", "v83", "v84", "v85", "v86", "v87", "v88", "v89",
+ "v90", "v91", "v92", "v93", "v94", "v95", "v96", "v97", "v98",
+ "v99", "v100", "v101", "v102", "v103", "v104", "v105", "v106", "v107",
+ "v108", "v109", "v110", "v111", "v112", "v113", "v114", "v115", "v116",
+ "v117", "v118", "v119", "v120", "v121", "v122", "v123", "v124", "v125",
+ "v126", "v127", "v128", "v129", "v130", "v131", "v132", "v133", "v134",
+ "v135", "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143",
+ "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151", "v152",
+ "v153", "v154", "v155", "v156", "v157", "v158", "v159", "v160", "v161",
+ "v162", "v163", "v164", "v165", "v166", "v167", "v168", "v169", "v170",
+ "v171", "v172", "v173", "v174", "v175", "v176", "v177", "v178", "v179",
+ "v180", "v181", "v182", "v183", "v184", "v185", "v186", "v187", "v188",
+ "v189", "v190", "v191", "v192", "v193", "v194", "v195", "v196", "v197",
+ "v198", "v199", "v200", "v201", "v202", "v203", "v204", "v205", "v206",
+ "v207", "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215",
+ "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223", "v224",
+ "v225", "v226", "v227", "v228", "v229", "v230", "v231", "v232", "v233",
+ "v234", "v235", "v236", "v237", "v238", "v239", "v240", "v241", "v242",
+ "v243", "v244", "v245", "v246", "v247", "v248", "v249", "v250", "v251",
+ "v252", "v253", "v254", "v255", "s0", "s1", "s2", "s3", "s4",
+ "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13",
+ "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
+ "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+ "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", "s40",
+ "s41", "s42", "s43", "s44", "s45", "s46", "s47", "s48", "s49",
+ "s50", "s51", "s52", "s53", "s54", "s55", "s56", "s57", "s58",
+ "s59", "s60", "s61", "s62", "s63", "s64", "s65", "s66", "s67",
+ "s68", "s69", "s70", "s71", "s72", "s73", "s74", "s75", "s76",
+ "s77", "s78", "s79", "s80", "s81", "s82", "s83", "s84", "s85",
+ "s86", "s87", "s88", "s89", "s90", "s91", "s92", "s93", "s94",
+ "s95", "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103",
+ "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111", "s112",
+ "s113", "s114", "s115", "s116", "s117", "s118", "s119", "s120", "s121",
+ "s122", "s123", "s124", "s125", "s126", "s127", "exec", "vcc", "scc",
+ "m0", "flat_scratch", "exec_lo", "exec_hi", "vcc_lo", "vcc_hi",
+ "flat_scratch_lo", "flat_scratch_hi"
+};
+
+ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+bool AMDGPUTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const {
+
+ // XXX - What does the member GPU mean if device name string passed here?
+ if (isAMDGCN(getTriple())) {
+ if (CPU.empty())
+ CPU = "gfx600";
+
+ switch (parseAMDGCNName(CPU).Kind) {
+ case GK_GFX906:
+ Features["dl-insts"] = true;
+ LLVM_FALLTHROUGH;
+ case GK_GFX904:
+ case GK_GFX902:
+ case GK_GFX900:
+ Features["gfx9-insts"] = true;
+ LLVM_FALLTHROUGH;
+ case GK_GFX810:
+ case GK_GFX803:
+ case GK_GFX802:
+ case GK_GFX801:
+ Features["16-bit-insts"] = true;
+ Features["dpp"] = true;
+ Features["s-memrealtime"] = true;
+ break;
+ case GK_GFX704:
+ case GK_GFX703:
+ case GK_GFX702:
+ case GK_GFX701:
+ case GK_GFX700:
+ case GK_GFX601:
+ case GK_GFX600:
+ break;
+ case GK_NONE:
+ return false;
+ default:
+ llvm_unreachable("Unhandled GPU!");
+ }
+ } else {
+ if (CPU.empty())
+ CPU = "r600";
+
+ switch (parseR600Name(CPU).Kind) {
+ case GK_CAYMAN:
+ case GK_CYPRESS:
+ case GK_RV770:
+ case GK_RV670:
+ // TODO: Add fp64 when implemented.
+ break;
+ case GK_TURKS:
+ case GK_CAICOS:
+ case GK_BARTS:
+ case GK_SUMO:
+ case GK_REDWOOD:
+ case GK_JUNIPER:
+ case GK_CEDAR:
+ case GK_RV730:
+ case GK_RV710:
+ case GK_RS880:
+ case GK_R630:
+ case GK_R600:
+ break;
+ default:
+ llvm_unreachable("Unhandled GPU!");
+ }
+ }
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec);
+}
+
+void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts,
+ TargetOptions &TargetOpts) const {
+ bool hasFP32Denormals = false;
+ bool hasFP64Denormals = false;
+ GPUInfo CGOptsGPU = parseGPUName(TargetOpts.CPU);
+ for (auto &I : TargetOpts.FeaturesAsWritten) {
+ if (I == "+fp32-denormals" || I == "-fp32-denormals")
+ hasFP32Denormals = true;
+ if (I == "+fp64-fp16-denormals" || I == "-fp64-fp16-denormals")
+ hasFP64Denormals = true;
+ }
+ if (!hasFP32Denormals)
+ TargetOpts.Features.push_back(
+ (Twine(CGOptsGPU.HasFastFMAF && !CGOpts.FlushDenorm
+ ? '+'
+ : '-') +
+ Twine("fp32-denormals"))
+ .str());
+ // Always do not flush fp64 or fp16 denorms.
+ if (!hasFP64Denormals && CGOptsGPU.HasFP64)
+ TargetOpts.Features.push_back("+fp64-fp16-denormals");
+}
+
+constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::InvalidGPU;
+constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::R600GPUs[];
+constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::AMDGCNGPUs[];
+
+AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseR600Name(StringRef Name) {
+ const auto *Result = llvm::find_if(
+ R600GPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; });
+
+ if (Result == std::end(R600GPUs))
+ return InvalidGPU;
+ return *Result;
+}
+
+AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseAMDGCNName(StringRef Name) {
+ const auto *Result = llvm::find_if(
+ AMDGCNGPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; });
+
+ if (Result == std::end(AMDGCNGPUs))
+ return InvalidGPU;
+ return *Result;
+}
+
+AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseGPUName(StringRef Name) const {
+ if (isAMDGCN(getTriple()))
+ return parseAMDGCNName(Name);
+ else
+ return parseR600Name(Name);
+}
+
+void AMDGPUTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ if (isAMDGCN(getTriple()))
+ llvm::for_each(AMDGCNGPUs, [&Values](const GPUInfo &GPU) {
+ Values.emplace_back(GPU.Name);});
+ else
+ llvm::for_each(R600GPUs, [&Values](const GPUInfo &GPU) {
+ Values.emplace_back(GPU.Name);});
+}
+
+void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) {
+ AddrSpaceMap = DefaultIsPrivate ? &AMDGPUDefIsPrivMap : &AMDGPUDefIsGenMap;
+}
+
+AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : TargetInfo(Triple),
+ GPU(isAMDGCN(Triple) ? AMDGCNGPUs[0] : parseR600Name(Opts.CPU)) {
+ resetDataLayout(isAMDGCN(getTriple()) ? DataLayoutStringAMDGCN
+ : DataLayoutStringR600);
+ assert(DataLayout->getAllocaAddrSpace() == Private);
+
+ setAddressSpaceMap(Triple.getOS() == llvm::Triple::Mesa3D ||
+ !isAMDGCN(Triple));
+ UseAddrSpaceMapMangling = true;
+
+ // Set pointer width and alignment for target address space 0.
+ PointerWidth = PointerAlign = DataLayout->getPointerSizeInBits();
+ if (getMaxPointerWidth() == 64) {
+ LongWidth = LongAlign = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ }
+
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+}
+
+void AMDGPUTargetInfo::adjust(LangOptions &Opts) {
+ TargetInfo::adjust(Opts);
+ // ToDo: There are still a few places using default address space as private
+ // address space in OpenCL, which needs to be cleaned up, then Opts.OpenCL
+ // can be removed from the following line.
+ setAddressSpaceMap(/*DefaultIsPrivate=*/Opts.OpenCL ||
+ !isAMDGCN(getTriple()));
+}
+
+ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::AMDGPU::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__AMD__");
+ Builder.defineMacro("__AMDGPU__");
+
+ if (isAMDGCN(getTriple()))
+ Builder.defineMacro("__AMDGCN__");
+ else
+ Builder.defineMacro("__R600__");
+
+ if (GPU.Kind != GK_NONE)
+ Builder.defineMacro(Twine("__") + Twine(GPU.CanonicalName) + Twine("__"));
+
+ // TODO: __HAS_FMAF__, __HAS_LDEXPF__, __HAS_FP64__ are deprecated and will be
+ // removed in the near future.
+ if (GPU.HasFMAF)
+ Builder.defineMacro("__HAS_FMAF__");
+ if (GPU.HasFastFMAF)
+ Builder.defineMacro("FP_FAST_FMAF");
+ if (GPU.HasLDEXPF)
+ Builder.defineMacro("__HAS_LDEXPF__");
+ if (GPU.HasFP64)
+ Builder.defineMacro("__HAS_FP64__");
+ if (GPU.HasFastFMA)
+ Builder.defineMacro("FP_FAST_FMA");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h
new file mode 100644
index 000000000000..b0221031addf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h
@@ -0,0 +1,430 @@
+//===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares AMDGPU TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
+
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+
+ enum AddrSpace {
+ Generic = 0,
+ Global = 1,
+ Local = 3,
+ Constant = 4,
+ Private = 5
+ };
+ static const LangASMap AMDGPUDefIsGenMap;
+ static const LangASMap AMDGPUDefIsPrivMap;
+
+ /// GPU kinds supported by the AMDGPU target.
+ enum GPUKind : uint32_t {
+ // Not specified processor.
+ GK_NONE = 0,
+
+ // R600-based processors.
+ GK_R600,
+ GK_R630,
+ GK_RS880,
+ GK_RV670,
+ GK_RV710,
+ GK_RV730,
+ GK_RV770,
+ GK_CEDAR,
+ GK_CYPRESS,
+ GK_JUNIPER,
+ GK_REDWOOD,
+ GK_SUMO,
+ GK_BARTS,
+ GK_CAICOS,
+ GK_CAYMAN,
+ GK_TURKS,
+
+ GK_R600_FIRST = GK_R600,
+ GK_R600_LAST = GK_TURKS,
+
+ // AMDGCN-based processors.
+ GK_GFX600,
+ GK_GFX601,
+ GK_GFX700,
+ GK_GFX701,
+ GK_GFX702,
+ GK_GFX703,
+ GK_GFX704,
+ GK_GFX801,
+ GK_GFX802,
+ GK_GFX803,
+ GK_GFX810,
+ GK_GFX900,
+ GK_GFX902,
+ GK_GFX904,
+ GK_GFX906,
+
+ GK_AMDGCN_FIRST = GK_GFX600,
+ GK_AMDGCN_LAST = GK_GFX906,
+ };
+
+ struct GPUInfo {
+ llvm::StringLiteral Name;
+ llvm::StringLiteral CanonicalName;
+ AMDGPUTargetInfo::GPUKind Kind;
+ bool HasFMAF;
+ bool HasFastFMAF;
+ bool HasLDEXPF;
+ bool HasFP64;
+ bool HasFastFMA;
+ };
+
+ static constexpr GPUInfo InvalidGPU =
+ {{""}, {""}, GK_NONE, false, false, false, false, false};
+ static constexpr GPUInfo R600GPUs[26] = {
+ // Name Canonical Kind Has Has Has Has Has
+ // Name FMAF Fast LDEXPF FP64 Fast
+ // FMAF FMA
+ {{"r600"}, {"r600"}, GK_R600, false, false, false, false, false},
+ {{"rv630"}, {"r600"}, GK_R600, false, false, false, false, false},
+ {{"rv635"}, {"r600"}, GK_R600, false, false, false, false, false},
+ {{"r630"}, {"r630"}, GK_R630, false, false, false, false, false},
+ {{"rs780"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rs880"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rv610"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rv620"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rv670"}, {"rv670"}, GK_RV670, false, false, false, false, false},
+ {{"rv710"}, {"rv710"}, GK_RV710, false, false, false, false, false},
+ {{"rv730"}, {"rv730"}, GK_RV730, false, false, false, false, false},
+ {{"rv740"}, {"rv770"}, GK_RV770, false, false, false, false, false},
+ {{"rv770"}, {"rv770"}, GK_RV770, false, false, false, false, false},
+ {{"cedar"}, {"cedar"}, GK_CEDAR, false, false, false, false, false},
+ {{"palm"}, {"cedar"}, GK_CEDAR, false, false, false, false, false},
+ {{"cypress"}, {"cypress"}, GK_CYPRESS, true, false, false, false, false},
+ {{"hemlock"}, {"cypress"}, GK_CYPRESS, true, false, false, false, false},
+ {{"juniper"}, {"juniper"}, GK_JUNIPER, false, false, false, false, false},
+ {{"redwood"}, {"redwood"}, GK_REDWOOD, false, false, false, false, false},
+ {{"sumo"}, {"sumo"}, GK_SUMO, false, false, false, false, false},
+ {{"sumo2"}, {"sumo"}, GK_SUMO, false, false, false, false, false},
+ {{"barts"}, {"barts"}, GK_BARTS, false, false, false, false, false},
+ {{"caicos"}, {"caicos"}, GK_BARTS, false, false, false, false, false},
+ {{"aruba"}, {"cayman"}, GK_CAYMAN, true, false, false, false, false},
+ {{"cayman"}, {"cayman"}, GK_CAYMAN, true, false, false, false, false},
+ {{"turks"}, {"turks"}, GK_TURKS, false, false, false, false, false},
+ };
+ static constexpr GPUInfo AMDGCNGPUs[32] = {
+ // Name Canonical Kind Has Has Has Has Has
+ // Name FMAF Fast LDEXPF FP64 Fast
+ // FMAF FMA
+ {{"gfx600"}, {"gfx600"}, GK_GFX600, true, true, true, true, true},
+ {{"tahiti"}, {"gfx600"}, GK_GFX600, true, true, true, true, true},
+ {{"gfx601"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"hainan"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"oland"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"pitcairn"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"verde"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"gfx700"}, {"gfx700"}, GK_GFX700, true, false, true, true, true},
+ {{"kaveri"}, {"gfx700"}, GK_GFX700, true, false, true, true, true},
+ {{"gfx701"}, {"gfx701"}, GK_GFX701, true, true, true, true, true},
+ {{"hawaii"}, {"gfx701"}, GK_GFX701, true, true, true, true, true},
+ {{"gfx702"}, {"gfx702"}, GK_GFX702, true, true, true, true, true},
+ {{"gfx703"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
+ {{"kabini"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
+ {{"mullins"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
+ {{"gfx704"}, {"gfx704"}, GK_GFX704, true, false, true, true, true},
+ {{"bonaire"}, {"gfx704"}, GK_GFX704, true, false, true, true, true},
+ {{"gfx801"}, {"gfx801"}, GK_GFX801, true, true, true, true, true},
+ {{"carrizo"}, {"gfx801"}, GK_GFX801, true, true, true, true, true},
+ {{"gfx802"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
+ {{"iceland"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
+ {{"tonga"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
+ {{"gfx803"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"fiji"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"polaris10"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"polaris11"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"gfx810"}, {"gfx810"}, GK_GFX810, true, false, true, true, true},
+ {{"stoney"}, {"gfx810"}, GK_GFX810, true, false, true, true, true},
+ {{"gfx900"}, {"gfx900"}, GK_GFX900, true, true, true, true, true},
+ {{"gfx902"}, {"gfx902"}, GK_GFX900, true, true, true, true, true},
+ {{"gfx904"}, {"gfx904"}, GK_GFX904, true, true, true, true, true},
+ {{"gfx906"}, {"gfx906"}, GK_GFX906, true, true, true, true, true},
+ };
+
+ static GPUInfo parseR600Name(StringRef Name);
+
+ static GPUInfo parseAMDGCNName(StringRef Name);
+
+ GPUInfo parseGPUName(StringRef Name) const;
+
+ GPUInfo GPU;
+
+ static bool isAMDGCN(const llvm::Triple &TT) {
+ return TT.getArch() == llvm::Triple::amdgcn;
+ }
+
+public:
+ AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void setAddressSpaceMap(bool DefaultIsPrivate);
+
+ void adjust(LangOptions &Opts) override;
+
+ uint64_t getPointerWidthV(unsigned AddrSpace) const override {
+ if (GPU.Kind <= GK_R600_LAST)
+ return 32;
+ if (AddrSpace == Private || AddrSpace == Local)
+ return 32;
+ return 64;
+ }
+
+ uint64_t getPointerAlignV(unsigned AddrSpace) const override {
+ return getPointerWidthV(AddrSpace);
+ }
+
+ uint64_t getMaxPointerWidth() const override {
+ return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ /// Accepted register names: (n, m is unsigned integer, n < m)
+ /// v
+ /// s
+ /// {vn}, {v[n]}
+ /// {sn}, {s[n]}
+ /// {S} , where S is a special register name
+ ////{v[n:m]}
+ /// {s[n:m]}
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ static const ::llvm::StringSet<> SpecialRegs({
+ "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
+ "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
+ "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
+ });
+
+ StringRef S(Name);
+ bool HasLeftParen = false;
+ if (S.front() == '{') {
+ HasLeftParen = true;
+ S = S.drop_front();
+ }
+ if (S.empty())
+ return false;
+ if (S.front() != 'v' && S.front() != 's') {
+ if (!HasLeftParen)
+ return false;
+ auto E = S.find('}');
+ if (!SpecialRegs.count(S.substr(0, E)))
+ return false;
+ S = S.drop_front(E + 1);
+ if (!S.empty())
+ return false;
+ // Found {S} where S is a special register.
+ Info.setAllowsRegister();
+ Name = S.data() - 1;
+ return true;
+ }
+ S = S.drop_front();
+ if (!HasLeftParen) {
+ if (!S.empty())
+ return false;
+ // Found s or v.
+ Info.setAllowsRegister();
+ Name = S.data() - 1;
+ return true;
+ }
+ bool HasLeftBracket = false;
+ if (!S.empty() && S.front() == '[') {
+ HasLeftBracket = true;
+ S = S.drop_front();
+ }
+ unsigned long long N;
+ if (S.empty() || consumeUnsignedInteger(S, 10, N))
+ return false;
+ if (!S.empty() && S.front() == ':') {
+ if (!HasLeftBracket)
+ return false;
+ S = S.drop_front();
+ unsigned long long M;
+ if (consumeUnsignedInteger(S, 10, M) || N >= M)
+ return false;
+ }
+ if (HasLeftBracket) {
+ if (S.empty() || S.front() != ']')
+ return false;
+ S = S.drop_front();
+ }
+ if (S.empty() || S.front() != '}')
+ return false;
+ S = S.drop_front();
+ if (!S.empty())
+ return false;
+ // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
+ Info.setAllowsRegister();
+ Name = S.data() - 1;
+ return true;
+ }
+
+ // \p Constraint will be left pointing at the last character of
+ // the constraint. In practice, it won't be changed unless the
+ // constraint is longer than one character.
+ std::string convertConstraint(const char *&Constraint) const override {
+ const char *Begin = Constraint;
+ TargetInfo::ConstraintInfo Info("", "");
+ if (validateAsmConstraint(Constraint, Info))
+ return std::string(Begin).substr(0, Constraint - Begin + 1);
+
+ Constraint = Begin;
+ return std::string(1, *Constraint);
+ }
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const override;
+
+ void adjustTargetOptions(const CodeGenOptions &CGOpts,
+ TargetOptions &TargetOpts) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ if (getTriple().getArch() == llvm::Triple::amdgcn)
+ return GK_NONE != parseAMDGCNName(Name).Kind;
+ else
+ return GK_NONE != parseR600Name(Name).Kind;
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ if (getTriple().getArch() == llvm::Triple::amdgcn)
+ GPU = parseAMDGCNName(Name);
+ else
+ GPU = parseR600Name(Name);
+
+ return GK_NONE != GPU.Kind;
+ }
+
+ void setSupportedOpenCLOpts() override {
+ auto &Opts = getSupportedOpenCLOpts();
+ Opts.support("cl_clang_storage_class_specifiers");
+ Opts.support("cl_khr_icd");
+
+ if (GPU.HasFP64)
+ Opts.support("cl_khr_fp64");
+ if (GPU.Kind >= GK_CEDAR) {
+ Opts.support("cl_khr_byte_addressable_store");
+ Opts.support("cl_khr_global_int32_base_atomics");
+ Opts.support("cl_khr_global_int32_extended_atomics");
+ Opts.support("cl_khr_local_int32_base_atomics");
+ Opts.support("cl_khr_local_int32_extended_atomics");
+ }
+ if (GPU.Kind >= GK_AMDGCN_FIRST) {
+ Opts.support("cl_khr_fp16");
+ Opts.support("cl_khr_int64_base_atomics");
+ Opts.support("cl_khr_int64_extended_atomics");
+ Opts.support("cl_khr_mipmap_image");
+ Opts.support("cl_khr_subgroups");
+ Opts.support("cl_khr_3d_image_writes");
+ Opts.support("cl_amd_media_ops");
+ Opts.support("cl_amd_media_ops2");
+ }
+ }
+
+ LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
+ switch (TK) {
+ case OCLTK_Image:
+ return LangAS::opencl_constant;
+
+ case OCLTK_ClkEvent:
+ case OCLTK_Queue:
+ case OCLTK_ReserveID:
+ return LangAS::opencl_global;
+
+ default:
+ return TargetInfo::getOpenCLTypeAddrSpace(TK);
+ }
+ }
+
+ llvm::Optional<LangAS> getConstantAddressSpace() const override {
+ return getLangASFromTargetAS(Constant);
+ }
+
+ /// \returns Target specific vtbl ptr address space.
+ unsigned getVtblPtrAddressSpace() const override {
+ return static_cast<unsigned>(Constant);
+ }
+
+ /// \returns If a target requires an address within a target specific address
+ /// space \p AddressSpace to be converted in order to be used, then return the
+ /// corresponding target specific DWARF address space.
+ ///
+ /// \returns Otherwise return None and no conversion will be emitted in the
+ /// DWARF.
+ Optional<unsigned>
+ getDWARFAddressSpace(unsigned AddressSpace) const override {
+ const unsigned DWARF_Private = 1;
+ const unsigned DWARF_Local = 2;
+ if (AddressSpace == Private) {
+ return DWARF_Private;
+ } else if (AddressSpace == Local) {
+ return DWARF_Local;
+ } else {
+ return None;
+ }
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ default:
+ return CCCR_Warning;
+ case CC_C:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ }
+ }
+
+ // In amdgcn target the null pointer in global, constant, and generic
+ // address space has value 0 but in private and local address space has
+ // value ~0.
+ uint64_t getNullPointerValue(LangAS AS) const override {
+ return AS == LangAS::opencl_local ? ~0 : 0;
+ }
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
new file mode 100644
index 000000000000..19fcc5abea97
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
@@ -0,0 +1,1102 @@
+//===--- ARM.cpp - Implement ARM target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements ARM TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARM.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void ARMTargetInfo::setABIAAPCS() {
+ IsAAPCS = true;
+
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
+ const llvm::Triple &T = getTriple();
+
+ bool IsNetBSD = T.getOS() == llvm::Triple::NetBSD;
+ bool IsOpenBSD = T.getOS() == llvm::Triple::OpenBSD;
+ if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
+ WCharType = UnsignedInt;
+
+ UseBitFieldTypeAlignment = true;
+
+ ZeroLengthBitfieldBoundary = 0;
+
+ // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
+ // so set preferred for small types to 32.
+ if (T.isOSBinFormatMachO()) {
+ resetDataLayout(BigEndian
+ ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+ : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+ } else if (T.isOSWindows()) {
+ assert(!BigEndian && "Windows on ARM does not support big endian");
+ resetDataLayout("e"
+ "-m:w"
+ "-p:32:32"
+ "-i64:64"
+ "-v128:64:128"
+ "-a:0:32"
+ "-n32"
+ "-S64");
+ } else if (T.isOSNaCl()) {
+ assert(!BigEndian && "NaCl on ARM does not support big endian");
+ resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
+ } else {
+ resetDataLayout(BigEndian
+ ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+ : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+ }
+
+ // FIXME: Enumerated types are variable width in straight AAPCS.
+}
+
+void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
+ const llvm::Triple &T = getTriple();
+
+ IsAAPCS = false;
+
+ if (IsAAPCS16)
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
+ else
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
+
+ WCharType = SignedInt;
+
+ // Do not respect the alignment of bit-field types when laying out
+ // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
+ UseBitFieldTypeAlignment = false;
+
+ /// gcc forces the alignment to 4 bytes, regardless of the type of the
+ /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in
+ /// gcc.
+ ZeroLengthBitfieldBoundary = 32;
+
+ if (T.isOSBinFormatMachO() && IsAAPCS16) {
+ assert(!BigEndian && "AAPCS16 does not support big-endian");
+ resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
+ } else if (T.isOSBinFormatMachO())
+ resetDataLayout(
+ BigEndian
+ ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+ : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+ else
+ resetDataLayout(
+ BigEndian
+ ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+ : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+
+ // FIXME: Override "preferred align" for double and long long.
+}
+
+void ARMTargetInfo::setArchInfo() {
+ StringRef ArchName = getTriple().getArchName();
+
+ ArchISA = llvm::ARM::parseArchISA(ArchName);
+ CPU = llvm::ARM::getDefaultCPU(ArchName);
+ llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);
+ if (AK != llvm::ARM::ArchKind::INVALID)
+ ArchKind = AK;
+ setArchInfo(ArchKind);
+}
+
+void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
+ StringRef SubArch;
+
+ // cache TargetParser info
+ ArchKind = Kind;
+ SubArch = llvm::ARM::getSubArch(ArchKind);
+ ArchProfile = llvm::ARM::parseArchProfile(SubArch);
+ ArchVersion = llvm::ARM::parseArchVersion(SubArch);
+
+ // cache CPU related strings
+ CPUAttr = getCPUAttr();
+ CPUProfile = getCPUProfile();
+}
+
+void ARMTargetInfo::setAtomic() {
+ // when triple does not specify a sub arch,
+ // then we are not using inline atomics
+ bool ShouldUseInlineAtomic =
+ (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
+ (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
+ // Cortex M does not support 8 byte atomics, while general Thumb2 does.
+ if (ArchProfile == llvm::ARM::ProfileKind::M) {
+ MaxAtomicPromoteWidth = 32;
+ if (ShouldUseInlineAtomic)
+ MaxAtomicInlineWidth = 32;
+ } else {
+ MaxAtomicPromoteWidth = 64;
+ if (ShouldUseInlineAtomic)
+ MaxAtomicInlineWidth = 64;
+ }
+}
+
+bool ARMTargetInfo::isThumb() const {
+ return ArchISA == llvm::ARM::ISAKind::THUMB;
+}
+
+bool ARMTargetInfo::supportsThumb() const {
+ return CPUAttr.count('T') || ArchVersion >= 6;
+}
+
+bool ARMTargetInfo::supportsThumb2() const {
+ return CPUAttr.equals("6T2") ||
+ (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
+}
+
+StringRef ARMTargetInfo::getCPUAttr() const {
+ // For most sub-arches, the build attribute CPU name is enough.
+ // For Cortex variants, it's slightly different.
+ switch (ArchKind) {
+ default:
+ return llvm::ARM::getCPUAttr(ArchKind);
+ case llvm::ARM::ArchKind::ARMV6M:
+ return "6M";
+ case llvm::ARM::ArchKind::ARMV7S:
+ return "7S";
+ case llvm::ARM::ArchKind::ARMV7A:
+ return "7A";
+ case llvm::ARM::ArchKind::ARMV7R:
+ return "7R";
+ case llvm::ARM::ArchKind::ARMV7M:
+ return "7M";
+ case llvm::ARM::ArchKind::ARMV7EM:
+ return "7EM";
+ case llvm::ARM::ArchKind::ARMV7VE:
+ return "7VE";
+ case llvm::ARM::ArchKind::ARMV8A:
+ return "8A";
+ case llvm::ARM::ArchKind::ARMV8_1A:
+ return "8_1A";
+ case llvm::ARM::ArchKind::ARMV8_2A:
+ return "8_2A";
+ case llvm::ARM::ArchKind::ARMV8_3A:
+ return "8_3A";
+ case llvm::ARM::ArchKind::ARMV8_4A:
+ return "8_4A";
+ case llvm::ARM::ArchKind::ARMV8MBaseline:
+ return "8M_BASE";
+ case llvm::ARM::ArchKind::ARMV8MMainline:
+ return "8M_MAIN";
+ case llvm::ARM::ArchKind::ARMV8R:
+ return "8R";
+ }
+}
+
+StringRef ARMTargetInfo::getCPUProfile() const {
+ switch (ArchProfile) {
+ case llvm::ARM::ProfileKind::A:
+ return "A";
+ case llvm::ARM::ProfileKind::R:
+ return "R";
+ case llvm::ARM::ProfileKind::M:
+ return "M";
+ default:
+ return "";
+ }
+}
+
+ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
+ HW_FP(0) {
+ bool IsOpenBSD = Triple.getOS() == llvm::Triple::OpenBSD;
+ bool IsNetBSD = Triple.getOS() == llvm::Triple::NetBSD;
+
+ // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
+ // environment where size_t is `unsigned long` rather than `unsigned int`
+
+ PtrDiffType = IntPtrType =
+ (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
+ IsNetBSD)
+ ? SignedLong
+ : SignedInt;
+
+ SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
+ IsNetBSD)
+ ? UnsignedLong
+ : UnsignedInt;
+
+ // ptrdiff_t is inconsistent on Darwin
+ if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
+ !Triple.isWatchABI())
+ PtrDiffType = SignedInt;
+
+ // Cache arch related info.
+ setArchInfo();
+
+ // {} in inline assembly are neon specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
+ // FIXME: This duplicates code from the driver that sets the -target-abi
+ // option - this code is used if -target-abi isn't passed and should
+ // be unified in some way.
+ if (Triple.isOSBinFormatMachO()) {
+ // The backend is hardwired to assume AAPCS for M-class processors, ensure
+ // the frontend matches that.
+ if (Triple.getEnvironment() == llvm::Triple::EABI ||
+ Triple.getOS() == llvm::Triple::UnknownOS ||
+ ArchProfile == llvm::ARM::ProfileKind::M) {
+ setABI("aapcs");
+ } else if (Triple.isWatchABI()) {
+ setABI("aapcs16");
+ } else {
+ setABI("apcs-gnu");
+ }
+ } else if (Triple.isOSWindows()) {
+ // FIXME: this is invalid for WindowsCE
+ setABI("aapcs");
+ } else {
+ // Select the default based on the platform.
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::Android:
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::GNUEABIHF:
+ case llvm::Triple::MuslEABI:
+ case llvm::Triple::MuslEABIHF:
+ setABI("aapcs-linux");
+ break;
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::EABI:
+ setABI("aapcs");
+ break;
+ case llvm::Triple::GNU:
+ setABI("apcs-gnu");
+ break;
+ default:
+ if (Triple.getOS() == llvm::Triple::NetBSD)
+ setABI("apcs-gnu");
+ else if (Triple.getOS() == llvm::Triple::OpenBSD)
+ setABI("aapcs-linux");
+ else
+ setABI("aapcs");
+ break;
+ }
+ }
+
+ // ARM targets default to using the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+
+ // ARM has atomics up to 8 bytes
+ setAtomic();
+
+ // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
+ if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
+ MaxVectorAlign = 64;
+
+ // Do force alignment of members that follow zero length bitfields. If
+ // the alignment of the zero-length bitfield is greater than the member
+ // that follows it, `bar', `bar' will be aligned as the type of the
+ // zero length bitfield.
+ UseZeroLengthBitfieldAlignment = true;
+
+ if (Triple.getOS() == llvm::Triple::Linux ||
+ Triple.getOS() == llvm::Triple::UnknownOS)
+ this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
+ ? "\01__gnu_mcount_nc"
+ : "\01mcount";
+}
+
+StringRef ARMTargetInfo::getABI() const { return ABI; }
+
+bool ARMTargetInfo::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" || Name == "aapcs16") {
+ setABIAPCS(Name == "aapcs16");
+ return true;
+ }
+ if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
+ setABIAAPCS();
+ return true;
+ }
+ return false;
+}
+
+// FIXME: This should be based on Arch attributes, not CPU names.
+bool ARMTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+
+ std::string ArchFeature;
+ std::vector<StringRef> TargetFeatures;
+ llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
+
+ // Map the base architecture to an appropriate target feature, so we don't
+ // rely on the target triple.
+ llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
+ if (CPUArch == llvm::ARM::ArchKind::INVALID)
+ CPUArch = Arch;
+ if (CPUArch != llvm::ARM::ArchKind::INVALID) {
+ ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();
+ TargetFeatures.push_back(ArchFeature);
+ }
+
+ // get default FPU features
+ unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
+ llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
+
+ // get default Extension features
+ unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
+ llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
+
+ for (auto Feature : TargetFeatures)
+ if (Feature[0] == '+')
+ Features[Feature.drop_front(1)] = true;
+
+ // Enable or disable thumb-mode explicitly per function to enable mixed
+ // ARM and Thumb code generation.
+ if (isThumb())
+ Features["thumb-mode"] = true;
+ else
+ Features["thumb-mode"] = false;
+
+ // Convert user-provided arm and thumb GNU target attributes to
+ // [-|+]thumb-mode target features respectively.
+ std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
+ for (auto &Feature : UpdatedFeaturesVec) {
+ if (Feature.compare("+arm") == 0)
+ Feature = "-thumb-mode";
+ else if (Feature.compare("+thumb") == 0)
+ Feature = "+thumb-mode";
+ }
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
+}
+
+
+bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ FPU = 0;
+ CRC = 0;
+ Crypto = 0;
+ DSP = 0;
+ Unaligned = 1;
+ SoftFloat = SoftFloatABI = false;
+ HWDiv = 0;
+ DotProd = 0;
+
+ // This does not diagnose illegal cases like having both
+ // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
+ uint32_t HW_FP_remove = 0;
+ for (const auto &Feature : Features) {
+ if (Feature == "+soft-float") {
+ SoftFloat = true;
+ } else if (Feature == "+soft-float-abi") {
+ SoftFloatABI = true;
+ } else if (Feature == "+vfp2") {
+ FPU |= VFP2FPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
+ } else if (Feature == "+vfp3") {
+ FPU |= VFP3FPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
+ } else if (Feature == "+vfp4") {
+ FPU |= VFP4FPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
+ } else if (Feature == "+fp-armv8") {
+ FPU |= FPARMV8;
+ HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
+ } else if (Feature == "+neon") {
+ FPU |= NeonFPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
+ } else if (Feature == "+hwdiv") {
+ HWDiv |= HWDivThumb;
+ } else if (Feature == "+hwdiv-arm") {
+ HWDiv |= HWDivARM;
+ } else if (Feature == "+crc") {
+ CRC = 1;
+ } else if (Feature == "+crypto") {
+ Crypto = 1;
+ } else if (Feature == "+dsp") {
+ DSP = 1;
+ } else if (Feature == "+fp-only-sp") {
+ HW_FP_remove |= HW_FP_DP;
+ } else if (Feature == "+strict-align") {
+ Unaligned = 0;
+ } else if (Feature == "+fp16") {
+ HW_FP |= HW_FP_HP;
+ } else if (Feature == "+fullfp16") {
+ HasLegalHalfType = true;
+ } else if (Feature == "+dotprod") {
+ DotProd = true;
+ }
+ }
+ HW_FP &= ~HW_FP_remove;
+
+ switch (ArchVersion) {
+ case 6:
+ if (ArchProfile == llvm::ARM::ProfileKind::M)
+ LDREX = 0;
+ else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+ else
+ LDREX = LDREX_W;
+ break;
+ case 7:
+ if (ArchProfile == llvm::ARM::ProfileKind::M)
+ LDREX = LDREX_W | LDREX_H | LDREX_B;
+ else
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+ break;
+ case 8:
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+ }
+
+ if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
+ Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
+ return false;
+ }
+
+ if (FPMath == FP_Neon)
+ Features.push_back("+neonfp");
+ else if (FPMath == FP_VFP)
+ Features.push_back("-neonfp");
+
+ // Remove front-end specific options which the backend handles differently.
+ auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi");
+ if (Feature != Features.end())
+ Features.erase(Feature);
+
+ return true;
+}
+
+bool ARMTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("arm", true)
+ .Case("aarch32", true)
+ .Case("softfloat", SoftFloat)
+ .Case("thumb", isThumb())
+ .Case("neon", (FPU & NeonFPU) && !SoftFloat)
+ .Case("vfp", FPU && !SoftFloat)
+ .Case("hwdiv", HWDiv & HWDivThumb)
+ .Case("hwdiv-arm", HWDiv & HWDivARM)
+ .Default(false);
+}
+
+bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
+ return Name == "generic" ||
+ llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
+}
+
+void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ llvm::ARM::fillValidCPUArchList(Values);
+}
+
+bool ARMTargetInfo::setCPU(const std::string &Name) {
+ if (Name != "generic")
+ setArchInfo(llvm::ARM::parseCPUArch(Name));
+
+ if (ArchKind == llvm::ARM::ArchKind::INVALID)
+ return false;
+ setAtomic();
+ CPU = Name;
+ return true;
+}
+
+bool ARMTargetInfo::setFPMath(StringRef Name) {
+ if (Name == "neon") {
+ FPMath = FP_Neon;
+ return true;
+ } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
+ Name == "vfp4") {
+ FPMath = FP_VFP;
+ return true;
+ }
+ return false;
+}
+
+void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+}
+
+void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Also include the ARMv8.1-A defines
+ getTargetDefinesARMV81A(Opts, Builder);
+}
+
+void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__arm");
+ Builder.defineMacro("__arm__");
+ // For bare-metal none-eabi.
+ if (getTriple().getOS() == llvm::Triple::UnknownOS &&
+ (getTriple().getEnvironment() == llvm::Triple::EABI ||
+ getTriple().getEnvironment() == llvm::Triple::EABIHF))
+ Builder.defineMacro("__ELF__");
+
+ // Target properties.
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
+ // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
+ if (getTriple().isWatchABI())
+ Builder.defineMacro("__ARM_ARCH_7K__", "2");
+
+ if (!CPUAttr.empty())
+ Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
+
+ // ACLE 6.4.1 ARM/Thumb instruction set architecture
+ // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
+ Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
+
+ if (ArchVersion >= 8) {
+ // ACLE 6.5.7 Crypto Extension
+ if (Crypto)
+ Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+ // ACLE 6.5.8 CRC32 Extension
+ if (CRC)
+ Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
+ // ACLE 6.5.10 Numeric Maximum and Minimum
+ Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
+ // ACLE 6.5.9 Directed Rounding
+ Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
+ }
+
+ // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
+ // is not defined for the M-profile.
+ // NOTE that the default profile is assumed to be 'A'
+ if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
+ Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
+
+ // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
+ // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the
+ // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
+ // v7 and v8 architectures excluding v8-M Baseline.
+ if (supportsThumb2())
+ Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
+ else if (supportsThumb())
+ Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
+
+ // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
+ // instruction set such as ARM or Thumb.
+ Builder.defineMacro("__ARM_32BIT_STATE", "1");
+
+ // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
+
+ // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
+ if (!CPUProfile.empty())
+ Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
+
+ // ACLE 6.4.3 Unaligned access supported in hardware
+ if (Unaligned)
+ Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+
+ // ACLE 6.4.4 LDREX/STREX
+ if (LDREX)
+ Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));
+
+ // ACLE 6.4.5 CLZ
+ if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
+ ArchVersion > 6)
+ Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
+
+ // ACLE 6.5.1 Hardware Floating Point
+ if (HW_FP)
+ Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));
+
+ // ACLE predefines.
+ Builder.defineMacro("__ARM_ACLE", "200");
+
+ // FP16 support (we currently only support IEEE format).
+ Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+ Builder.defineMacro("__ARM_FP16_ARGS", "1");
+
+ // ACLE 6.5.3 Fused multiply-accumulate (FMA)
+ if (ArchVersion >= 7 && (FPU & VFP4FPU))
+ Builder.defineMacro("__ARM_FEATURE_FMA", "1");
+
+ // Subtarget options.
+
+ // FIXME: It's more complicated than this and we don't really support
+ // interworking.
+ // Windows on ARM does not "support" interworking
+ if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
+ Builder.defineMacro("__THUMB_INTERWORK__");
+
+ if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
+ // Embedded targets on Darwin follow AAPCS, but not EABI.
+ // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
+ if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
+ Builder.defineMacro("__ARM_EABI__");
+ Builder.defineMacro("__ARM_PCS", "1");
+ }
+
+ if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
+ Builder.defineMacro("__ARM_PCS_VFP", "1");
+
+ if (SoftFloat)
+ Builder.defineMacro("__SOFTFP__");
+
+ if (ArchKind == llvm::ARM::ArchKind::XSCALE)
+ Builder.defineMacro("__XSCALE__");
+
+ if (isThumb()) {
+ Builder.defineMacro("__THUMBEL__");
+ Builder.defineMacro("__thumb__");
+ if (supportsThumb2())
+ Builder.defineMacro("__thumb2__");
+ }
+
+ // ACLE 6.4.9 32-bit SIMD instructions
+ if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM"))
+ Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
+
+ // ACLE 6.4.10 Hardware Integer Divide
+ if (((HWDiv & HWDivThumb) && isThumb()) ||
+ ((HWDiv & HWDivARM) && !isThumb())) {
+ Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
+ Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
+ }
+
+ // Note, this is always on in gcc, even though it doesn't make sense.
+ Builder.defineMacro("__APCS_32__");
+
+ if (FPUModeIsVFP((FPUMode)FPU)) {
+ Builder.defineMacro("__VFP_FP__");
+ if (FPU & VFP2FPU)
+ Builder.defineMacro("__ARM_VFPV2__");
+ if (FPU & VFP3FPU)
+ Builder.defineMacro("__ARM_VFPV3__");
+ if (FPU & VFP4FPU)
+ Builder.defineMacro("__ARM_VFPV4__");
+ if (FPU & FPARMV8)
+ Builder.defineMacro("__ARM_FPV5__");
+ }
+
+ // This only gets set when Neon instructions are actually available, unlike
+ // the VFP define, hence the soft float and arch check. This is subtly
+ // different from gcc, we follow the intent which was that it should be set
+ // when Neon instructions are actually available.
+ if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
+ Builder.defineMacro("__ARM_NEON", "1");
+ Builder.defineMacro("__ARM_NEON__");
+ // current AArch32 NEON implementations do not support double-precision
+ // floating-point even when it is present in VFP.
+ Builder.defineMacro("__ARM_NEON_FP",
+ "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));
+ }
+
+ Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
+ Twine(Opts.WCharSize ? Opts.WCharSize : 4));
+
+ Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
+
+ if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+ }
+
+ // ACLE 6.4.7 DSP instructions
+ if (DSP) {
+ Builder.defineMacro("__ARM_FEATURE_DSP", "1");
+ }
+
+ // ACLE 6.4.8 Saturation instructions
+ bool SAT = false;
+ if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
+ Builder.defineMacro("__ARM_FEATURE_SAT", "1");
+ SAT = true;
+ }
+
+ // ACLE 6.4.6 Q (saturation) flag
+ if (DSP || SAT)
+ Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
+
+ if (Opts.UnsafeFPMath)
+ Builder.defineMacro("__ARM_FP_FAST", "1");
+
+ // Armv8.2-A FP16 vector intrinsic
+ if ((FPU & NeonFPU) && HasLegalHalfType)
+ Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+
+ // Armv8.2-A FP16 scalar intrinsics
+ if (HasLegalHalfType)
+ Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
+
+ // Armv8.2-A dot product intrinsics
+ if (DotProd)
+ Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
+
+ switch (ArchKind) {
+ default:
+ break;
+ case llvm::ARM::ArchKind::ARMV8_1A:
+ getTargetDefinesARMV81A(Opts, Builder);
+ break;
+ case llvm::ARM::ArchKind::ARMV8_2A:
+ getTargetDefinesARMV82A(Opts, Builder);
+ break;
+ }
+}
+
+const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsNEON.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
+ {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsARM.def"
+};
+
+ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
+TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
+ return IsAAPCS
+ ? AAPCSABIBuiltinVaList
+ : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
+ : TargetInfo::VoidPtrBuiltinVaList);
+}
+
+const char *const ARMTargetInfo::GCCRegNames[] = {
+ // Integer registers
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
+ "r12", "sp", "lr", "pc",
+
+ // Float registers
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
+ "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
+ "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+
+ // Double registers
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
+ "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
+ "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+
+ // Quad registers
+ "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
+ "q12", "q13", "q14", "q15"};
+
+ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(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"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"},
+ // The S, D and Q registers overlap, but aren't really aliases; we
+ // don't want to substitute one of these for a different-sized one.
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool ARMTargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ break;
+ case 'l': // r0-r7
+ case 'h': // r8-r15
+ case 't': // VFP Floating point register single precision
+ case 'w': // VFP Floating point register double precision
+ Info.setAllowsRegister();
+ return true;
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ // FIXME
+ return true;
+ case 'Q': // A memory address that is a single base register.
+ Info.setAllowsMemory();
+ return true;
+ case 'U': // a memory reference...
+ switch (Name[1]) {
+ case 'q': // ...ARMV4 ldrsb
+ case 'v': // ...VFP load/store (reg+constant offset)
+ case 'y': // ...iWMMXt load/store
+ case 't': // address valid for load/store opaque types wider
+ // than 128-bits
+ case 'n': // valid address for Neon doubleword vector load/store
+ case 'm': // valid address for Neon element and structure load/store
+ case 's': // valid address for non-offset loads/stores of quad-word
+ // values in four ARM registers
+ Info.setAllowsMemory();
+ Name++;
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
+ std::string R;
+ switch (*Constraint) {
+ case 'U': // Two-character constraint; add "^" hint for later parsing.
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ break;
+ case 'p': // 'p' should be translated to 'r' by default.
+ R = std::string("r");
+ break;
+ default:
+ return std::string(1, *Constraint);
+ }
+ return R;
+}
+
+bool ARMTargetInfo::validateConstraintModifier(
+ StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const {
+ bool isOutput = (Constraint[0] == '=');
+ bool isInOut = (Constraint[0] == '+');
+
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ switch (Constraint[0]) {
+ default:
+ break;
+ case 'r': {
+ switch (Modifier) {
+ default:
+ return (isInOut || isOutput || Size <= 64);
+ case 'q':
+ // A register of size 32 cannot fit a vector type.
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+const char *ARMTargetInfo::getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+}
+
+TargetInfo::CallingConvCheckResult
+ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_AAPCS:
+ case CC_AAPCS_VFP:
+ case CC_Swift:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 1;
+ return -1;
+}
+
+bool ARMTargetInfo::hasSjLjLowering() const { return true; }
+
+ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMTargetInfo(Triple, Opts) {}
+
+void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARMEL__");
+ ARMTargetInfo::getTargetDefines(Opts, Builder);
+}
+
+ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMTargetInfo(Triple, Opts) {}
+
+void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARMEB__");
+ Builder.defineMacro("__ARM_BIG_ENDIAN");
+ ARMTargetInfo::getTargetDefines(Opts, Builder);
+}
+
+WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
+}
+
+void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
+
+ // FIXME: this is invalid for WindowsCE
+ Builder.defineMacro("_M_ARM_NT", "1");
+ Builder.defineMacro("_M_ARMT", "_M_ARM");
+ Builder.defineMacro("_M_THUMB", "_M_ARM");
+
+ assert((Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb) &&
+ "invalid architecture for Windows ARM target info");
+ unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
+ Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
+
+ // TODO map the complete set of values
+ // 31: VFPv3 40: VFPv4
+ Builder.defineMacro("_M_ARM_FP", "31");
+}
+
+TargetInfo::BuiltinVaListKind
+WindowsARMTargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::CharPtrBuiltinVaList;
+}
+
+TargetInfo::CallingConvCheckResult
+WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ case CC_X86VectorCall:
+ return CCCR_Ignore;
+ case CC_C:
+ case CC_OpenCLKernel:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+// Windows ARM + Itanium C++ ABI Target
+ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
+ const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsARMTargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+}
+
+void ItaniumWindowsARMleTargetInfo::getTargetDefines(
+ const LangOptions &Opts, MacroBuilder &Builder) const {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+
+ if (Opts.MSVCCompat)
+ WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+}
+
+// Windows ARM, MS (C++) ABI
+MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARMTargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::Microsoft);
+}
+
+void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+ WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+}
+
+MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARMTargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+}
+
+void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_ARM_");
+}
+
+CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMleTargetInfo(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ TLSSupported = false;
+ DoubleAlign = LongLongAlign = 64;
+ resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+}
+
+void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ ARMleTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_ARM_");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN32__");
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+}
+
+DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
+ HasAlignMac68kSupport = true;
+ // iOS always has 64-bit atomic instructions.
+ // FIXME: This should be based off of the target features in
+ // ARMleTargetInfo.
+ MaxAtomicInlineWidth = 64;
+
+ if (Triple.isWatchABI()) {
+ // Darwin on iOS uses a variant of the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::WatchOS);
+
+ // BOOL should be a real boolean on the new ABI
+ UseSignedCharForObjCBool = false;
+ } else
+ TheCXXABI.set(TargetCXXABI::iOS);
+}
+
+void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
+ const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+}
+
+RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
+ Triple.getOSName(),
+ Triple.getEnvironmentName()),
+ Opts) {
+ IsRenderScriptTarget = true;
+ LongWidth = LongAlign = 64;
+}
+
+void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__RENDERSCRIPT__");
+ ARMleTargetInfo::getTargetDefines(Opts, Builder);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h
new file mode 100644
index 000000000000..9c72c3387f7a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h
@@ -0,0 +1,264 @@
+//===--- ARM.h - Declare ARM target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares ARM TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TargetParser.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
+ // Possible FPU choices.
+ enum FPUMode {
+ VFP2FPU = (1 << 0),
+ VFP3FPU = (1 << 1),
+ VFP4FPU = (1 << 2),
+ NeonFPU = (1 << 3),
+ FPARMV8 = (1 << 4)
+ };
+
+ // Possible HWDiv features.
+ enum HWDivMode { HWDivThumb = (1 << 0), HWDivARM = (1 << 1) };
+
+ static bool FPUModeIsVFP(FPUMode Mode) {
+ return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU | FPARMV8);
+ }
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+
+ std::string ABI, CPU;
+
+ StringRef CPUProfile;
+ StringRef CPUAttr;
+
+ enum { FP_Default, FP_VFP, FP_Neon } FPMath;
+
+ llvm::ARM::ISAKind ArchISA;
+ llvm::ARM::ArchKind ArchKind = llvm::ARM::ArchKind::ARMV4T;
+ llvm::ARM::ProfileKind ArchProfile;
+ unsigned ArchVersion;
+
+ unsigned FPU : 5;
+
+ unsigned IsAAPCS : 1;
+ unsigned HWDiv : 2;
+
+ // Initialized via features.
+ unsigned SoftFloat : 1;
+ unsigned SoftFloatABI : 1;
+
+ unsigned CRC : 1;
+ unsigned Crypto : 1;
+ unsigned DSP : 1;
+ unsigned Unaligned : 1;
+ unsigned DotProd : 1;
+
+ enum {
+ LDREX_B = (1 << 0), /// byte (8-bit)
+ LDREX_H = (1 << 1), /// half (16-bit)
+ LDREX_W = (1 << 2), /// word (32-bit)
+ LDREX_D = (1 << 3), /// double (64-bit)
+ };
+
+ uint32_t LDREX;
+
+ // ACLE 6.5.1 Hardware floating point
+ enum {
+ HW_FP_HP = (1 << 1), /// half (16-bit)
+ HW_FP_SP = (1 << 2), /// single (32-bit)
+ HW_FP_DP = (1 << 3), /// double (64-bit)
+ };
+ uint32_t HW_FP;
+
+ static const Builtin::Info BuiltinInfo[];
+
+ void setABIAAPCS();
+ void setABIAPCS(bool IsAAPCS16);
+
+ void setArchInfo();
+ void setArchInfo(llvm::ARM::ArchKind Kind);
+
+ void setAtomic();
+
+ bool isThumb() const;
+ bool supportsThumb() const;
+ bool supportsThumb2() const;
+
+ StringRef getCPUAttr() const;
+ StringRef getCPUProfile() const;
+
+public:
+ ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ StringRef getABI() const override;
+ bool setABI(const std::string &Name) override;
+
+ // FIXME: This should be based on Arch attributes, not CPU names.
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override;
+
+ bool setFPMath(StringRef Name) override;
+
+ bool useFP16ConversionIntrinsics() const override {
+ return false;
+ }
+
+ void getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+
+ void getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool isCLZForZeroUndef() const override;
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override;
+ std::string convertConstraint(const char *&Constraint) const override;
+ bool
+ validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const override;
+ const char *getClobbers() const override;
+
+ StringRef getConstraintRegister(StringRef Constraint,
+ StringRef Expression) const override {
+ return Expression;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override;
+
+ bool hasSjLjLowering() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
+public:
+ ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY ARMbeTargetInfo : public ARMTargetInfo {
+public:
+ ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY WindowsARMTargetInfo
+ : public WindowsTargetInfo<ARMleTargetInfo> {
+ const llvm::Triple Triple;
+
+public:
+ WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+};
+
+// Windows ARM + Itanium C++ ABI Target
+class LLVM_LIBRARY_VISIBILITY ItaniumWindowsARMleTargetInfo
+ : public WindowsARMTargetInfo {
+public:
+ ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+// Windows ARM, MS (C++) ABI
+class LLVM_LIBRARY_VISIBILITY MicrosoftARMleTargetInfo
+ : public WindowsARMTargetInfo {
+public:
+ MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+// ARM MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWARMTargetInfo : public WindowsARMTargetInfo {
+public:
+ MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+// ARM Cygwin target
+class LLVM_LIBRARY_VISIBILITY CygwinARMTargetInfo : public ARMleTargetInfo {
+public:
+ CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinARMTargetInfo
+ : public DarwinTargetInfo<ARMleTargetInfo> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override;
+
+public:
+ DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+};
+
+// 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes
+class LLVM_LIBRARY_VISIBILITY RenderScript32TargetInfo
+ : public ARMleTargetInfo {
+public:
+ RenderScript32TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp
new file mode 100644
index 000000000000..9b66449cbca6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp
@@ -0,0 +1,312 @@
+//===--- AVR.cpp - Implement AVR target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AVR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AVR.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+namespace clang {
+namespace targets {
+
+/// Information about a specific microcontroller.
+struct LLVM_LIBRARY_VISIBILITY MCUInfo {
+ const char *Name;
+ const char *DefineName;
+};
+
+// This list should be kept up-to-date with AVRDevices.td in LLVM.
+static MCUInfo AVRMcus[] = {
+ {"at90s1200", "__AVR_AT90S1200__"},
+ {"attiny11", "__AVR_ATtiny11__"},
+ {"attiny12", "__AVR_ATtiny12__"},
+ {"attiny15", "__AVR_ATtiny15__"},
+ {"attiny28", "__AVR_ATtiny28__"},
+ {"at90s2313", "__AVR_AT90S2313__"},
+ {"at90s2323", "__AVR_AT90S2323__"},
+ {"at90s2333", "__AVR_AT90S2333__"},
+ {"at90s2343", "__AVR_AT90S2343__"},
+ {"attiny22", "__AVR_ATtiny22__"},
+ {"attiny26", "__AVR_ATtiny26__"},
+ {"at86rf401", "__AVR_AT86RF401__"},
+ {"at90s4414", "__AVR_AT90S4414__"},
+ {"at90s4433", "__AVR_AT90S4433__"},
+ {"at90s4434", "__AVR_AT90S4434__"},
+ {"at90s8515", "__AVR_AT90S8515__"},
+ {"at90c8534", "__AVR_AT90c8534__"},
+ {"at90s8535", "__AVR_AT90S8535__"},
+ {"ata5272", "__AVR_ATA5272__"},
+ {"attiny13", "__AVR_ATtiny13__"},
+ {"attiny13a", "__AVR_ATtiny13A__"},
+ {"attiny2313", "__AVR_ATtiny2313__"},
+ {"attiny2313a", "__AVR_ATtiny2313A__"},
+ {"attiny24", "__AVR_ATtiny24__"},
+ {"attiny24a", "__AVR_ATtiny24A__"},
+ {"attiny4313", "__AVR_ATtiny4313__"},
+ {"attiny44", "__AVR_ATtiny44__"},
+ {"attiny44a", "__AVR_ATtiny44A__"},
+ {"attiny84", "__AVR_ATtiny84__"},
+ {"attiny84a", "__AVR_ATtiny84A__"},
+ {"attiny25", "__AVR_ATtiny25__"},
+ {"attiny45", "__AVR_ATtiny45__"},
+ {"attiny85", "__AVR_ATtiny85__"},
+ {"attiny261", "__AVR_ATtiny261__"},
+ {"attiny261a", "__AVR_ATtiny261A__"},
+ {"attiny461", "__AVR_ATtiny461__"},
+ {"attiny461a", "__AVR_ATtiny461A__"},
+ {"attiny861", "__AVR_ATtiny861__"},
+ {"attiny861a", "__AVR_ATtiny861A__"},
+ {"attiny87", "__AVR_ATtiny87__"},
+ {"attiny43u", "__AVR_ATtiny43U__"},
+ {"attiny48", "__AVR_ATtiny48__"},
+ {"attiny88", "__AVR_ATtiny88__"},
+ {"attiny828", "__AVR_ATtiny828__"},
+ {"at43usb355", "__AVR_AT43USB355__"},
+ {"at76c711", "__AVR_AT76C711__"},
+ {"atmega103", "__AVR_ATmega103__"},
+ {"at43usb320", "__AVR_AT43USB320__"},
+ {"attiny167", "__AVR_ATtiny167__"},
+ {"at90usb82", "__AVR_AT90USB82__"},
+ {"at90usb162", "__AVR_AT90USB162__"},
+ {"ata5505", "__AVR_ATA5505__"},
+ {"atmega8u2", "__AVR_ATmega8U2__"},
+ {"atmega16u2", "__AVR_ATmega16U2__"},
+ {"atmega32u2", "__AVR_ATmega32U2__"},
+ {"attiny1634", "__AVR_ATtiny1634__"},
+ {"atmega8", "__AVR_ATmega8__"},
+ {"ata6289", "__AVR_ATA6289__"},
+ {"atmega8a", "__AVR_ATmega8A__"},
+ {"ata6285", "__AVR_ATA6285__"},
+ {"ata6286", "__AVR_ATA6286__"},
+ {"atmega48", "__AVR_ATmega48__"},
+ {"atmega48a", "__AVR_ATmega48A__"},
+ {"atmega48pa", "__AVR_ATmega48PA__"},
+ {"atmega48p", "__AVR_ATmega48P__"},
+ {"atmega88", "__AVR_ATmega88__"},
+ {"atmega88a", "__AVR_ATmega88A__"},
+ {"atmega88p", "__AVR_ATmega88P__"},
+ {"atmega88pa", "__AVR_ATmega88PA__"},
+ {"atmega8515", "__AVR_ATmega8515__"},
+ {"atmega8535", "__AVR_ATmega8535__"},
+ {"atmega8hva", "__AVR_ATmega8HVA__"},
+ {"at90pwm1", "__AVR_AT90PWM1__"},
+ {"at90pwm2", "__AVR_AT90PWM2__"},
+ {"at90pwm2b", "__AVR_AT90PWM2B__"},
+ {"at90pwm3", "__AVR_AT90PWM3__"},
+ {"at90pwm3b", "__AVR_AT90PWM3B__"},
+ {"at90pwm81", "__AVR_AT90PWM81__"},
+ {"ata5790", "__AVR_ATA5790__"},
+ {"ata5795", "__AVR_ATA5795__"},
+ {"atmega16", "__AVR_ATmega16__"},
+ {"atmega16a", "__AVR_ATmega16A__"},
+ {"atmega161", "__AVR_ATmega161__"},
+ {"atmega162", "__AVR_ATmega162__"},
+ {"atmega163", "__AVR_ATmega163__"},
+ {"atmega164a", "__AVR_ATmega164A__"},
+ {"atmega164p", "__AVR_ATmega164P__"},
+ {"atmega164pa", "__AVR_ATmega164PA__"},
+ {"atmega165", "__AVR_ATmega165__"},
+ {"atmega165a", "__AVR_ATmega165A__"},
+ {"atmega165p", "__AVR_ATmega165P__"},
+ {"atmega165pa", "__AVR_ATmega165PA__"},
+ {"atmega168", "__AVR_ATmega168__"},
+ {"atmega168a", "__AVR_ATmega168A__"},
+ {"atmega168p", "__AVR_ATmega168P__"},
+ {"atmega168pa", "__AVR_ATmega168PA__"},
+ {"atmega169", "__AVR_ATmega169__"},
+ {"atmega169a", "__AVR_ATmega169A__"},
+ {"atmega169p", "__AVR_ATmega169P__"},
+ {"atmega169pa", "__AVR_ATmega169PA__"},
+ {"atmega32", "__AVR_ATmega32__"},
+ {"atmega32a", "__AVR_ATmega32A__"},
+ {"atmega323", "__AVR_ATmega323__"},
+ {"atmega324a", "__AVR_ATmega324A__"},
+ {"atmega324p", "__AVR_ATmega324P__"},
+ {"atmega324pa", "__AVR_ATmega324PA__"},
+ {"atmega325", "__AVR_ATmega325__"},
+ {"atmega325a", "__AVR_ATmega325A__"},
+ {"atmega325p", "__AVR_ATmega325P__"},
+ {"atmega325pa", "__AVR_ATmega325PA__"},
+ {"atmega3250", "__AVR_ATmega3250__"},
+ {"atmega3250a", "__AVR_ATmega3250A__"},
+ {"atmega3250p", "__AVR_ATmega3250P__"},
+ {"atmega3250pa", "__AVR_ATmega3250PA__"},
+ {"atmega328", "__AVR_ATmega328__"},
+ {"atmega328p", "__AVR_ATmega328P__"},
+ {"atmega329", "__AVR_ATmega329__"},
+ {"atmega329a", "__AVR_ATmega329A__"},
+ {"atmega329p", "__AVR_ATmega329P__"},
+ {"atmega329pa", "__AVR_ATmega329PA__"},
+ {"atmega3290", "__AVR_ATmega3290__"},
+ {"atmega3290a", "__AVR_ATmega3290A__"},
+ {"atmega3290p", "__AVR_ATmega3290P__"},
+ {"atmega3290pa", "__AVR_ATmega3290PA__"},
+ {"atmega406", "__AVR_ATmega406__"},
+ {"atmega64", "__AVR_ATmega64__"},
+ {"atmega64a", "__AVR_ATmega64A__"},
+ {"atmega640", "__AVR_ATmega640__"},
+ {"atmega644", "__AVR_ATmega644__"},
+ {"atmega644a", "__AVR_ATmega644A__"},
+ {"atmega644p", "__AVR_ATmega644P__"},
+ {"atmega644pa", "__AVR_ATmega644PA__"},
+ {"atmega645", "__AVR_ATmega645__"},
+ {"atmega645a", "__AVR_ATmega645A__"},
+ {"atmega645p", "__AVR_ATmega645P__"},
+ {"atmega649", "__AVR_ATmega649__"},
+ {"atmega649a", "__AVR_ATmega649A__"},
+ {"atmega649p", "__AVR_ATmega649P__"},
+ {"atmega6450", "__AVR_ATmega6450__"},
+ {"atmega6450a", "__AVR_ATmega6450A__"},
+ {"atmega6450p", "__AVR_ATmega6450P__"},
+ {"atmega6490", "__AVR_ATmega6490__"},
+ {"atmega6490a", "__AVR_ATmega6490A__"},
+ {"atmega6490p", "__AVR_ATmega6490P__"},
+ {"atmega64rfr2", "__AVR_ATmega64RFR2__"},
+ {"atmega644rfr2", "__AVR_ATmega644RFR2__"},
+ {"atmega16hva", "__AVR_ATmega16HVA__"},
+ {"atmega16hva2", "__AVR_ATmega16HVA2__"},
+ {"atmega16hvb", "__AVR_ATmega16HVB__"},
+ {"atmega16hvbrevb", "__AVR_ATmega16HVBREVB__"},
+ {"atmega32hvb", "__AVR_ATmega32HVB__"},
+ {"atmega32hvbrevb", "__AVR_ATmega32HVBREVB__"},
+ {"atmega64hve", "__AVR_ATmega64HVE__"},
+ {"at90can32", "__AVR_AT90CAN32__"},
+ {"at90can64", "__AVR_AT90CAN64__"},
+ {"at90pwm161", "__AVR_AT90PWM161__"},
+ {"at90pwm216", "__AVR_AT90PWM216__"},
+ {"at90pwm316", "__AVR_AT90PWM316__"},
+ {"atmega32c1", "__AVR_ATmega32C1__"},
+ {"atmega64c1", "__AVR_ATmega64C1__"},
+ {"atmega16m1", "__AVR_ATmega16M1__"},
+ {"atmega32m1", "__AVR_ATmega32M1__"},
+ {"atmega64m1", "__AVR_ATmega64M1__"},
+ {"atmega16u4", "__AVR_ATmega16U4__"},
+ {"atmega32u4", "__AVR_ATmega32U4__"},
+ {"atmega32u6", "__AVR_ATmega32U6__"},
+ {"at90usb646", "__AVR_AT90USB646__"},
+ {"at90usb647", "__AVR_AT90USB647__"},
+ {"at90scr100", "__AVR_AT90SCR100__"},
+ {"at94k", "__AVR_AT94K__"},
+ {"m3000", "__AVR_AT000__"},
+ {"atmega128", "__AVR_ATmega128__"},
+ {"atmega128a", "__AVR_ATmega128A__"},
+ {"atmega1280", "__AVR_ATmega1280__"},
+ {"atmega1281", "__AVR_ATmega1281__"},
+ {"atmega1284", "__AVR_ATmega1284__"},
+ {"atmega1284p", "__AVR_ATmega1284P__"},
+ {"atmega128rfa1", "__AVR_ATmega128RFA1__"},
+ {"atmega128rfr2", "__AVR_ATmega128RFR2__"},
+ {"atmega1284rfr2", "__AVR_ATmega1284RFR2__"},
+ {"at90can128", "__AVR_AT90CAN128__"},
+ {"at90usb1286", "__AVR_AT90USB1286__"},
+ {"at90usb1287", "__AVR_AT90USB1287__"},
+ {"atmega2560", "__AVR_ATmega2560__"},
+ {"atmega2561", "__AVR_ATmega2561__"},
+ {"atmega256rfr2", "__AVR_ATmega256RFR2__"},
+ {"atmega2564rfr2", "__AVR_ATmega2564RFR2__"},
+ {"atxmega16a4", "__AVR_ATxmega16A4__"},
+ {"atxmega16a4u", "__AVR_ATxmega16a4U__"},
+ {"atxmega16c4", "__AVR_ATxmega16C4__"},
+ {"atxmega16d4", "__AVR_ATxmega16D4__"},
+ {"atxmega32a4", "__AVR_ATxmega32A4__"},
+ {"atxmega32a4u", "__AVR_ATxmega32A4U__"},
+ {"atxmega32c4", "__AVR_ATxmega32C4__"},
+ {"atxmega32d4", "__AVR_ATxmega32D4__"},
+ {"atxmega32e5", "__AVR_ATxmega32E5__"},
+ {"atxmega16e5", "__AVR_ATxmega16E5__"},
+ {"atxmega8e5", "__AVR_ATxmega8E5__"},
+ {"atxmega32x1", "__AVR_ATxmega32X1__"},
+ {"atxmega64a3", "__AVR_ATxmega64A3__"},
+ {"atxmega64a3u", "__AVR_ATxmega64A3U__"},
+ {"atxmega64a4u", "__AVR_ATxmega64A4U__"},
+ {"atxmega64b1", "__AVR_ATxmega64B1__"},
+ {"atxmega64b3", "__AVR_ATxmega64B3__"},
+ {"atxmega64c3", "__AVR_ATxmega64C3__"},
+ {"atxmega64d3", "__AVR_ATxmega64D3__"},
+ {"atxmega64d4", "__AVR_ATxmega64D4__"},
+ {"atxmega64a1", "__AVR_ATxmega64A1__"},
+ {"atxmega64a1u", "__AVR_ATxmega64A1U__"},
+ {"atxmega128a3", "__AVR_ATxmega128A3__"},
+ {"atxmega128a3u", "__AVR_ATxmega128A3U__"},
+ {"atxmega128b1", "__AVR_ATxmega128B1__"},
+ {"atxmega128b3", "__AVR_ATxmega128B3__"},
+ {"atxmega128c3", "__AVR_ATxmega128C3__"},
+ {"atxmega128d3", "__AVR_ATxmega128D3__"},
+ {"atxmega128d4", "__AVR_ATxmega128D4__"},
+ {"atxmega192a3", "__AVR_ATxmega192A3__"},
+ {"atxmega192a3u", "__AVR_ATxmega192A3U__"},
+ {"atxmega192c3", "__AVR_ATxmega192C3__"},
+ {"atxmega192d3", "__AVR_ATxmega192D3__"},
+ {"atxmega256a3", "__AVR_ATxmega256A3__"},
+ {"atxmega256a3u", "__AVR_ATxmega256A3U__"},
+ {"atxmega256a3b", "__AVR_ATxmega256A3B__"},
+ {"atxmega256a3bu", "__AVR_ATxmega256A3BU__"},
+ {"atxmega256c3", "__AVR_ATxmega256C3__"},
+ {"atxmega256d3", "__AVR_ATxmega256D3__"},
+ {"atxmega384c3", "__AVR_ATxmega384C3__"},
+ {"atxmega384d3", "__AVR_ATxmega384D3__"},
+ {"atxmega128a1", "__AVR_ATxmega128A1__"},
+ {"atxmega128a1u", "__AVR_ATxmega128A1U__"},
+ {"atxmega128a4u", "__AVR_ATxmega128a4U__"},
+ {"attiny4", "__AVR_ATtiny4__"},
+ {"attiny5", "__AVR_ATtiny5__"},
+ {"attiny9", "__AVR_ATtiny9__"},
+ {"attiny10", "__AVR_ATtiny10__"},
+ {"attiny20", "__AVR_ATtiny20__"},
+ {"attiny40", "__AVR_ATtiny40__"},
+ {"attiny102", "__AVR_ATtiny102__"},
+ {"attiny104", "__AVR_ATtiny104__"},
+};
+
+} // namespace targets
+} // namespace clang
+
+static constexpr llvm::StringLiteral ValidFamilyNames[] = {
+ "avr1", "avr2", "avr25", "avr3", "avr31",
+ "avr35", "avr4", "avr5", "avr51", "avr6",
+ "avrxmega1", "avrxmega2", "avrxmega3", "avrxmega4", "avrxmega5",
+ "avrxmega6", "avrxmega7", "avrtiny"};
+
+bool AVRTargetInfo::isValidCPUName(StringRef Name) const {
+ bool IsFamily =
+ llvm::find(ValidFamilyNames, Name) != std::end(ValidFamilyNames);
+
+ bool IsMCU =
+ llvm::find_if(AVRMcus, [&](const MCUInfo &Info) {
+ return Info.Name == Name;
+ }) != std::end(AVRMcus);
+ return IsFamily || IsMCU;
+}
+
+void AVRTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidFamilyNames), std::end(ValidFamilyNames));
+ for (const MCUInfo &Info : AVRMcus)
+ Values.push_back(Info.Name);
+}
+
+void AVRTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("AVR");
+ Builder.defineMacro("__AVR");
+ Builder.defineMacro("__AVR__");
+
+ if (!this->CPU.empty()) {
+ auto It = llvm::find_if(
+ AVRMcus, [&](const MCUInfo &Info) { return Info.Name == this->CPU; });
+
+ if (It != std::end(AVRMcus))
+ Builder.defineMacro(It->DefineName);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h
new file mode 100644
index 000000000000..d595f48e8ef7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h
@@ -0,0 +1,185 @@
+//===--- AVR.h - Declare AVR target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares AVR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// AVR Target
+class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
+public:
+ AVRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ TLSSupported = false;
+ PointerWidth = 16;
+ PointerAlign = 8;
+ IntWidth = 16;
+ IntAlign = 8;
+ LongWidth = 32;
+ LongAlign = 8;
+ LongLongWidth = 64;
+ LongLongAlign = 8;
+ SuitableAlign = 8;
+ DefaultAlignForAttributeAligned = 8;
+ HalfWidth = 16;
+ HalfAlign = 8;
+ FloatWidth = 32;
+ FloatAlign = 8;
+ DoubleWidth = 32;
+ DoubleAlign = 8;
+ DoubleFormat = &llvm::APFloat::IEEEsingle();
+ LongDoubleWidth = 32;
+ LongDoubleAlign = 8;
+ LongDoubleFormat = &llvm::APFloat::IEEEsingle();
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ Char16Type = UnsignedInt;
+ WIntType = SignedInt;
+ Char32Type = UnsignedLong;
+ SigAtomicType = SignedChar;
+ resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ "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", "X", "Y", "Z", "SP"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override {
+ static const TargetInfo::AddlRegName AddlRegNames[] = {
+ {{"r26", "r27"}, 26},
+ {{"r28", "r29"}, 27},
+ {{"r30", "r31"}, 28},
+ {{"SPL", "SPH"}, 29},
+ };
+ return llvm::makeArrayRef(AddlRegNames);
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ // There aren't any multi-character AVR specific constraints.
+ if (StringRef(Name).size() > 1)
+ return false;
+
+ switch (*Name) {
+ default:
+ return false;
+ case 'a': // Simple upper registers
+ case 'b': // Base pointer registers pairs
+ case 'd': // Upper register
+ case 'l': // Lower registers
+ case 'e': // Pointer register pairs
+ case 'q': // Stack pointer register
+ case 'r': // Any register
+ case 'w': // Special upper register pairs
+ case 't': // Temporary register
+ case 'x':
+ case 'X': // Pointer register pair X
+ case 'y':
+ case 'Y': // Pointer register pair Y
+ case 'z':
+ case 'Z': // Pointer register pair Z
+ Info.setAllowsRegister();
+ return true;
+ case 'I': // 6-bit positive integer constant
+ Info.setRequiresImmediate(0, 63);
+ return true;
+ case 'J': // 6-bit negative integer constant
+ Info.setRequiresImmediate(-63, 0);
+ return true;
+ case 'K': // Integer constant (Range: 2)
+ Info.setRequiresImmediate(2);
+ return true;
+ case 'L': // Integer constant (Range: 0)
+ Info.setRequiresImmediate(0);
+ return true;
+ case 'M': // 8-bit integer constant
+ Info.setRequiresImmediate(0, 0xff);
+ return true;
+ case 'N': // Integer constant (Range: -1)
+ Info.setRequiresImmediate(-1);
+ return true;
+ case 'O': // Integer constant (Range: 8, 16, 24)
+ Info.setRequiresImmediate({8, 16, 24});
+ return true;
+ case 'P': // Integer constant (Range: 1)
+ Info.setRequiresImmediate(1);
+ return true;
+ case 'R': // Integer constant (Range: -6 to 5)
+ Info.setRequiresImmediate(-6, 5);
+ return true;
+ case 'G': // Floating point constant
+ case 'Q': // A memory address based on Y or Z pointer with displacement.
+ return true;
+ }
+
+ return false;
+ }
+
+ IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // AVR prefers int for 16-bit integers.
+ return BitWidth == 16 ? (IsSigned ? SignedInt : UnsignedInt)
+ : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
+ }
+
+ IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // AVR uses int for int_least16_t and int_fast16_t.
+ return BitWidth == 16
+ ? (IsSigned ? SignedInt : UnsignedInt)
+ : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
+ }
+
+ bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+ bool setCPU(const std::string &Name) override {
+ bool isValid = isValidCPUName(Name);
+ if (isValid)
+ CPU = Name;
+ return isValid;
+ }
+
+protected:
+ std::string CPU;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp
new file mode 100644
index 000000000000..cf41a09d76f5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp
@@ -0,0 +1,37 @@
+//===--- BPF.cpp - Implement BPF target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements BPF TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BPF.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "bpf", Opts);
+ Builder.defineMacro("__BPF__");
+}
+
+static constexpr llvm::StringLiteral ValidCPUNames[] = {"generic", "v1", "v2",
+ "probe"};
+
+bool BPFTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void BPFTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h
new file mode 100644
index 000000000000..7f97f8189145
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h
@@ -0,0 +1,99 @@
+//===--- BPF.h - Declare BPF target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares BPF TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo {
+public:
+ BPFTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
+ RegParmMax = 5;
+ if (Triple.getArch() == llvm::Triple::bpfeb) {
+ resetDataLayout("E-m:e-p:64:64-i64:64-n32:64-S128");
+ } else {
+ resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
+ }
+ MaxAtomicPromoteWidth = 64;
+ MaxAtomicInlineWidth = 64;
+ TLSSupported = false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "bpf" || Feature == "alu32" || Feature == "dwarfris";
+ }
+
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override {
+ Features[Name] = Enabled;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ const char *getClobbers() const override { return ""; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ bool isValidGCCRegisterName(StringRef Name) const override { return true; }
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ default:
+ return CCCR_Warning;
+ case CC_C:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ }
+ }
+
+ bool isValidCPUName(StringRef Name) const override;
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ StringRef CPUName(Name);
+ return isValidCPUName(CPUName);
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp
new file mode 100644
index 000000000000..0ef1f6db281e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp
@@ -0,0 +1,175 @@
+//===--- Hexagon.cpp - Implement Hexagon target feature support -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Hexagon TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Hexagon.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__qdsp6__", "1");
+ Builder.defineMacro("__hexagon__", "1");
+
+ if (CPU == "hexagonv4") {
+ Builder.defineMacro("__HEXAGON_V4__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "4");
+ if (Opts.HexagonQdsp6Compat) {
+ Builder.defineMacro("__QDSP6_V4__");
+ Builder.defineMacro("__QDSP6_ARCH__", "4");
+ }
+ } else if (CPU == "hexagonv5") {
+ Builder.defineMacro("__HEXAGON_V5__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "5");
+ if (Opts.HexagonQdsp6Compat) {
+ Builder.defineMacro("__QDSP6_V5__");
+ Builder.defineMacro("__QDSP6_ARCH__", "5");
+ }
+ } else if (CPU == "hexagonv55") {
+ Builder.defineMacro("__HEXAGON_V55__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "55");
+ Builder.defineMacro("__QDSP6_V55__");
+ Builder.defineMacro("__QDSP6_ARCH__", "55");
+ } else if (CPU == "hexagonv60") {
+ Builder.defineMacro("__HEXAGON_V60__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "60");
+ Builder.defineMacro("__QDSP6_V60__");
+ Builder.defineMacro("__QDSP6_ARCH__", "60");
+ } else if (CPU == "hexagonv62") {
+ Builder.defineMacro("__HEXAGON_V62__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "62");
+ } else if (CPU == "hexagonv65") {
+ Builder.defineMacro("__HEXAGON_V65__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "65");
+ }
+
+ if (hasFeature("hvx-length64b")) {
+ Builder.defineMacro("__HVX__");
+ Builder.defineMacro("__HVX_ARCH__", HVXVersion);
+ Builder.defineMacro("__HVX_LENGTH__", "64");
+ }
+
+ if (hasFeature("hvx-length128b")) {
+ Builder.defineMacro("__HVX__");
+ Builder.defineMacro("__HVX_ARCH__", HVXVersion);
+ Builder.defineMacro("__HVX_LENGTH__", "128");
+ // FIXME: This macro is deprecated.
+ Builder.defineMacro("__HVXDBL__");
+ }
+}
+
+bool HexagonTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ Features["long-calls"] = false;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
+bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (auto &F : Features) {
+ if (F == "+hvx-length64b")
+ HasHVX = HasHVX64B = true;
+ else if (F == "+hvx-length128b")
+ HasHVX = HasHVX128B = true;
+ else if (F.find("+hvxv") != std::string::npos) {
+ HasHVX = true;
+ HVXVersion = F.substr(std::string("+hvxv").length());
+ } else if (F == "-hvx")
+ HasHVX = HasHVX64B = HasHVX128B = false;
+ else if (F == "+long-calls")
+ UseLongCalls = true;
+ else if (F == "-long-calls")
+ UseLongCalls = false;
+ }
+ return true;
+}
+
+const char *const HexagonTargetInfo::GCCRegNames[] = {
+ "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", "p0", "p1", "p2", "p3",
+ "sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp"
+};
+
+ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
+ {{"sp"}, "r29"},
+ {{"fp"}, "r30"},
+ {{"lr"}, "r31"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsHexagon.def"
+};
+
+bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
+ std::string VS = "hvxv" + HVXVersion;
+ if (Feature == VS)
+ return true;
+
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("hexagon", true)
+ .Case("hvx", HasHVX)
+ .Case("hvx-length64b", HasHVX64B)
+ .Case("hvx-length128b", HasHVX128B)
+ .Case("long-calls", UseLongCalls)
+ .Default(false);
+}
+
+struct CPUSuffix {
+ llvm::StringLiteral Name;
+ llvm::StringLiteral Suffix;
+};
+
+static constexpr CPUSuffix Suffixes[] = {
+ {{"hexagonv4"}, {"4"}}, {{"hexagonv5"}, {"5"}},
+ {{"hexagonv55"}, {"55"}}, {{"hexagonv60"}, {"60"}},
+ {{"hexagonv62"}, {"62"}}, {{"hexagonv65"}, {"65"}},
+};
+
+const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
+ const CPUSuffix *Item = llvm::find_if(
+ Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
+ if (Item == std::end(Suffixes))
+ return nullptr;
+ return Item->Suffix.data();
+}
+
+void HexagonTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const CPUSuffix &Suffix : Suffixes)
+ Values.push_back(Suffix.Name);
+}
+
+ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h
new file mode 100644
index 000000000000..fb4956a9e53d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h
@@ -0,0 +1,130 @@
+//===--- Hexagon.h - Declare Hexagon target feature support -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Hexagon TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// Hexagon abstract base class
+class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo {
+
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ std::string CPU;
+ std::string HVXVersion;
+ bool HasHVX = false;
+ bool HasHVX64B = false;
+ bool HasHVX128B = false;
+ bool UseLongCalls = false;
+
+public:
+ HexagonTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ // Specify the vector alignment explicitly. For v512x1, the calculated
+ // alignment would be 512*alignment(i1), which is 512 bytes, instead of
+ // the required minimum of 64 bytes.
+ resetDataLayout(
+ "e-m:e-p:32:32:32-a:0-n16:32-"
+ "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-"
+ "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048");
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+
+ // {} in inline assembly are packet specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
+ LargeArrayMinWidth = 64;
+ LargeArrayAlign = 64;
+ UseBitFieldTypeAlignment = true;
+ ZeroLengthBitfieldBoundary = 32;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ case 'v':
+ case 'q':
+ if (HasHVX) {
+ Info.setAllowsRegister();
+ return true;
+ }
+ break;
+ case 'a': // Modifier register m0-m1.
+ Info.setAllowsRegister();
+ return true;
+ case 's':
+ // Relocatable constant.
+ return true;
+ }
+ return false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool isCLZForZeroUndef() const override { return false; }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ const char *getClobbers() const override { return ""; }
+
+ static const char *getHexagonCPUSuffix(StringRef Name);
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getHexagonCPUSuffix(Name);
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ if (!isValidCPUName(Name))
+ return false;
+ CPU = Name;
+ return true;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ return RegNo < 2 ? RegNo : -1;
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp
new file mode 100644
index 000000000000..0e8030c04e5c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp
@@ -0,0 +1,71 @@
+//===--- Lanai.cpp - Implement Lanai target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Lanai TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Lanai.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const char *const LanaiTargetInfo::GCCRegNames[] = {
+ "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"
+};
+
+ArrayRef<const char *> LanaiTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias LanaiTargetInfo::GCCRegAliases[] = {
+ {{"pc"}, "r2"}, {{"sp"}, "r4"}, {{"fp"}, "r5"}, {{"rv"}, "r8"},
+ {{"rr1"}, "r10"}, {{"rr2"}, "r11"}, {{"rca"}, "r15"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> LanaiTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool LanaiTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name).Case("v11", true).Default(false);
+}
+void LanaiTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ Values.emplace_back("v11");
+}
+
+bool LanaiTargetInfo::setCPU(const std::string &Name) {
+ CPU = llvm::StringSwitch<CPUKind>(Name).Case("v11", CK_V11).Default(CK_NONE);
+
+ return CPU != CK_NONE;
+}
+
+bool LanaiTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature).Case("lanai", true).Default(false);
+}
+
+void LanaiTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Define __lanai__ when building for target lanai.
+ Builder.defineMacro("__lanai__");
+
+ // Set define for the CPU specified.
+ switch (CPU) {
+ case CK_V11:
+ Builder.defineMacro("__LANAI_V11__");
+ break;
+ case CK_NONE:
+ llvm_unreachable("Unhandled target CPU");
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h
new file mode 100644
index 000000000000..b9e6dbe04433
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h
@@ -0,0 +1,94 @@
+//===--- Lanai.h - Declare Lanai target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Lanai TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY LanaiTargetInfo : public TargetInfo {
+ // Class for Lanai (32-bit).
+ // The CPU profiles supported by the Lanai backend
+ enum CPUKind {
+ CK_NONE,
+ CK_V11,
+ } CPU;
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+
+public:
+ LanaiTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ // Description string has to be kept in sync with backend.
+ resetDataLayout("E" // Big endian
+ "-m:e" // ELF name manging
+ "-p:32:32" // 32 bit pointers, 32 bit aligned
+ "-i64:64" // 64 bit integers, 64 bit aligned
+ "-a:0:32" // 32 bit alignment of objects of aggregate type
+ "-n32" // 32 bit native integer width
+ "-S64" // 64 bit natural stack alignment
+ );
+
+ // Setting RegParmMax equal to what mregparm was set to in the old
+ // toolchain
+ RegParmMax = 4;
+
+ // Set the default CPU to V11
+ CPU = CK_V11;
+
+ // Temporary approach to make everything at least word-aligned and allow for
+ // safely casting between pointers with different alignment requirements.
+ // TODO: Remove this when there are no more cast align warnings on the
+ // firmware.
+ MinGlobalAlign = 32;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool isValidCPUName(StringRef Name) const override;
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return false;
+ }
+
+ const char *getClobbers() const override { return ""; }
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp
new file mode 100644
index 000000000000..5a1c1c88e7e3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp
@@ -0,0 +1,39 @@
+//===--- Le64.cpp - Implement Le64 target feature support -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Le64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Le64.h"
+#include "Targets.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info Le64TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsLe64.def"
+};
+
+ArrayRef<Builtin::Info> Le64TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Le64::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+void Le64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "unix", Opts);
+ defineCPUMacros(Builder, "le64", /*Tuning=*/false);
+ Builder.defineMacro("__ELF__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h
new file mode 100644
index 000000000000..5e18d0498641
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h
@@ -0,0 +1,64 @@
+//===--- Le64.h - Declare Le64 target feature support -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Le64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY Le64TargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+
+public:
+ Le64TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ NoAsmVariants = true;
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ resetDataLayout("e-m:e-v128:32-v16:16-v32:32-v96:32-n8:16:32:64-S128");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::PNaClABIBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ bool hasProtectedVisibility() const override { return false; }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp
new file mode 100644
index 000000000000..86f85a398f14
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp
@@ -0,0 +1,34 @@
+//===--- MSP430.cpp - Implement MSP430 target feature support -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements MSP430 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSP430.h"
+#include "clang/Basic/MacroBuilder.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const char *const MSP430TargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+
+ArrayRef<const char *> MSP430TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+void MSP430TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("MSP430");
+ Builder.defineMacro("__MSP430__");
+ // FIXME: defines for different 'flavours' of MCU
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h
new file mode 100644
index 000000000000..72aafb9459bd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h
@@ -0,0 +1,92 @@
+//===--- MSP430.h - Declare MSP430 target feature support -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares MSP430 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY MSP430TargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+
+public:
+ MSP430TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ TLSSupported = false;
+ IntWidth = 16;
+ IntAlign = 16;
+ LongWidth = 32;
+ LongLongWidth = 64;
+ LongAlign = LongLongAlign = 16;
+ PointerWidth = 16;
+ PointerAlign = 16;
+ SuitableAlign = 16;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLongLong;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ SigAtomicType = SignedLong;
+ resetDataLayout("e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16");
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ // FIXME: Implement.
+ return None;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "msp430";
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ // FIXME: implement
+ switch (*Name) {
+ case 'K': // the constant 1
+ case 'L': // constant -1^20 .. 1^19
+ case 'M': // constant 1-4:
+ return true;
+ }
+ // No target constraints for now.
+ return false;
+ }
+
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // FIXME: implement
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp
new file mode 100644
index 000000000000..cbd5a01c3da8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp
@@ -0,0 +1,239 @@
+//===--- Mips.cpp - Implement Mips target feature support -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Mips TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Mips.h"
+#include "Targets.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info MipsTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsMips.def"
+};
+
+bool MipsTargetInfo::processorSupportsGPR64() const {
+ return llvm::StringSwitch<bool>(CPU)
+ .Case("mips3", true)
+ .Case("mips4", true)
+ .Case("mips5", true)
+ .Case("mips64", true)
+ .Case("mips64r2", true)
+ .Case("mips64r3", true)
+ .Case("mips64r5", true)
+ .Case("mips64r6", true)
+ .Case("octeon", true)
+ .Default(false);
+ return false;
+}
+
+static constexpr llvm::StringLiteral ValidCPUNames[] = {
+ {"mips1"}, {"mips2"}, {"mips3"}, {"mips4"}, {"mips5"},
+ {"mips32"}, {"mips32r2"}, {"mips32r3"}, {"mips32r5"}, {"mips32r6"},
+ {"mips64"}, {"mips64r2"}, {"mips64r3"}, {"mips64r5"}, {"mips64r6"},
+ {"octeon"}, {"p5600"}};
+
+bool MipsTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void MipsTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
+}
+
+void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ if (BigEndian) {
+ DefineStd(Builder, "MIPSEB", Opts);
+ Builder.defineMacro("_MIPSEB");
+ } else {
+ DefineStd(Builder, "MIPSEL", Opts);
+ Builder.defineMacro("_MIPSEL");
+ }
+
+ Builder.defineMacro("__mips__");
+ Builder.defineMacro("_mips");
+ if (Opts.GNUMode)
+ Builder.defineMacro("mips");
+
+ if (ABI == "o32") {
+ Builder.defineMacro("__mips", "32");
+ Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS32");
+ } else {
+ Builder.defineMacro("__mips", "64");
+ Builder.defineMacro("__mips64");
+ Builder.defineMacro("__mips64__");
+ Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");
+ }
+
+ const std::string ISARev = llvm::StringSwitch<std::string>(getCPU())
+ .Cases("mips32", "mips64", "1")
+ .Cases("mips32r2", "mips64r2", "2")
+ .Cases("mips32r3", "mips64r3", "3")
+ .Cases("mips32r5", "mips64r5", "5")
+ .Cases("mips32r6", "mips64r6", "6")
+ .Default("");
+ if (!ISARev.empty())
+ Builder.defineMacro("__mips_isa_rev", ISARev);
+
+ if (ABI == "o32") {
+ Builder.defineMacro("__mips_o32");
+ Builder.defineMacro("_ABIO32", "1");
+ Builder.defineMacro("_MIPS_SIM", "_ABIO32");
+ } else if (ABI == "n32") {
+ Builder.defineMacro("__mips_n32");
+ Builder.defineMacro("_ABIN32", "2");
+ Builder.defineMacro("_MIPS_SIM", "_ABIN32");
+ } else if (ABI == "n64") {
+ Builder.defineMacro("__mips_n64");
+ Builder.defineMacro("_ABI64", "3");
+ Builder.defineMacro("_MIPS_SIM", "_ABI64");
+ } else
+ llvm_unreachable("Invalid ABI.");
+
+ if (!IsNoABICalls) {
+ Builder.defineMacro("__mips_abicalls");
+ if (CanUseBSDABICalls)
+ Builder.defineMacro("__ABICALLS__");
+ }
+
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ switch (FloatABI) {
+ case HardFloat:
+ Builder.defineMacro("__mips_hard_float", Twine(1));
+ break;
+ case SoftFloat:
+ Builder.defineMacro("__mips_soft_float", Twine(1));
+ break;
+ }
+
+ if (IsSingleFloat)
+ Builder.defineMacro("__mips_single_float", Twine(1));
+
+ Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32));
+ Builder.defineMacro("_MIPS_FPSET",
+ Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2)));
+
+ if (IsMips16)
+ Builder.defineMacro("__mips16", Twine(1));
+
+ if (IsMicromips)
+ Builder.defineMacro("__mips_micromips", Twine(1));
+
+ if (IsNan2008)
+ Builder.defineMacro("__mips_nan2008", Twine(1));
+
+ if (IsAbs2008)
+ Builder.defineMacro("__mips_abs2008", Twine(1));
+
+ switch (DspRev) {
+ default:
+ break;
+ case DSP1:
+ Builder.defineMacro("__mips_dsp_rev", Twine(1));
+ Builder.defineMacro("__mips_dsp", Twine(1));
+ break;
+ case DSP2:
+ Builder.defineMacro("__mips_dsp_rev", Twine(2));
+ Builder.defineMacro("__mips_dspr2", Twine(1));
+ Builder.defineMacro("__mips_dsp", Twine(1));
+ break;
+ }
+
+ if (HasMSA)
+ Builder.defineMacro("__mips_msa", Twine(1));
+
+ if (DisableMadd4)
+ Builder.defineMacro("__mips_no_madd4", Twine(1));
+
+ Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0)));
+ Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
+ Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));
+
+ Builder.defineMacro("_MIPS_ARCH", "\"" + CPU + "\"");
+ Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper());
+
+ // These shouldn't be defined for MIPS-I but there's no need to check
+ // for that since MIPS-I isn't supported.
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+
+ // 32-bit MIPS processors don't have the necessary lld/scd instructions
+ // found in 64-bit processors. In the case of O32 on a 64-bit processor,
+ // the instructions exist but using them violates the ABI since they
+ // require 64-bit GPRs and O32 only supports 32-bit GPRs.
+ if (ABI == "n32" || ABI == "n64")
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+}
+
+bool MipsTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("mips", true)
+ .Case("fp64", HasFP64)
+ .Default(false);
+}
+
+ArrayRef<Builtin::Info> MipsTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Mips::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
+ // microMIPS64R6 backend was removed.
+ if (getTriple().isMIPS64() && IsMicromips && (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU;
+ return false;
+ }
+ // FIXME: It's valid to use O32 on a 64-bit CPU but the backend can't handle
+ // this yet. It's better to fail here than on the backend assertion.
+ if (processorSupportsGPR64() && ABI == "o32") {
+ Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
+ return false;
+ }
+
+ // 64-bit ABI's require 64-bit CPU's.
+ if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
+ return false;
+ }
+
+ // FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend
+ // can't handle this yet. It's better to fail here than on the
+ // backend assertion.
+ if (getTriple().isMIPS64() && ABI == "o32") {
+ Diags.Report(diag::err_target_unsupported_abi_for_triple)
+ << ABI << getTriple().str();
+ return false;
+ }
+
+ // FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend
+ // can't handle this yet. It's better to fail here than on the
+ // backend assertion.
+ if (getTriple().isMIPS32() && (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_target_unsupported_abi_for_triple)
+ << ABI << getTriple().str();
+ return false;
+ }
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h
new file mode 100644
index 000000000000..11e9ac914430
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h
@@ -0,0 +1,401 @@
+//===--- Mips.h - Declare Mips target feature support -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Mips TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
+ void setDataLayout() {
+ StringRef Layout;
+
+ if (ABI == "o32")
+ Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
+ else if (ABI == "n32")
+ Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ else if (ABI == "n64")
+ Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ else
+ llvm_unreachable("Invalid ABI");
+
+ if (BigEndian)
+ resetDataLayout(("E-" + Layout).str());
+ else
+ resetDataLayout(("e-" + Layout).str());
+ }
+
+ static const Builtin::Info BuiltinInfo[];
+ std::string CPU;
+ bool IsMips16;
+ bool IsMicromips;
+ bool IsNan2008;
+ bool IsAbs2008;
+ bool IsSingleFloat;
+ bool IsNoABICalls;
+ bool CanUseBSDABICalls;
+ enum MipsFloatABI { HardFloat, SoftFloat } FloatABI;
+ enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev;
+ bool HasMSA;
+ bool DisableMadd4;
+ bool UseIndirectJumpHazard;
+
+protected:
+ bool HasFP64;
+ std::string ABI;
+
+public:
+ MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), IsMips16(false), IsMicromips(false),
+ IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),
+ IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),
+ DspRev(NoDSP), HasMSA(false), DisableMadd4(false),
+ UseIndirectJumpHazard(false), HasFP64(false) {
+ TheCXXABI.set(TargetCXXABI::GenericMIPS);
+
+ setABI(getTriple().isMIPS32() ? "o32" : "n64");
+
+ CPU = ABI == "o32" ? "mips32r2" : "mips64r2";
+
+ CanUseBSDABICalls = Triple.getOS() == llvm::Triple::FreeBSD ||
+ Triple.getOS() == llvm::Triple::OpenBSD;
+ }
+
+ bool isIEEE754_2008Default() const {
+ return CPU == "mips32r6" || CPU == "mips64r6";
+ }
+
+ bool isFP64Default() const {
+ return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64";
+ }
+
+ bool isNan2008() const override { return IsNan2008; }
+
+ bool processorSupportsGPR64() const;
+
+ StringRef getABI() const override { return ABI; }
+
+ bool setABI(const std::string &Name) override {
+ if (Name == "o32") {
+ setO32ABITypes();
+ ABI = Name;
+ return true;
+ }
+
+ if (Name == "n32") {
+ setN32ABITypes();
+ ABI = Name;
+ return true;
+ }
+ if (Name == "n64") {
+ setN64ABITypes();
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+
+ void setO32ABITypes() {
+ Int64Type = SignedLongLong;
+ IntMaxType = Int64Type;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongWidth = LongAlign = 32;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ PointerWidth = PointerAlign = 32;
+ PtrDiffType = SignedInt;
+ SizeType = UnsignedInt;
+ SuitableAlign = 64;
+ }
+
+ void setN32N64ABITypes() {
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ if (getTriple().getOS() == llvm::Triple::FreeBSD) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ SuitableAlign = 128;
+ }
+
+ void setN64ABITypes() {
+ setN32N64ABITypes();
+ if (getTriple().getOS() == llvm::Triple::OpenBSD) {
+ Int64Type = SignedLongLong;
+ } else {
+ Int64Type = SignedLong;
+ }
+ IntMaxType = Int64Type;
+ LongWidth = LongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ PtrDiffType = SignedLong;
+ SizeType = UnsignedLong;
+ }
+
+ void setN32ABITypes() {
+ setN32N64ABITypes();
+ Int64Type = SignedLongLong;
+ IntMaxType = Int64Type;
+ LongWidth = LongAlign = 32;
+ PointerWidth = PointerAlign = 32;
+ PtrDiffType = SignedInt;
+ SizeType = UnsignedInt;
+ }
+
+ bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ CPU = Name;
+ return isValidCPUName(Name);
+ }
+
+ const std::string &getCPU() const { return CPU; }
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ if (CPU.empty())
+ CPU = getCPU();
+ if (CPU == "octeon")
+ Features["mips64r2"] = Features["cnmips"] = true;
+ else
+ Features[CPU] = true;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ // CPU register names
+ // Must match second column of GCCRegAliases
+ "$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",
+ // Floating point register names
+ "$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",
+ // Hi/lo and condition register names
+ "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5",
+ "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi",
+ "$ac3lo",
+ // MSA register names
+ "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9",
+ "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18",
+ "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27",
+ "$w28", "$w29", "$w30", "$w31",
+ // MSA control register names
+ "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",
+ "$msarequest", "$msamap", "$msaunmap"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+ case 'r': // CPU registers.
+ case 'd': // Equivalent to "r" unless generating MIPS16 code.
+ case 'y': // Equivalent to "r", backward compatibility only.
+ case 'f': // floating-point registers.
+ case 'c': // $25 for indirect jumps
+ case 'l': // lo register
+ case 'x': // hilo register pair
+ Info.setAllowsRegister();
+ return true;
+ case 'I': // Signed 16-bit constant
+ case 'J': // Integer 0
+ case 'K': // Unsigned 16-bit constant
+ case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui)
+ case 'M': // Constants not loadable via lui, addiu, or ori
+ case 'N': // Constant -1 to -65535
+ case 'O': // A signed 15-bit constant
+ case 'P': // A constant between 1 go 65535
+ return true;
+ case 'R': // An address that can be used in a non-macro load or store
+ Info.setAllowsMemory();
+ return true;
+ case 'Z':
+ if (Name[1] == 'C') { // An address usable by ll, and sc.
+ Info.setAllowsMemory();
+ Name++; // Skip over 'Z'.
+ return true;
+ }
+ return false;
+ }
+ }
+
+ std::string convertConstraint(const char *&Constraint) const override {
+ std::string R;
+ switch (*Constraint) {
+ case 'Z': // Two-character constraint; add "^" hint for later parsing.
+ if (Constraint[1] == 'C') {
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ return R;
+ }
+ break;
+ }
+ return TargetInfo::convertConstraint(Constraint);
+ }
+
+ const char *getClobbers() const override {
+ // In GCC, $1 is not widely used in generated code (it's used only in a few
+ // specific situations), so there is no real need for users to add it to
+ // the clobbers list if they want to use it in their inline assembly code.
+ //
+ // In LLVM, $1 is treated as a normal GPR and is always allocatable during
+ // code generation, so using it in inline assembly without adding it to the
+ // clobbers list can cause conflicts between the inline assembly code and
+ // the surrounding generated code.
+ //
+ // Another problem is that LLVM is allowed to choose $1 for inline assembly
+ // operands, which will conflict with the ".set at" assembler option (which
+ // we use only for inline assembly, in order to maintain compatibility with
+ // GCC) and will also conflict with the user's usage of $1.
+ //
+ // The easiest way to avoid these conflicts and keep $1 as an allocatable
+ // register for generated code is to automatically clobber $1 for all inline
+ // assembly code.
+ //
+ // FIXME: We should automatically clobber $1 only for inline assembly code
+ // which actually uses it. This would allow LLVM to use $1 for inline
+ // assembly operands if the user's assembly code doesn't use it.
+ return "~{$1}";
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ IsMips16 = false;
+ IsMicromips = false;
+ IsNan2008 = isIEEE754_2008Default();
+ IsAbs2008 = isIEEE754_2008Default();
+ IsSingleFloat = false;
+ FloatABI = HardFloat;
+ DspRev = NoDSP;
+ HasFP64 = isFP64Default();
+
+ for (const auto &Feature : Features) {
+ if (Feature == "+single-float")
+ IsSingleFloat = true;
+ else if (Feature == "+soft-float")
+ FloatABI = SoftFloat;
+ else if (Feature == "+mips16")
+ IsMips16 = true;
+ else if (Feature == "+micromips")
+ IsMicromips = true;
+ else if (Feature == "+dsp")
+ DspRev = std::max(DspRev, DSP1);
+ else if (Feature == "+dspr2")
+ DspRev = std::max(DspRev, DSP2);
+ else if (Feature == "+msa")
+ HasMSA = true;
+ else if (Feature == "+nomadd4")
+ DisableMadd4 = true;
+ else if (Feature == "+fp64")
+ HasFP64 = true;
+ else if (Feature == "-fp64")
+ HasFP64 = false;
+ else if (Feature == "+nan2008")
+ IsNan2008 = true;
+ else if (Feature == "-nan2008")
+ IsNan2008 = false;
+ else if (Feature == "+abs2008")
+ IsAbs2008 = true;
+ else if (Feature == "-abs2008")
+ IsAbs2008 = false;
+ else if (Feature == "+noabicalls")
+ IsNoABICalls = true;
+ else if (Feature == "+use-indirect-jump-hazard")
+ UseIndirectJumpHazard = true;
+ }
+
+ setDataLayout();
+
+ return true;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 4;
+ if (RegNo == 1)
+ return 5;
+ return -1;
+ }
+
+ bool isCLZForZeroUndef() const override { return false; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ static const TargetInfo::GCCRegAlias O32RegAliases[] = {
+ {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
+ {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
+ {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"},
+ {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"},
+ {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"},
+ {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
+ {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
+ {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
+ {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
+ {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
+ {{"ra"}, "$31"}
+ };
+ static const TargetInfo::GCCRegAlias NewABIRegAliases[] = {
+ {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
+ {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
+ {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"},
+ {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"},
+ {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"},
+ {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
+ {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
+ {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
+ {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
+ {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
+ {{"ra"}, "$31"}
+ };
+ if (ABI == "o32")
+ return llvm::makeArrayRef(O32RegAliases);
+ return llvm::makeArrayRef(NewABIRegAliases);
+ }
+
+ bool hasInt128Type() const override {
+ return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128;
+ }
+
+ bool validateTarget(DiagnosticsEngine &Diags) const override;
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp
new file mode 100644
index 000000000000..fd4ee1606061
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp
@@ -0,0 +1,234 @@
+//===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements NVPTX TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NVPTX.h"
+#include "Targets.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsNVPTX.def"
+};
+
+const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
+
+NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts,
+ unsigned TargetPointerWidth)
+ : TargetInfo(Triple) {
+ assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
+ "NVPTX only supports 32- and 64-bit modes.");
+
+ PTXVersion = 32;
+ for (const StringRef Feature : Opts.FeaturesAsWritten) {
+ if (!Feature.startswith("+ptx"))
+ continue;
+ PTXVersion = llvm::StringSwitch<unsigned>(Feature)
+ .Case("+ptx61", 61)
+ .Case("+ptx60", 60)
+ .Case("+ptx50", 50)
+ .Case("+ptx43", 43)
+ .Case("+ptx42", 42)
+ .Case("+ptx41", 41)
+ .Case("+ptx40", 40)
+ .Case("+ptx32", 32)
+ .Default(32);
+ }
+
+ TLSSupported = false;
+ VLASupported = false;
+ AddrSpaceMap = &NVPTXAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+
+ // Define available target features
+ // These must be defined in sorted order!
+ NoAsmVariants = true;
+ GPU = CudaArch::SM_20;
+
+ if (TargetPointerWidth == 32)
+ resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
+ else if (Opts.NVPTXUseShortPointers)
+ resetDataLayout(
+ "e-p3:32:32-p4:32:32-p5:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
+ else
+ resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64");
+
+ // If possible, get a TargetInfo for our host triple, so we can match its
+ // types.
+ llvm::Triple HostTriple(Opts.HostTriple);
+ if (!HostTriple.isNVPTX())
+ HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts));
+
+ // If no host target, make some guesses about the data layout and return.
+ if (!HostTarget) {
+ LongWidth = LongAlign = TargetPointerWidth;
+ PointerWidth = PointerAlign = TargetPointerWidth;
+ switch (TargetPointerWidth) {
+ case 32:
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = TargetInfo::SignedInt;
+ IntPtrType = TargetInfo::SignedInt;
+ break;
+ case 64:
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = TargetInfo::SignedLong;
+ IntPtrType = TargetInfo::SignedLong;
+ break;
+ default:
+ llvm_unreachable("TargetPointerWidth must be 32 or 64");
+ }
+ return;
+ }
+
+ // Copy properties from host target.
+ PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0);
+ PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0);
+ BoolWidth = HostTarget->getBoolWidth();
+ BoolAlign = HostTarget->getBoolAlign();
+ IntWidth = HostTarget->getIntWidth();
+ IntAlign = HostTarget->getIntAlign();
+ HalfWidth = HostTarget->getHalfWidth();
+ HalfAlign = HostTarget->getHalfAlign();
+ FloatWidth = HostTarget->getFloatWidth();
+ FloatAlign = HostTarget->getFloatAlign();
+ DoubleWidth = HostTarget->getDoubleWidth();
+ DoubleAlign = HostTarget->getDoubleAlign();
+ LongWidth = HostTarget->getLongWidth();
+ LongAlign = HostTarget->getLongAlign();
+ LongLongWidth = HostTarget->getLongLongWidth();
+ LongLongAlign = HostTarget->getLongLongAlign();
+ MinGlobalAlign = HostTarget->getMinGlobalAlign();
+ NewAlign = HostTarget->getNewAlign();
+ DefaultAlignForAttributeAligned =
+ HostTarget->getDefaultAlignForAttributeAligned();
+ SizeType = HostTarget->getSizeType();
+ IntMaxType = HostTarget->getIntMaxType();
+ PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0);
+ IntPtrType = HostTarget->getIntPtrType();
+ WCharType = HostTarget->getWCharType();
+ WIntType = HostTarget->getWIntType();
+ Char16Type = HostTarget->getChar16Type();
+ Char32Type = HostTarget->getChar32Type();
+ Int64Type = HostTarget->getInt64Type();
+ SigAtomicType = HostTarget->getSigAtomicType();
+ ProcessIDType = HostTarget->getProcessIDType();
+
+ UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
+ UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();
+ UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
+ ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
+
+ // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
+ // we need those macros to be identical on host and device, because (among
+ // other things) they affect which standard library classes are defined, and
+ // we need all classes to be defined on both the host and device.
+ MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
+
+ // Properties intentionally not copied from host:
+ // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
+ // host/device boundary.
+ // - SuitableAlign: Not visible across the host/device boundary, and may
+ // correctly be different on host/device, e.g. if host has wider vector
+ // types than device.
+ // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
+ // as its double type, but that's not necessarily true on the host.
+ // TODO: nvcc emits a warning when using long double on device; we should
+ // do the same.
+}
+
+ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Cases("ptx", "nvptx", true)
+ .Default(false);
+}
+
+void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__PTX__");
+ Builder.defineMacro("__NVPTX__");
+ if (Opts.CUDAIsDevice) {
+ // Set __CUDA_ARCH__ for the GPU specified.
+ std::string CUDAArchCode = [this] {
+ switch (GPU) {
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ case CudaArch::LAST:
+ break;
+ case CudaArch::UNKNOWN:
+ assert(false && "No GPU arch when compiling CUDA device code.");
+ return "";
+ case CudaArch::SM_20:
+ return "200";
+ case CudaArch::SM_21:
+ return "210";
+ case CudaArch::SM_30:
+ return "300";
+ case CudaArch::SM_32:
+ return "320";
+ case CudaArch::SM_35:
+ return "350";
+ case CudaArch::SM_37:
+ return "370";
+ case CudaArch::SM_50:
+ return "500";
+ case CudaArch::SM_52:
+ return "520";
+ case CudaArch::SM_53:
+ return "530";
+ case CudaArch::SM_60:
+ return "600";
+ case CudaArch::SM_61:
+ return "610";
+ case CudaArch::SM_62:
+ return "620";
+ case CudaArch::SM_70:
+ return "700";
+ case CudaArch::SM_72:
+ return "720";
+ }
+ llvm_unreachable("unhandled CudaArch");
+ }();
+ Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
+ }
+}
+
+ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h
new file mode 100644
index 000000000000..84d466d2f49f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h
@@ -0,0 +1,140 @@
+//===--- NVPTX.h - Declare NVPTX target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares NVPTX TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
+
+#include "clang/Basic/Cuda.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+static const unsigned NVPTXAddrSpaceMap[] = {
+ 0, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 4, // opencl_constant
+ 0, // opencl_private
+ // FIXME: generic has to be added to the target
+ 0, // opencl_generic
+ 1, // cuda_device
+ 4, // cuda_constant
+ 3, // cuda_shared
+};
+
+class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+ static const Builtin::Info BuiltinInfo[];
+ CudaArch GPU;
+ uint32_t PTXVersion;
+ std::unique_ptr<TargetInfo> HostTarget;
+
+public:
+ NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts,
+ unsigned TargetPointerWidth);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ Features[CudaArchToString(GPU)] = true;
+ Features["ptx" + std::to_string(PTXVersion)] = true;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+ case 'c':
+ case 'h':
+ case 'r':
+ case 'l':
+ case 'f':
+ case 'd':
+ Info.setAllowsRegister();
+ return true;
+ }
+ }
+
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // FIXME: implement
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ return StringToCudaArch(Name) != CudaArch::UNKNOWN;
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
+ for (int i = static_cast<int>(CudaArch::SM_20);
+ i < static_cast<int>(CudaArch::LAST); ++i)
+ Values.emplace_back(CudaArchToString(static_cast<CudaArch>(i)));
+ }
+
+ bool setCPU(const std::string &Name) override {
+ GPU = StringToCudaArch(Name);
+ return GPU != CudaArch::UNKNOWN;
+ }
+
+ void setSupportedOpenCLOpts() override {
+ auto &Opts = getSupportedOpenCLOpts();
+ Opts.support("cl_clang_storage_class_specifiers");
+ Opts.support("cl_khr_gl_sharing");
+ Opts.support("cl_khr_icd");
+
+ Opts.support("cl_khr_fp64");
+ Opts.support("cl_khr_byte_addressable_store");
+ Opts.support("cl_khr_global_int32_base_atomics");
+ Opts.support("cl_khr_global_int32_extended_atomics");
+ Opts.support("cl_khr_local_int32_base_atomics");
+ Opts.support("cl_khr_local_int32_extended_atomics");
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ // CUDA compilations support all of the host's calling conventions.
+ //
+ // TODO: We should warn if you apply a non-default CC to anything other than
+ // a host function.
+ if (HostTarget)
+ return HostTarget->checkCallingConvention(CC);
+ return CCCR_Warning;
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp
new file mode 100644
index 000000000000..48f662dd98c1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp
@@ -0,0 +1,56 @@
+//===--- Nios2.cpp - Implement Nios2 target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Nios2 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Nios2.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info Nios2TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsNios2.def"
+};
+
+bool Nios2TargetInfo::isFeatureSupportedByCPU(StringRef Feature,
+ StringRef CPU) const {
+ const bool isR2 = CPU == "nios2r2";
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("nios2r2mandatory", isR2)
+ .Case("nios2r2bmx", isR2)
+ .Case("nios2r2mpx", isR2)
+ .Case("nios2r2cdx", isR2)
+ .Default(false);
+}
+
+void Nios2TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "nios2", Opts);
+ DefineStd(Builder, "NIOS2", Opts);
+
+ Builder.defineMacro("__nios2");
+ Builder.defineMacro("__NIOS2");
+ Builder.defineMacro("__nios2__");
+ Builder.defineMacro("__NIOS2__");
+}
+
+ArrayRef<Builtin::Info> Nios2TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Nios2::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h
new file mode 100644
index 000000000000..ffeb414d4778
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h
@@ -0,0 +1,151 @@
+//===--- Nios2.h - Declare Nios2 target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Nios2 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY Nios2TargetInfo : public TargetInfo {
+ void setDataLayout() {
+ if (BigEndian)
+ resetDataLayout("E-p:32:32:32-i8:8:32-i16:16:32-n32");
+ else
+ resetDataLayout("e-p:32:32:32-i8:8:32-i16:16:32-n32");
+ }
+
+ static const Builtin::Info BuiltinInfo[];
+ std::string CPU;
+ std::string ABI;
+
+public:
+ Nios2TargetInfo(const llvm::Triple &triple, const TargetOptions &opts)
+ : TargetInfo(triple), CPU(opts.CPU), ABI(opts.ABI) {
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ setDataLayout();
+ }
+
+ StringRef getABI() const override { return ABI; }
+ bool setABI(const std::string &Name) override {
+ if (Name == "o32" || Name == "eabi") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ return Name == "nios2r1" || Name == "nios2r2";
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
+ Values.append({"nios2r1", "nios2r2"});
+ }
+
+ bool setCPU(const std::string &Name) override {
+ if (isValidCPUName(Name)) {
+ CPU = Name;
+ return true;
+ }
+ return false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool isFeatureSupportedByCPU(StringRef Feature, StringRef CPU) const;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const override {
+ static const char *allFeatures[] = {"nios2r2mandatory", "nios2r2bmx",
+ "nios2r2mpx", "nios2r2cdx"
+ };
+ for (const char *feature : allFeatures) {
+ Features[feature] = isFeatureSupportedByCPU(feature, CPU);
+ }
+ return true;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return isFeatureSupportedByCPU(Feature, CPU);
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ // CPU register names
+ // Must match second column of GCCRegAliases
+ "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",
+ // Floating point register names
+ "ctl0", "ctl1", "ctl2", "ctl3", "ctl4", "ctl5", "ctl6", "ctl7", "ctl8",
+ "ctl9", "ctl10", "ctl11", "ctl12", "ctl13", "ctl14", "ctl15"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+
+ case 'r': // CPU registers.
+ case 'd': // Equivalent to "r" unless generating MIPS16 code.
+ case 'y': // Equivalent to "r", backwards compatibility only.
+ case 'f': // floating-point registers.
+ case 'c': // $25 for indirect jumps
+ case 'l': // lo register
+ case 'x': // hilo register pair
+ Info.setAllowsRegister();
+ return true;
+ }
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ static const TargetInfo::GCCRegAlias aliases[] = {
+ {{"zero"}, "r0"}, {{"at"}, "r1"}, {{"et"}, "r24"},
+ {{"bt"}, "r25"}, {{"gp"}, "r26"}, {{"sp"}, "r27"},
+ {{"fp"}, "r28"}, {{"ea"}, "r29"}, {{"ba"}, "r30"},
+ {{"ra"}, "r31"}, {{"status"}, "ctl0"}, {{"estatus"}, "ctl1"},
+ {{"bstatus"}, "ctl2"}, {{"ienable"}, "ctl3"}, {{"ipending"}, "ctl4"},
+ {{"cpuid"}, "ctl5"}, {{"exception"}, "ctl7"}, {{"pteaddr"}, "ctl8"},
+ {{"tlbacc"}, "ctl9"}, {{"tlbmisc"}, "ctl10"}, {{"badaddr"}, "ctl12"},
+ {{"config"}, "ctl13"}, {{"mpubase"}, "ctl14"}, {{"mpuacc"}, "ctl15"},
+ };
+ return llvm::makeArrayRef(aliases);
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp
new file mode 100644
index 000000000000..50abd4ce0c8c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp
@@ -0,0 +1,139 @@
+//===--- OSTargets.cpp - Implement OS target feature support --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements OS specific TargetInfo types.
+//===----------------------------------------------------------------------===//
+
+#include "OSTargets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+namespace clang {
+namespace targets {
+
+void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
+ const llvm::Triple &Triple, StringRef &PlatformName,
+ VersionTuple &PlatformMinVersion) {
+ Builder.defineMacro("__APPLE_CC__", "6000");
+ Builder.defineMacro("__APPLE__");
+ Builder.defineMacro("__STDC_NO_THREADS__");
+ Builder.defineMacro("OBJC_NEW_PROPERTIES");
+ // AddressSanitizer doesn't play well with source fortification, which is on
+ // by default on Darwin.
+ if (Opts.Sanitize.has(SanitizerKind::Address))
+ Builder.defineMacro("_FORTIFY_SOURCE", "0");
+
+ // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode.
+ if (!Opts.ObjC1) {
+ // __weak is always defined, for use in blocks and with objc pointers.
+ Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
+ Builder.defineMacro("__strong", "");
+ Builder.defineMacro("__unsafe_unretained", "");
+ }
+
+ if (Opts.Static)
+ Builder.defineMacro("__STATIC__");
+ else
+ Builder.defineMacro("__DYNAMIC__");
+
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+
+ // Get the platform type and version number from the triple.
+ unsigned Maj, Min, Rev;
+ if (Triple.isMacOSX()) {
+ Triple.getMacOSXVersion(Maj, Min, Rev);
+ PlatformName = "macos";
+ } else {
+ Triple.getOSVersion(Maj, Min, Rev);
+ PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
+ }
+
+ // If -target arch-pc-win32-macho option specified, we're
+ // generating code for Win32 ABI. No need to emit
+ // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__.
+ if (PlatformName == "win32") {
+ PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+ return;
+ }
+
+ // Set the appropriate OS version define.
+ if (Triple.isiOS()) {
+ assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
+ char Str[7];
+ if (Maj < 10) {
+ Str[0] = '0' + Maj;
+ Str[1] = '0' + (Min / 10);
+ Str[2] = '0' + (Min % 10);
+ Str[3] = '0' + (Rev / 10);
+ Str[4] = '0' + (Rev % 10);
+ Str[5] = '\0';
+ } else {
+ // Handle versions >= 10.
+ Str[0] = '0' + (Maj / 10);
+ Str[1] = '0' + (Maj % 10);
+ Str[2] = '0' + (Min / 10);
+ Str[3] = '0' + (Min % 10);
+ Str[4] = '0' + (Rev / 10);
+ Str[5] = '0' + (Rev % 10);
+ Str[6] = '\0';
+ }
+ if (Triple.isTvOS())
+ Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str);
+ else
+ Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
+ Str);
+
+ } else if (Triple.isWatchOS()) {
+ assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!");
+ char Str[6];
+ Str[0] = '0' + Maj;
+ Str[1] = '0' + (Min / 10);
+ Str[2] = '0' + (Min % 10);
+ Str[3] = '0' + (Rev / 10);
+ Str[4] = '0' + (Rev % 10);
+ Str[5] = '\0';
+ Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str);
+ } else if (Triple.isMacOSX()) {
+ // Note that the Driver allows versions which aren't representable in the
+ // define (because we only get a single digit for the minor and micro
+ // revision numbers). So, we limit them to the maximum representable
+ // version.
+ assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
+ char Str[7];
+ if (Maj < 10 || (Maj == 10 && Min < 10)) {
+ Str[0] = '0' + (Maj / 10);
+ Str[1] = '0' + (Maj % 10);
+ Str[2] = '0' + std::min(Min, 9U);
+ Str[3] = '0' + std::min(Rev, 9U);
+ Str[4] = '\0';
+ } else {
+ // Handle versions > 10.9.
+ Str[0] = '0' + (Maj / 10);
+ Str[1] = '0' + (Maj % 10);
+ Str[2] = '0' + (Min / 10);
+ Str[3] = '0' + (Min % 10);
+ Str[4] = '0' + (Rev / 10);
+ Str[5] = '0' + (Rev % 10);
+ Str[6] = '\0';
+ }
+ Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
+ }
+
+ // Tell users about the kernel if there is one.
+ if (Triple.isOSDarwin())
+ Builder.defineMacro("__MACH__");
+
+ PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+}
+} // namespace targets
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h
new file mode 100644
index 000000000000..d0354784acf9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h
@@ -0,0 +1,745 @@
+//===--- OSTargets.h - Declare OS target feature support --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares OS specific TargetInfo types.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
+
+#include "Targets.h"
+#include "llvm/MC/MCSectionMachO.h"
+
+namespace clang {
+namespace targets {
+
+template <typename TgtInfo>
+class LLVM_LIBRARY_VISIBILITY OSTargetInfo : public TgtInfo {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const = 0;
+
+public:
+ OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : TgtInfo(Triple, Opts) {}
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ TgtInfo::getTargetDefines(Opts, Builder);
+ getOSDefines(Opts, TgtInfo::getTriple(), Builder);
+ }
+};
+
+// CloudABI Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY CloudABITargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__CloudABI__");
+ Builder.defineMacro("__ELF__");
+
+ // CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t.
+ Builder.defineMacro("__STDC_ISO_10646__", "201206L");
+ Builder.defineMacro("__STDC_UTF_16__");
+ Builder.defineMacro("__STDC_UTF_32__");
+ }
+
+public:
+ CloudABITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+// Ananas target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY AnanasTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Ananas defines
+ Builder.defineMacro("__Ananas__");
+ Builder.defineMacro("__ELF__");
+ }
+
+public:
+ AnanasTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
+ const llvm::Triple &Triple, StringRef &PlatformName,
+ VersionTuple &PlatformMinVersion);
+
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ getDarwinDefines(Builder, Opts, Triple, this->PlatformName,
+ this->PlatformMinVersion);
+ }
+
+public:
+ DarwinTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ // By default, no TLS, and we whitelist permitted architecture/OS
+ // combinations.
+ this->TLSSupported = false;
+
+ if (Triple.isMacOSX())
+ this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
+ else if (Triple.isiOS()) {
+ // 64-bit iOS supported it from 8 onwards, 32-bit device from 9 onwards,
+ // 32-bit simulator from 10 onwards.
+ if (Triple.isArch64Bit())
+ this->TLSSupported = !Triple.isOSVersionLT(8);
+ else if (Triple.isArch32Bit()) {
+ if (!Triple.isSimulatorEnvironment())
+ this->TLSSupported = !Triple.isOSVersionLT(9);
+ else
+ this->TLSSupported = !Triple.isOSVersionLT(10);
+ }
+ } else if (Triple.isWatchOS()) {
+ if (!Triple.isSimulatorEnvironment())
+ this->TLSSupported = !Triple.isOSVersionLT(2);
+ else
+ this->TLSSupported = !Triple.isOSVersionLT(3);
+ }
+
+ this->MCountName = "\01mcount";
+ }
+
+ std::string isValidSectionSpecifier(StringRef SR) const override {
+ // Let MCSectionMachO validate this.
+ StringRef Segment, Section;
+ unsigned TAA, StubSize;
+ bool HasTAA;
+ return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
+ TAA, HasTAA, StubSize);
+ }
+
+ const char *getStaticInitSectionSpecifier() const override {
+ // FIXME: We should return 0 when building kexts.
+ return "__TEXT,__StaticInit,regular,pure_instructions";
+ }
+
+ /// Darwin does not support protected visibility. Darwin's "default"
+ /// is very similar to ELF's "protected"; Darwin requires a "weak"
+ /// attribute on declarations that can be dynamically replaced.
+ bool hasProtectedVisibility() const override { return false; }
+};
+
+// DragonFlyBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY DragonFlyBSDTargetInfo
+ : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // DragonFly defines; list based off of gcc output
+ Builder.defineMacro("__DragonFly__");
+ Builder.defineMacro("__DragonFly_cc_version", "100001");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ Builder.defineMacro("__tune_i386__");
+ DefineStd(Builder, "unix", Opts);
+ }
+
+public:
+ DragonFlyBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ break;
+ }
+ }
+};
+
+#ifndef FREEBSD_CC_VERSION
+#define FREEBSD_CC_VERSION 0U
+#endif
+
+// FreeBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY FreeBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // FreeBSD defines; list based off of gcc output
+
+ unsigned Release = Triple.getOSMajorVersion();
+ if (Release == 0U)
+ Release = 8U;
+ unsigned CCVersion = FREEBSD_CC_VERSION;
+ if (CCVersion == 0U)
+ CCVersion = Release * 100000U + 1U;
+
+ Builder.defineMacro("__FreeBSD__", Twine(Release));
+ Builder.defineMacro("__FreeBSD_cc_version", Twine(CCVersion));
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+
+ // On FreeBSD, wchar_t contains the number of the code point as
+ // used by the character set of the locale. These character sets are
+ // not necessarily a superset of ASCII.
+ //
+ // FIXME: This is wrong; the macro refers to the numerical values
+ // of wchar_t *literals*, which are not locale-dependent. However,
+ // FreeBSD systems apparently depend on us getting this wrong, and
+ // setting this to 1 is conforming even if all the basic source
+ // character literals have the same encoding as char and wchar_t.
+ Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1");
+ }
+
+public:
+ FreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ this->MCountName = "_mcount";
+ break;
+ case llvm::Triple::arm:
+ this->MCountName = "__mcount";
+ break;
+ }
+ }
+};
+
+// GNU/kFreeBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY KFreeBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // GNU/kFreeBSD defines; list based off of gcc output
+
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__FreeBSD_kernel__");
+ Builder.defineMacro("__GLIBC__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ KFreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+// Haiku Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY HaikuTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Haiku defines; list based off of gcc output
+ Builder.defineMacro("__HAIKU__");
+ Builder.defineMacro("__ELF__");
+ DefineStd(Builder, "unix", Opts);
+ }
+
+public:
+ HaikuTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->SizeType = TargetInfo::UnsignedLong;
+ this->IntPtrType = TargetInfo::SignedLong;
+ this->PtrDiffType = TargetInfo::SignedLong;
+ this->ProcessIDType = TargetInfo::SignedLong;
+ this->TLSSupported = false;
+ }
+};
+
+// Minix Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY MinixTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Minix defines
+
+ Builder.defineMacro("__minix", "3");
+ Builder.defineMacro("_EM_WSIZE", "4");
+ Builder.defineMacro("_EM_PSIZE", "4");
+ Builder.defineMacro("_EM_SSIZE", "2");
+ Builder.defineMacro("_EM_LSIZE", "4");
+ Builder.defineMacro("_EM_FSIZE", "4");
+ Builder.defineMacro("_EM_DSIZE", "8");
+ Builder.defineMacro("__ELF__");
+ DefineStd(Builder, "unix", Opts);
+ }
+
+public:
+ MinixTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+// Linux target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Linux defines; list based off of gcc output
+ DefineStd(Builder, "unix", Opts);
+ DefineStd(Builder, "linux", Opts);
+ Builder.defineMacro("__gnu_linux__");
+ Builder.defineMacro("__ELF__");
+ if (Triple.isAndroid()) {
+ Builder.defineMacro("__ANDROID__", "1");
+ unsigned Maj, Min, Rev;
+ Triple.getEnvironmentVersion(Maj, Min, Rev);
+ this->PlatformName = "android";
+ this->PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+ if (Maj)
+ Builder.defineMacro("__ANDROID_API__", Twine(Maj));
+ }
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
+ }
+
+public:
+ LinuxTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WIntType = TargetInfo::UnsignedInt;
+
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ this->MCountName = "_mcount";
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ case llvm::Triple::systemz:
+ this->HasFloat128 = true;
+ break;
+ }
+ }
+
+ const char *getStaticInitSectionSpecifier() const override {
+ return ".text.startup";
+ }
+};
+
+// NetBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY NetBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // NetBSD defines; list based off of gcc output
+ Builder.defineMacro("__NetBSD__");
+ Builder.defineMacro("__unix__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ }
+
+public:
+ NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->MCountName = "__mcount";
+ }
+};
+
+// OpenBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // OpenBSD defines; list based off of gcc output
+
+ Builder.defineMacro("__OpenBSD__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
+ }
+
+public:
+ OpenBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->HasFloat128 = true;
+ // FALLTHROUGH
+ default:
+ this->MCountName = "__mcount";
+ break;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::ppc:
+ case llvm::Triple::sparcv9:
+ this->MCountName = "_mcount";
+ break;
+ }
+ }
+};
+
+// PSP Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY PSPTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // PSP defines; list based on the output of the pspdev gcc toolchain.
+ Builder.defineMacro("PSP");
+ Builder.defineMacro("_PSP");
+ Builder.defineMacro("__psp__");
+ Builder.defineMacro("__ELF__");
+ }
+
+public:
+ PSPTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {}
+};
+
+// PS3 PPU Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY PS3PPUTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // PS3 PPU defines.
+ Builder.defineMacro("__PPC__");
+ Builder.defineMacro("__PPU__");
+ Builder.defineMacro("__CELLOS_LV2__");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__LP32__");
+ Builder.defineMacro("_ARCH_PPC64");
+ Builder.defineMacro("__powerpc64__");
+ }
+
+public:
+ PS3PPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->LongWidth = this->LongAlign = 32;
+ this->PointerWidth = this->PointerAlign = 32;
+ this->IntMaxType = TargetInfo::SignedLongLong;
+ this->Int64Type = TargetInfo::SignedLongLong;
+ this->SizeType = TargetInfo::UnsignedInt;
+ this->resetDataLayout("E-m:e-p:32:32-i64:64-n32:64");
+ }
+};
+
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY PS4OSTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__FreeBSD__", "9");
+ Builder.defineMacro("__FreeBSD_cc_version", "900001");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__ORBIS__");
+ }
+
+public:
+ PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+
+ // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits).
+ this->MaxTLSAlign = 256;
+
+ // On PS4, do not honor explicit bit field alignment,
+ // as in "__attribute__((aligned(2))) int b : 1;".
+ this->UseExplicitBitFieldAlignment = false;
+
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ this->NewAlign = 256;
+ break;
+ }
+ }
+};
+
+// RTEMS Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY RTEMSTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // RTEMS defines; list based off of gcc output
+
+ Builder.defineMacro("__rtems__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ RTEMSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86:
+ // this->MCountName = ".mcount";
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ // this->MCountName = "_mcount";
+ break;
+ case llvm::Triple::arm:
+ // this->MCountName = "__mcount";
+ break;
+ }
+ }
+};
+
+// Solaris target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY SolarisTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "sun", Opts);
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__svr4__");
+ Builder.defineMacro("__SVR4");
+ // Solaris headers require _XOPEN_SOURCE to be set to 600 for C99 and
+ // newer, but to 500 for everything else. feature_test.h has a check to
+ // ensure that you are not using C99 with an old version of X/Open or C89
+ // with a new version.
+ if (Opts.C99)
+ Builder.defineMacro("_XOPEN_SOURCE", "600");
+ else
+ Builder.defineMacro("_XOPEN_SOURCE", "500");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("__C99FEATURES__");
+ Builder.defineMacro("_LARGEFILE_SOURCE");
+ Builder.defineMacro("_LARGEFILE64_SOURCE");
+ Builder.defineMacro("__EXTENSIONS__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
+ }
+
+public:
+ SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ // FIXME: WIntType should be SignedLong
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->HasFloat128 = true;
+ break;
+ }
+ }
+};
+
+// Windows target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY WindowsTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("_WIN32");
+ if (Triple.isArch64Bit())
+ Builder.defineMacro("_WIN64");
+ if (Triple.isWindowsGNUEnvironment())
+ addMinGWDefines(Triple, Opts, Builder);
+
+ }
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ if (Opts.CPlusPlus) {
+ if (Opts.RTTIData)
+ Builder.defineMacro("_CPPRTTI");
+
+ if (Opts.CXXExceptions)
+ Builder.defineMacro("_CPPUNWIND");
+ }
+
+ if (Opts.Bool)
+ Builder.defineMacro("__BOOL_DEFINED");
+
+ if (!Opts.CharIsSigned)
+ Builder.defineMacro("_CHAR_UNSIGNED");
+
+ // FIXME: POSIXThreads isn't exactly the option this should be defined for,
+ // but it works for now.
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_MT");
+
+ if (Opts.MSCompatibilityVersion) {
+ Builder.defineMacro("_MSC_VER",
+ Twine(Opts.MSCompatibilityVersion / 100000));
+ Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion));
+ // FIXME We cannot encode the revision information into 32-bits
+ Builder.defineMacro("_MSC_BUILD", Twine(1));
+
+ if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015))
+ Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
+
+ if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
+ if (Opts.CPlusPlus2a)
+ Builder.defineMacro("_MSVC_LANG", "201704L");
+ else if (Opts.CPlusPlus17)
+ Builder.defineMacro("_MSVC_LANG", "201703L");
+ else if (Opts.CPlusPlus14)
+ Builder.defineMacro("_MSVC_LANG", "201402L");
+ }
+ }
+
+ if (Opts.MicrosoftExt) {
+ Builder.defineMacro("_MSC_EXTENSIONS");
+
+ if (Opts.CPlusPlus11) {
+ Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
+ Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
+ Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
+ }
+ }
+
+ Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
+ }
+
+public:
+ WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ }
+};
+
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY NaClTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__native_client__");
+ }
+
+public:
+ NaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->LongAlign = 32;
+ this->LongWidth = 32;
+ this->PointerAlign = 32;
+ this->PointerWidth = 32;
+ this->IntMaxType = TargetInfo::SignedLongLong;
+ this->Int64Type = TargetInfo::SignedLongLong;
+ this->DoubleAlign = 64;
+ this->LongDoubleWidth = 64;
+ this->LongDoubleAlign = 64;
+ this->LongLongWidth = 64;
+ this->LongLongAlign = 64;
+ this->SizeType = TargetInfo::UnsignedInt;
+ this->PtrDiffType = TargetInfo::SignedInt;
+ this->IntPtrType = TargetInfo::SignedInt;
+ // RegParmMax is inherited from the underlying architecture.
+ this->LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ if (Triple.getArch() == llvm::Triple::arm) {
+ // Handled in ARM's setABI().
+ } else if (Triple.getArch() == llvm::Triple::x86) {
+ this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32-S128");
+ } else if (Triple.getArch() == llvm::Triple::x86_64) {
+ this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32:64-S128");
+ } else if (Triple.getArch() == llvm::Triple::mipsel) {
+ // Handled on mips' setDataLayout.
+ } else {
+ assert(Triple.getArch() == llvm::Triple::le32);
+ this->resetDataLayout("e-p:32:32-i64:64");
+ }
+ }
+};
+
+// Fuchsia Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY FuchsiaTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__Fuchsia__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ // Required by the libc++ locale support.
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ FuchsiaTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->MCountName = "__mcount";
+ }
+};
+
+// WebAssembly target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo
+ : public OSTargetInfo<Target> {
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const final {
+ // A common platform macro.
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ // Follow g++ convention and predefine _GNU_SOURCE for C++.
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->MCountName = "__mcount";
+ this->TheCXXABI.set(TargetCXXABI::WebAssembly);
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp
new file mode 100644
index 000000000000..b9128c2716e8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp
@@ -0,0 +1,30 @@
+//===--- PNaCl.cpp - Implement PNaCl target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements PNaCl TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PNaCl.h"
+#include "clang/Basic/MacroBuilder.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+ArrayRef<const char *> PNaClTargetInfo::getGCCRegNames() const { return None; }
+
+ArrayRef<TargetInfo::GCCRegAlias> PNaClTargetInfo::getGCCRegAliases() const {
+ return None;
+}
+
+void PNaClTargetInfo::getArchDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__le32__");
+ Builder.defineMacro("__pnacl__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h
new file mode 100644
index 000000000000..922944e85ca2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h
@@ -0,0 +1,87 @@
+//===--- PNaCl.h - Declare PNaCl target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares PNaCl TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_PNACL_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_PNACL_H
+
+#include "Mips.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY PNaClTargetInfo : public TargetInfo {
+public:
+ PNaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : TargetInfo(Triple) {
+ this->LongAlign = 32;
+ this->LongWidth = 32;
+ this->PointerAlign = 32;
+ this->PointerWidth = 32;
+ this->IntMaxType = TargetInfo::SignedLongLong;
+ this->Int64Type = TargetInfo::SignedLongLong;
+ this->DoubleAlign = 64;
+ this->LongDoubleWidth = 64;
+ this->LongDoubleAlign = 64;
+ this->SizeType = TargetInfo::UnsignedInt;
+ this->PtrDiffType = TargetInfo::SignedInt;
+ this->IntPtrType = TargetInfo::SignedInt;
+ this->RegParmMax = 0; // Disallow regparm
+ }
+
+ void getArchDefines(const LangOptions &Opts, MacroBuilder &Builder) const;
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ getArchDefines(Opts, Builder);
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "pnacl";
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::PNaClABIBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ const char *getClobbers() const override { return ""; }
+};
+
+// We attempt to use PNaCl (le32) frontend and Mips32EL backend.
+class LLVM_LIBRARY_VISIBILITY NaClMips32TargetInfo : public MipsTargetInfo {
+public:
+ NaClMips32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : MipsTargetInfo(Triple, Opts) {}
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::PNaClABIBuiltinVaList;
+ }
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_PNACL_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp
new file mode 100644
index 000000000000..b4eb3b1b97b7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp
@@ -0,0 +1,445 @@
+//===--- PPC.cpp - Implement PPC target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements PPC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPC.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsPPC.def"
+};
+
+/// handleTargetFeatures - Perform initialization based on the user
+/// configured set of features.
+bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature == "+altivec") {
+ HasAltivec = true;
+ } else if (Feature == "+vsx") {
+ HasVSX = true;
+ } else if (Feature == "+bpermd") {
+ HasBPERMD = true;
+ } else if (Feature == "+extdiv") {
+ HasExtDiv = true;
+ } else if (Feature == "+power8-vector") {
+ HasP8Vector = true;
+ } else if (Feature == "+crypto") {
+ HasP8Crypto = true;
+ } else if (Feature == "+direct-move") {
+ HasDirectMove = true;
+ } else if (Feature == "+qpx") {
+ HasQPX = true;
+ } else if (Feature == "+htm") {
+ HasHTM = true;
+ } else if (Feature == "+float128") {
+ HasFloat128 = true;
+ } else if (Feature == "+power9-vector") {
+ HasP9Vector = true;
+ }
+ // TODO: Finish this list and add an assert that we've handled them
+ // all.
+ }
+
+ return true;
+}
+
+/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
+/// #defines that are not tied to a specific subtarget.
+void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__ppc__");
+ Builder.defineMacro("__PPC__");
+ Builder.defineMacro("_ARCH_PPC");
+ Builder.defineMacro("__powerpc__");
+ Builder.defineMacro("__POWERPC__");
+ if (PointerWidth == 64) {
+ Builder.defineMacro("_ARCH_PPC64");
+ Builder.defineMacro("__powerpc64__");
+ Builder.defineMacro("__ppc64__");
+ Builder.defineMacro("__PPC64__");
+ }
+
+ // Target properties.
+ if (getTriple().getArch() == llvm::Triple::ppc64le) {
+ Builder.defineMacro("_LITTLE_ENDIAN");
+ } else {
+ if (getTriple().getOS() != llvm::Triple::NetBSD &&
+ getTriple().getOS() != llvm::Triple::OpenBSD)
+ Builder.defineMacro("_BIG_ENDIAN");
+ }
+
+ // ABI options.
+ if (ABI == "elfv1" || ABI == "elfv1-qpx")
+ Builder.defineMacro("_CALL_ELF", "1");
+ if (ABI == "elfv2")
+ Builder.defineMacro("_CALL_ELF", "2");
+
+ // This typically is only for a new enough linker (bfd >= 2.16.2 or gold), but
+ // our support post-dates this and it should work on all 64-bit ppc linux
+ // platforms. It is guaranteed to work on all elfv2 platforms.
+ if (getTriple().getOS() == llvm::Triple::Linux && PointerWidth == 64)
+ Builder.defineMacro("_CALL_LINUX", "1");
+
+ // Subtarget options.
+ Builder.defineMacro("__NATURAL_ALIGNMENT__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // FIXME: Should be controlled by command line option.
+ if (LongDoubleWidth == 128) {
+ Builder.defineMacro("__LONG_DOUBLE_128__");
+ Builder.defineMacro("__LONGDOUBLE128");
+ }
+
+ // Define this for elfv2 (64-bit only) or 64-bit darwin.
+ if (ABI == "elfv2" ||
+ (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64))
+ Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16");
+
+ if (ArchDefs & ArchDefineName)
+ Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper()));
+ if (ArchDefs & ArchDefinePpcgr)
+ Builder.defineMacro("_ARCH_PPCGR");
+ if (ArchDefs & ArchDefinePpcsq)
+ Builder.defineMacro("_ARCH_PPCSQ");
+ if (ArchDefs & ArchDefine440)
+ Builder.defineMacro("_ARCH_440");
+ if (ArchDefs & ArchDefine603)
+ Builder.defineMacro("_ARCH_603");
+ if (ArchDefs & ArchDefine604)
+ Builder.defineMacro("_ARCH_604");
+ if (ArchDefs & ArchDefinePwr4)
+ Builder.defineMacro("_ARCH_PWR4");
+ if (ArchDefs & ArchDefinePwr5)
+ Builder.defineMacro("_ARCH_PWR5");
+ if (ArchDefs & ArchDefinePwr5x)
+ Builder.defineMacro("_ARCH_PWR5X");
+ if (ArchDefs & ArchDefinePwr6)
+ Builder.defineMacro("_ARCH_PWR6");
+ if (ArchDefs & ArchDefinePwr6x)
+ Builder.defineMacro("_ARCH_PWR6X");
+ if (ArchDefs & ArchDefinePwr7)
+ Builder.defineMacro("_ARCH_PWR7");
+ if (ArchDefs & ArchDefinePwr8)
+ Builder.defineMacro("_ARCH_PWR8");
+ if (ArchDefs & ArchDefinePwr9)
+ Builder.defineMacro("_ARCH_PWR9");
+ if (ArchDefs & ArchDefineA2)
+ Builder.defineMacro("_ARCH_A2");
+ if (ArchDefs & ArchDefineA2q) {
+ Builder.defineMacro("_ARCH_A2Q");
+ Builder.defineMacro("_ARCH_QP");
+ }
+
+ if (getTriple().getVendor() == llvm::Triple::BGQ) {
+ Builder.defineMacro("__bg__");
+ Builder.defineMacro("__THW_BLUEGENE__");
+ Builder.defineMacro("__bgq__");
+ Builder.defineMacro("__TOS_BGQ__");
+ }
+
+ if (HasAltivec) {
+ Builder.defineMacro("__VEC__", "10206");
+ Builder.defineMacro("__ALTIVEC__");
+ }
+ if (HasVSX)
+ Builder.defineMacro("__VSX__");
+ if (HasP8Vector)
+ Builder.defineMacro("__POWER8_VECTOR__");
+ if (HasP8Crypto)
+ Builder.defineMacro("__CRYPTO__");
+ if (HasHTM)
+ Builder.defineMacro("__HTM__");
+ if (HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
+ if (HasP9Vector)
+ Builder.defineMacro("__POWER9_VECTOR__");
+
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ if (PointerWidth == 64)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+
+ // We have support for the bswap intrinsics so we can define this.
+ Builder.defineMacro("__HAVE_BSWAP__", "1");
+
+ // FIXME: The following are not yet generated here by Clang, but are
+ // generated by GCC:
+ //
+ // _SOFT_FLOAT_
+ // __RECIP_PRECISION__
+ // __APPLE_ALTIVEC__
+ // __RECIP__
+ // __RECIPF__
+ // __RSQRTE__
+ // __RSQRTEF__
+ // _SOFT_DOUBLE_
+ // __NO_LWSYNC__
+ // __CMODEL_MEDIUM__
+ // __CMODEL_LARGE__
+ // _CALL_SYSV
+ // _CALL_DARWIN
+ // __NO_FPRS__
+}
+
+// Handle explicit options being passed to the compiler here: if we've
+// explicitly turned off vsx and turned on any of:
+// - power8-vector
+// - direct-move
+// - float128
+// - power9-vector
+// then go ahead and error since the customer has expressed an incompatible
+// set of options.
+static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
+ const std::vector<std::string> &FeaturesVec) {
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "-vsx") !=
+ FeaturesVec.end()) {
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power8-vector") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector"
+ << "-mno-vsx";
+ return false;
+ }
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+direct-move") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move"
+ << "-mno-vsx";
+ return false;
+ }
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128"
+ << "-mno-vsx";
+ return false;
+ }
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power9-vector") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower9-vector"
+ << "-mno-vsx";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PPCTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ Features["altivec"] = llvm::StringSwitch<bool>(CPU)
+ .Case("7400", true)
+ .Case("g4", true)
+ .Case("7450", true)
+ .Case("g4+", true)
+ .Case("970", true)
+ .Case("g5", true)
+ .Case("pwr6", true)
+ .Case("pwr7", true)
+ .Case("pwr8", true)
+ .Case("pwr9", true)
+ .Case("ppc64", true)
+ .Case("ppc64le", true)
+ .Default(false);
+
+ Features["qpx"] = (CPU == "a2q");
+ Features["power9-vector"] = (CPU == "pwr9");
+ Features["crypto"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["power8-vector"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["bpermd"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["extdiv"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["direct-move"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["vsx"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["htm"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+
+ if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
+ return false;
+
+ if (!(ArchDefs & ArchDefinePwr9) && (ArchDefs & ArchDefinePpcgr) &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") !=
+ FeaturesVec.end()) {
+ // We have __float128 on PPC but not power 9 and above.
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" << CPU;
+ return false;
+ }
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
+bool PPCTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("powerpc", true)
+ .Case("altivec", HasAltivec)
+ .Case("vsx", HasVSX)
+ .Case("power8-vector", HasP8Vector)
+ .Case("crypto", HasP8Crypto)
+ .Case("direct-move", HasDirectMove)
+ .Case("qpx", HasQPX)
+ .Case("htm", HasHTM)
+ .Case("bpermd", HasBPERMD)
+ .Case("extdiv", HasExtDiv)
+ .Case("float128", HasFloat128)
+ .Case("power9-vector", HasP9Vector)
+ .Default(false);
+}
+
+void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled) const {
+ if (Enabled) {
+ // If we're enabling any of the vsx based features then enable vsx and
+ // altivec. We'll diagnose any problems later.
+ bool FeatureHasVSX = llvm::StringSwitch<bool>(Name)
+ .Case("vsx", true)
+ .Case("direct-move", true)
+ .Case("power8-vector", true)
+ .Case("power9-vector", true)
+ .Case("float128", true)
+ .Default(false);
+ if (FeatureHasVSX)
+ Features["vsx"] = Features["altivec"] = true;
+ if (Name == "power9-vector")
+ Features["power8-vector"] = true;
+ Features[Name] = true;
+ } else {
+ // If we're disabling altivec or vsx go ahead and disable all of the vsx
+ // features.
+ if ((Name == "altivec") || (Name == "vsx"))
+ Features["vsx"] = Features["direct-move"] = Features["power8-vector"] =
+ Features["float128"] = Features["power9-vector"] = false;
+ if (Name == "power8-vector")
+ Features["power9-vector"] = false;
+ Features[Name] = false;
+ }
+}
+
+const char *const PPCTargetInfo::GCCRegNames[] = {
+ "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", "cr0", "cr1", "cr2", "cr3",
+ "cr4", "cr5", "cr6", "cr7", "xer", "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"
+};
+
+ArrayRef<const char *> PPCTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
+ // While some of these aliases do map to different registers
+ // they still share the same register name.
+ {{"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"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+static constexpr llvm::StringLiteral ValidCPUNames[] = {
+ {"generic"}, {"440"}, {"450"}, {"601"}, {"602"},
+ {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"},
+ {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"},
+ {"7450"}, {"g4+"}, {"750"}, {"970"}, {"g5"},
+ {"a2"}, {"a2q"}, {"e500mc"}, {"e5500"}, {"power3"},
+ {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"}, {"pwr5"},
+ {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"}, {"power6x"},
+ {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"}, {"pwr8"},
+ {"power9"}, {"pwr9"}, {"powerpc"}, {"ppc"}, {"powerpc64"},
+ {"ppc64"}, {"powerpc64le"}, {"ppc64le"},
+};
+
+bool PPCTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void PPCTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
+}
+
+void PPCTargetInfo::adjust(LangOptions &Opts) {
+ if (HasAltivec)
+ Opts.AltiVec = 1;
+ TargetInfo::adjust(Opts);
+}
+
+ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::PPC::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h
new file mode 100644
index 000000000000..439c73a0e326
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h
@@ -0,0 +1,429 @@
+//===--- PPC.h - Declare PPC target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares PPC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// PPC abstract base class
+class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
+
+ /// Flags for architecture specific defines.
+ typedef enum {
+ ArchDefineNone = 0,
+ ArchDefineName = 1 << 0, // <name> is substituted for arch name.
+ ArchDefinePpcgr = 1 << 1,
+ ArchDefinePpcsq = 1 << 2,
+ ArchDefine440 = 1 << 3,
+ ArchDefine603 = 1 << 4,
+ ArchDefine604 = 1 << 5,
+ ArchDefinePwr4 = 1 << 6,
+ ArchDefinePwr5 = 1 << 7,
+ ArchDefinePwr5x = 1 << 8,
+ ArchDefinePwr6 = 1 << 9,
+ ArchDefinePwr6x = 1 << 10,
+ ArchDefinePwr7 = 1 << 11,
+ ArchDefinePwr8 = 1 << 12,
+ ArchDefinePwr9 = 1 << 13,
+ ArchDefineA2 = 1 << 14,
+ ArchDefineA2q = 1 << 15
+ } ArchDefineTypes;
+
+
+ ArchDefineTypes ArchDefs = ArchDefineNone;
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ std::string CPU;
+
+ // Target cpu features.
+ bool HasAltivec = false;
+ bool HasVSX = false;
+ bool HasP8Vector = false;
+ bool HasP8Crypto = false;
+ bool HasDirectMove = false;
+ bool HasQPX = false;
+ bool HasHTM = false;
+ bool HasBPERMD = false;
+ bool HasExtDiv = false;
+ bool HasP9Vector = false;
+
+protected:
+ std::string ABI;
+
+public:
+ PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ SuitableAlign = 128;
+ SimdDefaultAlign = 128;
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
+ }
+
+ // Set the language option for altivec based on our value.
+ void adjust(LangOptions &Opts) override;
+
+ // Note: GCC recognizes the following additional cpus:
+ // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801,
+ // 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell,
+ // titan, rs64.
+ bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ bool CPUKnown = isValidCPUName(Name);
+ if (CPUKnown) {
+ CPU = Name;
+
+ // CPU identification.
+ ArchDefs =
+ (ArchDefineTypes)llvm::StringSwitch<int>(CPU)
+ .Case("440", ArchDefineName)
+ .Case("450", ArchDefineName | ArchDefine440)
+ .Case("601", ArchDefineName)
+ .Case("602", ArchDefineName | ArchDefinePpcgr)
+ .Case("603", ArchDefineName | ArchDefinePpcgr)
+ .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)
+ .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)
+ .Case("604", ArchDefineName | ArchDefinePpcgr)
+ .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr)
+ .Case("620", ArchDefineName | ArchDefinePpcgr)
+ .Case("630", ArchDefineName | ArchDefinePpcgr)
+ .Case("7400", ArchDefineName | ArchDefinePpcgr)
+ .Case("7450", ArchDefineName | ArchDefinePpcgr)
+ .Case("750", ArchDefineName | ArchDefinePpcgr)
+ .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("a2", ArchDefineA2)
+ .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q)
+ .Cases("power3", "pwr3", ArchDefinePpcgr)
+ .Cases("power4", "pwr4",
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power5", "pwr5",
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Cases("power5x", "pwr5x",
+ ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power6", "pwr6",
+ ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power6x", "pwr6x",
+ ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Cases("power7", "pwr7",
+ ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 |
+ ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ // powerpc64le automatically defaults to at least power8.
+ .Cases("power8", "pwr8", "ppc64le",
+ ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x |
+ ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power9", "pwr9",
+ ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |
+ ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Default(ArchDefineNone);
+ }
+ return CPUKnown;
+ }
+
+ StringRef getABI() const override { return ABI; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool isCLZForZeroUndef() const override { return false; }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+ case 'O': // Zero
+ break;
+ case 'b': // Base register
+ case 'f': // Floating point register
+ Info.setAllowsRegister();
+ break;
+ // FIXME: The following are added to allow parsing.
+ // I just took a guess at what the actions should be.
+ // Also, is more specific checking needed? I.e. specific registers?
+ case 'd': // Floating point register (containing 64-bit value)
+ case 'v': // Altivec vector register
+ Info.setAllowsRegister();
+ break;
+ case 'w':
+ switch (Name[1]) {
+ case 'd': // VSX vector register to hold vector double data
+ case 'f': // VSX vector register to hold vector float data
+ case 's': // VSX vector register to hold scalar float data
+ case 'a': // Any VSX register
+ case 'c': // An individual CR bit
+ break;
+ default:
+ return false;
+ }
+ Info.setAllowsRegister();
+ Name++; // Skip over 'w'.
+ break;
+ case 'h': // `MQ', `CTR', or `LINK' register
+ case 'q': // `MQ' register
+ case 'c': // `CTR' register
+ case 'l': // `LINK' register
+ case 'x': // `CR' register (condition register) number 0
+ case 'y': // `CR' register (condition register)
+ case 'z': // `XER[CA]' carry bit (part of the XER register)
+ Info.setAllowsRegister();
+ break;
+ case 'I': // Signed 16-bit constant
+ case 'J': // Unsigned 16-bit constant shifted left 16 bits
+ // (use `L' instead for SImode constants)
+ case 'K': // Unsigned 16-bit constant
+ case 'L': // Signed 16-bit constant shifted left 16 bits
+ case 'M': // Constant larger than 31
+ case 'N': // Exact power of 2
+ case 'P': // Constant whose negation is a signed 16-bit constant
+ case 'G': // Floating point constant that can be loaded into a
+ // register with one instruction per word
+ case 'H': // Integer/Floating point constant that can be loaded
+ // into a register using three instructions
+ break;
+ case 'm': // Memory operand. Note that on PowerPC targets, m can
+ // include addresses that update the base register. It
+ // is therefore only safe to use `m' in an asm statement
+ // if that asm statement accesses the operand exactly once.
+ // The asm statement must also use `%U<opno>' as a
+ // placeholder for the "update" flag in the corresponding
+ // load or store instruction. For example:
+ // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val));
+ // is correct but:
+ // asm ("st %1,%0" : "=m" (mem) : "r" (val));
+ // is not. Use es rather than m if you don't want the base
+ // register to be updated.
+ case 'e':
+ if (Name[1] != 's')
+ return false;
+ // es: A "stable" memory operand; that is, one which does not
+ // include any automodification of the base register. Unlike
+ // `m', this constraint can be used in asm statements that
+ // might access the operand several times, or that might not
+ // access it at all.
+ Info.setAllowsMemory();
+ Name++; // Skip over 'e'.
+ break;
+ case 'Q': // Memory operand that is an offset from a register (it is
+ // usually better to use `m' or `es' in asm statements)
+ case 'Z': // Memory operand that is an indexed or indirect from a
+ // register (it is usually better to use `m' or `es' in
+ // asm statements)
+ Info.setAllowsMemory();
+ Info.setAllowsRegister();
+ break;
+ case 'R': // AIX TOC entry
+ case 'a': // Address operand that is an indexed or indirect from a
+ // register (`p' is preferable for asm statements)
+ case 'S': // Constant suitable as a 64-bit mask operand
+ case 'T': // Constant suitable as a 32-bit mask operand
+ case 'U': // System V Release 4 small data area reference
+ case 't': // AND masks that can be performed by two rldic{l, r}
+ // instructions
+ case 'W': // Vector constant that does not require memory
+ case 'j': // Vector constant that is all zeros.
+ break;
+ // End FIXME.
+ }
+ return true;
+ }
+
+ std::string convertConstraint(const char *&Constraint) const override {
+ std::string R;
+ switch (*Constraint) {
+ case 'e':
+ case 'w':
+ // Two-character constraint; add "^" hint for later parsing.
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ break;
+ default:
+ return TargetInfo::convertConstraint(Constraint);
+ }
+ return R;
+ }
+
+ const char *getClobbers() const override { return ""; }
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 3;
+ if (RegNo == 1)
+ return 4;
+ return -1;
+ }
+
+ bool hasSjLjLowering() const override { return true; }
+
+ bool useFloat128ManglingForLongDouble() const override {
+ return LongDoubleWidth == 128 &&
+ LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble() &&
+ getTriple().isOSBinFormatELF();
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {
+public:
+ PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : PPCTargetInfo(Triple, Opts) {
+ resetDataLayout("E-m:e-p:32:32-i64:64-n32");
+
+ switch (getTriple().getOS()) {
+ case llvm::Triple::Linux:
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::NetBSD:
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ break;
+ default:
+ break;
+ }
+
+ if (getTriple().getOS() == llvm::Triple::FreeBSD) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+
+ // PPC32 supports atomics up to 4 bytes.
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // This is the ELF definition, and is overridden by the Darwin sub-target
+ return TargetInfo::PowerABIBuiltinVaList;
+ }
+};
+
+// Note: ABI differences may eventually require us to have a separate
+// TargetInfo for little endian.
+class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
+public:
+ PPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : PPCTargetInfo(Triple, Opts) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
+
+ if ((Triple.getArch() == llvm::Triple::ppc64le)) {
+ resetDataLayout("e-m:e-i64:64-n32:64");
+ ABI = "elfv2";
+ } else {
+ resetDataLayout("E-m:e-i64:64-n32:64");
+ ABI = "elfv1";
+ }
+
+ switch (getTriple().getOS()) {
+ case llvm::Triple::FreeBSD:
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ break;
+ default:
+ break;
+ }
+
+ // PPC64 supports atomics up to 8 bytes.
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ // PPC64 Linux-specific ABI options.
+ bool setABI(const std::string &Name) override {
+ if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_Swift:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinPPC32TargetInfo
+ : public DarwinTargetInfo<PPC32TargetInfo> {
+public:
+ DarwinPPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<PPC32TargetInfo>(Triple, Opts) {
+ HasAlignMac68kSupport = true;
+ BoolWidth = BoolAlign = 32; // XXX support -mone-byte-bool?
+ PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726
+ LongLongAlign = 32;
+ resetDataLayout("E-m:o-p:32:32-f64:32:64-n32");
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinPPC64TargetInfo
+ : public DarwinTargetInfo<PPC64TargetInfo> {
+public:
+ DarwinPPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<PPC64TargetInfo>(Triple, Opts) {
+ HasAlignMac68kSupport = true;
+ resetDataLayout("E-m:o-i64:64-n32:64");
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp
new file mode 100644
index 000000000000..7eb5e6a686a9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp
@@ -0,0 +1,104 @@
+//===--- RISCV.cpp - Implement RISCV target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements RISCV TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
+ static const char *const GCCRegNames[] = {
+ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
+ "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
+ "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+ "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31"};
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
+ static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
+ {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"},
+ {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"},
+ {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"},
+ {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x15"}, {{"a5"}, "x15"},
+ {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"},
+ {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"},
+ {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"},
+ {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}};
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__riscv");
+ bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
+ Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
+ // TODO: modify when more code models and ABIs are supported.
+ Builder.defineMacro("__riscv_cmodel_medlow");
+ Builder.defineMacro("__riscv_float_abi_soft");
+
+ if (HasM) {
+ Builder.defineMacro("__riscv_mul");
+ Builder.defineMacro("__riscv_div");
+ Builder.defineMacro("__riscv_muldiv");
+ }
+
+ if (HasA)
+ Builder.defineMacro("__riscv_atomic");
+
+ if (HasF || HasD) {
+ Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
+ Builder.defineMacro("__riscv_fdiv");
+ Builder.defineMacro("__riscv_fsqrt");
+ }
+
+ if (HasC)
+ Builder.defineMacro("__riscv_compressed");
+}
+
+/// Return true if has this feature, need to sync with handleTargetFeatures.
+bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
+ bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("riscv", true)
+ .Case("riscv32", !Is64Bit)
+ .Case("riscv64", Is64Bit)
+ .Case("m", HasM)
+ .Case("a", HasA)
+ .Case("f", HasF)
+ .Case("d", HasD)
+ .Case("c", HasC)
+ .Default(false);
+}
+
+/// Perform initialization based on the user configured set of features.
+bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature == "+m")
+ HasM = true;
+ else if (Feature == "+a")
+ HasA = true;
+ else if (Feature == "+f")
+ HasF = true;
+ else if (Feature == "+d")
+ HasD = true;
+ else if (Feature == "+c")
+ HasC = true;
+ }
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h
new file mode 100644
index 000000000000..f83aae539391
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h
@@ -0,0 +1,114 @@
+//===--- RISCV.h - Declare RISCV target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares RISCV TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// RISC-V Target
+class RISCVTargetInfo : public TargetInfo {
+protected:
+ std::string ABI;
+ bool HasM;
+ bool HasA;
+ bool HasF;
+ bool HasD;
+ bool HasC;
+
+public:
+ RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), HasM(false), HasA(false), HasF(false),
+ HasD(false), HasC(false) {
+ TLSSupported = false;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ SuitableAlign = 128;
+ WCharType = SignedInt;
+ WIntType = UnsignedInt;
+ }
+
+ StringRef getABI() const override { return ABI; }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+};
+class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
+public:
+ RISCV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : RISCVTargetInfo(Triple, Opts) {
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ SizeType = UnsignedInt;
+ resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128");
+ }
+
+ bool setABI(const std::string &Name) override {
+ // TODO: support ilp32f and ilp32d ABIs.
+ if (Name == "ilp32") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+};
+class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo {
+public:
+ RISCV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : RISCVTargetInfo(Triple, Opts) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ IntMaxType = Int64Type = SignedLong;
+ resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n64-S128");
+ }
+
+ bool setABI(const std::string &Name) override {
+ // TODO: support lp64f and lp64d ABIs.
+ if (Name == "lp64") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp
new file mode 100644
index 000000000000..304d904368ca
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp
@@ -0,0 +1,33 @@
+//===--- SPIR.cpp - Implement SPIR target feature support -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements SPIR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIR.h"
+#include "Targets.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "SPIR", Opts);
+}
+
+void SPIR32TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "SPIR32", Opts);
+}
+
+void SPIR64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "SPIR64", Opts);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h
new file mode 100644
index 000000000000..9815292fc276
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h
@@ -0,0 +1,132 @@
+//===--- SPIR.h - Declare SPIR target feature support -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares SPIR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+static const unsigned SPIRAddrSpaceMap[] = {
+ 0, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 0, // opencl_private
+ 4, // opencl_generic
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0 // cuda_shared
+};
+
+class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
+public:
+ SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
+ "SPIR target must use unknown OS");
+ assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
+ "SPIR target must use unknown environment type");
+ TLSSupported = false;
+ VLASupported = false;
+ LongWidth = LongAlign = 64;
+ AddrSpaceMap = &SPIRAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+ HasLegalHalfType = true;
+ // Define available target features
+ // These must be defined in sorted order!
+ NoAsmVariants = true;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "spir";
+ }
+
+ // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is
+ // memcpy as per section 3 of the SPIR spec.
+ bool useFP16ConversionIntrinsics() const override { return false; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
+ : CCCR_Warning;
+ }
+
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return CC_SpirFunction;
+ }
+
+ void setSupportedOpenCLOpts() override {
+ // Assume all OpenCL extensions and optional core features are supported
+ // for SPIR since it is a generic target.
+ getSupportedOpenCLOpts().supportAll();
+ }
+};
+class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
+public:
+ SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SPIRTargetInfo(Triple, Opts) {
+ PointerWidth = PointerAlign = 32;
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = IntPtrType = TargetInfo::SignedInt;
+ resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
+ "v96:128-v192:256-v256:256-v512:512-v1024:1024");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
+public:
+ SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SPIRTargetInfo(Triple, Opts) {
+ PointerWidth = PointerAlign = 64;
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = IntPtrType = TargetInfo::SignedLong;
+ resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
+ "v96:128-v192:256-v256:256-v512:512-v1024:1024");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp
new file mode 100644
index 000000000000..ee4f309363af
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp
@@ -0,0 +1,251 @@
+//===--- Sparc.cpp - Implement Sparc target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Sparc TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sparc.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const char *const SparcTargetInfo::GCCRegNames[] = {
+ // Integer registers
+ "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",
+
+ // Floating-point registers
+ "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", "f32",
+ "f34", "f36", "f38", "f40", "f42", "f44", "f46", "f48", "f50", "f52", "f54",
+ "f56", "f58", "f60", "f62",
+};
+
+ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
+ {{"g0"}, "r0"}, {{"g1"}, "r1"}, {{"g2"}, "r2"}, {{"g3"}, "r3"},
+ {{"g4"}, "r4"}, {{"g5"}, "r5"}, {{"g6"}, "r6"}, {{"g7"}, "r7"},
+ {{"o0"}, "r8"}, {{"o1"}, "r9"}, {{"o2"}, "r10"}, {{"o3"}, "r11"},
+ {{"o4"}, "r12"}, {{"o5"}, "r13"}, {{"o6", "sp"}, "r14"}, {{"o7"}, "r15"},
+ {{"l0"}, "r16"}, {{"l1"}, "r17"}, {{"l2"}, "r18"}, {{"l3"}, "r19"},
+ {{"l4"}, "r20"}, {{"l5"}, "r21"}, {{"l6"}, "r22"}, {{"l7"}, "r23"},
+ {{"i0"}, "r24"}, {{"i1"}, "r25"}, {{"i2"}, "r26"}, {{"i3"}, "r27"},
+ {{"i4"}, "r28"}, {{"i5"}, "r29"}, {{"i6", "fp"}, "r30"}, {{"i7"}, "r31"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool SparcTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("softfloat", SoftFloat)
+ .Case("sparc", true)
+ .Default(false);
+}
+
+struct SparcCPUInfo {
+ llvm::StringLiteral Name;
+ SparcTargetInfo::CPUKind Kind;
+ SparcTargetInfo::CPUGeneration Generation;
+};
+
+static constexpr SparcCPUInfo CPUInfo[] = {
+ {{"v8"}, SparcTargetInfo::CK_V8, SparcTargetInfo::CG_V8},
+ {{"supersparc"}, SparcTargetInfo::CK_SUPERSPARC, SparcTargetInfo::CG_V8},
+ {{"sparclite"}, SparcTargetInfo::CK_SPARCLITE, SparcTargetInfo::CG_V8},
+ {{"f934"}, SparcTargetInfo::CK_F934, SparcTargetInfo::CG_V8},
+ {{"hypersparc"}, SparcTargetInfo::CK_HYPERSPARC, SparcTargetInfo::CG_V8},
+ {{"sparclite86x"},
+ SparcTargetInfo::CK_SPARCLITE86X,
+ SparcTargetInfo::CG_V8},
+ {{"sparclet"}, SparcTargetInfo::CK_SPARCLET, SparcTargetInfo::CG_V8},
+ {{"tsc701"}, SparcTargetInfo::CK_TSC701, SparcTargetInfo::CG_V8},
+ {{"v9"}, SparcTargetInfo::CK_V9, SparcTargetInfo::CG_V9},
+ {{"ultrasparc"}, SparcTargetInfo::CK_ULTRASPARC, SparcTargetInfo::CG_V9},
+ {{"ultrasparc3"}, SparcTargetInfo::CK_ULTRASPARC3, SparcTargetInfo::CG_V9},
+ {{"niagara"}, SparcTargetInfo::CK_NIAGARA, SparcTargetInfo::CG_V9},
+ {{"niagara2"}, SparcTargetInfo::CK_NIAGARA2, SparcTargetInfo::CG_V9},
+ {{"niagara3"}, SparcTargetInfo::CK_NIAGARA3, SparcTargetInfo::CG_V9},
+ {{"niagara4"}, SparcTargetInfo::CK_NIAGARA4, SparcTargetInfo::CG_V9},
+ {{"ma2100"}, SparcTargetInfo::CK_MYRIAD2100, SparcTargetInfo::CG_V8},
+ {{"ma2150"}, SparcTargetInfo::CK_MYRIAD2150, SparcTargetInfo::CG_V8},
+ {{"ma2155"}, SparcTargetInfo::CK_MYRIAD2155, SparcTargetInfo::CG_V8},
+ {{"ma2450"}, SparcTargetInfo::CK_MYRIAD2450, SparcTargetInfo::CG_V8},
+ {{"ma2455"}, SparcTargetInfo::CK_MYRIAD2455, SparcTargetInfo::CG_V8},
+ {{"ma2x5x"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
+ {{"ma2080"}, SparcTargetInfo::CK_MYRIAD2080, SparcTargetInfo::CG_V8},
+ {{"ma2085"}, SparcTargetInfo::CK_MYRIAD2085, SparcTargetInfo::CG_V8},
+ {{"ma2480"}, SparcTargetInfo::CK_MYRIAD2480, SparcTargetInfo::CG_V8},
+ {{"ma2485"}, SparcTargetInfo::CK_MYRIAD2485, SparcTargetInfo::CG_V8},
+ {{"ma2x8x"}, SparcTargetInfo::CK_MYRIAD2x8x, SparcTargetInfo::CG_V8},
+ // FIXME: the myriad2[.n] spellings are obsolete,
+ // but a grace period is needed to allow updating dependent builds.
+ {{"myriad2"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
+ {{"myriad2.1"}, SparcTargetInfo::CK_MYRIAD2100, SparcTargetInfo::CG_V8},
+ {{"myriad2.2"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
+ {{"myriad2.3"}, SparcTargetInfo::CK_MYRIAD2x8x, SparcTargetInfo::CG_V8},
+ {{"leon2"}, SparcTargetInfo::CK_LEON2, SparcTargetInfo::CG_V8},
+ {{"at697e"}, SparcTargetInfo::CK_LEON2_AT697E, SparcTargetInfo::CG_V8},
+ {{"at697f"}, SparcTargetInfo::CK_LEON2_AT697F, SparcTargetInfo::CG_V8},
+ {{"leon3"}, SparcTargetInfo::CK_LEON3, SparcTargetInfo::CG_V8},
+ {{"ut699"}, SparcTargetInfo::CK_LEON3_UT699, SparcTargetInfo::CG_V8},
+ {{"gr712rc"}, SparcTargetInfo::CK_LEON3_GR712RC, SparcTargetInfo::CG_V8},
+ {{"leon4"}, SparcTargetInfo::CK_LEON4, SparcTargetInfo::CG_V8},
+ {{"gr740"}, SparcTargetInfo::CK_LEON4_GR740, SparcTargetInfo::CG_V8},
+};
+
+SparcTargetInfo::CPUGeneration
+SparcTargetInfo::getCPUGeneration(CPUKind Kind) const {
+ if (Kind == CK_GENERIC)
+ return CG_V8;
+ const SparcCPUInfo *Item = llvm::find_if(
+ CPUInfo, [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; });
+ if (Item == std::end(CPUInfo))
+ llvm_unreachable("Unexpected CPU kind");
+ return Item->Generation;
+}
+
+SparcTargetInfo::CPUKind SparcTargetInfo::getCPUKind(StringRef Name) const {
+ const SparcCPUInfo *Item = llvm::find_if(
+ CPUInfo, [Name](const SparcCPUInfo &Info) { return Info.Name == Name; });
+
+ if (Item == std::end(CPUInfo))
+ return CK_GENERIC;
+ return Item->Kind;
+}
+
+void SparcTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const SparcCPUInfo &Info : CPUInfo)
+ Values.push_back(Info.Name);
+}
+
+void SparcTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sparc", Opts);
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ if (SoftFloat)
+ Builder.defineMacro("SOFT_FLOAT", "1");
+}
+
+void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ SparcTargetInfo::getTargetDefines(Opts, Builder);
+ switch (getCPUGeneration(CPU)) {
+ case CG_V8:
+ Builder.defineMacro("__sparcv8");
+ if (getTriple().getOS() != llvm::Triple::Solaris)
+ Builder.defineMacro("__sparcv8__");
+ break;
+ case CG_V9:
+ Builder.defineMacro("__sparcv9");
+ if (getTriple().getOS() != llvm::Triple::Solaris) {
+ Builder.defineMacro("__sparcv9__");
+ Builder.defineMacro("__sparc_v9__");
+ }
+ break;
+ }
+ if (getTriple().getVendor() == llvm::Triple::Myriad) {
+ std::string MyriadArchValue, Myriad2Value;
+ Builder.defineMacro("__sparc_v8__");
+ Builder.defineMacro("__leon__");
+ switch (CPU) {
+ case CK_MYRIAD2100:
+ MyriadArchValue = "__ma2100";
+ Myriad2Value = "1";
+ break;
+ case CK_MYRIAD2150:
+ MyriadArchValue = "__ma2150";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2155:
+ MyriadArchValue = "__ma2155";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2450:
+ MyriadArchValue = "__ma2450";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2455:
+ MyriadArchValue = "__ma2455";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2x5x:
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2080:
+ MyriadArchValue = "__ma2080";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2085:
+ MyriadArchValue = "__ma2085";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2480:
+ MyriadArchValue = "__ma2480";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2485:
+ MyriadArchValue = "__ma2485";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2x8x:
+ Myriad2Value = "3";
+ break;
+ default:
+ MyriadArchValue = "__ma2100";
+ Myriad2Value = "1";
+ break;
+ }
+ if (!MyriadArchValue.empty()) {
+ Builder.defineMacro(MyriadArchValue, "1");
+ Builder.defineMacro(MyriadArchValue + "__", "1");
+ }
+ if (Myriad2Value == "2") {
+ Builder.defineMacro("__ma2x5x", "1");
+ Builder.defineMacro("__ma2x5x__", "1");
+ } else if (Myriad2Value == "3") {
+ Builder.defineMacro("__ma2x8x", "1");
+ Builder.defineMacro("__ma2x8x__", "1");
+ }
+ Builder.defineMacro("__myriad2__", Myriad2Value);
+ Builder.defineMacro("__myriad2", Myriad2Value);
+ }
+}
+
+void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ SparcTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__sparcv9");
+ Builder.defineMacro("__arch64__");
+ // Solaris doesn't need these variants, but the BSDs do.
+ if (getTriple().getOS() != llvm::Triple::Solaris) {
+ Builder.defineMacro("__sparc64__");
+ Builder.defineMacro("__sparc_v9__");
+ Builder.defineMacro("__sparcv9__");
+ }
+}
+
+void SparcV9TargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const SparcCPUInfo &Info : CPUInfo)
+ if (Info.Generation == CG_V9)
+ Values.push_back(Info.Name);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h
new file mode 100644
index 000000000000..af2189f21468
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h
@@ -0,0 +1,233 @@
+//===--- Sparc.h - declare sparc target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Sparc TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+namespace clang {
+namespace targets {
+// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
+class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+ bool SoftFloat;
+
+public:
+ SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), SoftFloat(false) {}
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 24;
+ if (RegNo == 1)
+ return 25;
+ return -1;
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ // Check if software floating point is enabled
+ auto Feature = std::find(Features.begin(), Features.end(), "+soft-float");
+ if (Feature != Features.end()) {
+ SoftFloat = true;
+ }
+ return true;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool hasSjLjLowering() const override { return true; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ // FIXME: Implement!
+ return None;
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ // FIXME: Implement!
+ switch (*Name) {
+ case 'I': // Signed 13-bit constant
+ case 'J': // Zero
+ case 'K': // 32-bit constant with the low 12 bits clear
+ case 'L': // A constant in the range supported by movcc (11-bit signed imm)
+ case 'M': // A constant in the range supported by movrcc (19-bit signed imm)
+ case 'N': // Same as 'K' but zext (required for SIMode)
+ case 'O': // The constant 4096
+ return true;
+
+ case 'f':
+ case 'e':
+ info.setAllowsRegister();
+ return true;
+ }
+ return false;
+ }
+ const char *getClobbers() const override {
+ // FIXME: Implement!
+ return "";
+ }
+
+ // No Sparc V7 for now, the backend doesn't support it anyway.
+ enum CPUKind {
+ CK_GENERIC,
+ CK_V8,
+ CK_SUPERSPARC,
+ CK_SPARCLITE,
+ CK_F934,
+ CK_HYPERSPARC,
+ CK_SPARCLITE86X,
+ CK_SPARCLET,
+ CK_TSC701,
+ CK_V9,
+ CK_ULTRASPARC,
+ CK_ULTRASPARC3,
+ CK_NIAGARA,
+ CK_NIAGARA2,
+ CK_NIAGARA3,
+ CK_NIAGARA4,
+ CK_MYRIAD2100,
+ CK_MYRIAD2150,
+ CK_MYRIAD2155,
+ CK_MYRIAD2450,
+ CK_MYRIAD2455,
+ CK_MYRIAD2x5x,
+ CK_MYRIAD2080,
+ CK_MYRIAD2085,
+ CK_MYRIAD2480,
+ CK_MYRIAD2485,
+ CK_MYRIAD2x8x,
+ CK_LEON2,
+ CK_LEON2_AT697E,
+ CK_LEON2_AT697F,
+ CK_LEON3,
+ CK_LEON3_UT699,
+ CK_LEON3_GR712RC,
+ CK_LEON4,
+ CK_LEON4_GR740
+ } CPU = CK_GENERIC;
+
+ enum CPUGeneration {
+ CG_V8,
+ CG_V9,
+ };
+
+ CPUGeneration getCPUGeneration(CPUKind Kind) const;
+
+ CPUKind getCPUKind(StringRef Name) const;
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getCPUKind(Name) != CK_GENERIC;
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ CPU = getCPUKind(Name);
+ return CPU != CK_GENERIC;
+ }
+};
+
+// SPARC v8 is the 32-bit mode selected by Triple::sparc.
+class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo {
+public:
+ SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SparcTargetInfo(Triple, Opts) {
+ resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64");
+ // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int.
+ switch (getTriple().getOS()) {
+ default:
+ SizeType = UnsignedInt;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ break;
+ case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ break;
+ }
+ // Up to 32 bits are lock-free atomic, but we're willing to do atomic ops
+ // on up to 64 bits.
+ MaxAtomicPromoteWidth = 64;
+ MaxAtomicInlineWidth = 32;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasSjLjLowering() const override { return true; }
+};
+
+// SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel.
+class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo {
+public:
+ SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SparcV8TargetInfo(Triple, Opts) {
+ resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64");
+ }
+};
+
+// SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
+class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo {
+public:
+ SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SparcTargetInfo(Triple, Opts) {
+ // FIXME: Support Sparc quad-precision long double?
+ resetDataLayout("E-m:e-i64:64-n32:64-S128");
+ // This is an LP64 platform.
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+
+ // OpenBSD uses long long for int64_t and intmax_t.
+ if (getTriple().getOS() == llvm::Triple::OpenBSD)
+ IntMaxType = SignedLongLong;
+ else
+ IntMaxType = SignedLong;
+ Int64Type = IntMaxType;
+
+ // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
+ // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9;
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ if (!SparcTargetInfo::setCPU(Name))
+ return false;
+ return getCPUGeneration(CPU) == CG_V9;
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp
new file mode 100644
index 000000000000..6f06f1fc760c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp
@@ -0,0 +1,152 @@
+//===--- SystemZ.cpp - Implement SystemZ target feature support -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements SystemZ TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZ.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsSystemZ.def"
+};
+
+const char *const SystemZTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7",
+ "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15",
+ /*ap*/"", "cc", /*fp*/"", /*rp*/"", "a0", "a1",
+ "v16", "v18", "v20", "v22", "v17", "v19", "v21", "v23",
+ "v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31"
+};
+
+const TargetInfo::AddlRegName GCCAddlRegNames[] = {
+ {{"v0"}, 16}, {{"v2"}, 17}, {{"v4"}, 18}, {{"v6"}, 19},
+ {{"v1"}, 20}, {{"v3"}, 21}, {{"v5"}, 22}, {{"v7"}, 23},
+ {{"v8"}, 24}, {{"v10"}, 25}, {{"v12"}, 26}, {{"v14"}, 27},
+ {{"v9"}, 28}, {{"v11"}, 29}, {{"v13"}, 30}, {{"v15"}, 31}
+};
+
+ArrayRef<const char *> SystemZTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::AddlRegName> SystemZTargetInfo::getGCCAddlRegNames() const {
+ return llvm::makeArrayRef(GCCAddlRegNames);
+}
+
+bool SystemZTargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+
+ case 'a': // Address register
+ case 'd': // Data register (equivalent to 'r')
+ case 'f': // Floating-point register
+ case 'v': // Vector register
+ Info.setAllowsRegister();
+ return true;
+
+ case 'I': // Unsigned 8-bit constant
+ case 'J': // Unsigned 12-bit constant
+ case 'K': // Signed 16-bit constant
+ case 'L': // Signed 20-bit displacement (on all targets we support)
+ case 'M': // 0x7fffffff
+ return true;
+
+ case 'Q': // Memory with base and unsigned 12-bit displacement
+ case 'R': // Likewise, plus an index
+ case 'S': // Memory with base and signed 20-bit displacement
+ case 'T': // Likewise, plus an index
+ Info.setAllowsMemory();
+ return true;
+ }
+}
+
+struct ISANameRevision {
+ llvm::StringLiteral Name;
+ int ISARevisionID;
+};
+static constexpr ISANameRevision ISARevisions[] = {
+ {{"arch8"}, 8}, {{"z10"}, 8},
+ {{"arch9"}, 9}, {{"z196"}, 9},
+ {{"arch10"}, 10}, {{"zEC12"}, 10},
+ {{"arch11"}, 11}, {{"z13"}, 11},
+ {{"arch12"}, 12}, {{"z14"}, 12}
+};
+
+int SystemZTargetInfo::getISARevision(StringRef Name) const {
+ const auto Rev =
+ llvm::find_if(ISARevisions, [Name](const ISANameRevision &CR) {
+ return CR.Name == Name;
+ });
+ if (Rev == std::end(ISARevisions))
+ return -1;
+ return Rev->ISARevisionID;
+}
+
+void SystemZTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const ISANameRevision &Rev : ISARevisions)
+ Values.push_back(Rev.Name);
+}
+
+bool SystemZTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("systemz", true)
+ .Case("arch8", ISARevision >= 8)
+ .Case("arch9", ISARevision >= 9)
+ .Case("arch10", ISARevision >= 10)
+ .Case("arch11", ISARevision >= 11)
+ .Case("arch12", ISARevision >= 12)
+ .Case("htm", HasTransactionalExecution)
+ .Case("vx", HasVector)
+ .Default(false);
+}
+
+void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__s390__");
+ Builder.defineMacro("__s390x__");
+ Builder.defineMacro("__zarch__");
+ Builder.defineMacro("__LONG_DOUBLE_128__");
+
+ Builder.defineMacro("__ARCH__", Twine(ISARevision));
+
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+
+ if (HasTransactionalExecution)
+ Builder.defineMacro("__HTM__");
+ if (HasVector)
+ Builder.defineMacro("__VX__");
+ if (Opts.ZVector)
+ Builder.defineMacro("__VEC__", "10302");
+}
+
+ArrayRef<Builtin::Info> SystemZTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::SystemZ::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h
new file mode 100644
index 000000000000..842316005ed9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h
@@ -0,0 +1,149 @@
+//===--- SystemZ.h - Declare SystemZ target feature support -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares SystemZ TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
+
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+ std::string CPU;
+ int ISARevision;
+ bool HasTransactionalExecution;
+ bool HasVector;
+
+public:
+ SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), CPU("z10"), ISARevision(8),
+ HasTransactionalExecution(false), HasVector(false) {
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
+ TLSSupported = true;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ DefaultAlignForAttributeAligned = 64;
+ MinGlobalAlign = 16;
+ resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64");
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override;
+
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::SystemZBuiltinVaList;
+ }
+
+ int getISARevision(StringRef Name) const;
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getISARevision(Name) != -1;
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ CPU = Name;
+ ISARevision = getISARevision(CPU);
+ return ISARevision != -1;
+ }
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ int ISARevision = getISARevision(CPU);
+ if (ISARevision >= 10)
+ Features["transactional-execution"] = true;
+ if (ISARevision >= 11)
+ Features["vector"] = true;
+ if (ISARevision >= 12)
+ Features["vector-enhancements-1"] = true;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ HasTransactionalExecution = false;
+ HasVector = false;
+ for (const auto &Feature : Features) {
+ if (Feature == "+transactional-execution")
+ HasTransactionalExecution = true;
+ else if (Feature == "+vector")
+ HasVector = true;
+ }
+ // If we use the vector ABI, vector types are 64-bit aligned.
+ if (HasVector) {
+ MaxVectorAlign = 64;
+ resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64"
+ "-v128:64-a:8:16-n32:64");
+ }
+ return true;
+ }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_C:
+ case CC_Swift:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+
+ StringRef getABI() const override {
+ if (HasVector)
+ return "vector";
+ return "";
+ }
+
+ bool useFloat128ManglingForLongDouble() const override { return true; }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp
new file mode 100644
index 000000000000..bf89c1dc549e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp
@@ -0,0 +1,35 @@
+//===--- TCE.cpp - Implement TCE target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements TCE TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TCE.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void TCETargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "tce", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
+}
+
+void TCELETargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "tcele", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
+ Builder.defineMacro("__TCELE__");
+ Builder.defineMacro("__TCELE_V1__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h
new file mode 100644
index 000000000000..be43bed98d80
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h
@@ -0,0 +1,123 @@
+//===--- TCE.h - Declare TCE target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares TCE TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_TCE_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_TCE_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// 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
+
+static const unsigned TCEOpenCLAddrSpaceMap[] = {
+ 0, // Default
+ 3, // opencl_global
+ 4, // opencl_local
+ 5, // opencl_constant
+ 0, // opencl_private
+ // FIXME: generic has to be added to the target
+ 0, // opencl_generic
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0 // cuda_shared
+};
+
+class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo {
+public:
+ TCETargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ TLSSupported = false;
+ IntWidth = 32;
+ LongWidth = LongLongWidth = 32;
+ PointerWidth = 32;
+ IntAlign = 32;
+ LongAlign = LongLongAlign = 32;
+ PointerAlign = 32;
+ SuitableAlign = 32;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLong;
+ 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();
+ resetDataLayout("E-p:32:32:32-i1:8:8-i8:8:32-"
+ "i16:16:32-i32:32:32-i64:32:32-"
+ "f32:32:32-f64:32:32-v64:32:32-"
+ "v128:32:32-v256:32:32-v512:32:32-"
+ "v1024:32:32-a0:0:32-n32");
+ AddrSpaceMap = &TCEOpenCLAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override { return Feature == "tce"; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ const char *getClobbers() const override { return ""; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY TCELETargetInfo : public TCETargetInfo {
+public:
+ TCELETargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : TCETargetInfo(Triple, Opts) {
+ BigEndian = false;
+
+ resetDataLayout("e-p:32:32:32-i1:8:8-i8:8:32-"
+ "i16:16:32-i32:32:32-i64:32:32-"
+ "f32:32:32-f64:32:32-v64:32:32-"
+ "v128:32:32-v256:32:32-v512:32:32-"
+ "v1024:32:32-a0:0:32-n32");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_TCE_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp
new file mode 100644
index 000000000000..b8a2a092aff4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -0,0 +1,118 @@
+//===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements WebAssembly TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WebAssembly.h"
+#include "Targets.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsWebAssembly.def"
+};
+
+static constexpr llvm::StringLiteral ValidCPUNames[] = {
+ {"mvp"}, {"bleeding-edge"}, {"generic"}};
+
+bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("simd128", SIMDLevel >= SIMD128)
+ .Case("nontrapping-fptoint", HasNontrappingFPToInt)
+ .Case("sign-ext", HasSignExt)
+ .Case("exception-handling", HasExceptionHandling)
+ .Default(false);
+}
+
+bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void WebAssemblyTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
+}
+
+void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
+ if (SIMDLevel >= SIMD128)
+ Builder.defineMacro("__wasm_simd128__");
+}
+
+bool WebAssemblyTargetInfo::handleTargetFeatures(
+ std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature == "+simd128") {
+ SIMDLevel = std::max(SIMDLevel, SIMD128);
+ continue;
+ }
+ if (Feature == "-simd128") {
+ SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
+ continue;
+ }
+ if (Feature == "+nontrapping-fptoint") {
+ HasNontrappingFPToInt = true;
+ continue;
+ }
+ if (Feature == "-nontrapping-fptoint") {
+ HasNontrappingFPToInt = false;
+ continue;
+ }
+ if (Feature == "+sign-ext") {
+ HasSignExt = true;
+ continue;
+ }
+ if (Feature == "-sign-ext") {
+ HasSignExt = false;
+ continue;
+ }
+ if (Feature == "+exception-handling") {
+ HasExceptionHandling = true;
+ continue;
+ }
+ if (Feature == "-exception-handling") {
+ HasExceptionHandling = false;
+ continue;
+ }
+
+ Diags.Report(diag::err_opt_not_valid_with_opt)
+ << Feature << "-target-feature";
+ return false;
+ }
+ return true;
+}
+
+ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
+ defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
+}
+
+void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
+ defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h
new file mode 100644
index 000000000000..c04c5cb6fb3a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h
@@ -0,0 +1,154 @@
+//=== WebAssembly.h - Declare WebAssembly target feature support *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares WebAssembly TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+
+ enum SIMDEnum {
+ NoSIMD,
+ SIMD128,
+ } SIMDLevel;
+
+ bool HasNontrappingFPToInt;
+ bool HasSignExt;
+ bool HasExceptionHandling;
+
+public:
+ explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
+ : TargetInfo(T), SIMDLevel(NoSIMD), HasNontrappingFPToInt(false),
+ HasSignExt(false), HasExceptionHandling(false) {
+ NoAsmVariants = true;
+ SuitableAlign = 128;
+ LargeArrayMinWidth = 128;
+ LargeArrayAlign = 128;
+ SimdDefaultAlign = 128;
+ SigAtomicType = SignedLong;
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ // size_t being unsigned long for both wasm32 and wasm64 makes mangled names
+ // more consistent between the two.
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+private:
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ if (CPU == "bleeding-edge") {
+ Features["simd128"] = true;
+ Features["nontrapping-fptoint"] = true;
+ Features["sign-ext"] = true;
+ }
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ bool hasFeature(StringRef Feature) const final;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) final;
+
+ bool isValidCPUName(StringRef Name) const final;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final;
+
+ bool setCPU(const std::string &Name) final { return isValidCPUName(Name); }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const final;
+
+ BuiltinVaListKind getBuiltinVaListKind() const final {
+ return VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const final { return None; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const final {
+ return false;
+ }
+
+ const char *getClobbers() const final { return ""; }
+
+ bool isCLZForZeroUndef() const final { return false; }
+
+ bool hasInt128Type() const final { return true; }
+
+ IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // WebAssembly prefers long long for explicitly 64-bit integers.
+ return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
+ : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
+ }
+
+ IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // WebAssembly uses long long for int_least64_t and int_fast64_t.
+ return BitWidth == 64
+ ? (IsSigned ? SignedLongLong : UnsignedLongLong)
+ : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
+ }
+};
+class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
+ : public WebAssemblyTargetInfo {
+public:
+ explicit WebAssembly32TargetInfo(const llvm::Triple &T,
+ const TargetOptions &Opts)
+ : WebAssemblyTargetInfo(T, Opts) {
+ resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128");
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo
+ : public WebAssemblyTargetInfo {
+public:
+ explicit WebAssembly64TargetInfo(const llvm::Triple &T,
+ const TargetOptions &Opts)
+ : WebAssemblyTargetInfo(T, Opts) {
+ LongAlign = LongWidth = 64;
+ PointerAlign = PointerWidth = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp
new file mode 100644
index 000000000000..e295cff9d5d2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp
@@ -0,0 +1,1792 @@
+//===--- X86.cpp - Implement X86 target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements X86 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/TargetParser.h"
+
+namespace clang {
+namespace targets {
+
+const Builtin::Info BuiltinInfoX86[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsX86.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsX86_64.def"
+};
+
+static const char *const GCCRegNames[] = {
+ "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
+ "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+ "argp", "flags", "fpcr", "fpsr", "dirflag", "frame", "xmm0", "xmm1",
+ "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "mm0", "mm1",
+ "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "r8", "r9",
+ "r10", "r11", "r12", "r13", "r14", "r15", "xmm8", "xmm9",
+ "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "ymm0", "ymm1",
+ "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9",
+ "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "xmm16", "xmm17",
+ "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25",
+ "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31", "ymm16", "ymm17",
+ "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25",
+ "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31", "zmm0", "zmm1",
+ "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9",
+ "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17",
+ "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25",
+ "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "k0", "k1",
+ "k2", "k3", "k4", "k5", "k6", "k7",
+ "cr0", "cr2", "cr3", "cr4", "cr8",
+ "dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
+ "bnd0", "bnd1", "bnd2", "bnd3",
+};
+
+const TargetInfo::AddlRegName AddlRegNames[] = {
+ {{"al", "ah", "eax", "rax"}, 0},
+ {{"bl", "bh", "ebx", "rbx"}, 3},
+ {{"cl", "ch", "ecx", "rcx"}, 2},
+ {{"dl", "dh", "edx", "rdx"}, 1},
+ {{"esi", "rsi"}, 4},
+ {{"edi", "rdi"}, 5},
+ {{"esp", "rsp"}, 7},
+ {{"ebp", "rbp"}, 6},
+ {{"r8d", "r8w", "r8b"}, 38},
+ {{"r9d", "r9w", "r9b"}, 39},
+ {{"r10d", "r10w", "r10b"}, 40},
+ {{"r11d", "r11w", "r11b"}, 41},
+ {{"r12d", "r12w", "r12b"}, 42},
+ {{"r13d", "r13w", "r13b"}, 43},
+ {{"r14d", "r14w", "r14b"}, 44},
+ {{"r15d", "r15w", "r15b"}, 45},
+};
+
+} // namespace targets
+} // namespace clang
+
+using namespace clang;
+using namespace clang::targets;
+
+bool X86TargetInfo::setFPMath(StringRef Name) {
+ if (Name == "387") {
+ FPMath = FP_387;
+ return true;
+ }
+ if (Name == "sse") {
+ FPMath = FP_SSE;
+ return true;
+ }
+ return false;
+}
+
+bool X86TargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ // FIXME: This *really* should not be here.
+ // X86_64 always has SSE2.
+ if (getTriple().getArch() == llvm::Triple::x86_64)
+ setFeatureEnabledImpl(Features, "sse2", true);
+
+ const CPUKind Kind = getCPUKind(CPU);
+
+ // Enable X87 for all X86 processors but Lakemont.
+ if (Kind != CK_Lakemont)
+ setFeatureEnabledImpl(Features, "x87", true);
+
+ switch (Kind) {
+ case CK_Generic:
+ case CK_i386:
+ case CK_i486:
+ case CK_i586:
+ case CK_Pentium:
+ case CK_PentiumPro:
+ case CK_Lakemont:
+ break;
+
+ case CK_PentiumMMX:
+ case CK_Pentium2:
+ case CK_K6:
+ case CK_WinChipC6:
+ setFeatureEnabledImpl(Features, "mmx", true);
+ break;
+
+ case CK_IcelakeServer:
+ setFeatureEnabledImpl(Features, "pconfig", true);
+ setFeatureEnabledImpl(Features, "wbnoinvd", true);
+ LLVM_FALLTHROUGH;
+ case CK_IcelakeClient:
+ setFeatureEnabledImpl(Features, "vaes", true);
+ setFeatureEnabledImpl(Features, "gfni", true);
+ setFeatureEnabledImpl(Features, "vpclmulqdq", true);
+ setFeatureEnabledImpl(Features, "avx512bitalg", true);
+ setFeatureEnabledImpl(Features, "avx512vnni", true);
+ setFeatureEnabledImpl(Features, "avx512vbmi2", true);
+ setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
+ setFeatureEnabledImpl(Features, "rdpid", true);
+ LLVM_FALLTHROUGH;
+ case CK_Cannonlake:
+ setFeatureEnabledImpl(Features, "avx512ifma", true);
+ setFeatureEnabledImpl(Features, "avx512vbmi", true);
+ setFeatureEnabledImpl(Features, "sha", true);
+ LLVM_FALLTHROUGH;
+ case CK_SkylakeServer:
+ setFeatureEnabledImpl(Features, "avx512f", true);
+ setFeatureEnabledImpl(Features, "avx512cd", true);
+ setFeatureEnabledImpl(Features, "avx512dq", true);
+ setFeatureEnabledImpl(Features, "avx512bw", true);
+ setFeatureEnabledImpl(Features, "avx512vl", true);
+ setFeatureEnabledImpl(Features, "pku", true);
+ if (Kind != CK_Cannonlake) // CNL inherits all SKX features, except CLWB
+ setFeatureEnabledImpl(Features, "clwb", true);
+ LLVM_FALLTHROUGH;
+ case CK_SkylakeClient:
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "mpx", true);
+ if (Kind != CK_SkylakeServer) // SKX inherits all SKL features, except SGX
+ setFeatureEnabledImpl(Features, "sgx", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "rtm", true);
+ LLVM_FALLTHROUGH;
+ case CK_Broadwell:
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ LLVM_FALLTHROUGH;
+ case CK_Haswell:
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "invpcid", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ LLVM_FALLTHROUGH;
+ case CK_IvyBridge:
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ LLVM_FALLTHROUGH;
+ case CK_SandyBridge:
+ setFeatureEnabledImpl(Features, "avx", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ LLVM_FALLTHROUGH;
+ case CK_Westmere:
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ LLVM_FALLTHROUGH;
+ case CK_Nehalem:
+ setFeatureEnabledImpl(Features, "sse4.2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Penryn:
+ setFeatureEnabledImpl(Features, "sse4.1", true);
+ LLVM_FALLTHROUGH;
+ case CK_Core2:
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
+ LLVM_FALLTHROUGH;
+ case CK_Yonah:
+ case CK_Prescott:
+ case CK_Nocona:
+ setFeatureEnabledImpl(Features, "sse3", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ LLVM_FALLTHROUGH;
+ case CK_PentiumM:
+ case CK_Pentium4:
+ case CK_x86_64:
+ setFeatureEnabledImpl(Features, "sse2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Pentium3:
+ case CK_C3_2:
+ setFeatureEnabledImpl(Features, "sse", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ break;
+
+ case CK_Tremont:
+ setFeatureEnabledImpl(Features, "cldemote", true);
+ setFeatureEnabledImpl(Features, "movdiri", true);
+ setFeatureEnabledImpl(Features, "movdir64b", true);
+ setFeatureEnabledImpl(Features, "gfni", true);
+ setFeatureEnabledImpl(Features, "waitpkg", true);
+ LLVM_FALLTHROUGH;
+ case CK_GoldmontPlus:
+ setFeatureEnabledImpl(Features, "ptwrite", true);
+ setFeatureEnabledImpl(Features, "rdpid", true);
+ setFeatureEnabledImpl(Features, "sgx", true);
+ LLVM_FALLTHROUGH;
+ case CK_Goldmont:
+ setFeatureEnabledImpl(Features, "sha", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "mpx", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ LLVM_FALLTHROUGH;
+ case CK_Silvermont:
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "sse4.2", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ LLVM_FALLTHROUGH;
+ case CK_Bonnell:
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
+ break;
+
+ case CK_KNM:
+ // TODO: Add avx5124fmaps/avx5124vnniw.
+ setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
+ LLVM_FALLTHROUGH;
+ case CK_KNL:
+ setFeatureEnabledImpl(Features, "avx512f", true);
+ setFeatureEnabledImpl(Features, "avx512cd", true);
+ setFeatureEnabledImpl(Features, "avx512er", true);
+ setFeatureEnabledImpl(Features, "avx512pf", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "prefetchwt1", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "rtm", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
+ break;
+
+ case CK_K6_2:
+ case CK_K6_3:
+ case CK_WinChip2:
+ case CK_C3:
+ setFeatureEnabledImpl(Features, "3dnow", true);
+ break;
+
+ case CK_AMDFAM10:
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
+ LLVM_FALLTHROUGH;
+ case CK_K8SSE3:
+ setFeatureEnabledImpl(Features, "sse3", true);
+ LLVM_FALLTHROUGH;
+ case CK_K8:
+ setFeatureEnabledImpl(Features, "sse2", true);
+ LLVM_FALLTHROUGH;
+ case CK_AthlonXP:
+ setFeatureEnabledImpl(Features, "sse", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ LLVM_FALLTHROUGH;
+ case CK_Athlon:
+ case CK_Geode:
+ setFeatureEnabledImpl(Features, "3dnowa", true);
+ break;
+
+ case CK_BTVER2:
+ setFeatureEnabledImpl(Features, "avx", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ LLVM_FALLTHROUGH;
+ case CK_BTVER1:
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
+ break;
+
+ case CK_ZNVER1:
+ setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "clzero", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "mwaitx", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
+ setFeatureEnabledImpl(Features, "sha", true);
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ break;
+
+ case CK_BDVER4:
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "mwaitx", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER3:
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER2:
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "tbm", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER1:
+ // xop implies avx, sse4a and fma4.
+ setFeatureEnabledImpl(Features, "xop", true);
+ setFeatureEnabledImpl(Features, "lwp", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
+ break;
+ }
+ if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
+ return false;
+
+ // Can't do this earlier because we need to be able to explicitly enable
+ // or disable these features and the things that they depend upon.
+
+ // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled.
+ auto I = Features.find("sse4.2");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-popcnt") ==
+ FeaturesVec.end())
+ Features["popcnt"] = true;
+
+ // Enable prfchw if 3DNow! is enabled and prfchw is not explicitly disabled.
+ I = Features.find("3dnow");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-prfchw") ==
+ FeaturesVec.end())
+ Features["prfchw"] = true;
+
+ // Additionally, if SSE is enabled and mmx is not explicitly disabled,
+ // then enable MMX.
+ I = Features.find("sse");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-mmx") ==
+ FeaturesVec.end())
+ Features["mmx"] = true;
+
+ return true;
+}
+
+void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
+ X86SSEEnum Level, bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case AVX512F:
+ Features["avx512f"] = Features["fma"] = Features["f16c"] = true;
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Features["avx2"] = true;
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Features["avx"] = true;
+ Features["xsave"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Features["sse4.2"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Features["sse4.1"] = true;
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Features["ssse3"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Features["sse3"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Features["sse2"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE1:
+ Features["sse"] = true;
+ LLVM_FALLTHROUGH;
+ case NoSSE:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoSSE:
+ case SSE1:
+ Features["sse"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Features["sse2"] = Features["pclmul"] = Features["aes"] = Features["sha"] =
+ Features["gfni"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Features["sse3"] = false;
+ setXOPLevel(Features, NoXOP, false);
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Features["ssse3"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Features["sse4.1"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Features["sse4.2"] = false;
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Features["fma"] = Features["avx"] = Features["f16c"] = Features["xsave"] =
+ Features["xsaveopt"] = Features["vaes"] = Features["vpclmulqdq"] = false;
+ setXOPLevel(Features, FMA4, false);
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Features["avx2"] = false;
+ LLVM_FALLTHROUGH;
+ case AVX512F:
+ Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] =
+ Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] =
+ Features["avx512vl"] = Features["avx512vbmi"] =
+ Features["avx512ifma"] = Features["avx512vpopcntdq"] =
+ Features["avx512bitalg"] = Features["avx512vnni"] =
+ Features["avx512vbmi2"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features,
+ MMX3DNowEnum Level, bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case AMD3DNowAthlon:
+ Features["3dnowa"] = true;
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Features["3dnow"] = true;
+ LLVM_FALLTHROUGH;
+ case MMX:
+ Features["mmx"] = true;
+ LLVM_FALLTHROUGH;
+ case NoMMX3DNow:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoMMX3DNow:
+ case MMX:
+ Features["mmx"] = false;
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Features["3dnow"] = false;
+ LLVM_FALLTHROUGH;
+ case AMD3DNowAthlon:
+ Features["3dnowa"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
+ bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case XOP:
+ Features["xop"] = true;
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Features["fma4"] = true;
+ setSSELevel(Features, AVX, true);
+ LLVM_FALLTHROUGH;
+ case SSE4A:
+ Features["sse4a"] = true;
+ setSSELevel(Features, SSE3, true);
+ LLVM_FALLTHROUGH;
+ case NoXOP:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoXOP:
+ case SSE4A:
+ Features["sse4a"] = false;
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Features["fma4"] = false;
+ LLVM_FALLTHROUGH;
+ case XOP:
+ Features["xop"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled) {
+ // This is a bit of a hack to deal with the sse4 target feature when used
+ // as part of the target attribute. We handle sse4 correctly everywhere
+ // else. See below for more information on how we handle the sse4 options.
+ if (Name != "sse4")
+ Features[Name] = Enabled;
+
+ if (Name == "mmx") {
+ setMMXLevel(Features, MMX, Enabled);
+ } else if (Name == "sse") {
+ setSSELevel(Features, SSE1, Enabled);
+ } else if (Name == "sse2") {
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "sse3") {
+ setSSELevel(Features, SSE3, Enabled);
+ } else if (Name == "ssse3") {
+ setSSELevel(Features, SSSE3, Enabled);
+ } else if (Name == "sse4.2") {
+ setSSELevel(Features, SSE42, Enabled);
+ } else if (Name == "sse4.1") {
+ setSSELevel(Features, SSE41, Enabled);
+ } else if (Name == "3dnow") {
+ setMMXLevel(Features, AMD3DNow, Enabled);
+ } else if (Name == "3dnowa") {
+ setMMXLevel(Features, AMD3DNowAthlon, Enabled);
+ } else if (Name == "aes") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ else
+ Features["vaes"] = false;
+ } else if (Name == "vaes") {
+ if (Enabled) {
+ setSSELevel(Features, AVX, Enabled);
+ Features["aes"] = true;
+ }
+ } else if (Name == "pclmul") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ else
+ Features["vpclmulqdq"] = false;
+ } else if (Name == "vpclmulqdq") {
+ if (Enabled) {
+ setSSELevel(Features, AVX, Enabled);
+ Features["pclmul"] = true;
+ }
+ } else if (Name == "gfni") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "avx") {
+ setSSELevel(Features, AVX, Enabled);
+ } else if (Name == "avx2") {
+ setSSELevel(Features, AVX2, Enabled);
+ } else if (Name == "avx512f") {
+ setSSELevel(Features, AVX512F, Enabled);
+ } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf" ||
+ Name == "avx512dq" || Name == "avx512bw" || Name == "avx512vl" ||
+ Name == "avx512vbmi" || Name == "avx512ifma" ||
+ Name == "avx512vpopcntdq" || Name == "avx512bitalg" ||
+ Name == "avx512vnni" || Name == "avx512vbmi2") {
+ if (Enabled)
+ setSSELevel(Features, AVX512F, Enabled);
+ // Enable BWI instruction if VBMI/VBMI2/BITALG is being enabled.
+ if ((Name.startswith("avx512vbmi") || Name == "avx512bitalg") && Enabled)
+ Features["avx512bw"] = true;
+ // Also disable VBMI/VBMI2/BITALG if BWI is being disabled.
+ if (Name == "avx512bw" && !Enabled)
+ Features["avx512vbmi"] = Features["avx512vbmi2"] =
+ Features["avx512bitalg"] = false;
+ } else if (Name == "fma") {
+ if (Enabled)
+ setSSELevel(Features, AVX, Enabled);
+ else
+ setSSELevel(Features, AVX512F, Enabled);
+ } else if (Name == "fma4") {
+ setXOPLevel(Features, FMA4, Enabled);
+ } else if (Name == "xop") {
+ setXOPLevel(Features, XOP, Enabled);
+ } else if (Name == "sse4a") {
+ setXOPLevel(Features, SSE4A, Enabled);
+ } else if (Name == "f16c") {
+ if (Enabled)
+ setSSELevel(Features, AVX, Enabled);
+ else
+ setSSELevel(Features, AVX512F, Enabled);
+ } else if (Name == "sha") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "sse4") {
+ // We can get here via the __target__ attribute since that's not controlled
+ // via the -msse4/-mno-sse4 command line alias. Handle this the same way
+ // here - turn on the sse4.2 if enabled, turn off the sse4.1 level if
+ // disabled.
+ if (Enabled)
+ setSSELevel(Features, SSE42, Enabled);
+ else
+ setSSELevel(Features, SSE41, Enabled);
+ } else if (Name == "xsave") {
+ if (!Enabled)
+ Features["xsaveopt"] = false;
+ } else if (Name == "xsaveopt" || Name == "xsavec" || Name == "xsaves") {
+ if (Enabled)
+ Features["xsave"] = true;
+ }
+}
+
+/// handleTargetFeatures - Perform initialization based on the user
+/// configured set of features.
+bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature[0] != '+')
+ continue;
+
+ if (Feature == "+aes") {
+ HasAES = true;
+ } else if (Feature == "+vaes") {
+ HasVAES = true;
+ } else if (Feature == "+pclmul") {
+ HasPCLMUL = true;
+ } else if (Feature == "+vpclmulqdq") {
+ HasVPCLMULQDQ = true;
+ } else if (Feature == "+lzcnt") {
+ HasLZCNT = true;
+ } else if (Feature == "+rdrnd") {
+ HasRDRND = true;
+ } else if (Feature == "+fsgsbase") {
+ HasFSGSBASE = true;
+ } else if (Feature == "+bmi") {
+ HasBMI = true;
+ } else if (Feature == "+bmi2") {
+ HasBMI2 = true;
+ } else if (Feature == "+popcnt") {
+ HasPOPCNT = true;
+ } else if (Feature == "+rtm") {
+ HasRTM = true;
+ } else if (Feature == "+prfchw") {
+ HasPRFCHW = true;
+ } else if (Feature == "+rdseed") {
+ HasRDSEED = true;
+ } else if (Feature == "+adx") {
+ HasADX = true;
+ } else if (Feature == "+tbm") {
+ HasTBM = true;
+ } else if (Feature == "+lwp") {
+ HasLWP = true;
+ } else if (Feature == "+fma") {
+ HasFMA = true;
+ } else if (Feature == "+f16c") {
+ HasF16C = true;
+ } else if (Feature == "+gfni") {
+ HasGFNI = true;
+ } else if (Feature == "+avx512cd") {
+ HasAVX512CD = true;
+ } else if (Feature == "+avx512vpopcntdq") {
+ HasAVX512VPOPCNTDQ = true;
+ } else if (Feature == "+avx512vnni") {
+ HasAVX512VNNI = true;
+ } else if (Feature == "+avx512er") {
+ HasAVX512ER = true;
+ } else if (Feature == "+avx512pf") {
+ HasAVX512PF = true;
+ } else if (Feature == "+avx512dq") {
+ HasAVX512DQ = true;
+ } else if (Feature == "+avx512bitalg") {
+ HasAVX512BITALG = true;
+ } else if (Feature == "+avx512bw") {
+ HasAVX512BW = true;
+ } else if (Feature == "+avx512vl") {
+ HasAVX512VL = true;
+ } else if (Feature == "+avx512vbmi") {
+ HasAVX512VBMI = true;
+ } else if (Feature == "+avx512vbmi2") {
+ HasAVX512VBMI2 = true;
+ } else if (Feature == "+avx512ifma") {
+ HasAVX512IFMA = true;
+ } else if (Feature == "+sha") {
+ HasSHA = true;
+ } else if (Feature == "+mpx") {
+ HasMPX = true;
+ } else if (Feature == "+shstk") {
+ HasSHSTK = true;
+ } else if (Feature == "+movbe") {
+ HasMOVBE = true;
+ } else if (Feature == "+sgx") {
+ HasSGX = true;
+ } else if (Feature == "+cx16") {
+ HasCX16 = true;
+ } else if (Feature == "+fxsr") {
+ HasFXSR = true;
+ } else if (Feature == "+xsave") {
+ HasXSAVE = true;
+ } else if (Feature == "+xsaveopt") {
+ HasXSAVEOPT = true;
+ } else if (Feature == "+xsavec") {
+ HasXSAVEC = true;
+ } else if (Feature == "+xsaves") {
+ HasXSAVES = true;
+ } else if (Feature == "+mwaitx") {
+ HasMWAITX = true;
+ } else if (Feature == "+pku") {
+ HasPKU = true;
+ } else if (Feature == "+clflushopt") {
+ HasCLFLUSHOPT = true;
+ } else if (Feature == "+clwb") {
+ HasCLWB = true;
+ } else if (Feature == "+wbnoinvd") {
+ HasWBNOINVD = true;
+ } else if (Feature == "+prefetchwt1") {
+ HasPREFETCHWT1 = true;
+ } else if (Feature == "+clzero") {
+ HasCLZERO = true;
+ } else if (Feature == "+cldemote") {
+ HasCLDEMOTE = true;
+ } else if (Feature == "+rdpid") {
+ HasRDPID = true;
+ } else if (Feature == "+retpoline") {
+ HasRetpoline = true;
+ } else if (Feature == "+retpoline-external-thunk") {
+ HasRetpolineExternalThunk = true;
+ } else if (Feature == "+sahf") {
+ HasLAHFSAHF = true;
+ } else if (Feature == "+waitpkg") {
+ HasWAITPKG = true;
+ } else if (Feature == "+movdiri") {
+ HasMOVDIRI = true;
+ } else if (Feature == "+movdir64b") {
+ HasMOVDIR64B = true;
+ } else if (Feature == "+pconfig") {
+ HasPCONFIG = true;
+ } else if (Feature == "+ptwrite") {
+ HasPTWRITE = true;
+ } else if (Feature == "+invpcid") {
+ HasINVPCID = true;
+ }
+
+ X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
+ .Case("+avx512f", AVX512F)
+ .Case("+avx2", AVX2)
+ .Case("+avx", AVX)
+ .Case("+sse4.2", SSE42)
+ .Case("+sse4.1", SSE41)
+ .Case("+ssse3", SSSE3)
+ .Case("+sse3", SSE3)
+ .Case("+sse2", SSE2)
+ .Case("+sse", SSE1)
+ .Default(NoSSE);
+ SSELevel = std::max(SSELevel, Level);
+
+ MMX3DNowEnum ThreeDNowLevel = llvm::StringSwitch<MMX3DNowEnum>(Feature)
+ .Case("+3dnowa", AMD3DNowAthlon)
+ .Case("+3dnow", AMD3DNow)
+ .Case("+mmx", MMX)
+ .Default(NoMMX3DNow);
+ MMX3DNowLevel = std::max(MMX3DNowLevel, ThreeDNowLevel);
+
+ XOPEnum XLevel = llvm::StringSwitch<XOPEnum>(Feature)
+ .Case("+xop", XOP)
+ .Case("+fma4", FMA4)
+ .Case("+sse4a", SSE4A)
+ .Default(NoXOP);
+ XOPLevel = std::max(XOPLevel, XLevel);
+ }
+
+ // LLVM doesn't have a separate switch for fpmath, so only accept it if it
+ // matches the selected sse level.
+ if ((FPMath == FP_SSE && SSELevel < SSE1) ||
+ (FPMath == FP_387 && SSELevel >= SSE1)) {
+ Diags.Report(diag::err_target_unsupported_fpmath)
+ << (FPMath == FP_SSE ? "sse" : "387");
+ return false;
+ }
+
+ SimdDefaultAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+}
+
+/// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro
+/// definitions for this particular subtarget.
+void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ if (getTriple().getArch() == llvm::Triple::x86_64) {
+ Builder.defineMacro("__amd64__");
+ Builder.defineMacro("__amd64");
+ Builder.defineMacro("__x86_64");
+ Builder.defineMacro("__x86_64__");
+ if (getTriple().getArchName() == "x86_64h") {
+ Builder.defineMacro("__x86_64h");
+ Builder.defineMacro("__x86_64h__");
+ }
+ } else {
+ DefineStd(Builder, "i386", Opts);
+ }
+
+ // Subtarget options.
+ // FIXME: We are hard-coding the tune parameters based on the CPU, but they
+ // truly should be based on -mtune options.
+ switch (CPU) {
+ case CK_Generic:
+ break;
+ case CK_i386:
+ // The rest are coming from the i386 define above.
+ Builder.defineMacro("__tune_i386__");
+ break;
+ case CK_i486:
+ case CK_WinChipC6:
+ case CK_WinChip2:
+ case CK_C3:
+ defineCPUMacros(Builder, "i486");
+ break;
+ case CK_PentiumMMX:
+ Builder.defineMacro("__pentium_mmx__");
+ Builder.defineMacro("__tune_pentium_mmx__");
+ LLVM_FALLTHROUGH;
+ case CK_i586:
+ case CK_Pentium:
+ defineCPUMacros(Builder, "i586");
+ defineCPUMacros(Builder, "pentium");
+ break;
+ case CK_Pentium3:
+ case CK_PentiumM:
+ Builder.defineMacro("__tune_pentium3__");
+ LLVM_FALLTHROUGH;
+ case CK_Pentium2:
+ case CK_C3_2:
+ Builder.defineMacro("__tune_pentium2__");
+ LLVM_FALLTHROUGH;
+ case CK_PentiumPro:
+ defineCPUMacros(Builder, "i686");
+ defineCPUMacros(Builder, "pentiumpro");
+ break;
+ case CK_Pentium4:
+ defineCPUMacros(Builder, "pentium4");
+ break;
+ case CK_Yonah:
+ case CK_Prescott:
+ case CK_Nocona:
+ defineCPUMacros(Builder, "nocona");
+ break;
+ case CK_Core2:
+ case CK_Penryn:
+ defineCPUMacros(Builder, "core2");
+ break;
+ case CK_Bonnell:
+ defineCPUMacros(Builder, "atom");
+ break;
+ case CK_Silvermont:
+ defineCPUMacros(Builder, "slm");
+ break;
+ case CK_Goldmont:
+ defineCPUMacros(Builder, "goldmont");
+ break;
+ case CK_GoldmontPlus:
+ defineCPUMacros(Builder, "goldmont_plus");
+ break;
+ case CK_Tremont:
+ defineCPUMacros(Builder, "tremont");
+ break;
+ case CK_Nehalem:
+ case CK_Westmere:
+ case CK_SandyBridge:
+ case CK_IvyBridge:
+ case CK_Haswell:
+ case CK_Broadwell:
+ case CK_SkylakeClient:
+ case CK_SkylakeServer:
+ case CK_Cannonlake:
+ case CK_IcelakeClient:
+ case CK_IcelakeServer:
+ // FIXME: Historically, we defined this legacy name, it would be nice to
+ // remove it at some point. We've never exposed fine-grained names for
+ // recent primary x86 CPUs, and we should keep it that way.
+ defineCPUMacros(Builder, "corei7");
+ break;
+ case CK_KNL:
+ defineCPUMacros(Builder, "knl");
+ break;
+ case CK_KNM:
+ break;
+ case CK_Lakemont:
+ defineCPUMacros(Builder, "i586", /*Tuning*/false);
+ defineCPUMacros(Builder, "pentium", /*Tuning*/false);
+ Builder.defineMacro("__tune_lakemont__");
+ break;
+ case CK_K6_2:
+ Builder.defineMacro("__k6_2__");
+ Builder.defineMacro("__tune_k6_2__");
+ LLVM_FALLTHROUGH;
+ case CK_K6_3:
+ if (CPU != CK_K6_2) { // In case of fallthrough
+ // FIXME: GCC may be enabling these in cases where some other k6
+ // architecture is specified but -m3dnow is explicitly provided. The
+ // exact semantics need to be determined and emulated here.
+ Builder.defineMacro("__k6_3__");
+ Builder.defineMacro("__tune_k6_3__");
+ }
+ LLVM_FALLTHROUGH;
+ case CK_K6:
+ defineCPUMacros(Builder, "k6");
+ break;
+ case CK_Athlon:
+ case CK_AthlonXP:
+ defineCPUMacros(Builder, "athlon");
+ if (SSELevel != NoSSE) {
+ Builder.defineMacro("__athlon_sse__");
+ Builder.defineMacro("__tune_athlon_sse__");
+ }
+ break;
+ case CK_K8:
+ case CK_K8SSE3:
+ case CK_x86_64:
+ defineCPUMacros(Builder, "k8");
+ break;
+ case CK_AMDFAM10:
+ defineCPUMacros(Builder, "amdfam10");
+ break;
+ case CK_BTVER1:
+ defineCPUMacros(Builder, "btver1");
+ break;
+ case CK_BTVER2:
+ defineCPUMacros(Builder, "btver2");
+ break;
+ case CK_BDVER1:
+ defineCPUMacros(Builder, "bdver1");
+ break;
+ case CK_BDVER2:
+ defineCPUMacros(Builder, "bdver2");
+ break;
+ case CK_BDVER3:
+ defineCPUMacros(Builder, "bdver3");
+ break;
+ case CK_BDVER4:
+ defineCPUMacros(Builder, "bdver4");
+ break;
+ case CK_ZNVER1:
+ defineCPUMacros(Builder, "znver1");
+ break;
+ case CK_Geode:
+ defineCPUMacros(Builder, "geode");
+ break;
+ }
+
+ // Target properties.
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline
+ // functions in glibc header files that use FP Stack inline asm which the
+ // backend can't deal with (PR879).
+ Builder.defineMacro("__NO_MATH_INLINES");
+
+ if (HasAES)
+ Builder.defineMacro("__AES__");
+
+ if (HasVAES)
+ Builder.defineMacro("__VAES__");
+
+ if (HasPCLMUL)
+ Builder.defineMacro("__PCLMUL__");
+
+ if (HasVPCLMULQDQ)
+ Builder.defineMacro("__VPCLMULQDQ__");
+
+ if (HasLZCNT)
+ Builder.defineMacro("__LZCNT__");
+
+ if (HasRDRND)
+ Builder.defineMacro("__RDRND__");
+
+ if (HasFSGSBASE)
+ Builder.defineMacro("__FSGSBASE__");
+
+ if (HasBMI)
+ Builder.defineMacro("__BMI__");
+
+ if (HasBMI2)
+ Builder.defineMacro("__BMI2__");
+
+ if (HasPOPCNT)
+ Builder.defineMacro("__POPCNT__");
+
+ if (HasRTM)
+ Builder.defineMacro("__RTM__");
+
+ if (HasPRFCHW)
+ Builder.defineMacro("__PRFCHW__");
+
+ if (HasRDSEED)
+ Builder.defineMacro("__RDSEED__");
+
+ if (HasADX)
+ Builder.defineMacro("__ADX__");
+
+ if (HasTBM)
+ Builder.defineMacro("__TBM__");
+
+ if (HasLWP)
+ Builder.defineMacro("__LWP__");
+
+ if (HasMWAITX)
+ Builder.defineMacro("__MWAITX__");
+
+ switch (XOPLevel) {
+ case XOP:
+ Builder.defineMacro("__XOP__");
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Builder.defineMacro("__FMA4__");
+ LLVM_FALLTHROUGH;
+ case SSE4A:
+ Builder.defineMacro("__SSE4A__");
+ LLVM_FALLTHROUGH;
+ case NoXOP:
+ break;
+ }
+
+ if (HasFMA)
+ Builder.defineMacro("__FMA__");
+
+ if (HasF16C)
+ Builder.defineMacro("__F16C__");
+
+ if (HasGFNI)
+ Builder.defineMacro("__GFNI__");
+
+ if (HasAVX512CD)
+ Builder.defineMacro("__AVX512CD__");
+ if (HasAVX512VPOPCNTDQ)
+ Builder.defineMacro("__AVX512VPOPCNTDQ__");
+ if (HasAVX512VNNI)
+ Builder.defineMacro("__AVX512VNNI__");
+ if (HasAVX512ER)
+ Builder.defineMacro("__AVX512ER__");
+ if (HasAVX512PF)
+ Builder.defineMacro("__AVX512PF__");
+ if (HasAVX512DQ)
+ Builder.defineMacro("__AVX512DQ__");
+ if (HasAVX512BITALG)
+ Builder.defineMacro("__AVX512BITALG__");
+ if (HasAVX512BW)
+ Builder.defineMacro("__AVX512BW__");
+ if (HasAVX512VL)
+ Builder.defineMacro("__AVX512VL__");
+ if (HasAVX512VBMI)
+ Builder.defineMacro("__AVX512VBMI__");
+ if (HasAVX512VBMI2)
+ Builder.defineMacro("__AVX512VBMI2__");
+ if (HasAVX512IFMA)
+ Builder.defineMacro("__AVX512IFMA__");
+
+ if (HasSHA)
+ Builder.defineMacro("__SHA__");
+
+ if (HasFXSR)
+ Builder.defineMacro("__FXSR__");
+ if (HasXSAVE)
+ Builder.defineMacro("__XSAVE__");
+ if (HasXSAVEOPT)
+ Builder.defineMacro("__XSAVEOPT__");
+ if (HasXSAVEC)
+ Builder.defineMacro("__XSAVEC__");
+ if (HasXSAVES)
+ Builder.defineMacro("__XSAVES__");
+ if (HasPKU)
+ Builder.defineMacro("__PKU__");
+ if (HasCLFLUSHOPT)
+ Builder.defineMacro("__CLFLUSHOPT__");
+ if (HasCLWB)
+ Builder.defineMacro("__CLWB__");
+ if (HasWBNOINVD)
+ Builder.defineMacro("__WBNOINVD__");
+ if (HasMPX)
+ Builder.defineMacro("__MPX__");
+ if (HasSHSTK)
+ Builder.defineMacro("__SHSTK__");
+ if (HasSGX)
+ Builder.defineMacro("__SGX__");
+ if (HasPREFETCHWT1)
+ Builder.defineMacro("__PREFETCHWT1__");
+ if (HasCLZERO)
+ Builder.defineMacro("__CLZERO__");
+ if (HasRDPID)
+ Builder.defineMacro("__RDPID__");
+ if (HasCLDEMOTE)
+ Builder.defineMacro("__CLDEMOTE__");
+ if (HasWAITPKG)
+ Builder.defineMacro("__WAITPKG__");
+ if (HasMOVDIRI)
+ Builder.defineMacro("__MOVDIRI__");
+ if (HasMOVDIR64B)
+ Builder.defineMacro("__MOVDIR64B__");
+ if (HasPCONFIG)
+ Builder.defineMacro("__PCONFIG__");
+ if (HasPTWRITE)
+ Builder.defineMacro("__PTWRITE__");
+ if (HasINVPCID)
+ Builder.defineMacro("__INVPCID__");
+
+ // Each case falls through to the previous one here.
+ switch (SSELevel) {
+ case AVX512F:
+ Builder.defineMacro("__AVX512F__");
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Builder.defineMacro("__AVX2__");
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Builder.defineMacro("__AVX__");
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Builder.defineMacro("__SSE4_2__");
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Builder.defineMacro("__SSE4_1__");
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Builder.defineMacro("__SSSE3__");
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Builder.defineMacro("__SSE3__");
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Builder.defineMacro("__SSE2__");
+ Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
+ LLVM_FALLTHROUGH;
+ case SSE1:
+ Builder.defineMacro("__SSE__");
+ Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
+ LLVM_FALLTHROUGH;
+ case NoSSE:
+ break;
+ }
+
+ if (Opts.MicrosoftExt && getTriple().getArch() == llvm::Triple::x86) {
+ switch (SSELevel) {
+ case AVX512F:
+ case AVX2:
+ case AVX:
+ case SSE42:
+ case SSE41:
+ case SSSE3:
+ case SSE3:
+ case SSE2:
+ Builder.defineMacro("_M_IX86_FP", Twine(2));
+ break;
+ case SSE1:
+ Builder.defineMacro("_M_IX86_FP", Twine(1));
+ break;
+ default:
+ Builder.defineMacro("_M_IX86_FP", Twine(0));
+ break;
+ }
+ }
+
+ // Each case falls through to the previous one here.
+ switch (MMX3DNowLevel) {
+ case AMD3DNowAthlon:
+ Builder.defineMacro("__3dNOW_A__");
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Builder.defineMacro("__3dNOW__");
+ LLVM_FALLTHROUGH;
+ case MMX:
+ Builder.defineMacro("__MMX__");
+ LLVM_FALLTHROUGH;
+ case NoMMX3DNow:
+ break;
+ }
+
+ if (CPU >= CK_i486) {
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ }
+ if (CPU >= CK_i586)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+ if (HasCX16)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+
+ if (HasFloat128)
+ Builder.defineMacro("__SIZEOF_FLOAT128__", "16");
+}
+
+bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("3dnow", true)
+ .Case("3dnowa", true)
+ .Case("adx", true)
+ .Case("aes", true)
+ .Case("avx", true)
+ .Case("avx2", true)
+ .Case("avx512f", true)
+ .Case("avx512cd", true)
+ .Case("avx512vpopcntdq", true)
+ .Case("avx512vnni", true)
+ .Case("avx512er", true)
+ .Case("avx512pf", true)
+ .Case("avx512dq", true)
+ .Case("avx512bitalg", true)
+ .Case("avx512bw", true)
+ .Case("avx512vl", true)
+ .Case("avx512vbmi", true)
+ .Case("avx512vbmi2", true)
+ .Case("avx512ifma", true)
+ .Case("bmi", true)
+ .Case("bmi2", true)
+ .Case("cldemote", true)
+ .Case("clflushopt", true)
+ .Case("clwb", true)
+ .Case("clzero", true)
+ .Case("cx16", true)
+ .Case("f16c", true)
+ .Case("fma", true)
+ .Case("fma4", true)
+ .Case("fsgsbase", true)
+ .Case("fxsr", true)
+ .Case("gfni", true)
+ .Case("invpcid", true)
+ .Case("lwp", true)
+ .Case("lzcnt", true)
+ .Case("mmx", true)
+ .Case("movbe", true)
+ .Case("movdiri", true)
+ .Case("movdir64b", true)
+ .Case("mpx", true)
+ .Case("mwaitx", true)
+ .Case("pclmul", true)
+ .Case("pconfig", true)
+ .Case("pku", true)
+ .Case("popcnt", true)
+ .Case("prefetchwt1", true)
+ .Case("prfchw", true)
+ .Case("ptwrite", true)
+ .Case("rdpid", true)
+ .Case("rdrnd", true)
+ .Case("rdseed", true)
+ .Case("rtm", true)
+ .Case("sahf", true)
+ .Case("sgx", true)
+ .Case("sha", true)
+ .Case("shstk", true)
+ .Case("sse", true)
+ .Case("sse2", true)
+ .Case("sse3", true)
+ .Case("ssse3", true)
+ .Case("sse4", true)
+ .Case("sse4.1", true)
+ .Case("sse4.2", true)
+ .Case("sse4a", true)
+ .Case("tbm", true)
+ .Case("vaes", true)
+ .Case("vpclmulqdq", true)
+ .Case("wbnoinvd", true)
+ .Case("waitpkg", true)
+ .Case("x87", true)
+ .Case("xop", true)
+ .Case("xsave", true)
+ .Case("xsavec", true)
+ .Case("xsaves", true)
+ .Case("xsaveopt", true)
+ .Default(false);
+}
+
+bool X86TargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("adx", HasADX)
+ .Case("aes", HasAES)
+ .Case("avx", SSELevel >= AVX)
+ .Case("avx2", SSELevel >= AVX2)
+ .Case("avx512f", SSELevel >= AVX512F)
+ .Case("avx512cd", HasAVX512CD)
+ .Case("avx512vpopcntdq", HasAVX512VPOPCNTDQ)
+ .Case("avx512vnni", HasAVX512VNNI)
+ .Case("avx512er", HasAVX512ER)
+ .Case("avx512pf", HasAVX512PF)
+ .Case("avx512dq", HasAVX512DQ)
+ .Case("avx512bitalg", HasAVX512BITALG)
+ .Case("avx512bw", HasAVX512BW)
+ .Case("avx512vl", HasAVX512VL)
+ .Case("avx512vbmi", HasAVX512VBMI)
+ .Case("avx512vbmi2", HasAVX512VBMI2)
+ .Case("avx512ifma", HasAVX512IFMA)
+ .Case("bmi", HasBMI)
+ .Case("bmi2", HasBMI2)
+ .Case("cldemote", HasCLDEMOTE)
+ .Case("clflushopt", HasCLFLUSHOPT)
+ .Case("clwb", HasCLWB)
+ .Case("clzero", HasCLZERO)
+ .Case("cx16", HasCX16)
+ .Case("f16c", HasF16C)
+ .Case("fma", HasFMA)
+ .Case("fma4", XOPLevel >= FMA4)
+ .Case("fsgsbase", HasFSGSBASE)
+ .Case("fxsr", HasFXSR)
+ .Case("gfni", HasGFNI)
+ .Case("invpcid", HasINVPCID)
+ .Case("lwp", HasLWP)
+ .Case("lzcnt", HasLZCNT)
+ .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
+ .Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
+ .Case("mmx", MMX3DNowLevel >= MMX)
+ .Case("movbe", HasMOVBE)
+ .Case("movdiri", HasMOVDIRI)
+ .Case("movdir64b", HasMOVDIR64B)
+ .Case("mpx", HasMPX)
+ .Case("mwaitx", HasMWAITX)
+ .Case("pclmul", HasPCLMUL)
+ .Case("pconfig", HasPCONFIG)
+ .Case("pku", HasPKU)
+ .Case("popcnt", HasPOPCNT)
+ .Case("prefetchwt1", HasPREFETCHWT1)
+ .Case("prfchw", HasPRFCHW)
+ .Case("ptwrite", HasPTWRITE)
+ .Case("rdpid", HasRDPID)
+ .Case("rdrnd", HasRDRND)
+ .Case("rdseed", HasRDSEED)
+ .Case("retpoline", HasRetpoline)
+ .Case("retpoline-external-thunk", HasRetpolineExternalThunk)
+ .Case("rtm", HasRTM)
+ .Case("sahf", HasLAHFSAHF)
+ .Case("sgx", HasSGX)
+ .Case("sha", HasSHA)
+ .Case("shstk", HasSHSTK)
+ .Case("sse", SSELevel >= SSE1)
+ .Case("sse2", SSELevel >= SSE2)
+ .Case("sse3", SSELevel >= SSE3)
+ .Case("ssse3", SSELevel >= SSSE3)
+ .Case("sse4.1", SSELevel >= SSE41)
+ .Case("sse4.2", SSELevel >= SSE42)
+ .Case("sse4a", XOPLevel >= SSE4A)
+ .Case("tbm", HasTBM)
+ .Case("vaes", HasVAES)
+ .Case("vpclmulqdq", HasVPCLMULQDQ)
+ .Case("wbnoinvd", HasWBNOINVD)
+ .Case("waitpkg", HasWAITPKG)
+ .Case("x86", true)
+ .Case("x86_32", getTriple().getArch() == llvm::Triple::x86)
+ .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64)
+ .Case("xop", XOPLevel >= XOP)
+ .Case("xsave", HasXSAVE)
+ .Case("xsavec", HasXSAVEC)
+ .Case("xsaves", HasXSAVES)
+ .Case("xsaveopt", HasXSAVEOPT)
+ .Default(false);
+}
+
+// We can't use a generic validation scheme for the features accepted here
+// versus subtarget features accepted in the target attribute because the
+// bitfield structure that's initialized in the runtime only supports the
+// below currently rather than the full range of subtarget features. (See
+// X86TargetInfo::hasFeature for a somewhat comprehensive list).
+bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
+ return llvm::StringSwitch<bool>(FeatureStr)
+#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, true)
+#include "llvm/Support/X86TargetParser.def"
+ .Default(false);
+}
+
+static llvm::X86::ProcessorFeatures getFeature(StringRef Name) {
+ return llvm::StringSwitch<llvm::X86::ProcessorFeatures>(Name)
+#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, llvm::X86::ENUM)
+#include "llvm/Support/X86TargetParser.def"
+ ;
+ // Note, this function should only be used after ensuring the value is
+ // correct, so it asserts if the value is out of range.
+}
+
+static unsigned getFeaturePriority(llvm::X86::ProcessorFeatures Feat) {
+ enum class FeatPriority {
+#define FEATURE(FEAT) FEAT,
+#include "clang/Basic/X86Target.def"
+ };
+ switch (Feat) {
+#define FEATURE(FEAT) \
+ case llvm::X86::FEAT: \
+ return static_cast<unsigned>(FeatPriority::FEAT);
+#include "clang/Basic/X86Target.def"
+ default:
+ llvm_unreachable("No Feature Priority for non-CPUSupports Features");
+ }
+}
+
+unsigned X86TargetInfo::multiVersionSortPriority(StringRef Name) const {
+ // Valid CPUs have a 'key feature' that compares just better than its key
+ // feature.
+ CPUKind Kind = getCPUKind(Name);
+ if (Kind != CK_Generic) {
+ switch (Kind) {
+ default:
+ llvm_unreachable(
+ "CPU Type without a key feature used in 'target' attribute");
+#define PROC_WITH_FEAT(ENUM, STR, IS64, KEY_FEAT) \
+ case CK_##ENUM: \
+ return (getFeaturePriority(llvm::X86::KEY_FEAT) << 1) + 1;
+#include "clang/Basic/X86Target.def"
+ }
+ }
+
+ // Now we know we have a feature, so get its priority and shift it a few so
+ // that we have sufficient room for the CPUs (above).
+ return getFeaturePriority(getFeature(Name)) << 1;
+}
+
+bool X86TargetInfo::validateCPUSpecificCPUDispatch(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, true)
+#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, true)
+#include "clang/Basic/X86Target.def"
+ .Default(false);
+}
+
+static StringRef CPUSpecificCPUDispatchNameDealias(StringRef Name) {
+ return llvm::StringSwitch<StringRef>(Name)
+#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, NAME)
+#include "clang/Basic/X86Target.def"
+ .Default(Name);
+}
+
+char X86TargetInfo::CPUSpecificManglingCharacter(StringRef Name) const {
+ return llvm::StringSwitch<char>(CPUSpecificCPUDispatchNameDealias(Name))
+#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, MANGLING)
+#include "clang/Basic/X86Target.def"
+ .Default(0);
+}
+
+void X86TargetInfo::getCPUSpecificCPUDispatchFeatures(
+ StringRef Name, llvm::SmallVectorImpl<StringRef> &Features) const {
+ StringRef WholeList =
+ llvm::StringSwitch<StringRef>(CPUSpecificCPUDispatchNameDealias(Name))
+#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, FEATURES)
+#include "clang/Basic/X86Target.def"
+ .Default("");
+ WholeList.split(Features, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+}
+
+std::string X86TargetInfo::getCPUKindCanonicalName(CPUKind Kind) const {
+ switch (Kind) {
+ case CK_Generic:
+ return "";
+#define PROC(ENUM, STRING, IS64BIT) \
+ case CK_##ENUM: \
+ return STRING;
+#include "clang/Basic/X86Target.def"
+ }
+ llvm_unreachable("Invalid CPUKind");
+}
+
+// We can't use a generic validation scheme for the cpus accepted here
+// versus subtarget cpus accepted in the target attribute because the
+// variables intitialized by the runtime only support the below currently
+// rather than the full range of cpus.
+bool X86TargetInfo::validateCpuIs(StringRef FeatureStr) const {
+ return llvm::StringSwitch<bool>(FeatureStr)
+#define X86_VENDOR(ENUM, STRING) .Case(STRING, true)
+#define X86_CPU_TYPE_COMPAT_WITH_ALIAS(ARCHNAME, ENUM, STR, ALIAS) \
+ .Cases(STR, ALIAS, true)
+#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true)
+#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true)
+#include "llvm/Support/X86TargetParser.def"
+ .Default(false);
+}
+
+bool X86TargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+ // Constant constraints.
+ case 'e': // 32-bit signed integer constant for use with sign-extending x86_64
+ // instructions.
+ case 'Z': // 32-bit unsigned integer constant for use with zero-extending
+ // x86_64 instructions.
+ case 's':
+ Info.setRequiresImmediate();
+ return true;
+ case 'I':
+ Info.setRequiresImmediate(0, 31);
+ return true;
+ case 'J':
+ Info.setRequiresImmediate(0, 63);
+ return true;
+ case 'K':
+ Info.setRequiresImmediate(-128, 127);
+ return true;
+ case 'L':
+ Info.setRequiresImmediate({int(0xff), int(0xffff), int(0xffffffff)});
+ return true;
+ case 'M':
+ Info.setRequiresImmediate(0, 3);
+ return true;
+ case 'N':
+ Info.setRequiresImmediate(0, 255);
+ return true;
+ case 'O':
+ Info.setRequiresImmediate(0, 127);
+ return true;
+ // Register constraints.
+ case 'Y': // 'Y' is the first character for several 2-character constraints.
+ // Shift the pointer to the second character of the constraint.
+ Name++;
+ switch (*Name) {
+ default:
+ return false;
+ case 'z':
+ case '0': // First SSE register.
+ case '2':
+ case 't': // Any SSE register, when SSE2 is enabled.
+ case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
+ case 'm': // Any MMX register, when inter-unit moves enabled.
+ case 'k': // AVX512 arch mask registers: k1-k7.
+ Info.setAllowsRegister();
+ return true;
+ }
+ case 'f': // Any x87 floating point stack register.
+ // Constraint 'f' cannot be used for output operands.
+ if (Info.ConstraintStr[0] == '=')
+ return false;
+ Info.setAllowsRegister();
+ return true;
+ case 'a': // eax.
+ case 'b': // ebx.
+ case 'c': // ecx.
+ case 'd': // edx.
+ case 'S': // esi.
+ case 'D': // edi.
+ case 'A': // edx:eax.
+ case 't': // Top of floating point stack.
+ case 'u': // Second from top of floating point stack.
+ case 'q': // Any register accessible as [r]l: a, b, c, and d.
+ case 'y': // Any MMX register.
+ case 'v': // Any {X,Y,Z}MM register (Arch & context dependent)
+ case 'x': // Any SSE register.
+ case 'k': // Any AVX512 mask register (same as Yk, additionally allows k0
+ // for intermideate k reg operations).
+ case 'Q': // Any register accessible as [r]h: a, b, c, and d.
+ case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
+ case 'l': // "Index" registers: any general register that can be used as an
+ // index in a base+index memory access.
+ Info.setAllowsRegister();
+ return true;
+ // Floating point constant constraints.
+ case 'C': // SSE floating point constant.
+ case 'G': // x87 floating point constant.
+ return true;
+ }
+}
+
+bool X86TargetInfo::validateOutputSize(StringRef Constraint,
+ unsigned Size) const {
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ return validateOperandSize(Constraint, Size);
+}
+
+bool X86TargetInfo::validateInputSize(StringRef Constraint,
+ unsigned Size) const {
+ return validateOperandSize(Constraint, Size);
+}
+
+bool X86TargetInfo::validateOperandSize(StringRef Constraint,
+ unsigned Size) const {
+ switch (Constraint[0]) {
+ default:
+ break;
+ case 'k':
+ // Registers k0-k7 (AVX512) size limit is 64 bit.
+ case 'y':
+ return Size <= 64;
+ case 'f':
+ case 't':
+ case 'u':
+ return Size <= 128;
+ case 'Y':
+ // 'Y' is the first character for several 2-character constraints.
+ switch (Constraint[1]) {
+ default:
+ return false;
+ case 'm':
+ // 'Ym' is synonymous with 'y'.
+ case 'k':
+ return Size <= 64;
+ case 'z':
+ case '0':
+ // XMM0
+ if (SSELevel >= SSE1)
+ return Size <= 128U;
+ return false;
+ case 'i':
+ case 't':
+ case '2':
+ // 'Yi','Yt','Y2' are synonymous with 'x' when SSE2 is enabled.
+ if (SSELevel < SSE2)
+ return false;
+ break;
+ }
+ case 'v':
+ case 'x':
+ if (SSELevel >= AVX512F)
+ // 512-bit zmm registers can be used if target supports AVX512F.
+ return Size <= 512U;
+ else if (SSELevel >= AVX)
+ // 256-bit ymm registers can be used if target supports AVX.
+ return Size <= 256U;
+ return Size <= 128U;
+
+ }
+
+ return true;
+}
+
+std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
+ switch (*Constraint) {
+ case 'a':
+ return std::string("{ax}");
+ case 'b':
+ return std::string("{bx}");
+ case 'c':
+ return std::string("{cx}");
+ case 'd':
+ return std::string("{dx}");
+ case 'S':
+ return std::string("{si}");
+ case 'D':
+ return std::string("{di}");
+ case 'p': // address
+ return std::string("im");
+ case 't': // top of floating point stack.
+ return std::string("{st}");
+ case 'u': // second from top of floating point stack.
+ return std::string("{st(1)}"); // second from top of floating point stack.
+ case 'Y':
+ switch (Constraint[1]) {
+ default:
+ // Break from inner switch and fall through (copy single char),
+ // continue parsing after copying the current constraint into
+ // the return string.
+ break;
+ case 'k':
+ case 'm':
+ case 'i':
+ case 't':
+ case 'z':
+ case '0':
+ case '2':
+ // "^" hints llvm that this is a 2 letter constraint.
+ // "Constraint++" is used to promote the string iterator
+ // to the next constraint.
+ return std::string("^") + std::string(Constraint++, 2);
+ }
+ LLVM_FALLTHROUGH;
+ default:
+ return std::string(1, *Constraint);
+ }
+}
+
+bool X86TargetInfo::checkCPUKind(CPUKind Kind) const {
+ // Perform any per-CPU checks necessary to determine if this CPU is
+ // acceptable.
+ switch (Kind) {
+ case CK_Generic:
+ // No processor selected!
+ return false;
+#define PROC(ENUM, STRING, IS64BIT) \
+ case CK_##ENUM: \
+ return IS64BIT || getTriple().getArch() == llvm::Triple::x86;
+#include "clang/Basic/X86Target.def"
+ }
+ llvm_unreachable("Unhandled CPU kind");
+}
+
+void X86TargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+#define PROC(ENUM, STRING, IS64BIT) \
+ if (IS64BIT || getTriple().getArch() == llvm::Triple::x86) \
+ Values.emplace_back(STRING);
+ // Go through CPUKind checking to ensure that the alias is de-aliased and
+ // 64 bit-ness is checked.
+#define PROC_ALIAS(ENUM, ALIAS) \
+ if (checkCPUKind(getCPUKind(ALIAS))) \
+ Values.emplace_back(ALIAS);
+#include "clang/Basic/X86Target.def"
+}
+
+X86TargetInfo::CPUKind X86TargetInfo::getCPUKind(StringRef CPU) const {
+ return llvm::StringSwitch<CPUKind>(CPU)
+#define PROC(ENUM, STRING, IS64BIT) .Case(STRING, CK_##ENUM)
+#define PROC_ALIAS(ENUM, ALIAS) .Case(ALIAS, CK_##ENUM)
+#include "clang/Basic/X86Target.def"
+ .Default(CK_Generic);
+}
+
+ArrayRef<const char *> X86TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::AddlRegName> X86TargetInfo::getGCCAddlRegNames() const {
+ return llvm::makeArrayRef(AddlRegNames);
+}
+
+ArrayRef<Builtin::Info> X86_32TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin -
+ Builtin::FirstTSBuiltin + 1);
+}
+
+ArrayRef<Builtin::Info> X86_64TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfoX86,
+ X86::LastTSBuiltin - Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h
new file mode 100644
index 000000000000..1d23b0ef6933
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h
@@ -0,0 +1,853 @@
+//===--- X86.h - Declare X86 target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares X86 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// X86 target abstract base class; x86-32 and x86-64 are very close, so
+// most of the implementation can be shared.
+class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
+
+ enum X86SSEEnum {
+ NoSSE,
+ SSE1,
+ SSE2,
+ SSE3,
+ SSSE3,
+ SSE41,
+ SSE42,
+ AVX,
+ AVX2,
+ AVX512F
+ } SSELevel = NoSSE;
+ enum MMX3DNowEnum {
+ NoMMX3DNow,
+ MMX,
+ AMD3DNow,
+ AMD3DNowAthlon
+ } MMX3DNowLevel = NoMMX3DNow;
+ enum XOPEnum { NoXOP, SSE4A, FMA4, XOP } XOPLevel = NoXOP;
+
+ bool HasAES = false;
+ bool HasVAES = false;
+ bool HasPCLMUL = false;
+ bool HasVPCLMULQDQ = false;
+ bool HasGFNI = false;
+ bool HasLZCNT = false;
+ bool HasRDRND = false;
+ bool HasFSGSBASE = false;
+ bool HasBMI = false;
+ bool HasBMI2 = false;
+ bool HasPOPCNT = false;
+ bool HasRTM = false;
+ bool HasPRFCHW = false;
+ bool HasRDSEED = false;
+ bool HasADX = false;
+ bool HasTBM = false;
+ bool HasLWP = false;
+ bool HasFMA = false;
+ bool HasF16C = false;
+ bool HasAVX512CD = false;
+ bool HasAVX512VPOPCNTDQ = false;
+ bool HasAVX512VNNI = false;
+ bool HasAVX512ER = false;
+ bool HasAVX512PF = false;
+ bool HasAVX512DQ = false;
+ bool HasAVX512BITALG = false;
+ bool HasAVX512BW = false;
+ bool HasAVX512VL = false;
+ bool HasAVX512VBMI = false;
+ bool HasAVX512VBMI2 = false;
+ bool HasAVX512IFMA = false;
+ bool HasSHA = false;
+ bool HasMPX = false;
+ bool HasSHSTK = false;
+ bool HasSGX = false;
+ bool HasCX16 = false;
+ bool HasFXSR = false;
+ bool HasXSAVE = false;
+ bool HasXSAVEOPT = false;
+ bool HasXSAVEC = false;
+ bool HasXSAVES = false;
+ bool HasMWAITX = false;
+ bool HasCLZERO = false;
+ bool HasCLDEMOTE = false;
+ bool HasPCONFIG = false;
+ bool HasPKU = false;
+ bool HasCLFLUSHOPT = false;
+ bool HasCLWB = false;
+ bool HasMOVBE = false;
+ bool HasPREFETCHWT1 = false;
+ bool HasRDPID = false;
+ bool HasRetpoline = false;
+ bool HasRetpolineExternalThunk = false;
+ bool HasLAHFSAHF = false;
+ bool HasWBNOINVD = false;
+ bool HasWAITPKG = false;
+ bool HasMOVDIRI = false;
+ bool HasMOVDIR64B = false;
+ bool HasPTWRITE = false;
+ bool HasINVPCID = false;
+
+protected:
+ /// Enumeration of all of the X86 CPUs supported by Clang.
+ ///
+ /// Each enumeration represents a particular CPU supported by Clang. These
+ /// loosely correspond to the options passed to '-march' or '-mtune' flags.
+ enum CPUKind {
+ CK_Generic,
+#define PROC(ENUM, STRING, IS64BIT) CK_##ENUM,
+#include "clang/Basic/X86Target.def"
+ } CPU = CK_Generic;
+
+ bool checkCPUKind(CPUKind Kind) const;
+
+ CPUKind getCPUKind(StringRef CPU) const;
+
+ std::string getCPUKindCanonicalName(CPUKind Kind) const;
+
+ enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
+
+public:
+ X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
+ }
+
+ unsigned getFloatEvalMethod() const override {
+ // X87 evaluates with 80 bits "long double" precision.
+ return SSELevel == NoSSE ? 2 : 0;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
+
+ bool validateCpuSupports(StringRef Name) const override;
+
+ bool validateCpuIs(StringRef Name) const override;
+
+ bool validateCPUSpecificCPUDispatch(StringRef Name) const override;
+
+ char CPUSpecificManglingCharacter(StringRef Name) const override;
+
+ void getCPUSpecificCPUDispatchFeatures(
+ StringRef Name,
+ llvm::SmallVectorImpl<StringRef> &Features) const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override;
+
+ bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
+ bool &HasSizeMismatch) const override {
+ // esp and ebp are the only 32-bit registers the x86 backend can currently
+ // handle.
+ if (RegName.equals("esp") || RegName.equals("ebp")) {
+ // Check that the register size is 32-bit.
+ HasSizeMismatch = RegSize != 32;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
+
+ bool validateInputSize(StringRef Constraint, unsigned Size) const override;
+
+ virtual bool
+ checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {
+ return true;
+ };
+
+ virtual bool
+ checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override {
+ return true;
+ };
+
+
+ virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
+
+ std::string convertConstraint(const char *&Constraint) const override;
+ const char *getClobbers() const override {
+ return "~{dirflag},~{fpsr},~{flags}";
+ }
+
+ StringRef getConstraintRegister(StringRef Constraint,
+ StringRef Expression) const override {
+ StringRef::iterator I, E;
+ for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
+ if (isalpha(*I))
+ break;
+ }
+ if (I == E)
+ return "";
+ switch (*I) {
+ // For the register constraints, return the matching register name
+ case 'a':
+ return "ax";
+ case 'b':
+ return "bx";
+ case 'c':
+ return "cx";
+ case 'd':
+ return "dx";
+ case 'S':
+ return "si";
+ case 'D':
+ return "di";
+ // In case the constraint is 'r' we need to return Expression
+ case 'r':
+ return Expression;
+ // Double letters Y<x> constraints
+ case 'Y':
+ if ((++I != E) && ((*I == '0') || (*I == 'z')))
+ return "xmm0";
+ default:
+ break;
+ }
+ return "";
+ }
+
+ bool useFP16ConversionIntrinsics() const override {
+ return false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level,
+ bool Enabled);
+
+ static void setMMXLevel(llvm::StringMap<bool> &Features, MMX3DNowEnum Level,
+ bool Enabled);
+
+ static void setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
+ bool Enabled);
+
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override {
+ setFeatureEnabledImpl(Features, Name, Enabled);
+ }
+
+ // This exists purely to cut down on the number of virtual calls in
+ // initFeatureMap which calls this repeatedly.
+ static void setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled);
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool isValidFeatureName(StringRef Name) const override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ StringRef getABI() const override {
+ if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
+ return "avx512";
+ if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
+ return "avx";
+ if (getTriple().getArch() == llvm::Triple::x86 &&
+ MMX3DNowLevel == NoMMX3DNow)
+ return "no-mmx";
+ return "";
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ return checkCPUKind(getCPUKind(Name));
+ }
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
+ bool setCPU(const std::string &Name) override {
+ return checkCPUKind(CPU = getCPUKind(Name));
+ }
+
+ bool supportsMultiVersioning() const override {
+ return getTriple().isOSBinFormatELF();
+ }
+ unsigned multiVersionSortPriority(StringRef Name) const override;
+
+ bool setFPMath(StringRef Name) override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ // Most of the non-ARM calling conventions are i386 conventions.
+ switch (CC) {
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ case CC_X86StdCall:
+ case CC_X86VectorCall:
+ case CC_X86RegCall:
+ case CC_C:
+ case CC_PreserveMost:
+ case CC_Swift:
+ case CC_X86Pascal:
+ case CC_IntelOclBicc:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return MT == CCMT_Member ? CC_X86ThisCall : CC_C;
+ }
+
+ bool hasSjLjLowering() const override { return true; }
+
+ void setSupportedOpenCLOpts() override {
+ getSupportedOpenCLOpts().supportAll();
+ }
+};
+
+// X86-32 generic target
+class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo {
+public:
+ X86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86TargetInfo(Triple, Opts) {
+ DoubleAlign = LongLongAlign = 32;
+ LongDoubleWidth = 96;
+ LongDoubleAlign = 32;
+ SuitableAlign = 128;
+ resetDataLayout("e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128");
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ RegParmMax = 3;
+
+ // Use fpret for all types.
+ RealTypeUsesObjCFPRet =
+ ((1 << TargetInfo::Float) | (1 << TargetInfo::Double) |
+ (1 << TargetInfo::LongDouble));
+
+ // x86-32 has atomics up to 8 bytes
+ // FIXME: Check that we actually have cmpxchg8b before setting
+ // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.)
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 2;
+ return -1;
+ }
+
+ bool validateOperandSize(StringRef Constraint, unsigned Size) const override {
+ switch (Constraint[0]) {
+ default:
+ break;
+ case 'R':
+ case 'q':
+ case 'Q':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'S':
+ case 'D':
+ return Size <= 32;
+ case 'A':
+ return Size <= 64;
+ }
+
+ return X86TargetInfo::validateOperandSize(Constraint, Size);
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo
+ : public NetBSDTargetInfo<X86_32TargetInfo> {
+public:
+ NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
+
+ unsigned getFloatEvalMethod() const override {
+ unsigned Major, Minor, Micro;
+ getTriple().getOSVersion(Major, Minor, Micro);
+ // New NetBSD uses the default rounding mode.
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 26) || Major == 0)
+ return X86_32TargetInfo::getFloatEvalMethod();
+ // NetBSD before 6.99.26 defaults to "double" rounding.
+ return 1;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
+ : public OpenBSDTargetInfo<X86_32TargetInfo> {
+public:
+ OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
+ : public DarwinTargetInfo<X86_32TargetInfo> {
+public:
+ DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ SuitableAlign = 128;
+ MaxVectorAlign = 256;
+ // The watchOS simulator uses the builtin bool type for Objective-C.
+ llvm::Triple T = llvm::Triple(Triple);
+ if (T.isWatchOS())
+ UseSignedCharForObjCBool = false;
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ resetDataLayout("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128");
+ HasAlignMac68kSupport = true;
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
+ Diags))
+ return false;
+ // We now know the features we have: we can decide how to align vectors.
+ MaxVectorAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+ }
+};
+
+// x86-32 Windows target
+class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
+ : public WindowsTargetInfo<X86_32TargetInfo> {
+public:
+ WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ DoubleAlign = LongLongAlign = 64;
+ bool IsWinCOFF =
+ getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
+ resetDataLayout(IsWinCOFF
+ ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+ : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32");
+ }
+};
+
+// x86-32 Windows Visual Studio target
+class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
+ : public WindowsX86_32TargetInfo {
+public:
+ MicrosoftX86_32TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsX86_32TargetInfo(Triple, Opts) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
+ WindowsX86_32TargetInfo::getVisualStudioDefines(Opts, Builder);
+ // 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.
+ Builder.defineMacro("_M_IX86", "600");
+ }
+};
+
+// x86-32 MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
+ : public WindowsX86_32TargetInfo {
+public:
+ MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsX86_32TargetInfo(Triple, Opts) {
+ HasFloat128 = true;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_X86_");
+ }
+};
+
+// x86-32 Cygwin target
+class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_32TargetInfo(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ DoubleAlign = LongLongAlign = 64;
+ resetDataLayout("e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_X86_");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN32__");
+ addCygMingDefines(Opts, Builder);
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+};
+
+// x86-32 Haiku target
+class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
+ : public HaikuTargetInfo<X86_32TargetInfo> {
+public:
+ HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__INTEL__");
+ }
+};
+
+// X86-32 MCU target
+class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_32TargetInfo(Triple, Opts) {
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ resetDataLayout("e-m:e-p:32:32-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32");
+ WIntType = UnsignedInt;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ // On MCU we support only C calling convention.
+ return CC == CC_C ? CCCR_OK : CCCR_Warning;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__iamcu");
+ Builder.defineMacro("__iamcu__");
+ }
+
+ bool allowsLargerPreferedTypeAlignment() const override { return false; }
+};
+
+// x86-32 RTEMS target
+class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_32TargetInfo(Triple, Opts) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__INTEL__");
+ Builder.defineMacro("__rtems__");
+ }
+};
+
+// x86-64 generic target
+class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
+public:
+ X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86TargetInfo(Triple, Opts) {
+ const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32;
+ bool IsWinCOFF =
+ getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
+ LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LargeArrayMinWidth = 128;
+ LargeArrayAlign = 128;
+ SuitableAlign = 128;
+ SizeType = IsX32 ? UnsignedInt : UnsignedLong;
+ PtrDiffType = IsX32 ? SignedInt : SignedLong;
+ IntPtrType = IsX32 ? SignedInt : SignedLong;
+ IntMaxType = IsX32 ? SignedLongLong : SignedLong;
+ Int64Type = IsX32 ? SignedLongLong : SignedLong;
+ RegParmMax = 6;
+
+ // Pointers are 32-bit in x32.
+ resetDataLayout(IsX32
+ ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"
+ : IsWinCOFF ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+ : "e-m:e-i64:64-f80:128-n8:16:32:64-S128");
+
+ // Use fpret only for long double.
+ RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
+
+ // Use fp2ret for _Complex long double.
+ ComplexLongDoubleUsesFP2Ret = true;
+
+ // Make __builtin_ms_va_list available.
+ HasBuiltinMSVaList = true;
+
+ // x86-64 has atomics up to 16 bytes.
+ MaxAtomicPromoteWidth = 128;
+ MaxAtomicInlineWidth = 64;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::X86_64ABIBuiltinVaList;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 1;
+ return -1;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_C:
+ case CC_Swift:
+ case CC_X86VectorCall:
+ case CC_IntelOclBicc:
+ case CC_Win64:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_X86RegCall:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return CC_C;
+ }
+
+ // for x32 we need it here explicitly
+ bool hasInt128Type() const override { return true; }
+
+ unsigned getUnwindWordWidth() const override { return 64; }
+
+ unsigned getRegisterWidth() const override { return 64; }
+
+ bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
+ bool &HasSizeMismatch) const override {
+ // rsp and rbp are the only 64-bit registers the x86 backend can currently
+ // handle.
+ if (RegName.equals("rsp") || RegName.equals("rbp")) {
+ // Check that the register size is 64-bit.
+ HasSizeMismatch = RegSize != 64;
+ return true;
+ }
+
+ // Check if the register is a 32-bit register the backend can handle.
+ return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
+ HasSizeMismatch);
+ }
+
+ void setMaxAtomicWidth() override {
+ if (hasFeature("cx16"))
+ MaxAtomicInlineWidth = 128;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+};
+
+// x86-64 Windows target
+class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
+ : public WindowsTargetInfo<X86_64TargetInfo> {
+public:
+ WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ LongWidth = LongAlign = 32;
+ DoubleAlign = LongLongAlign = 64;
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLongLong;
+ SizeType = UnsignedLongLong;
+ PtrDiffType = SignedLongLong;
+ IntPtrType = SignedLongLong;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ return CCCR_Ignore;
+ case CC_C:
+ case CC_X86VectorCall:
+ case CC_IntelOclBicc:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_X86_64SysV:
+ case CC_Swift:
+ case CC_X86RegCall:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+};
+
+// x86-64 Windows Visual Studio target
+class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
+ : public WindowsX86_64TargetInfo {
+public:
+ MicrosoftX86_64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsX86_64TargetInfo(Triple, Opts) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+ WindowsX86_64TargetInfo::getVisualStudioDefines(Opts, Builder);
+ Builder.defineMacro("_M_X64", "100");
+ Builder.defineMacro("_M_AMD64", "100");
+ }
+
+ TargetInfo::CallingConvKind
+ getCallingConvKind(bool ClangABICompat4) const override {
+ return CCK_MicrosoftWin64;
+ }
+};
+
+// x86-64 MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
+ : public WindowsX86_64TargetInfo {
+public:
+ MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsX86_64TargetInfo(Triple, Opts) {
+ // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
+ // with x86 FP ops. Weird.
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
+ HasFloat128 = true;
+ }
+};
+
+// x86-64 Cygwin target
+class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
+public:
+ CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_64TargetInfo(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ TLSSupported = false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_64TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__x86_64__");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN64__");
+ addCygMingDefines(Opts, Builder);
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
+ : public DarwinTargetInfo<X86_64TargetInfo> {
+public:
+ DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ Int64Type = SignedLongLong;
+ // The 64-bit iOS simulator uses the builtin bool type for Objective-C.
+ llvm::Triple T = llvm::Triple(Triple);
+ if (T.isiOS())
+ UseSignedCharForObjCBool = false;
+ resetDataLayout("e-m:o-i64:64-f80:128-n8:16:32:64-S128");
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
+ Diags))
+ return false;
+ // We now know the features we have: we can decide how to align vectors.
+ MaxVectorAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
+ : public OpenBSDTargetInfo<X86_64TargetInfo> {
+public:
+ OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLongLong;
+ }
+};
+
+// x86_32 Android target
+class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
+ : public LinuxTargetInfo<X86_32TargetInfo> {
+public:
+ AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ SuitableAlign = 32;
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+};
+
+// x86_64 Android target
+class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
+ : public LinuxTargetInfo<X86_64TargetInfo> {
+public:
+ AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ }
+
+ bool useFloat128ManglingForLongDouble() const override { return true; }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp
new file mode 100644
index 000000000000..793dca702dae
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp
@@ -0,0 +1,38 @@
+//===--- XCore.cpp - Implement XCore target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements XCore TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "XCore.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info XCoreTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsXCore.def"
+};
+
+void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__XS1B__");
+}
+
+ArrayRef<Builtin::Info> XCoreTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::XCore::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h
new file mode 100644
index 000000000000..346e0eee15b3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h
@@ -0,0 +1,82 @@
+//===--- XCore.h - Declare XCore target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares XCore TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_XCORE_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_XCORE_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY XCoreTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+
+public:
+ XCoreTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ NoAsmVariants = true;
+ LongLongAlign = 32;
+ SuitableAlign = 32;
+ DoubleAlign = LongDoubleAlign = 32;
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ WCharType = UnsignedChar;
+ WIntType = UnsignedInt;
+ UseZeroLengthBitfieldAlignment = true;
+ resetDataLayout("e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32"
+ "-f64:32-a:0:32-n32");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "cp", "dp", "sp", "lr"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister
+ return (RegNo < 2) ? RegNo : -1;
+ }
+
+ bool allowsLargerPreferedTypeAlignment() const override { return false; }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_XCORE_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp
new file mode 100644
index 000000000000..3b1f8fe34bef
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp
@@ -0,0 +1,48 @@
+//===--- TokenKinds.cpp - Token Kinds Support -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TokenKind enum and support functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+static const char * const TokNames[] = {
+#define TOK(X) #X,
+#define KEYWORD(X,Y) #X,
+#include "clang/Basic/TokenKinds.def"
+ nullptr
+};
+
+const char *tok::getTokenName(TokenKind Kind) {
+ if (Kind < tok::NUM_TOKENS)
+ return TokNames[Kind];
+ llvm_unreachable("unknown TokenKind");
+ return nullptr;
+}
+
+const char *tok::getPunctuatorSpelling(TokenKind Kind) {
+ switch (Kind) {
+#define PUNCTUATOR(X,Y) case X: return Y;
+#include "clang/Basic/TokenKinds.def"
+ default: break;
+ }
+ return nullptr;
+}
+
+const char *tok::getKeywordSpelling(TokenKind Kind) {
+ switch (Kind) {
+#define KEYWORD(X,Y) case kw_ ## X: return #X;
+#include "clang/Basic/TokenKinds.def"
+ default: break;
+ }
+ return nullptr;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
new file mode 100644
index 000000000000..0f23ad1824c2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
@@ -0,0 +1,151 @@
+//===- 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 "clang/Basic/Version.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Config/config.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
+#include <cstring>
+
+#ifdef HAVE_SVN_VERSION_INC
+# include "SVNVersion.inc"
+#endif
+
+namespace clang {
+
+std::string getClangRepositoryPath() {
+#if defined(CLANG_REPOSITORY_STRING)
+ return CLANG_REPOSITORY_STRING;
+#else
+#ifdef SVN_REPOSITORY
+ StringRef URL(SVN_REPOSITORY);
+#else
+ StringRef URL("");
+#endif
+
+ // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
+ // pick up a tag in an SVN export, for example.
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_701/final/lib/Basic/Version.cpp $");
+ if (URL.empty()) {
+ URL = SVNRepository.slice(SVNRepository.find(':'),
+ SVNRepository.find("/lib/Basic"));
+ }
+
+ // Strip off version from a build from an integration branch.
+ URL = URL.slice(0, URL.find("/src/tools/clang"));
+
+ // Trim path prefix off, assuming path came from standard cfe path.
+ size_t Start = URL.find("cfe/");
+ if (Start != StringRef::npos)
+ URL = URL.substr(Start + 4);
+
+ return URL;
+#endif
+}
+
+std::string getLLVMRepositoryPath() {
+#ifdef LLVM_REPOSITORY
+ StringRef URL(LLVM_REPOSITORY);
+#else
+ StringRef URL("");
+#endif
+
+ // Trim path prefix off, assuming path came from standard llvm path.
+ // Leave "llvm/" prefix to distinguish the following llvm revision from the
+ // clang revision.
+ size_t Start = URL.find("llvm/");
+ if (Start != StringRef::npos)
+ URL = URL.substr(Start);
+
+ return URL;
+}
+
+std::string getClangRevision() {
+#ifdef SVN_REVISION
+ return SVN_REVISION;
+#else
+ return "";
+#endif
+}
+
+std::string getLLVMRevision() {
+#ifdef LLVM_REVISION
+ return LLVM_REVISION;
+#else
+ return "";
+#endif
+}
+
+std::string getClangFullRepositoryVersion() {
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+ std::string Path = getClangRepositoryPath();
+ std::string Revision = getClangRevision();
+ if (!Path.empty() || !Revision.empty()) {
+ OS << '(';
+ if (!Path.empty())
+ OS << Path;
+ if (!Revision.empty()) {
+ if (!Path.empty())
+ OS << ' ';
+ OS << Revision;
+ }
+ OS << ')';
+ }
+ // Support LLVM in a separate repository.
+ std::string LLVMRev = getLLVMRevision();
+ if (!LLVMRev.empty() && LLVMRev != Revision) {
+ OS << " (";
+ std::string LLVMRepo = getLLVMRepositoryPath();
+ if (!LLVMRepo.empty())
+ OS << LLVMRepo << ' ';
+ OS << LLVMRev << ')';
+ }
+ return OS.str();
+}
+
+std::string getClangFullVersion() {
+ return getClangToolFullVersion("clang");
+}
+
+std::string getClangToolFullVersion(StringRef ToolName) {
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+#ifdef CLANG_VENDOR
+ OS << CLANG_VENDOR;
+#endif
+ OS << ToolName << " version " CLANG_VERSION_STRING " "
+ << getClangFullRepositoryVersion();
+
+ // If vendor supplied, include the base LLVM version as well.
+#ifdef CLANG_VENDOR
+ OS << " (based on " << BACKEND_PACKAGE_STRING << ")";
+#endif
+
+ return OS.str();
+}
+
+std::string getClangFullCPPVersion() {
+ // The version string we report in __VERSION__ is just a compacted version of
+ // the one we report on the command line.
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+#ifdef CLANG_VENDOR
+ OS << CLANG_VENDOR;
+#endif
+ OS << "Clang " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion();
+ return OS.str();
+}
+
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
new file mode 100644
index 000000000000..bcfcbdbb9014
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
@@ -0,0 +1,2026 @@
+//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the VirtualFileSystem interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <atomic>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <limits>
+#include <map>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace vfs;
+using namespace llvm;
+
+using llvm::sys::fs::file_status;
+using llvm::sys::fs::file_type;
+using llvm::sys::fs::perms;
+using llvm::sys::fs::UniqueID;
+
+Status::Status(const file_status &Status)
+ : UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
+ User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
+ Type(Status.type()), Perms(Status.permissions()) {}
+
+Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime,
+ uint32_t User, uint32_t Group, uint64_t Size, file_type Type,
+ perms Perms)
+ : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
+ Type(Type), Perms(Perms) {}
+
+Status Status::copyWithNewName(const Status &In, StringRef NewName) {
+ return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
+ In.getUser(), In.getGroup(), In.getSize(), In.getType(),
+ In.getPermissions());
+}
+
+Status Status::copyWithNewName(const file_status &In, StringRef NewName) {
+ return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
+ In.getUser(), In.getGroup(), In.getSize(), In.type(),
+ In.permissions());
+}
+
+bool Status::equivalent(const Status &Other) const {
+ assert(isStatusKnown() && Other.isStatusKnown());
+ return getUniqueID() == Other.getUniqueID();
+}
+
+bool Status::isDirectory() const {
+ return Type == file_type::directory_file;
+}
+
+bool Status::isRegularFile() const {
+ return Type == file_type::regular_file;
+}
+
+bool Status::isOther() const {
+ return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
+}
+
+bool Status::isSymlink() const {
+ return Type == file_type::symlink_file;
+}
+
+bool Status::isStatusKnown() const {
+ return Type != file_type::status_error;
+}
+
+bool Status::exists() const {
+ return isStatusKnown() && Type != file_type::file_not_found;
+}
+
+File::~File() = default;
+
+FileSystem::~FileSystem() = default;
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
+ bool RequiresNullTerminator, bool IsVolatile) {
+ auto F = openFileForRead(Name);
+ if (!F)
+ return F.getError();
+
+ return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
+}
+
+std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
+ if (llvm::sys::path::is_absolute(Path))
+ return {};
+
+ auto WorkingDir = getCurrentWorkingDirectory();
+ if (!WorkingDir)
+ return WorkingDir.getError();
+
+ return llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
+}
+
+std::error_code FileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ return errc::operation_not_permitted;
+}
+
+bool FileSystem::exists(const Twine &Path) {
+ auto Status = status(Path);
+ return Status && Status->exists();
+}
+
+#ifndef NDEBUG
+static bool isTraversalComponent(StringRef Component) {
+ return Component.equals("..") || Component.equals(".");
+}
+
+static bool pathHasTraversal(StringRef Path) {
+ using namespace llvm::sys;
+
+ for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
+ if (isTraversalComponent(Comp))
+ return true;
+ return false;
+}
+#endif
+
+//===-----------------------------------------------------------------------===/
+// RealFileSystem implementation
+//===-----------------------------------------------------------------------===/
+
+namespace {
+
+/// Wrapper around a raw file descriptor.
+class RealFile : public File {
+ friend class RealFileSystem;
+
+ int FD;
+ Status S;
+ std::string RealName;
+
+ RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
+ : FD(FD), S(NewName, {}, {}, {}, {}, {},
+ llvm::sys::fs::file_type::status_error, {}),
+ RealName(NewRealPathName.str()) {
+ assert(FD >= 0 && "Invalid or inactive file descriptor");
+ }
+
+public:
+ ~RealFile() override;
+
+ ErrorOr<Status> status() override;
+ ErrorOr<std::string> getName() override;
+ ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
+ int64_t FileSize,
+ bool RequiresNullTerminator,
+ bool IsVolatile) override;
+ std::error_code close() override;
+};
+
+} // namespace
+
+RealFile::~RealFile() { close(); }
+
+ErrorOr<Status> RealFile::status() {
+ assert(FD != -1 && "cannot stat closed file");
+ if (!S.isStatusKnown()) {
+ file_status RealStatus;
+ if (std::error_code EC = sys::fs::status(FD, RealStatus))
+ return EC;
+ S = Status::copyWithNewName(RealStatus, S.getName());
+ }
+ return S;
+}
+
+ErrorOr<std::string> RealFile::getName() {
+ return RealName.empty() ? S.getName().str() : RealName;
+}
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+RealFile::getBuffer(const Twine &Name, int64_t FileSize,
+ bool RequiresNullTerminator, bool IsVolatile) {
+ assert(FD != -1 && "cannot get buffer for closed file");
+ return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
+ IsVolatile);
+}
+
+std::error_code RealFile::close() {
+ std::error_code EC = sys::Process::SafelyCloseFileDescriptor(FD);
+ FD = -1;
+ return EC;
+}
+
+namespace {
+
+/// The file system according to your operating system.
+class RealFileSystem : public FileSystem {
+public:
+ ErrorOr<Status> status(const Twine &Path) override;
+ ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override;
+};
+
+} // namespace
+
+ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
+ sys::fs::file_status RealStatus;
+ if (std::error_code EC = sys::fs::status(Path, RealStatus))
+ return EC;
+ return Status::copyWithNewName(RealStatus, Path.str());
+}
+
+ErrorOr<std::unique_ptr<File>>
+RealFileSystem::openFileForRead(const Twine &Name) {
+ int FD;
+ SmallString<256> RealName;
+ if (std::error_code EC =
+ sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName))
+ return EC;
+ return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str()));
+}
+
+llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
+ SmallString<256> Dir;
+ if (std::error_code EC = llvm::sys::fs::current_path(Dir))
+ return EC;
+ return Dir.str().str();
+}
+
+std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
+ // FIXME: chdir is thread hostile; on the other hand, creating the same
+ // behavior as chdir is complex: chdir resolves the path once, thus
+ // guaranteeing that all subsequent relative path operations work
+ // on the same path the original chdir resulted in. This makes a
+ // difference for example on network filesystems, where symlinks might be
+ // switched during runtime of the tool. Fixing this depends on having a
+ // file system abstraction that allows openat() style interactions.
+ return llvm::sys::fs::set_current_path(Path);
+}
+
+std::error_code
+RealFileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ return llvm::sys::fs::real_path(Path, Output);
+}
+
+IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
+ static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem();
+ return FS;
+}
+
+namespace {
+
+class RealFSDirIter : public clang::vfs::detail::DirIterImpl {
+ llvm::sys::fs::directory_iterator Iter;
+
+public:
+ RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
+ if (Iter != llvm::sys::fs::directory_iterator()) {
+ llvm::sys::fs::file_status S;
+ std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
+ CurrentEntry = Status::copyWithNewName(S, Iter->path());
+ if (!EC)
+ EC = ErrorCode;
+ }
+ }
+
+ std::error_code increment() override {
+ std::error_code EC;
+ Iter.increment(EC);
+ if (Iter == llvm::sys::fs::directory_iterator()) {
+ CurrentEntry = Status();
+ } else {
+ llvm::sys::fs::file_status S;
+ std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
+ CurrentEntry = Status::copyWithNewName(S, Iter->path());
+ if (!EC)
+ EC = ErrorCode;
+ }
+ return EC;
+ }
+};
+
+} // namespace
+
+directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
+ std::error_code &EC) {
+ return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC));
+}
+
+//===-----------------------------------------------------------------------===/
+// OverlayFileSystem implementation
+//===-----------------------------------------------------------------------===/
+
+OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
+ FSList.push_back(std::move(BaseFS));
+}
+
+void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
+ FSList.push_back(FS);
+ // Synchronize added file systems by duplicating the working directory from
+ // the first one in the list.
+ FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
+}
+
+ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) {
+ // FIXME: handle symlinks that cross file systems
+ for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
+ ErrorOr<Status> Status = (*I)->status(Path);
+ if (Status || Status.getError() != llvm::errc::no_such_file_or_directory)
+ return Status;
+ }
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+ErrorOr<std::unique_ptr<File>>
+OverlayFileSystem::openFileForRead(const llvm::Twine &Path) {
+ // FIXME: handle symlinks that cross file systems
+ for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
+ auto Result = (*I)->openFileForRead(Path);
+ if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
+ return Result;
+ }
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+llvm::ErrorOr<std::string>
+OverlayFileSystem::getCurrentWorkingDirectory() const {
+ // All file systems are synchronized, just take the first working directory.
+ return FSList.front()->getCurrentWorkingDirectory();
+}
+
+std::error_code
+OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
+ for (auto &FS : FSList)
+ if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
+ return EC;
+ return {};
+}
+
+std::error_code
+OverlayFileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ for (auto &FS : FSList)
+ if (FS->exists(Path))
+ return FS->getRealPath(Path, Output);
+ return errc::no_such_file_or_directory;
+}
+
+clang::vfs::detail::DirIterImpl::~DirIterImpl() = default;
+
+namespace {
+
+class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
+ OverlayFileSystem &Overlays;
+ std::string Path;
+ OverlayFileSystem::iterator CurrentFS;
+ directory_iterator CurrentDirIter;
+ llvm::StringSet<> SeenNames;
+
+ std::error_code incrementFS() {
+ assert(CurrentFS != Overlays.overlays_end() && "incrementing past end");
+ ++CurrentFS;
+ for (auto E = Overlays.overlays_end(); CurrentFS != E; ++CurrentFS) {
+ std::error_code EC;
+ CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
+ if (EC && EC != errc::no_such_file_or_directory)
+ return EC;
+ if (CurrentDirIter != directory_iterator())
+ break; // found
+ }
+ return {};
+ }
+
+ std::error_code incrementDirIter(bool IsFirstTime) {
+ assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
+ "incrementing past end");
+ std::error_code EC;
+ if (!IsFirstTime)
+ CurrentDirIter.increment(EC);
+ if (!EC && CurrentDirIter == directory_iterator())
+ EC = incrementFS();
+ return EC;
+ }
+
+ std::error_code incrementImpl(bool IsFirstTime) {
+ while (true) {
+ std::error_code EC = incrementDirIter(IsFirstTime);
+ if (EC || CurrentDirIter == directory_iterator()) {
+ CurrentEntry = Status();
+ return EC;
+ }
+ CurrentEntry = *CurrentDirIter;
+ StringRef Name = llvm::sys::path::filename(CurrentEntry.getName());
+ if (SeenNames.insert(Name).second)
+ return EC; // name not seen before
+ }
+ llvm_unreachable("returned above");
+ }
+
+public:
+ OverlayFSDirIterImpl(const Twine &Path, OverlayFileSystem &FS,
+ std::error_code &EC)
+ : Overlays(FS), Path(Path.str()), CurrentFS(Overlays.overlays_begin()) {
+ CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
+ EC = incrementImpl(true);
+ }
+
+ std::error_code increment() override { return incrementImpl(false); }
+};
+
+} // namespace
+
+directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
+ std::error_code &EC) {
+ return directory_iterator(
+ std::make_shared<OverlayFSDirIterImpl>(Dir, *this, EC));
+}
+
+namespace clang {
+namespace vfs {
+
+namespace detail {
+
+enum InMemoryNodeKind { IME_File, IME_Directory };
+
+/// The in memory file system is a tree of Nodes. Every node can either be a
+/// file or a directory.
+class InMemoryNode {
+ Status Stat;
+ InMemoryNodeKind Kind;
+
+public:
+ InMemoryNode(Status Stat, InMemoryNodeKind Kind)
+ : Stat(std::move(Stat)), Kind(Kind) {}
+ virtual ~InMemoryNode() = default;
+
+ const Status &getStatus() const { return Stat; }
+ InMemoryNodeKind getKind() const { return Kind; }
+ virtual std::string toString(unsigned Indent) const = 0;
+};
+
+namespace {
+
+class InMemoryFile : public InMemoryNode {
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
+
+public:
+ InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
+ : InMemoryNode(std::move(Stat), IME_File), Buffer(std::move(Buffer)) {}
+
+ llvm::MemoryBuffer *getBuffer() { return Buffer.get(); }
+
+ std::string toString(unsigned Indent) const override {
+ return (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
+ }
+
+ static bool classof(const InMemoryNode *N) {
+ return N->getKind() == IME_File;
+ }
+};
+
+/// Adapt a InMemoryFile for VFS' File interface.
+class InMemoryFileAdaptor : public File {
+ InMemoryFile &Node;
+
+public:
+ explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
+
+ llvm::ErrorOr<Status> status() override { return Node.getStatus(); }
+
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool IsVolatile) override {
+ llvm::MemoryBuffer *Buf = Node.getBuffer();
+ return llvm::MemoryBuffer::getMemBuffer(
+ Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
+ }
+
+ std::error_code close() override { return {}; }
+};
+
+} // namespace
+
+class InMemoryDirectory : public InMemoryNode {
+ std::map<std::string, std::unique_ptr<InMemoryNode>> Entries;
+
+public:
+ InMemoryDirectory(Status Stat)
+ : InMemoryNode(std::move(Stat), IME_Directory) {}
+
+ InMemoryNode *getChild(StringRef Name) {
+ auto I = Entries.find(Name);
+ if (I != Entries.end())
+ return I->second.get();
+ return nullptr;
+ }
+
+ InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
+ return Entries.insert(make_pair(Name, std::move(Child)))
+ .first->second.get();
+ }
+
+ using const_iterator = decltype(Entries)::const_iterator;
+
+ const_iterator begin() const { return Entries.begin(); }
+ const_iterator end() const { return Entries.end(); }
+
+ std::string toString(unsigned Indent) const override {
+ std::string Result =
+ (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
+ for (const auto &Entry : Entries)
+ Result += Entry.second->toString(Indent + 2);
+ return Result;
+ }
+
+ static bool classof(const InMemoryNode *N) {
+ return N->getKind() == IME_Directory;
+ }
+};
+
+} // namespace detail
+
+InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
+ : Root(new detail::InMemoryDirectory(
+ Status("", getNextVirtualUniqueID(), llvm::sys::TimePoint<>(), 0, 0,
+ 0, llvm::sys::fs::file_type::directory_file,
+ llvm::sys::fs::perms::all_all))),
+ UseNormalizedPaths(UseNormalizedPaths) {}
+
+InMemoryFileSystem::~InMemoryFileSystem() = default;
+
+std::string InMemoryFileSystem::toString() const {
+ return Root->toString(/*Indent=*/0);
+}
+
+bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ Optional<uint32_t> User,
+ Optional<uint32_t> Group,
+ Optional<llvm::sys::fs::file_type> Type,
+ Optional<llvm::sys::fs::perms> Perms) {
+ SmallString<128> Path;
+ P.toVector(Path);
+
+ // Fix up relative paths. This just prepends the current working directory.
+ std::error_code EC = makeAbsolute(Path);
+ assert(!EC);
+ (void)EC;
+
+ if (useNormalizedPaths())
+ llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+ if (Path.empty())
+ return false;
+
+ detail::InMemoryDirectory *Dir = Root.get();
+ auto I = llvm::sys::path::begin(Path), E = sys::path::end(Path);
+ const auto ResolvedUser = User.getValueOr(0);
+ const auto ResolvedGroup = Group.getValueOr(0);
+ const auto ResolvedType = Type.getValueOr(sys::fs::file_type::regular_file);
+ const auto ResolvedPerms = Perms.getValueOr(sys::fs::all_all);
+ // Any intermediate directories we create should be accessible by
+ // the owner, even if Perms says otherwise for the final path.
+ const auto NewDirectoryPerms = ResolvedPerms | sys::fs::owner_all;
+ while (true) {
+ StringRef Name = *I;
+ detail::InMemoryNode *Node = Dir->getChild(Name);
+ ++I;
+ if (!Node) {
+ if (I == E) {
+ // End of the path, create a new file or directory.
+ Status Stat(P.str(), getNextVirtualUniqueID(),
+ llvm::sys::toTimePoint(ModificationTime), ResolvedUser,
+ ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
+ ResolvedPerms);
+ std::unique_ptr<detail::InMemoryNode> Child;
+ if (ResolvedType == sys::fs::file_type::directory_file) {
+ Child.reset(new detail::InMemoryDirectory(std::move(Stat)));
+ } else {
+ Child.reset(new detail::InMemoryFile(std::move(Stat),
+ std::move(Buffer)));
+ }
+ Dir->addChild(Name, std::move(Child));
+ return true;
+ }
+
+ // Create a new directory. Use the path up to here.
+ Status Stat(
+ StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
+ getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime),
+ ResolvedUser, ResolvedGroup, Buffer->getBufferSize(),
+ sys::fs::file_type::directory_file, NewDirectoryPerms);
+ Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
+ Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
+ continue;
+ }
+
+ if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
+ Dir = NewDir;
+ } else {
+ assert(isa<detail::InMemoryFile>(Node) &&
+ "Must be either file or directory!");
+
+ // Trying to insert a directory in place of a file.
+ if (I != E)
+ return false;
+
+ // Return false only if the new file is different from the existing one.
+ return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
+ Buffer->getBuffer();
+ }
+ }
+}
+
+bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
+ llvm::MemoryBuffer *Buffer,
+ Optional<uint32_t> User,
+ Optional<uint32_t> Group,
+ Optional<llvm::sys::fs::file_type> Type,
+ Optional<llvm::sys::fs::perms> Perms) {
+ return addFile(P, ModificationTime,
+ llvm::MemoryBuffer::getMemBuffer(
+ Buffer->getBuffer(), Buffer->getBufferIdentifier()),
+ std::move(User), std::move(Group), std::move(Type),
+ std::move(Perms));
+}
+
+static ErrorOr<detail::InMemoryNode *>
+lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
+ const Twine &P) {
+ SmallString<128> Path;
+ P.toVector(Path);
+
+ // Fix up relative paths. This just prepends the current working directory.
+ std::error_code EC = FS.makeAbsolute(Path);
+ assert(!EC);
+ (void)EC;
+
+ if (FS.useNormalizedPaths())
+ llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+ if (Path.empty())
+ return Dir;
+
+ auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
+ while (true) {
+ detail::InMemoryNode *Node = Dir->getChild(*I);
+ ++I;
+ if (!Node)
+ return errc::no_such_file_or_directory;
+
+ // Return the file if it's at the end of the path.
+ if (auto File = dyn_cast<detail::InMemoryFile>(Node)) {
+ if (I == E)
+ return File;
+ return errc::no_such_file_or_directory;
+ }
+
+ // Traverse directories.
+ Dir = cast<detail::InMemoryDirectory>(Node);
+ if (I == E)
+ return Dir;
+ }
+}
+
+llvm::ErrorOr<Status> InMemoryFileSystem::status(const Twine &Path) {
+ auto Node = lookupInMemoryNode(*this, Root.get(), Path);
+ if (Node)
+ return (*Node)->getStatus();
+ return Node.getError();
+}
+
+llvm::ErrorOr<std::unique_ptr<File>>
+InMemoryFileSystem::openFileForRead(const Twine &Path) {
+ auto Node = lookupInMemoryNode(*this, Root.get(), Path);
+ if (!Node)
+ return Node.getError();
+
+ // When we have a file provide a heap-allocated wrapper for the memory buffer
+ // to match the ownership semantics for File.
+ if (auto *F = dyn_cast<detail::InMemoryFile>(*Node))
+ return std::unique_ptr<File>(new detail::InMemoryFileAdaptor(*F));
+
+ // FIXME: errc::not_a_file?
+ return make_error_code(llvm::errc::invalid_argument);
+}
+
+namespace {
+
+/// Adaptor from InMemoryDir::iterator to directory_iterator.
+class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
+ detail::InMemoryDirectory::const_iterator I;
+ detail::InMemoryDirectory::const_iterator E;
+
+public:
+ InMemoryDirIterator() = default;
+
+ explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
+ : I(Dir.begin()), E(Dir.end()) {
+ if (I != E)
+ CurrentEntry = I->second->getStatus();
+ }
+
+ std::error_code increment() override {
+ ++I;
+ // When we're at the end, make CurrentEntry invalid and DirIterImpl will do
+ // the rest.
+ CurrentEntry = I != E ? I->second->getStatus() : Status();
+ return {};
+ }
+};
+
+} // namespace
+
+directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
+ std::error_code &EC) {
+ auto Node = lookupInMemoryNode(*this, Root.get(), Dir);
+ if (!Node) {
+ EC = Node.getError();
+ return directory_iterator(std::make_shared<InMemoryDirIterator>());
+ }
+
+ if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
+ return directory_iterator(std::make_shared<InMemoryDirIterator>(*DirNode));
+
+ EC = make_error_code(llvm::errc::not_a_directory);
+ return directory_iterator(std::make_shared<InMemoryDirIterator>());
+}
+
+std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
+ SmallString<128> Path;
+ P.toVector(Path);
+
+ // Fix up relative paths. This just prepends the current working directory.
+ std::error_code EC = makeAbsolute(Path);
+ assert(!EC);
+ (void)EC;
+
+ if (useNormalizedPaths())
+ llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+ if (!Path.empty())
+ WorkingDirectory = Path.str();
+ return {};
+}
+
+std::error_code
+InMemoryFileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ auto CWD = getCurrentWorkingDirectory();
+ if (!CWD || CWD->empty())
+ return errc::operation_not_permitted;
+ Path.toVector(Output);
+ if (auto EC = makeAbsolute(Output))
+ return EC;
+ llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true);
+ return {};
+}
+
+} // namespace vfs
+} // namespace clang
+
+//===-----------------------------------------------------------------------===/
+// RedirectingFileSystem implementation
+//===-----------------------------------------------------------------------===/
+
+namespace {
+
+enum EntryKind {
+ EK_Directory,
+ EK_File
+};
+
+/// A single file or directory in the VFS.
+class Entry {
+ EntryKind Kind;
+ std::string Name;
+
+public:
+ Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
+ virtual ~Entry() = default;
+
+ StringRef getName() const { return Name; }
+ EntryKind getKind() const { return Kind; }
+};
+
+class RedirectingDirectoryEntry : public Entry {
+ std::vector<std::unique_ptr<Entry>> Contents;
+ Status S;
+
+public:
+ RedirectingDirectoryEntry(StringRef Name,
+ std::vector<std::unique_ptr<Entry>> Contents,
+ Status S)
+ : Entry(EK_Directory, Name), Contents(std::move(Contents)),
+ S(std::move(S)) {}
+ RedirectingDirectoryEntry(StringRef Name, Status S)
+ : Entry(EK_Directory, Name), S(std::move(S)) {}
+
+ Status getStatus() { return S; }
+
+ void addContent(std::unique_ptr<Entry> Content) {
+ Contents.push_back(std::move(Content));
+ }
+
+ Entry *getLastContent() const { return Contents.back().get(); }
+
+ using iterator = decltype(Contents)::iterator;
+
+ iterator contents_begin() { return Contents.begin(); }
+ iterator contents_end() { return Contents.end(); }
+
+ static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
+};
+
+class RedirectingFileEntry : public Entry {
+public:
+ enum NameKind {
+ NK_NotSet,
+ NK_External,
+ NK_Virtual
+ };
+
+private:
+ std::string ExternalContentsPath;
+ NameKind UseName;
+
+public:
+ RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
+ NameKind UseName)
+ : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
+ UseName(UseName) {}
+
+ StringRef getExternalContentsPath() const { return ExternalContentsPath; }
+
+ /// whether to use the external path as the name for this file.
+ bool useExternalName(bool GlobalUseExternalName) const {
+ return UseName == NK_NotSet ? GlobalUseExternalName
+ : (UseName == NK_External);
+ }
+
+ NameKind getUseName() const { return UseName; }
+
+ static bool classof(const Entry *E) { return E->getKind() == EK_File; }
+};
+
+class RedirectingFileSystem;
+
+class VFSFromYamlDirIterImpl : public clang::vfs::detail::DirIterImpl {
+ std::string Dir;
+ RedirectingFileSystem &FS;
+ RedirectingDirectoryEntry::iterator Current, End;
+
+public:
+ VFSFromYamlDirIterImpl(const Twine &Path, RedirectingFileSystem &FS,
+ RedirectingDirectoryEntry::iterator Begin,
+ RedirectingDirectoryEntry::iterator End,
+ std::error_code &EC);
+
+ std::error_code increment() override;
+};
+
+/// A virtual file system parsed from a YAML file.
+///
+/// Currently, this class allows creating virtual directories and mapping
+/// virtual file paths to existing external files, available in \c ExternalFS.
+///
+/// The basic structure of the parsed file is:
+/// \verbatim
+/// {
+/// 'version': <version number>,
+/// <optional configuration>
+/// 'roots': [
+/// <directory entries>
+/// ]
+/// }
+/// \endverbatim
+///
+/// All configuration options are optional.
+/// 'case-sensitive': <boolean, default=true>
+/// 'use-external-names': <boolean, default=true>
+/// 'overlay-relative': <boolean, default=false>
+/// 'ignore-non-existent-contents': <boolean, default=true>
+///
+/// Virtual directories are represented as
+/// \verbatim
+/// {
+/// 'type': 'directory',
+/// 'name': <string>,
+/// 'contents': [ <file or directory entries> ]
+/// }
+/// \endverbatim
+///
+/// The default attributes for virtual directories are:
+/// \verbatim
+/// MTime = now() when created
+/// Perms = 0777
+/// User = Group = 0
+/// Size = 0
+/// UniqueID = unspecified unique value
+/// \endverbatim
+///
+/// Re-mapped files are represented as
+/// \verbatim
+/// {
+/// 'type': 'file',
+/// 'name': <string>,
+/// 'use-external-name': <boolean> # Optional
+/// 'external-contents': <path to external file>)
+/// }
+/// \endverbatim
+///
+/// and inherit their attributes from the external contents.
+///
+/// In both cases, the 'name' field may contain multiple path components (e.g.
+/// /path/to/file). However, any directory that contains more than one child
+/// must be uniquely represented by a directory entry.
+class RedirectingFileSystem : public vfs::FileSystem {
+ friend class RedirectingFileSystemParser;
+
+ /// The root(s) of the virtual file system.
+ std::vector<std::unique_ptr<Entry>> Roots;
+
+ /// The file system to use for external references.
+ IntrusiveRefCntPtr<FileSystem> ExternalFS;
+
+ /// If IsRelativeOverlay is set, this represents the directory
+ /// path that should be prefixed to each 'external-contents' entry
+ /// when reading from YAML files.
+ std::string ExternalContentsPrefixDir;
+
+ /// @name Configuration
+ /// @{
+
+ /// Whether to perform case-sensitive comparisons.
+ ///
+ /// Currently, case-insensitive matching only works correctly with ASCII.
+ bool CaseSensitive = true;
+
+ /// IsRelativeOverlay marks whether a IsExternalContentsPrefixDir path must
+ /// be prefixed in every 'external-contents' when reading from YAML files.
+ bool IsRelativeOverlay = false;
+
+ /// Whether to use to use the value of 'external-contents' for the
+ /// names of files. This global value is overridable on a per-file basis.
+ bool UseExternalNames = true;
+
+ /// Whether an invalid path obtained via 'external-contents' should
+ /// cause iteration on the VFS to stop. If 'true', the VFS should ignore
+ /// the entry and continue with the next. Allows YAML files to be shared
+ /// across multiple compiler invocations regardless of prior existent
+ /// paths in 'external-contents'. This global value is overridable on a
+ /// per-file basis.
+ bool IgnoreNonExistentContents = true;
+ /// @}
+
+ /// Virtual file paths and external files could be canonicalized without "..",
+ /// "." and "./" in their paths. FIXME: some unittests currently fail on
+ /// win32 when using remove_dots and remove_leading_dotslash on paths.
+ bool UseCanonicalizedPaths =
+#ifdef _WIN32
+ false;
+#else
+ true;
+#endif
+
+private:
+ RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
+ : ExternalFS(std::move(ExternalFS)) {}
+
+ /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
+ /// recursing into the contents of \p From if it is a directory.
+ ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start,
+ sys::path::const_iterator End, Entry *From);
+
+ /// Get the status of a given an \c Entry.
+ ErrorOr<Status> status(const Twine &Path, Entry *E);
+
+public:
+ /// Looks up \p Path in \c Roots.
+ ErrorOr<Entry *> lookupPath(const Twine &Path);
+
+ /// Parses \p Buffer, which is expected to be in YAML format and
+ /// returns a virtual file system representing its contents.
+ static RedirectingFileSystem *
+ create(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
+ void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
+
+ ErrorOr<Status> status(const Twine &Path) override;
+ ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
+
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+ return ExternalFS->getCurrentWorkingDirectory();
+ }
+
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+ return ExternalFS->setCurrentWorkingDirectory(Path);
+ }
+
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override{
+ ErrorOr<Entry *> E = lookupPath(Dir);
+ if (!E) {
+ EC = E.getError();
+ return {};
+ }
+ ErrorOr<Status> S = status(Dir, *E);
+ if (!S) {
+ EC = S.getError();
+ return {};
+ }
+ if (!S->isDirectory()) {
+ EC = std::error_code(static_cast<int>(errc::not_a_directory),
+ std::system_category());
+ return {};
+ }
+
+ auto *D = cast<RedirectingDirectoryEntry>(*E);
+ return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir,
+ *this, D->contents_begin(), D->contents_end(), EC));
+ }
+
+ void setExternalContentsPrefixDir(StringRef PrefixDir) {
+ ExternalContentsPrefixDir = PrefixDir.str();
+ }
+
+ StringRef getExternalContentsPrefixDir() const {
+ return ExternalContentsPrefixDir;
+ }
+
+ bool ignoreNonExistentContents() const {
+ return IgnoreNonExistentContents;
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void dump() const {
+ for (const auto &Root : Roots)
+ dumpEntry(Root.get());
+ }
+
+LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const {
+ StringRef Name = E->getName();
+ for (int i = 0, e = NumSpaces; i < e; ++i)
+ dbgs() << " ";
+ dbgs() << "'" << Name.str().c_str() << "'" << "\n";
+
+ if (E->getKind() == EK_Directory) {
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(E);
+ assert(DE && "Should be a directory");
+
+ for (std::unique_ptr<Entry> &SubEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end()))
+ dumpEntry(SubEntry.get(), NumSpaces+2);
+ }
+ }
+#endif
+};
+
+/// A helper class to hold the common YAML parsing state.
+class RedirectingFileSystemParser {
+ yaml::Stream &Stream;
+
+ void error(yaml::Node *N, const Twine &Msg) {
+ Stream.printError(N, Msg);
+ }
+
+ // false on error
+ bool parseScalarString(yaml::Node *N, StringRef &Result,
+ SmallVectorImpl<char> &Storage) {
+ const auto *S = dyn_cast<yaml::ScalarNode>(N);
+
+ if (!S) {
+ error(N, "expected string");
+ return false;
+ }
+ Result = S->getValue(Storage);
+ return true;
+ }
+
+ // false on error
+ bool parseScalarBool(yaml::Node *N, bool &Result) {
+ SmallString<5> Storage;
+ StringRef Value;
+ if (!parseScalarString(N, Value, Storage))
+ return false;
+
+ if (Value.equals_lower("true") || Value.equals_lower("on") ||
+ Value.equals_lower("yes") || Value == "1") {
+ Result = true;
+ return true;
+ } else if (Value.equals_lower("false") || Value.equals_lower("off") ||
+ Value.equals_lower("no") || Value == "0") {
+ Result = false;
+ return true;
+ }
+
+ error(N, "expected boolean value");
+ return false;
+ }
+
+ struct KeyStatus {
+ bool Required;
+ bool Seen = false;
+
+ KeyStatus(bool Required = false) : Required(Required) {}
+ };
+
+ using KeyStatusPair = std::pair<StringRef, KeyStatus>;
+
+ // false on error
+ bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
+ DenseMap<StringRef, KeyStatus> &Keys) {
+ if (!Keys.count(Key)) {
+ error(KeyNode, "unknown key");
+ return false;
+ }
+ KeyStatus &S = Keys[Key];
+ if (S.Seen) {
+ error(KeyNode, Twine("duplicate key '") + Key + "'");
+ return false;
+ }
+ S.Seen = true;
+ return true;
+ }
+
+ // false on error
+ bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
+ for (const auto &I : Keys) {
+ if (I.second.Required && !I.second.Seen) {
+ error(Obj, Twine("missing key '") + I.first + "'");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ Entry *lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
+ Entry *ParentEntry = nullptr) {
+ if (!ParentEntry) { // Look for a existent root
+ for (const auto &Root : FS->Roots) {
+ if (Name.equals(Root->getName())) {
+ ParentEntry = Root.get();
+ return ParentEntry;
+ }
+ }
+ } else { // Advance to the next component
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
+ for (std::unique_ptr<Entry> &Content :
+ llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+ auto *DirContent = dyn_cast<RedirectingDirectoryEntry>(Content.get());
+ if (DirContent && Name.equals(Content->getName()))
+ return DirContent;
+ }
+ }
+
+ // ... or create a new one
+ std::unique_ptr<Entry> E = llvm::make_unique<RedirectingDirectoryEntry>(
+ Name,
+ Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+ 0, 0, 0, file_type::directory_file, sys::fs::all_all));
+
+ if (!ParentEntry) { // Add a new root to the overlay
+ FS->Roots.push_back(std::move(E));
+ ParentEntry = FS->Roots.back().get();
+ return ParentEntry;
+ }
+
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
+ DE->addContent(std::move(E));
+ return DE->getLastContent();
+ }
+
+ void uniqueOverlayTree(RedirectingFileSystem *FS, Entry *SrcE,
+ Entry *NewParentE = nullptr) {
+ StringRef Name = SrcE->getName();
+ switch (SrcE->getKind()) {
+ case EK_Directory: {
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
+ assert(DE && "Must be a directory");
+ // Empty directories could be present in the YAML as a way to
+ // describe a file for a current directory after some of its subdir
+ // is parsed. This only leads to redundant walks, ignore it.
+ if (!Name.empty())
+ NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
+ for (std::unique_ptr<Entry> &SubEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end()))
+ uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
+ break;
+ }
+ case EK_File: {
+ auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
+ assert(FE && "Must be a file");
+ assert(NewParentE && "Parent entry must exist");
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(NewParentE);
+ DE->addContent(llvm::make_unique<RedirectingFileEntry>(
+ Name, FE->getExternalContentsPath(), FE->getUseName()));
+ break;
+ }
+ }
+ }
+
+ std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) {
+ auto *M = dyn_cast<yaml::MappingNode>(N);
+ if (!M) {
+ error(N, "expected mapping node for file or directory entry");
+ return nullptr;
+ }
+
+ KeyStatusPair Fields[] = {
+ KeyStatusPair("name", true),
+ KeyStatusPair("type", true),
+ KeyStatusPair("contents", false),
+ KeyStatusPair("external-contents", false),
+ KeyStatusPair("use-external-name", false),
+ };
+
+ DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
+
+ bool HasContents = false; // external or otherwise
+ std::vector<std::unique_ptr<Entry>> EntryArrayContents;
+ std::string ExternalContentsPath;
+ std::string Name;
+ auto UseExternalName = RedirectingFileEntry::NK_NotSet;
+ EntryKind Kind;
+
+ for (auto &I : *M) {
+ StringRef Key;
+ // Reuse the buffer for key and value, since we don't look at key after
+ // parsing value.
+ SmallString<256> Buffer;
+ if (!parseScalarString(I.getKey(), Key, Buffer))
+ return nullptr;
+
+ if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
+ return nullptr;
+
+ StringRef Value;
+ if (Key == "name") {
+ if (!parseScalarString(I.getValue(), Value, Buffer))
+ return nullptr;
+
+ if (FS->UseCanonicalizedPaths) {
+ SmallString<256> Path(Value);
+ // Guarantee that old YAML files containing paths with ".." and "."
+ // are properly canonicalized before read into the VFS.
+ Path = sys::path::remove_leading_dotslash(Path);
+ sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+ Name = Path.str();
+ } else {
+ Name = Value;
+ }
+ } else if (Key == "type") {
+ if (!parseScalarString(I.getValue(), Value, Buffer))
+ return nullptr;
+ if (Value == "file")
+ Kind = EK_File;
+ else if (Value == "directory")
+ Kind = EK_Directory;
+ else {
+ error(I.getValue(), "unknown value for 'type'");
+ return nullptr;
+ }
+ } else if (Key == "contents") {
+ if (HasContents) {
+ error(I.getKey(),
+ "entry already has 'contents' or 'external-contents'");
+ return nullptr;
+ }
+ HasContents = true;
+ auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
+ if (!Contents) {
+ // FIXME: this is only for directories, what about files?
+ error(I.getValue(), "expected array");
+ return nullptr;
+ }
+
+ for (auto &I : *Contents) {
+ if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
+ EntryArrayContents.push_back(std::move(E));
+ else
+ return nullptr;
+ }
+ } else if (Key == "external-contents") {
+ if (HasContents) {
+ error(I.getKey(),
+ "entry already has 'contents' or 'external-contents'");
+ return nullptr;
+ }
+ HasContents = true;
+ if (!parseScalarString(I.getValue(), Value, Buffer))
+ return nullptr;
+
+ SmallString<256> FullPath;
+ if (FS->IsRelativeOverlay) {
+ FullPath = FS->getExternalContentsPrefixDir();
+ assert(!FullPath.empty() &&
+ "External contents prefix directory must exist");
+ llvm::sys::path::append(FullPath, Value);
+ } else {
+ FullPath = Value;
+ }
+
+ if (FS->UseCanonicalizedPaths) {
+ // Guarantee that old YAML files containing paths with ".." and "."
+ // are properly canonicalized before read into the VFS.
+ FullPath = sys::path::remove_leading_dotslash(FullPath);
+ sys::path::remove_dots(FullPath, /*remove_dot_dot=*/true);
+ }
+ ExternalContentsPath = FullPath.str();
+ } else if (Key == "use-external-name") {
+ bool Val;
+ if (!parseScalarBool(I.getValue(), Val))
+ return nullptr;
+ UseExternalName = Val ? RedirectingFileEntry::NK_External
+ : RedirectingFileEntry::NK_Virtual;
+ } else {
+ llvm_unreachable("key missing from Keys");
+ }
+ }
+
+ if (Stream.failed())
+ return nullptr;
+
+ // check for missing keys
+ if (!HasContents) {
+ error(N, "missing key 'contents' or 'external-contents'");
+ return nullptr;
+ }
+ if (!checkMissingKeys(N, Keys))
+ return nullptr;
+
+ // check invalid configuration
+ if (Kind == EK_Directory &&
+ UseExternalName != RedirectingFileEntry::NK_NotSet) {
+ error(N, "'use-external-name' is not supported for directories");
+ return nullptr;
+ }
+
+ // Remove trailing slash(es), being careful not to remove the root path
+ StringRef Trimmed(Name);
+ size_t RootPathLen = sys::path::root_path(Trimmed).size();
+ while (Trimmed.size() > RootPathLen &&
+ sys::path::is_separator(Trimmed.back()))
+ Trimmed = Trimmed.slice(0, Trimmed.size()-1);
+ // Get the last component
+ StringRef LastComponent = sys::path::filename(Trimmed);
+
+ std::unique_ptr<Entry> Result;
+ switch (Kind) {
+ case EK_File:
+ Result = llvm::make_unique<RedirectingFileEntry>(
+ LastComponent, std::move(ExternalContentsPath), UseExternalName);
+ break;
+ case EK_Directory:
+ Result = llvm::make_unique<RedirectingDirectoryEntry>(
+ LastComponent, std::move(EntryArrayContents),
+ Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+ 0, 0, 0, file_type::directory_file, sys::fs::all_all));
+ break;
+ }
+
+ StringRef Parent = sys::path::parent_path(Trimmed);
+ if (Parent.empty())
+ return Result;
+
+ // if 'name' contains multiple components, create implicit directory entries
+ for (sys::path::reverse_iterator I = sys::path::rbegin(Parent),
+ E = sys::path::rend(Parent);
+ I != E; ++I) {
+ std::vector<std::unique_ptr<Entry>> Entries;
+ Entries.push_back(std::move(Result));
+ Result = llvm::make_unique<RedirectingDirectoryEntry>(
+ *I, std::move(Entries),
+ Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+ 0, 0, 0, file_type::directory_file, sys::fs::all_all));
+ }
+ return Result;
+ }
+
+public:
+ RedirectingFileSystemParser(yaml::Stream &S) : Stream(S) {}
+
+ // false on error
+ bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
+ auto *Top = dyn_cast<yaml::MappingNode>(Root);
+ if (!Top) {
+ error(Root, "expected mapping node");
+ return false;
+ }
+
+ KeyStatusPair Fields[] = {
+ KeyStatusPair("version", true),
+ KeyStatusPair("case-sensitive", false),
+ KeyStatusPair("use-external-names", false),
+ KeyStatusPair("overlay-relative", false),
+ KeyStatusPair("ignore-non-existent-contents", false),
+ KeyStatusPair("roots", true),
+ };
+
+ DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
+ std::vector<std::unique_ptr<Entry>> RootEntries;
+
+ // Parse configuration and 'roots'
+ for (auto &I : *Top) {
+ SmallString<10> KeyBuffer;
+ StringRef Key;
+ if (!parseScalarString(I.getKey(), Key, KeyBuffer))
+ return false;
+
+ if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
+ return false;
+
+ if (Key == "roots") {
+ auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
+ if (!Roots) {
+ error(I.getValue(), "expected array");
+ return false;
+ }
+
+ for (auto &I : *Roots) {
+ if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
+ RootEntries.push_back(std::move(E));
+ else
+ return false;
+ }
+ } else if (Key == "version") {
+ StringRef VersionString;
+ SmallString<4> Storage;
+ if (!parseScalarString(I.getValue(), VersionString, Storage))
+ return false;
+ int Version;
+ if (VersionString.getAsInteger<int>(10, Version)) {
+ error(I.getValue(), "expected integer");
+ return false;
+ }
+ if (Version < 0) {
+ error(I.getValue(), "invalid version number");
+ return false;
+ }
+ if (Version != 0) {
+ error(I.getValue(), "version mismatch, expected 0");
+ return false;
+ }
+ } else if (Key == "case-sensitive") {
+ if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
+ return false;
+ } else if (Key == "overlay-relative") {
+ if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
+ return false;
+ } else if (Key == "use-external-names") {
+ if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
+ return false;
+ } else if (Key == "ignore-non-existent-contents") {
+ if (!parseScalarBool(I.getValue(), FS->IgnoreNonExistentContents))
+ return false;
+ } else {
+ llvm_unreachable("key missing from Keys");
+ }
+ }
+
+ if (Stream.failed())
+ return false;
+
+ if (!checkMissingKeys(Top, Keys))
+ return false;
+
+ // Now that we sucessefully parsed the YAML file, canonicalize the internal
+ // representation to a proper directory tree so that we can search faster
+ // inside the VFS.
+ for (auto &E : RootEntries)
+ uniqueOverlayTree(FS, E.get());
+
+ return true;
+ }
+};
+
+} // namespace
+
+RedirectingFileSystem *
+RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ StringRef YAMLFilePath, void *DiagContext,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+ SourceMgr SM;
+ yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
+
+ SM.setDiagHandler(DiagHandler, DiagContext);
+ yaml::document_iterator DI = Stream.begin();
+ yaml::Node *Root = DI->getRoot();
+ if (DI == Stream.end() || !Root) {
+ SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node");
+ return nullptr;
+ }
+
+ RedirectingFileSystemParser P(Stream);
+
+ std::unique_ptr<RedirectingFileSystem> FS(
+ new RedirectingFileSystem(std::move(ExternalFS)));
+
+ if (!YAMLFilePath.empty()) {
+ // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
+ // to each 'external-contents' path.
+ //
+ // Example:
+ // -ivfsoverlay dummy.cache/vfs/vfs.yaml
+ // yields:
+ // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
+ //
+ SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
+ std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
+ assert(!EC && "Overlay dir final path must be absolute");
+ (void)EC;
+ FS->setExternalContentsPrefixDir(OverlayAbsDir);
+ }
+
+ if (!P.parse(Root, FS.get()))
+ return nullptr;
+
+ return FS.release();
+}
+
+ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
+ SmallString<256> Path;
+ Path_.toVector(Path);
+
+ // Handle relative paths
+ if (std::error_code EC = makeAbsolute(Path))
+ return EC;
+
+ // Canonicalize path by removing ".", "..", "./", etc components. This is
+ // a VFS request, do bot bother about symlinks in the path components
+ // but canonicalize in order to perform the correct entry search.
+ if (UseCanonicalizedPaths) {
+ Path = sys::path::remove_leading_dotslash(Path);
+ sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+ }
+
+ if (Path.empty())
+ return make_error_code(llvm::errc::invalid_argument);
+
+ sys::path::const_iterator Start = sys::path::begin(Path);
+ sys::path::const_iterator End = sys::path::end(Path);
+ for (const auto &Root : Roots) {
+ ErrorOr<Entry *> Result = lookupPath(Start, End, Root.get());
+ if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
+ return Result;
+ }
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+ErrorOr<Entry *>
+RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
+ sys::path::const_iterator End, Entry *From) {
+#ifndef _WIN32
+ assert(!isTraversalComponent(*Start) &&
+ !isTraversalComponent(From->getName()) &&
+ "Paths should not contain traversal components");
+#else
+ // FIXME: this is here to support windows, remove it once canonicalized
+ // paths become globally default.
+ if (Start->equals("."))
+ ++Start;
+#endif
+
+ StringRef FromName = From->getName();
+
+ // Forward the search to the next component in case this is an empty one.
+ if (!FromName.empty()) {
+ if (CaseSensitive ? !Start->equals(FromName)
+ : !Start->equals_lower(FromName))
+ // failure to match
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+
+ ++Start;
+
+ if (Start == End) {
+ // Match!
+ return From;
+ }
+ }
+
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(From);
+ if (!DE)
+ return make_error_code(llvm::errc::not_a_directory);
+
+ for (const std::unique_ptr<Entry> &DirEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+ ErrorOr<Entry *> Result = lookupPath(Start, End, DirEntry.get());
+ if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
+ return Result;
+ }
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames,
+ Status ExternalStatus) {
+ Status S = ExternalStatus;
+ if (!UseExternalNames)
+ S = Status::copyWithNewName(S, Path.str());
+ S.IsVFSMapped = true;
+ return S;
+}
+
+ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path, Entry *E) {
+ assert(E != nullptr);
+ if (auto *F = dyn_cast<RedirectingFileEntry>(E)) {
+ ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
+ assert(!S || S->getName() == F->getExternalContentsPath());
+ if (S)
+ return getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
+ *S);
+ return S;
+ } else { // directory
+ auto *DE = cast<RedirectingDirectoryEntry>(E);
+ return Status::copyWithNewName(DE->getStatus(), Path.str());
+ }
+}
+
+ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
+ ErrorOr<Entry *> Result = lookupPath(Path);
+ if (!Result)
+ return Result.getError();
+ return status(Path, *Result);
+}
+
+namespace {
+
+/// Provide a file wrapper with an overriden status.
+class FileWithFixedStatus : public File {
+ std::unique_ptr<File> InnerFile;
+ Status S;
+
+public:
+ FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
+ : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
+
+ ErrorOr<Status> status() override { return S; }
+ ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool IsVolatile) override {
+ return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
+ IsVolatile);
+ }
+
+ std::error_code close() override { return InnerFile->close(); }
+};
+
+} // namespace
+
+ErrorOr<std::unique_ptr<File>>
+RedirectingFileSystem::openFileForRead(const Twine &Path) {
+ ErrorOr<Entry *> E = lookupPath(Path);
+ if (!E)
+ return E.getError();
+
+ auto *F = dyn_cast<RedirectingFileEntry>(*E);
+ if (!F) // FIXME: errc::not_a_file?
+ return make_error_code(llvm::errc::invalid_argument);
+
+ auto Result = ExternalFS->openFileForRead(F->getExternalContentsPath());
+ if (!Result)
+ return Result;
+
+ auto ExternalStatus = (*Result)->status();
+ if (!ExternalStatus)
+ return ExternalStatus.getError();
+
+ // FIXME: Update the status with the name and VFSMapped.
+ Status S = getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
+ *ExternalStatus);
+ return std::unique_ptr<File>(
+ llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
+}
+
+IntrusiveRefCntPtr<FileSystem>
+vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ StringRef YAMLFilePath,
+ void *DiagContext,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+ return RedirectingFileSystem::create(std::move(Buffer), DiagHandler,
+ YAMLFilePath, DiagContext,
+ std::move(ExternalFS));
+}
+
+static void getVFSEntries(Entry *SrcE, SmallVectorImpl<StringRef> &Path,
+ SmallVectorImpl<YAMLVFSEntry> &Entries) {
+ auto Kind = SrcE->getKind();
+ if (Kind == EK_Directory) {
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
+ assert(DE && "Must be a directory");
+ for (std::unique_ptr<Entry> &SubEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+ Path.push_back(SubEntry->getName());
+ getVFSEntries(SubEntry.get(), Path, Entries);
+ Path.pop_back();
+ }
+ return;
+ }
+
+ assert(Kind == EK_File && "Must be a EK_File");
+ auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
+ assert(FE && "Must be a file");
+ SmallString<128> VPath;
+ for (auto &Comp : Path)
+ llvm::sys::path::append(VPath, Comp);
+ Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
+}
+
+void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ StringRef YAMLFilePath,
+ SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
+ void *DiagContext,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+ RedirectingFileSystem *VFS = RedirectingFileSystem::create(
+ std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
+ std::move(ExternalFS));
+ ErrorOr<Entry *> RootE = VFS->lookupPath("/");
+ if (!RootE)
+ return;
+ SmallVector<StringRef, 8> Components;
+ Components.push_back("/");
+ getVFSEntries(*RootE, Components, CollectedEntries);
+}
+
+UniqueID vfs::getNextVirtualUniqueID() {
+ static std::atomic<unsigned> UID;
+ unsigned ID = ++UID;
+ // The following assumes that uint64_t max will never collide with a real
+ // dev_t value from the OS.
+ return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
+}
+
+void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
+ assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
+ assert(sys::path::is_absolute(RealPath) && "real path not absolute");
+ assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
+ Mappings.emplace_back(VirtualPath, RealPath);
+}
+
+namespace {
+
+class JSONWriter {
+ llvm::raw_ostream &OS;
+ SmallVector<StringRef, 16> DirStack;
+
+ unsigned getDirIndent() { return 4 * DirStack.size(); }
+ unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
+ bool containedIn(StringRef Parent, StringRef Path);
+ StringRef containedPart(StringRef Parent, StringRef Path);
+ void startDirectory(StringRef Path);
+ void endDirectory();
+ void writeEntry(StringRef VPath, StringRef RPath);
+
+public:
+ JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
+
+ void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
+ Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
+ Optional<bool> IgnoreNonExistentContents, StringRef OverlayDir);
+};
+
+} // namespace
+
+bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
+ using namespace llvm::sys;
+
+ // Compare each path component.
+ auto IParent = path::begin(Parent), EParent = path::end(Parent);
+ for (auto IChild = path::begin(Path), EChild = path::end(Path);
+ IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
+ if (*IParent != *IChild)
+ return false;
+ }
+ // Have we exhausted the parent path?
+ return IParent == EParent;
+}
+
+StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
+ assert(!Parent.empty());
+ assert(containedIn(Parent, Path));
+ return Path.slice(Parent.size() + 1, StringRef::npos);
+}
+
+void JSONWriter::startDirectory(StringRef Path) {
+ StringRef Name =
+ DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
+ DirStack.push_back(Path);
+ unsigned Indent = getDirIndent();
+ OS.indent(Indent) << "{\n";
+ OS.indent(Indent + 2) << "'type': 'directory',\n";
+ OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n";
+ OS.indent(Indent + 2) << "'contents': [\n";
+}
+
+void JSONWriter::endDirectory() {
+ unsigned Indent = getDirIndent();
+ OS.indent(Indent + 2) << "]\n";
+ OS.indent(Indent) << "}";
+
+ DirStack.pop_back();
+}
+
+void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
+ unsigned Indent = getFileIndent();
+ OS.indent(Indent) << "{\n";
+ OS.indent(Indent + 2) << "'type': 'file',\n";
+ OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n";
+ OS.indent(Indent + 2) << "'external-contents': \""
+ << llvm::yaml::escape(RPath) << "\"\n";
+ OS.indent(Indent) << "}";
+}
+
+void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
+ Optional<bool> UseExternalNames,
+ Optional<bool> IsCaseSensitive,
+ Optional<bool> IsOverlayRelative,
+ Optional<bool> IgnoreNonExistentContents,
+ StringRef OverlayDir) {
+ using namespace llvm::sys;
+
+ OS << "{\n"
+ " 'version': 0,\n";
+ if (IsCaseSensitive.hasValue())
+ OS << " 'case-sensitive': '"
+ << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
+ if (UseExternalNames.hasValue())
+ OS << " 'use-external-names': '"
+ << (UseExternalNames.getValue() ? "true" : "false") << "',\n";
+ bool UseOverlayRelative = false;
+ if (IsOverlayRelative.hasValue()) {
+ UseOverlayRelative = IsOverlayRelative.getValue();
+ OS << " 'overlay-relative': '"
+ << (UseOverlayRelative ? "true" : "false") << "',\n";
+ }
+ if (IgnoreNonExistentContents.hasValue())
+ OS << " 'ignore-non-existent-contents': '"
+ << (IgnoreNonExistentContents.getValue() ? "true" : "false") << "',\n";
+ OS << " 'roots': [\n";
+
+ if (!Entries.empty()) {
+ const YAMLVFSEntry &Entry = Entries.front();
+ startDirectory(path::parent_path(Entry.VPath));
+
+ StringRef RPath = Entry.RPath;
+ if (UseOverlayRelative) {
+ unsigned OverlayDirLen = OverlayDir.size();
+ assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
+ "Overlay dir must be contained in RPath");
+ RPath = RPath.slice(OverlayDirLen, RPath.size());
+ }
+
+ writeEntry(path::filename(Entry.VPath), RPath);
+
+ for (const auto &Entry : Entries.slice(1)) {
+ StringRef Dir = path::parent_path(Entry.VPath);
+ if (Dir == DirStack.back())
+ OS << ",\n";
+ else {
+ while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
+ OS << "\n";
+ endDirectory();
+ }
+ OS << ",\n";
+ startDirectory(Dir);
+ }
+ StringRef RPath = Entry.RPath;
+ if (UseOverlayRelative) {
+ unsigned OverlayDirLen = OverlayDir.size();
+ assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
+ "Overlay dir must be contained in RPath");
+ RPath = RPath.slice(OverlayDirLen, RPath.size());
+ }
+ writeEntry(path::filename(Entry.VPath), RPath);
+ }
+
+ while (!DirStack.empty()) {
+ OS << "\n";
+ endDirectory();
+ }
+ OS << "\n";
+ }
+
+ OS << " ]\n"
+ << "}\n";
+}
+
+void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
+ llvm::sort(Mappings.begin(), Mappings.end(),
+ [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
+ return LHS.VPath < RHS.VPath;
+ });
+
+ JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
+ IsOverlayRelative, IgnoreNonExistentContents,
+ OverlayDir);
+}
+
+VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
+ const Twine &_Path, RedirectingFileSystem &FS,
+ RedirectingDirectoryEntry::iterator Begin,
+ RedirectingDirectoryEntry::iterator End, std::error_code &EC)
+ : Dir(_Path.str()), FS(FS), Current(Begin), End(End) {
+ while (Current != End) {
+ SmallString<128> PathStr(Dir);
+ llvm::sys::path::append(PathStr, (*Current)->getName());
+ llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
+ if (S) {
+ CurrentEntry = *S;
+ return;
+ }
+ // Skip entries which do not map to a reliable external content.
+ if (FS.ignoreNonExistentContents() &&
+ S.getError() == llvm::errc::no_such_file_or_directory) {
+ ++Current;
+ continue;
+ } else {
+ EC = S.getError();
+ break;
+ }
+ }
+}
+
+std::error_code VFSFromYamlDirIterImpl::increment() {
+ assert(Current != End && "cannot iterate past end");
+ while (++Current != End) {
+ SmallString<128> PathStr(Dir);
+ llvm::sys::path::append(PathStr, (*Current)->getName());
+ llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
+ if (!S) {
+ // Skip entries which do not map to a reliable external content.
+ if (FS.ignoreNonExistentContents() &&
+ S.getError() == llvm::errc::no_such_file_or_directory) {
+ continue;
+ } else {
+ return S.getError();
+ }
+ }
+ CurrentEntry = *S;
+ break;
+ }
+
+ if (Current == End)
+ CurrentEntry = Status();
+ return {};
+}
+
+vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_,
+ const Twine &Path,
+ std::error_code &EC)
+ : FS(&FS_) {
+ directory_iterator I = FS->dir_begin(Path, EC);
+ if (I != directory_iterator()) {
+ State = std::make_shared<IterState>();
+ State->push(I);
+ }
+}
+
+vfs::recursive_directory_iterator &
+recursive_directory_iterator::increment(std::error_code &EC) {
+ assert(FS && State && !State->empty() && "incrementing past end");
+ assert(State->top()->isStatusKnown() && "non-canonical end iterator");
+ vfs::directory_iterator End;
+ if (State->top()->isDirectory()) {
+ vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC);
+ if (I != End) {
+ State->push(I);
+ return *this;
+ }
+ }
+
+ while (!State->empty() && State->top().increment(EC) == End)
+ State->pop();
+
+ if (State->empty())
+ State.reset(); // end iterator
+
+ return *this;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp b/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp
new file mode 100644
index 000000000000..a999c45a0c3e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp
@@ -0,0 +1,230 @@
+//===--- Warnings.cpp - C-Language Front-end ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Command line warning options handler.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is responsible for handling all warning options. This includes
+// a number of -Wfoo options and their variants, which are driven by TableGen-
+// generated data, and the special cases -pedantic, -pedantic-errors, -w,
+// -Werror and -Wfatal-errors.
+//
+// Each warning option controls any number of actual warnings.
+// Given a warning option 'foo', the following are valid:
+// -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo
+//
+// Remark options are also handled here, analogously, except that they are much
+// simpler because a remark can't be promoted to an error.
+#include "clang/Basic/AllDiagnostics.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include <algorithm>
+#include <cstring>
+#include <utility>
+using namespace clang;
+
+// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning
+// opts
+static void EmitUnknownDiagWarning(DiagnosticsEngine &Diags,
+ diag::Flavor Flavor, StringRef Prefix,
+ StringRef Opt) {
+ StringRef Suggestion = DiagnosticIDs::getNearestOption(Flavor, Opt);
+ Diags.Report(diag::warn_unknown_diag_option)
+ << (Flavor == diag::Flavor::WarningOrError ? 0 : 1) << (Prefix.str() += Opt)
+ << !Suggestion.empty() << (Prefix.str() += Suggestion);
+}
+
+void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
+ const DiagnosticOptions &Opts,
+ bool ReportDiags) {
+ Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers
+ Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
+ Diags.setShowOverloads(Opts.getShowOverloads());
+
+ Diags.setElideType(Opts.ElideType);
+ Diags.setPrintTemplateTree(Opts.ShowTemplateTree);
+ Diags.setShowColors(Opts.ShowColors);
+
+ // Handle -ferror-limit
+ if (Opts.ErrorLimit)
+ Diags.setErrorLimit(Opts.ErrorLimit);
+ if (Opts.TemplateBacktraceLimit)
+ Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit);
+ if (Opts.ConstexprBacktraceLimit)
+ Diags.setConstexprBacktraceLimit(Opts.ConstexprBacktraceLimit);
+
+ // If -pedantic or -pedantic-errors was specified, then we want to map all
+ // extension diagnostics onto WARNING or ERROR unless the user has futz'd
+ // around with them explicitly.
+ if (Opts.PedanticErrors)
+ Diags.setExtensionHandlingBehavior(diag::Severity::Error);
+ else if (Opts.Pedantic)
+ Diags.setExtensionHandlingBehavior(diag::Severity::Warning);
+ else
+ Diags.setExtensionHandlingBehavior(diag::Severity::Ignored);
+
+ SmallVector<diag::kind, 10> _Diags;
+ const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs =
+ Diags.getDiagnosticIDs();
+ // We parse the warning options twice. The first pass sets diagnostic state,
+ // while the second pass reports warnings/errors. This has the effect that
+ // we follow the more canonical "last option wins" paradigm when there are
+ // conflicting options.
+ for (unsigned Report = 0, ReportEnd = 2; Report != ReportEnd; ++Report) {
+ bool SetDiagnostic = (Report == 0);
+
+ // If we've set the diagnostic state and are not reporting diagnostics then
+ // we're done.
+ if (!SetDiagnostic && !ReportDiags)
+ break;
+
+ for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
+ const auto Flavor = diag::Flavor::WarningOrError;
+ StringRef Opt = Opts.Warnings[i];
+ StringRef OrigOpt = Opts.Warnings[i];
+
+ // Treat -Wformat=0 as an alias for -Wno-format.
+ if (Opt == "format=0")
+ Opt = "no-format";
+
+ // Check to see if this warning starts with "no-", if so, this is a
+ // negative form of the option.
+ bool isPositive = true;
+ if (Opt.startswith("no-")) {
+ isPositive = false;
+ Opt = Opt.substr(3);
+ }
+
+ // Figure out how this option affects the warning. If -Wfoo, map the
+ // diagnostic to a warning, if -Wno-foo, map it to ignore.
+ diag::Severity Mapping =
+ isPositive ? diag::Severity::Warning : diag::Severity::Ignored;
+
+ // -Wsystem-headers is a special case, not driven by the option table. It
+ // cannot be controlled with -Werror.
+ if (Opt == "system-headers") {
+ if (SetDiagnostic)
+ Diags.setSuppressSystemWarnings(!isPositive);
+ continue;
+ }
+
+ // -Weverything is a special case as well. It implicitly enables all
+ // warnings, including ones not explicitly in a warning group.
+ if (Opt == "everything") {
+ if (SetDiagnostic) {
+ if (isPositive) {
+ Diags.setEnableAllWarnings(true);
+ } else {
+ Diags.setEnableAllWarnings(false);
+ Diags.setSeverityForAll(Flavor, diag::Severity::Ignored);
+ }
+ }
+ continue;
+ }
+
+ // -Werror/-Wno-error is a special case, not controlled by the option
+ // table. It also has the "specifier" form of -Werror=foo and -Werror-foo.
+ if (Opt.startswith("error")) {
+ StringRef Specifier;
+ if (Opt.size() > 5) { // Specifier must be present.
+ if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) {
+ if (Report)
+ Diags.Report(diag::warn_unknown_warning_specifier)
+ << "-Werror" << ("-W" + OrigOpt.str());
+ continue;
+ }
+ Specifier = Opt.substr(6);
+ }
+
+ if (Specifier.empty()) {
+ if (SetDiagnostic)
+ Diags.setWarningsAsErrors(isPositive);
+ continue;
+ }
+
+ if (SetDiagnostic) {
+ // Set the warning as error flag for this specifier.
+ Diags.setDiagnosticGroupWarningAsError(Specifier, isPositive);
+ } else if (DiagIDs->getDiagnosticsInGroup(Flavor, Specifier, _Diags)) {
+ EmitUnknownDiagWarning(Diags, Flavor, "-Werror=", Specifier);
+ }
+ continue;
+ }
+
+ // -Wfatal-errors is yet another special case.
+ if (Opt.startswith("fatal-errors")) {
+ StringRef Specifier;
+ if (Opt.size() != 12) {
+ if ((Opt[12] != '=' && Opt[12] != '-') || Opt.size() == 13) {
+ if (Report)
+ Diags.Report(diag::warn_unknown_warning_specifier)
+ << "-Wfatal-errors" << ("-W" + OrigOpt.str());
+ continue;
+ }
+ Specifier = Opt.substr(13);
+ }
+
+ if (Specifier.empty()) {
+ if (SetDiagnostic)
+ Diags.setErrorsAsFatal(isPositive);
+ continue;
+ }
+
+ if (SetDiagnostic) {
+ // Set the error as fatal flag for this specifier.
+ Diags.setDiagnosticGroupErrorAsFatal(Specifier, isPositive);
+ } else if (DiagIDs->getDiagnosticsInGroup(Flavor, Specifier, _Diags)) {
+ EmitUnknownDiagWarning(Diags, Flavor, "-Wfatal-errors=", Specifier);
+ }
+ continue;
+ }
+
+ if (Report) {
+ if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags))
+ EmitUnknownDiagWarning(Diags, Flavor, isPositive ? "-W" : "-Wno-",
+ Opt);
+ } else {
+ Diags.setSeverityForGroup(Flavor, Opt, Mapping);
+ }
+ }
+
+ for (unsigned i = 0, e = Opts.Remarks.size(); i != e; ++i) {
+ StringRef Opt = Opts.Remarks[i];
+ const auto Flavor = diag::Flavor::Remark;
+
+ // Check to see if this warning starts with "no-", if so, this is a
+ // negative form of the option.
+ bool IsPositive = !Opt.startswith("no-");
+ if (!IsPositive) Opt = Opt.substr(3);
+
+ auto Severity = IsPositive ? diag::Severity::Remark
+ : diag::Severity::Ignored;
+
+ // -Reverything sets the state of all remarks. Note that all remarks are
+ // in remark groups, so we don't need a separate 'all remarks enabled'
+ // flag.
+ if (Opt == "everything") {
+ if (SetDiagnostic)
+ Diags.setSeverityForAll(Flavor, Severity);
+ continue;
+ }
+
+ if (Report) {
+ if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags))
+ EmitUnknownDiagWarning(Diags, Flavor, IsPositive ? "-R" : "-Rno-",
+ Opt);
+ } else {
+ Diags.setSeverityForGroup(Flavor, Opt,
+ IsPositive ? diag::Severity::Remark
+ : diag::Severity::Ignored);
+ }
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp b/contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp
new file mode 100644
index 000000000000..8cc36df79468
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp
@@ -0,0 +1,30 @@
+//===--- XRayInstr.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is part of XRay, a function call instrumentation system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/XRayInstr.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace clang {
+
+XRayInstrMask parseXRayInstrValue(StringRef Value) {
+ XRayInstrMask ParsedKind = llvm::StringSwitch<XRayInstrMask>(Value)
+ .Case("all", XRayInstrKind::All)
+ .Case("custom", XRayInstrKind::Custom)
+ .Case("function", XRayInstrKind::Function)
+ .Case("typed", XRayInstrKind::Typed)
+ .Case("none", XRayInstrKind::None)
+ .Default(XRayInstrKind::None);
+ return ParsedKind;
+}
+
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp b/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
new file mode 100644
index 000000000000..ad331899d2e2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
@@ -0,0 +1,69 @@
+//===--- XRayFunctionFilter.cpp - XRay automatic-attribution --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided filters for always/never XRay instrumenting certain functions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/XRayLists.h"
+
+using namespace clang;
+
+XRayFunctionFilter::XRayFunctionFilter(
+ ArrayRef<std::string> AlwaysInstrumentPaths,
+ ArrayRef<std::string> NeverInstrumentPaths,
+ ArrayRef<std::string> AttrListPaths, SourceManager &SM)
+ : AlwaysInstrument(
+ llvm::SpecialCaseList::createOrDie(AlwaysInstrumentPaths)),
+ NeverInstrument(llvm::SpecialCaseList::createOrDie(NeverInstrumentPaths)),
+ AttrList(llvm::SpecialCaseList::createOrDie(AttrListPaths)), SM(SM) {}
+
+XRayFunctionFilter::ImbueAttribute
+XRayFunctionFilter::shouldImbueFunction(StringRef FunctionName) const {
+ // First apply the always instrument list, than if it isn't an "always" see
+ // whether it's treated as a "never" instrument function.
+ // TODO: Remove these as they're deprecated; use the AttrList exclusively.
+ if (AlwaysInstrument->inSection("xray_always_instrument", "fun", FunctionName,
+ "arg1") ||
+ AttrList->inSection("always", "fun", FunctionName, "arg1"))
+ return ImbueAttribute::ALWAYS_ARG1;
+ if (AlwaysInstrument->inSection("xray_always_instrument", "fun",
+ FunctionName) ||
+ AttrList->inSection("always", "fun", FunctionName))
+ return ImbueAttribute::ALWAYS;
+
+ if (NeverInstrument->inSection("xray_never_instrument", "fun",
+ FunctionName) ||
+ AttrList->inSection("never", "fun", FunctionName))
+ return ImbueAttribute::NEVER;
+
+ return ImbueAttribute::NONE;
+}
+
+XRayFunctionFilter::ImbueAttribute
+XRayFunctionFilter::shouldImbueFunctionsInFile(StringRef Filename,
+ StringRef Category) const {
+ if (AlwaysInstrument->inSection("xray_always_instrument", "src", Filename,
+ Category) ||
+ AttrList->inSection("always", "src", Filename, Category))
+ return ImbueAttribute::ALWAYS;
+ if (NeverInstrument->inSection("xray_never_instrument", "src", Filename,
+ Category) ||
+ AttrList->inSection("never", "src", Filename, Category))
+ return ImbueAttribute::NEVER;
+ return ImbueAttribute::NONE;
+}
+
+XRayFunctionFilter::ImbueAttribute
+XRayFunctionFilter::shouldImbueLocation(SourceLocation Loc,
+ StringRef Category) const {
+ if (!Loc.isValid())
+ return ImbueAttribute::NONE;
+ return this->shouldImbueFunctionsInFile(SM.getFilename(SM.getFileLoc(Loc)),
+ Category);
+}