diff options
| author | 2017-01-14 19:55:43 +0000 | |
|---|---|---|
| committer | 2017-01-14 19:55:43 +0000 | |
| commit | bd3306aecb3a15e8967143b8cdbbccf2b1b19b74 (patch) | |
| tree | 309a8132b44564b9e634c0da6815187ce8eab27c /gnu/llvm/tools/clang/utils | |
| parent | killp -a should not kill the window if only one pane. (diff) | |
| download | wireguard-openbsd-bd3306aecb3a15e8967143b8cdbbccf2b1b19b74.tar.xz wireguard-openbsd-bd3306aecb3a15e8967143b8cdbbccf2b1b19b74.zip | |
Import LLVM 3.9.1 including clang and lld.
Diffstat (limited to 'gnu/llvm/tools/clang/utils')
15 files changed, 1722 insertions, 200 deletions
diff --git a/gnu/llvm/tools/clang/utils/ClangVisualizers/CMakeLists.txt b/gnu/llvm/tools/clang/utils/ClangVisualizers/CMakeLists.txt new file mode 100644 index 00000000000..16d118a421b --- /dev/null +++ b/gnu/llvm/tools/clang/utils/ClangVisualizers/CMakeLists.txt @@ -0,0 +1,7 @@ +# Do this by hand instead of using add_llvm_utilities(), which +# tries to create a corresponding executable, which we don't want. +if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) + set(CLANG_VISUALIZERS clang.natvis) + add_custom_target(ClangVisualizers SOURCES ${CLANG_VISUALIZERS}) + set_target_properties(ClangVisualizers PROPERTIES FOLDER "Utils") +endif() diff --git a/gnu/llvm/tools/clang/utils/ClangVisualizers/clang.natvis b/gnu/llvm/tools/clang/utils/ClangVisualizers/clang.natvis new file mode 100644 index 00000000000..6e3ca96ffde --- /dev/null +++ b/gnu/llvm/tools/clang/utils/ClangVisualizers/clang.natvis @@ -0,0 +1,586 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!--
+Visual Studio Native Debugging Visualizers for LLVM
+
+For Visual Studio 2013 only, put this file into
+"%USERPROFILE%\Documents\Visual Studio 2013\Visualizers" or create a symbolic link so it updates automatically.
+
+For later versions of Visual Studio, no setup is required-->
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+ <Type Name="clang::Type">
+ <!-- To visualize clang::Types, we need to look at TypeBits.TC to determine the actual
+ type subclass and manually dispatch accordingly (Visual Studio can't identify the real type
+ because clang::Type has no virtual members hence no RTTI).
+
+ Views:
+ "cmn": Visualization that is common to all clang::Type subclasses
+ "poly": Visualization that is specific to the actual clang::Type subclass. The subtype-specific
+ <DisplayString> is typically as C++-like as possible (like in dump()) with <Expand>
+ containing all the gory details.
+ "cpp": Only occasionally used when we need to distinguish between an ordinary view and a C++-like view.
+ -->
+ <DisplayString IncludeView="cmn" Condition="TypeBits.TC==clang::LocInfoType::LocInfo">LocInfoType</DisplayString>
+ <DisplayString IncludeView="cmn">{(clang::Type::TypeClass)TypeBits.TC, en}Type</DisplayString>
+ <!-- Dispatch to visualizers for the actual Type subclass -->
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::Builtin" IncludeView="poly">{*(clang::BuiltinType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::Pointer" IncludeView="poly">{*(clang::PointerType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::LValueReference" IncludeView="poly">{*(clang::LValueReferenceType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::RValueReference" IncludeView="poly">{*(clang::RValueReferenceType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::Attributed" IncludeView="poly">{*(clang::AttributedType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::TemplateTypeParm" IncludeView="poly">{*(clang::TemplateTypeParmType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::SubstTemplateTypeParm" IncludeView="poly">{*(clang::SubstTemplateTypeParmType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::Record" IncludeView="poly">{*(clang::RecordType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::Record" IncludeView="cpp">{*(clang::RecordType *)this,view(cpp)}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::FunctionProto" IncludeView="poly">{*(clang::FunctionProtoType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::TemplateSpecialization" IncludeView="poly">{*(clang::TemplateSpecializationType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::InjectedClassName" IncludeView="poly">{*(clang::InjectedClassNameType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::PackExpansion" IncludeView="poly">{*(clang::PackExpansionType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::LocInfoType::LocInfo" IncludeView="poly">{*(clang::LocInfoType *)this}</DisplayString>
+ <DisplayString IncludeView="cpp">{*this,view(poly)}</DisplayString>
+ <DisplayString IncludeView="poly">{*this,view(cmn)}</DisplayString> <!-- Not yet implemented Type subclass -->
+ <DisplayString>{*this,view(cmn)} {{{*this,view(poly)}}}</DisplayString>
+ <Expand>
+ <Item Name="TypeClass" IncludeView="cmn">(clang::Type::TypeClass)TypeBits.TC</Item>
+ <Item Name="Flags" IncludeView="cmn">TypeBits</Item>
+ <Item Name="Canonical" IncludeView="cmn">CanonicalType</Item>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::Builtin">*(clang::BuiltinType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::Pointer">*(clang::PointerType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::LValueReference">*(clang::LValueReferenceType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::RValueReference">*(clang::RValueReferenceType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::Attributed">*(clang::AttributedType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::TemplateTypeParm">(clang::TemplateTypeParmType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::SubstTemplateTypeParm">(clang::SubstTemplateTypeParmType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::Record">(clang::RecordType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::FunctionProto">(clang::FunctionProtoType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::TemplateSpecialization">(clang::TemplateSpecializationType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::InjectedClassName">(clang::InjectedClassNameType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::PackExpansion">(clang::PackExpansionType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::LocInfoType::LocInfo">(clang::LocInfoType *)this</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::PointerType">
+ <DisplayString>{PointeeType, view(poly)} *</DisplayString>
+ <Expand>
+ <Item Name="PointeeType">PointeeType</Item>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ </Expand>
+ </Type>
+ <!-- We visualize all inner types for clang reference types. So a rvalue reference to an lvalue reference
+ to an int would visual as int & && This is a little different than GetPointeeType(),
+ but more clearly displays the data structure and seems natural -->
+ <Type Name="clang::LValueReferenceType">
+ <DisplayString>{((clang::ReferenceType *)this)->PointeeType,view(cpp)} &</DisplayString>
+ <Expand>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ <Item Name="PointeeType">PointeeType</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::RValueReferenceType">
+ <DisplayString>{((clang::ReferenceType *)this)->PointeeType,view(cpp)} &&</DisplayString>
+ <Expand>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ <Item Name="PointeeType">PointeeType</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::AttributedType">
+ <DisplayString>{ModifiedType} Attribute={(clang::AttributedType::Kind)AttributedTypeBits.AttrKind}</DisplayString>
+ </Type>
+
+ <!-- Unfortunately, Visual Studio has trouble seeing the PointerBitMask member PointerIntUnion, so I hardwire it to 2 bits-->
+ <Type Name="clang::DeclContext">
+ <DisplayString>{(clang::Decl::Kind)DeclKind,en}Decl</DisplayString>
+ <Expand>
+ <Item Name="DeclKind">(clang::Decl::Kind)DeclKind,en</Item>
+ <Synthetic Name="Members">
+ <DisplayString></DisplayString>
+ <Expand>
+ <LinkedListItems>
+ <HeadPointer>FirstDecl</HeadPointer>
+ <NextPointer>(clang::Decl *)(NextInContextAndBits.Value & ~3)</NextPointer>
+ <ValueNode>*this</ValueNode>
+ </LinkedListItems>
+ </Expand>
+ </Synthetic>
+ </Expand>
+ </Type>
+ <Type Name="clang::FieldDecl">
+ <DisplayString>Field {{{*(clang::DeclaratorDecl *)this,view(cpp)nd}}}</DisplayString>
+ </Type>
+ <Type Name="clang::CXXMethodDecl">
+ <DisplayString IncludeView="cpp">{*(clang::FunctionDecl *)this,nd}</DisplayString>
+ <DisplayString>Method {{{*this,view(cpp)}}}</DisplayString>
+ </Type>
+ <Type Name="clang::CXXConstructorDecl">
+ <DisplayString>Constructor {{{Name,view(cpp)}({*(clang::FunctionDecl *)this,view(parm0)nd})}}</DisplayString>
+ </Type>
+ <Type Name="clang::CXXDestructorDecl">
+ <DisplayString>Destructor {{~{Name,view(cpp)}()}}</DisplayString>
+ </Type>
+ <Type Name="clang::TemplateTypeParmDecl">
+ <DisplayString IncludeView="TorC" Condition="Typename">typename</DisplayString>
+ <DisplayString IncludeView="TorC" Condition="!Typename">class</DisplayString>
+ <DisplayString IncludeView="MaybeEllipses" Condition="((TemplateTypeParmType *)TypeForDecl)->CanTTPTInfo.ParameterPack">...</DisplayString>
+ <DisplayString IncludeView="MaybeEllipses" Condition="!((TemplateTypeParmType *)TypeForDecl)->CanTTPTInfo.ParameterPack"></DisplayString>
+ <DisplayString>{*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)}</DisplayString>
+ </Type>
+ <Type Name="clang::TemplateDecl">
+ <DisplayString>template{*TemplateParams} {*TemplatedDecl};</DisplayString>
+ </Type>
+ <Type Name="clang::NamedDecl" >
+ <DisplayString IncludeView="cpp">{Name,view(cpp)}</DisplayString>
+ <DisplayString>{Name}</DisplayString>
+ </Type>
+ <Type Name="clang::TagDecl">
+ <DisplayString IncludeView="implicit" Condition="Implicit">implicit{" ",sb}</DisplayString>
+ <DisplayString IncludeView="implicit"></DisplayString>
+ <DisplayString IncludeView="modifiers">{*this,view(implicit)}</DisplayString>
+ <DisplayString IncludeView="cpp">{*this,view(modifiers)}{Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Struct">{*this,view(modifiers)}struct {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Interface">{*this,view(modifiers)}interface {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Union">{*this,view(modifiers)}union {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Class">{*this,view(modifiers)}class {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Enum">{*this,view(modifiers)}enum {Name,view(cpp)}</DisplayString>
+ <Expand>
+ <ExpandedItem>(clang::DeclContext *)this</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::TagType">
+ <DisplayString IncludeView="cpp">{*decl,view(cpp)}</DisplayString>
+ <DisplayString>{*decl}</DisplayString>
+ <Expand>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ <Item Name="decl">decl</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::RecordType">
+ <DisplayString IncludeView="cpp">{*(clang::TagType *)this,view(cpp)}</DisplayString>
+ <DisplayString>{*(clang::TagType *)this}</DisplayString>
+ <Expand>
+ <Item Name="TagType">*(clang::TagType *)this</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::SubstTemplateTypeParmType">
+ <DisplayString>{*Replaced,view(cpp)} <= {CanonicalType,view(cpp)}</DisplayString>
+ <Expand>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ <Item Name="Replaced">*Replaced</Item>
+ </Expand>
+ </Type>
+ <!-- We only show the first 5 parameter types in the display string (can't figure out how to loop in DisplayString)
+ but the expansion has all parameters -->
+ <Type Name="clang::FunctionProtoType">
+ <DisplayString IncludeView="retType">{ResultType,view(cpp)}</DisplayString>
+ <DisplayString IncludeView="parm0" Condition="NumParams==0"></DisplayString>
+ <DisplayString IncludeView="parm0">{*(clang::QualType *)(this+1),view(cpp)}{*this,view(parm1)}</DisplayString>
+ <DisplayString IncludeView="parm1" Condition="NumParams==1"></DisplayString>
+ <DisplayString IncludeView="parm1">, {*((clang::QualType *)(this+1)+1),view(cpp)}{*this,view(parm2)}</DisplayString>
+ <DisplayString IncludeView="parm2" Condition="NumParams==2"></DisplayString>
+ <DisplayString IncludeView="parm2">, {*((clang::QualType *)(this+1)+2),view(cpp)}{*this,view(parm3)}</DisplayString>
+ <DisplayString IncludeView="parm3" Condition="NumParams==3"></DisplayString>
+ <DisplayString IncludeView="parm3">, {*((clang::QualType *)(this+1)+3),view(cpp)}{*this,view(parm4)}</DisplayString>
+ <DisplayString IncludeView="parm4" Condition="NumParams==4"></DisplayString>
+ <DisplayString IncludeView="parm4">, {*((clang::QualType *)(this+1)+4),view(cpp)}{*this,view(parm5)}</DisplayString>
+ <DisplayString IncludeView="parm5" Condition="NumParams==5"></DisplayString>
+ <DisplayString IncludeView="parm5">, /* expand for more params */</DisplayString>
+ <DisplayString>{*this,view(retType)}({*this,view(parm0)})</DisplayString>
+ <Expand>
+ <Item Name="ReturnType">ResultType</Item>
+ <Synthetic Name="Parameter Types">
+ <DisplayString>{*this,view(parm0)}</DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>NumParams</Size>
+ <ValuePointer>(clang::QualType *)(this+1)</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Synthetic>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::TemplateTypeParmType">
+ <DisplayString IncludeView="cpp">{*TTPDecl,view(cpp)}</DisplayString>
+ <DisplayString>{*TTPDecl}</DisplayString>
+ </Type>
+ <Type Name="clang::InjectedClassNameType">
+ <DisplayString>{*Decl,view(cpp)}</DisplayString>
+ <Expand>
+ <Item Name="Decl">Decl</Item>
+ <Item Name="InjectedType">InjectedType</Item>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::PackExpansionType">
+ <DisplayString>{Pattern}</DisplayString>
+ <Expand>
+ <Item Name="Pattern">Pattern</Item>
+ <Item Name="NumExpansions">NumExpansions</Item>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::QualType">
+ <!-- When VS2013 support is deprecated, change 4 to clang::TypeAlignmentInBits (not properly recognized by VS2013) -->
+ <DisplayString IncludeView="poly">{*((clang::ExtQualsTypeCommonBase *)(((uintptr_t)Value.Value) & ~(uintptr_t)((1 << 4) - 1)))->BaseType,view(poly)}{*this,view(fastQuals)}</DisplayString>
+ <DisplayString IncludeView="cpp">{*((clang::ExtQualsTypeCommonBase *)(((uintptr_t)Value.Value) & ~(uintptr_t)((1 << 4) - 1)))->BaseType,view(cpp)}{*this,view(fastQuals)}</DisplayString>
+ <!-- For the Fast Qualifiers, it is simpler (and probably more efficient) just to list all 8 cases than create
+ views for each qualifier. TODO: Non-fast qualifiers -->
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==0"></DisplayString>
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==1">{" ",sb}const</DisplayString>
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==2">{" ",sb}restrict</DisplayString>
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==3">{" ",sb}const restrict</DisplayString>
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==4">{" ",sb}volatile</DisplayString>
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==5">{" ",sb}const volatile</DisplayString>
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==6">{" ",sb}volatile restrict</DisplayString>
+ <DisplayString IncludeView="fastQuals" Condition="(Value.Value & 15)==7">{" ",sb}const volatile restrict</DisplayString>
+ <DisplayString IncludeView="fastQuals">Cannot visualize non-fast qualifiers</DisplayString>
+ <DisplayString>{*((clang::ExtQualsTypeCommonBase *)(((uintptr_t)Value.Value) & ~(uintptr_t)((1 << 4) - 1)))->BaseType}{*this,view(fastQuals)}</DisplayString>
+ <Expand>
+ <Item Name="Fast Quals">*this,view(fastQuals)</Item>
+ <Item Name="BaseType">*((clang::ExtQualsTypeCommonBase *)(((uintptr_t)Value.Value) & ~(uintptr_t)((1 << 4) - 1)))->BaseType</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::LocInfoType">
+ <DisplayString>{*DeclInfo}</DisplayString>
+ <Expand>
+ <Item Name="DeclInfo">DeclInfo</Item>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::TypeSourceInfo">
+ <DisplayString>{Ty}</DisplayString>
+ </Type>
+ <Type Name="clang::TemplateArgumentLoc">
+ <DisplayString>{Argument}</DisplayString>
+ <Expand>
+ <ExpandedItem>Argument</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::TemplateArgument">
+ <DisplayString IncludeView="cpp" Condition="Integer.Kind == clang::TemplateArgument::ArgKind::Type">{*(clang::QualType *)&TypeOrValue.V,view(cpp)}</DisplayString>
+ <DisplayString Condition="Integer.Kind == clang::TemplateArgument::ArgKind::Type">{(clang::TemplateArgument::ArgKind)TypeOrValue.Kind,en} template argument: {*(clang::QualType *)&TypeOrValue.V}</DisplayString>
+ <DisplayString IncludeView="arg0" Condition="Args.NumArgs==0"></DisplayString>
+ <DisplayString IncludeView="arg0">{Args.Args[0]}{*this,view(arg1)}</DisplayString>
+ <DisplayString IncludeView="arg1" Condition="Args.NumArgs==1"></DisplayString>
+ <DisplayString IncludeView="arg1">, {Args.Args[1]}{*this,view(arg2)}</DisplayString>
+ <DisplayString IncludeView="arg2" Condition="Args.NumArgs==2"></DisplayString>
+ <DisplayString IncludeView="arg2">, {Args.Args[2]}, ...</DisplayString>
+ <DisplayString IncludeView="arg0cpp" Condition="Args.NumArgs==0"></DisplayString>
+ <DisplayString IncludeView="arg0cpp">{Args.Args[0],view(cpp)}{*this,view(arg1cpp)}</DisplayString>
+ <DisplayString IncludeView="arg1cpp" Condition="Args.NumArgs==1"></DisplayString>
+ <DisplayString IncludeView="arg1cpp">, {Args.Args[1],view(cpp)}{*this,view(arg2cpp)}</DisplayString>
+ <DisplayString IncludeView="arg2cpp" Condition="Args.NumArgs==2"></DisplayString>
+ <DisplayString IncludeView="arg2cpp">, {Args.Args[2],view(cpp)}, ...</DisplayString>
+ <DisplayString IncludeView="cpp" Condition="Integer.Kind == clang::TemplateArgument::ArgKind::Pack">{*this,view(arg0cpp)}</DisplayString>
+ <DisplayString Condition="Integer.Kind == clang::TemplateArgument::ArgKind::Pack">{*this,view(arg0)}</DisplayString>
+ <DisplayString>{(clang::TemplateArgument::ArgKind)TypeOrValue.Kind,en}</DisplayString>
+ <Expand>
+ <Item Name="QualType" Condition="Integer.Kind == clang::TemplateArgument::ArgKind::Type">*(clang::QualType *)&TypeOrValue.V</Item>
+ <ArrayItems Condition="Integer.Kind == clang::TemplateArgument::ArgKind::Pack">
+ <Size>Args.NumArgs</Size>
+ <ValuePointer>Args.Args</ValuePointer>
+ </ArrayItems>
+ <!-- TODO: Other kinds-->
+ </Expand>
+ </Type>
+ <Type Name="clang::TemplateArgumentList">
+ <DisplayString IncludeView="arg0" Condition="NumArguments==0"></DisplayString>
+ <DisplayString IncludeView="arg0">{Arguments[0],view(cpp)}{*this,view(arg1)}</DisplayString>
+ <DisplayString IncludeView="arg1" Condition="NumArguments==1"></DisplayString>
+ <DisplayString IncludeView="arg1">, {Arguments[1],view(cpp)}{*this,view(arg2)}</DisplayString>
+ <DisplayString IncludeView="arg2" Condition="NumArguments==2"></DisplayString>
+ <DisplayString IncludeView="arg2">, {Arguments[1],view(cpp)}, ...</DisplayString>
+ <DisplayString><{*this,view(arg0)}></DisplayString>
+ <Expand>
+ <Item Name="NumArguments">NumArguments</Item>
+ <ArrayItems>
+ <Size>NumArguments</Size>
+ <ValuePointer>Arguments</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+ <Type Name="llvm::ArrayRef<clang::TemplateArgument>">
+ <DisplayString IncludeView="arg0" Condition="Length==0"></DisplayString>
+ <DisplayString IncludeView="arg0">{Data[0],view(cpp)}{*this,view(arg1)}</DisplayString>
+ <DisplayString IncludeView="arg1" Condition="Length==1"></DisplayString>
+ <DisplayString IncludeView="arg1">, {Data[1],view(cpp)}{*this,view(arg2)}</DisplayString>
+ <DisplayString IncludeView="arg2" Condition="Length==2"></DisplayString>
+ <DisplayString IncludeView="arg2">, {Data[2],view(cpp)}, ...</DisplayString>
+ <DisplayString><{*this,view(arg0)}></DisplayString>
+ </Type>
+ <Type Name="clang::MultiLevelTemplateArgumentList">
+ <DisplayString IncludeView="level0" Condition="(llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.EndX - (llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX==0"></DisplayString>
+ <DisplayString IncludeView="level0">{((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[0],view(cpp)}{*this,view(level1)}</DisplayString>
+ <DisplayString IncludeView="level1" Condition="(llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.EndX - (llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX==1"></DisplayString>
+ <DisplayString IncludeView="level1">::{((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[1],view(cpp)}{*this,view(level2)}</DisplayString>
+ <DisplayString IncludeView="level2" Condition="(llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.EndX - (llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX==2"></DisplayString>
+ <DisplayString IncludeView="level2">::{((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[2],view(cpp)}, ...</DisplayString>
+ <DisplayString>{*this,view(level0)}</DisplayString>
+ <Expand>
+ <Item Name="TemplateList">TemplateArgumentLists</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::ParsedTemplateArgument">
+ <DisplayString Condition="Kind==clang::ParsedTemplateArgument::Type">Type template argument: {*(clang::QualType *)Arg}</DisplayString>
+ <DisplayString Condition="Kind==clang::ParsedTemplateArgument::NonType">Non-type template argument: {*(clang::Expr *)Arg}</DisplayString>
+ <DisplayString Condition="Kind==clang::ParsedTemplateArgument::Template">Template template argument: {*(clang::TemplateName *)Arg</DisplayString>
+ <Expand>
+ <Item Name="Kind">Kind,en</Item>
+ <Item Name="Arg" Condition="Kind==clang::ParsedTemplateArgument::Type">(clang::QualType *)Arg</Item>
+ <Item Name="Arg" Condition="Kind==clang::ParsedTemplateArgument::NonType">(clang::Expr *)Arg</Item>
+ <Item Name="Arg" Condition="Kind==clang::ParsedTemplateArgument::Template">(clang::TemplateName *)Arg</Item>
+ </Expand>
+ </Type>
+ <!-- Builtin types that have C++ keywords are manually displayed as that keyword. Otherwise, just use the enum name -->
+ <Type Name="clang::BuiltinType">
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Void">void</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Bool">bool</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Char_U">char</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::UChar">unsigned char</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::WChar_U">wchar_t</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Char16">char16_t</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Char32">char32_t</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::UShort">unsigned short</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::UInt">unsigned int</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::ULong">unsigned long</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::ULongLong">unsigned long long</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::UInt128">__uint128_t</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Char_S">char</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::SChar">signed char</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::WChar_S">wchar_t</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Short">short</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Int">int</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Long">long</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::LongLong">long long</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Int128">__int128_t</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Half">__fp16</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Float">float</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::Double">double</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::LongDouble">long double</DisplayString>
+ <DisplayString Condition="BuiltinTypeBits.Kind==clang::BuiltinType::NullPtr">nullptr_t</DisplayString>
+ <DisplayString>{(clang::BuiltinType::Kind)BuiltinTypeBits.Kind, en}</DisplayString>
+ <Expand>
+ <Item Name="Kind">(clang::BuiltinType::Kind)BuiltinTypeBits.Kind</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="clang::TemplateSpecializationType">
+ <DisplayString IncludeView="arg0" Condition="NumArgs==0"></DisplayString>
+ <DisplayString IncludeView="arg0">{((clang::TemplateArgument *)(this+1))[0],view(cpp)}{*this,view(arg1)}</DisplayString>
+ <DisplayString IncludeView="arg1" Condition="NumArgs==1"></DisplayString>
+ <DisplayString IncludeView="arg1">, {((clang::TemplateArgument *)(this+1))[1],view(cpp)}{*this,view(arg2)}</DisplayString>
+ <DisplayString IncludeView="arg2" Condition="NumArgs==2"></DisplayString>
+ <DisplayString IncludeView="arg2">, {((clang::TemplateArgument *)(this+1))[2],view(cpp)}{*this,view(arg3)}</DisplayString>
+ <DisplayString Condition="(Template.Storage.Val.Val.Value & 3) == 0">
+ {*((clang::TemplateDecl *)((Template.Storage.Val.Val.Value >> 2) << 2))->TemplatedDecl,view(cpp)}<{*this,view(arg0)}>
+ </DisplayString>
+ <Expand>
+ <Item Name="Template">Template.Storage</Item>
+ <ArrayItems>
+ <Size>NumArgs</Size>
+ <ValuePointer>(clang::TemplateArgument *)(this+1)</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+ <Type Name="clang::IdentifierInfo">
+ <DisplayString Condition="Entry != 0">{((llvm::StringMapEntry<clang::IdentifierInfo *>*)Entry)+1,sb}</DisplayString>
+ <Expand>
+ <Item Condition="Entry != 0" Name="[Identifier]">((llvm::StringMapEntry<clang::IdentifierInfo *>*)Entry)+1,s</Item>
+ <Item Name="Token Kind">(clang::tok::TokenKind)TokenID</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::DeclarationName">
+ <DisplayString Condition="Ptr == 0" IncludeView="cpp"></DisplayString>
+ <DisplayString Condition="Ptr == 0">Empty</DisplayString>
+ <DisplayString Condition="(Ptr & PtrMask) == StoredIdentifier" IncludeView="cpp">{*(clang::IdentifierInfo *)(Ptr & ~PtrMask)}</DisplayString>
+ <DisplayString Condition="(Ptr & PtrMask) == StoredIdentifier">{{Identifier ({*(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}}</DisplayString>
+ <DisplayString Condition="(Ptr & PtrMask) == StoredObjCZeroArgSelector">{{ObjC Zero Arg Selector (*{(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}}</DisplayString>
+ <DisplayString Condition="(Ptr & PtrMask) == StoredObjCOneArgSelector">{{ObjC One Arg Selector (*{(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}}</DisplayString>
+ <DisplayString Condition="(Ptr & PtrMask) == StoredDeclarationNameExtra"
+ IncludeView="cpp">{*(clang::DeclarationNameExtra *)(Ptr & ~PtrMask),view(cpp)}</DisplayString>
+ <DisplayString Condition="(Ptr & PtrMask) == StoredDeclarationNameExtra">{{Extra ({*(clang::DeclarationNameExtra *)(Ptr & ~PtrMask)})}}</DisplayString>
+ <Expand>
+ <Item Condition="(Ptr & PtrMask) == StoredIdentifier" Name="[Identifier]">*(clang::IdentifierInfo *)(Ptr & ~PtrMask)</Item>
+ <Item Condition="(Ptr & PtrMask) == StoredObjCZeroArgSelector" Name="[ObjC Zero Arg Selector]">*(clang::IdentifierInfo *)(Ptr & ~PtrMask)</Item>
+ <Item Condition="(Ptr & PtrMask) == StoredObjCOneArgSelector" Name="[ObjC One Arg Selector]">*(clang::IdentifierInfo *)(Ptr & ~PtrMask)</Item>
+ <Item Condition="(Ptr & PtrMask) == StoredDeclarationNameExtra" Name="[Extra]">(clang::DeclarationNameExtra *)(Ptr & ~PtrMask)</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::DeclarationNameExtra">
+ <DisplayString IncludeView="cpp"
+ Condition="ExtraKindOrNumArgs >= clang::DeclarationNameExtra::CXXConstructor
+ && ExtraKindOrNumArgs <= clang::DeclarationNameExtra::CXXConversionFunction"
+ >{((clang::CXXSpecialName *)this)->Type,view(cpp)}</DisplayString>
+ <DisplayString>{(clang::DeclarationNameExtra::ExtraKind)ExtraKindOrNumArgs,en}{" ",sb}{*this,view(cpp)}</DisplayString>
+ </Type>
+ <Type Name="clang::Token">
+ <DisplayString Condition="Kind != clang::tok::identifier">{(clang::tok::TokenKind)Kind,en}</DisplayString>
+ <DisplayString Condition="Kind == clang::tok::identifier">{{Identifier ({*(clang::IdentifierInfo *)(PtrData)})}}</DisplayString>
+ </Type>
+ <Type Name="clang::DeclSpec">
+ <DisplayString>[{(clang::DeclSpec::SCS)StorageClassSpec}], [{(clang::TypeSpecifierType)TypeSpecType}]</DisplayString>
+ </Type>
+ <Type Name="clang::PragmaHandler">
+ <DisplayString>{Name,s}</DisplayString>
+ </Type>
+ <Type Name="clang::FileEntry">
+ <DisplayString>{Name,s}</DisplayString>
+ </Type>
+ <Type Name="clang::DirectoryEntry">
+ <DisplayString>{Name,s}</DisplayString>
+ </Type>
+ <Type Name="clang::VarDecl::VarDeclBitfields">
+ <Expand>
+ <Item Name="StorageClass">(clang::StorageClass)SClass</Item>
+ <Item Name="ThreadStorageClass">(clang::ThreadStorageClassSpecifier)TSCSpec</Item>
+ <Item Name="InitStyle">(clang::VarDecl::InitializationStyle)InitStyle</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::DeclaratorDecl">
+ <DisplayString>{DeclType,view(cpp)} {Name,view(cpp)}</DisplayString>
+ <Expand>
+ <Item Name="Name">Name</Item>
+ <Item Name="DeclType">DeclType</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::VarDecl">
+ <DisplayString>{*(DeclaratorDecl*)this,nd}</DisplayString>
+ <Expand>
+ <ExpandedItem>*(DeclaratorDecl*)this,nd</ExpandedItem>
+ <Item Name="VarDeclBits">VarDeclBits</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::ParmVarDecl">
+ <DisplayString>{*(VarDecl*)this,nd}</DisplayString>
+ <Expand>
+ <Item Name="ParmVarDeclBits">ParmVarDeclBits</Item>
+ <ExpandedItem>*(VarDecl*)this,nd</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::FunctionDecl">
+ <DisplayString IncludeView="retType">{*(clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType,view(retType)}</DisplayString>
+ <DisplayString IncludeView="parm0" Condition="0 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->NumParams"></DisplayString>
+ <DisplayString IncludeView="parm0">{*ParamInfo[0]}{*this,view(parm1)nd}</DisplayString>
+ <DisplayString IncludeView="parm1" Condition="1 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->NumParams"></DisplayString>
+ <DisplayString IncludeView="parm1">, {*ParamInfo[1]}{*this,view(parm2)nd}</DisplayString>
+ <DisplayString IncludeView="parm2" Condition="2 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->NumParams"></DisplayString>
+ <DisplayString IncludeView="parm2">, {*ParamInfo[2]}{*this,view(parm3)nd}</DisplayString>
+ <DisplayString IncludeView="parm3" Condition="3 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->NumParams"></DisplayString>
+ <DisplayString IncludeView="parm3">, {*ParamInfo[3]}{*this,view(parm4)nd}</DisplayString>
+ <DisplayString IncludeView="parm4" Condition="4 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->NumParams"></DisplayString>
+ <DisplayString IncludeView="parm4">, {*ParamInfo[4]}{*this,view(parm5)nd}</DisplayString>
+ <DisplayString IncludeView="parm5" Condition="5 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->NumParams"></DisplayString>
+ <DisplayString IncludeView="parm5">, /* expand for more params */</DisplayString>
+ <DisplayString>{*this,view(retType)nd} {Name,view(cpp)nd}({*this,view(parm0)nd})</DisplayString>
+ <Expand>
+ <Item Name="ReturnType">*this,view(retType)nd</Item>
+ <Synthetic Name="Parameter Types">
+ <DisplayString>{*this,view(parm0)nd}</DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->NumParams</Size>
+ <ValuePointer>ParamInfo</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Synthetic>
+ <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::OpaquePtr<clang::QualType>">
+ <DisplayString>{*(clang::QualType *)this}</DisplayString>
+ <Expand>
+ <Item Name="Ptr">*(clang::QualType *)this</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::UnionOpaquePtr<clang::QualType>">
+ <DisplayString>{*(clang::QualType *)this}</DisplayString>
+ <Expand>
+ <Item Name="Ptr">*(clang::QualType *)this</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::OpaquePtr<*>">
+ <DisplayString>{($T1 *)Ptr}</DisplayString>
+ <Expand>
+ <ExpandedItem>($T1 *)Ptr</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::UnionOpaquePtr<*>">
+ <DisplayString>{($T1 *)Ptr}</DisplayString>
+ <Expand>
+ <ExpandedItem>($T1 *)Ptr</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::TemplateParameterList">
+ <DisplayString IncludeView="parm0" Condition="NumParams==0"></DisplayString>
+ <DisplayString IncludeView="parm0">{*((NamedDecl **)(this+1))[0],view(cpp)}{*this,view(parm1)}</DisplayString>
+ <DisplayString IncludeView="parm1" Condition="NumParams==1"></DisplayString>
+ <DisplayString IncludeView="parm1">, {*((NamedDecl **)(this+1))[1],view(cpp)}{*this,view(parm2)}</DisplayString>
+ <DisplayString IncludeView="parm2" Condition="NumParams==2"></DisplayString>
+ <DisplayString IncludeView="parm2">, {*((NamedDecl **)(this+1))[2],view(cpp)}{*this,view(parm3)}</DisplayString>
+ <DisplayString IncludeView="parm3" Condition="NumParams==3"></DisplayString>
+ <DisplayString IncludeView="parm3">, {*((NamedDecl **)(this+1))[3],view(cpp)}{*this,view(parm4)}</DisplayString>
+ <DisplayString IncludeView="parm4" Condition="NumParams==4"></DisplayString>
+ <DisplayString IncludeView="parm4">, {*((NamedDecl **)(this+1))[4],view(cpp)}{*this,view(parm5)}</DisplayString>
+ <DisplayString IncludeView="parm5" Condition="NumParams==5"></DisplayString>
+ <DisplayString IncludeView="parm5">, /* Expand for more params */</DisplayString>
+ <DisplayString><{*this,view(parm0)}></DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>NumParams</Size>
+ <ValuePointer>(NamedDecl **)(this+1)</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+ <Type Name="clang::Stmt">
+ <DisplayString>{(clang::Stmt::StmtClass)StmtBits.sClass,en}</DisplayString>
+ <Expand>
+ <Item Name="Class">(clang::Stmt::StmtClass)StmtBits.sClass,en</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::Expr">
+ <DisplayString>Expression of class {(clang::Stmt::StmtClass)StmtBits.sClass,en} and type {TR,view(cpp)}</DisplayString>
+ </Type>
+ <Type Name="clang::DeclAccessPair">
+ <DisplayString IncludeView="access" Condition="(Ptr&Mask) == clang::AS_public">public</DisplayString>
+ <DisplayString IncludeView="access" Condition="(Ptr&Mask) == clang::AS_protected">protected</DisplayString>
+ <DisplayString IncludeView="access" Condition="(Ptr&Mask) == clang::AS_private">private</DisplayString>
+ <DisplayString IncludeView="access" Condition="(Ptr&Mask) == clang::AS_none">b</DisplayString>
+ <DisplayString IncludeView="decl">{*(clang::NamedDecl *)(Ptr&~Mask)}</DisplayString>
+ <DisplayString>{*this,view(access)} {*this,view(decl)}</DisplayString>
+ </Type>
+ <Type Name="clang::UnresolvedSet<*>">
+ <DisplayString>{Decls}</DisplayString>
+ <Expand>
+ <ExpandedItem>Decls</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::LookupResult">
+ <DisplayString Condition="ResultKind == clang::LookupResult::Ambiguous">{Ambiguity,en}: {Decls}</DisplayString>
+ <DisplayString>{ResultKind,en}: {Decls}</DisplayString>
+ </Type>
+ <Type Name="clang::ActionResult<*>" IncludeView="packedValidity">
+ <DisplayString Condition="PtrWithInvalid&1">Invalid</DisplayString>
+ <DisplayString Condition="!(PtrWithInvalid&1)">Valid</DisplayString>
+ </Type>
+ <Type Name="clang::ActionResult<*>" IncludeView="unpackedValidity">
+ <DisplayString Condition="Invalid">Invalid</DisplayString>
+ <DisplayString Condition="!Invalid">Valid</DisplayString>
+ </Type>
+ <Type Name="clang::ActionResult<*>" IncludeView="packed">
+ <DisplayString>{*this,view(packedValidity)}: {($T1 *)(PtrWithInvalid&~1)}</DisplayString>
+ <Expand>
+ <Item Name="Invalid">(bool)(PtrWithInvalid&1)</Item>
+ <Item Name="Val">($T1 *)(PtrWithInvalid&~1)</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::ActionResult<*>" IncludeView="unpacked">
+ <DisplayString>{*this,view(unpackedValidity)}: {Val}</DisplayString>
+ </Type>
+ <Type Name="clang::ActionResult<*>">
+ <DisplayString Condition="$T2">{*this,view(packed)}</DisplayString>
+ <DisplayString Condition="!$T2">{*this,view(unpacked)}</DisplayString>
+ <Expand>
+ <ExpandedItem Condition="$T2">*this,view(packed)</ExpandedItem>
+ <ExpandedItem Condition="!$T2">*this,view(unpacked)</ExpandedItem>
+ </Expand>
+ </Type>
+</AutoVisualizer>
diff --git a/gnu/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/gnu/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp index f70bff2c3b7..50102af33a5 100644 --- a/gnu/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/gnu/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -11,24 +11,36 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringMatcher.h" #include "llvm/TableGen/TableGenBackend.h" #include <algorithm> +#include <cassert> #include <cctype> +#include <cstddef> +#include <cstdint> +#include <map> #include <memory> #include <set> #include <sstream> +#include <string> +#include <utility> +#include <vector> using namespace llvm; namespace { + class FlattenedSpelling { std::string V, N, NS; bool K; @@ -54,6 +66,7 @@ public: const std::string &nameSpace() const { return NS; } bool knownToGCC() const { return K; } }; + } // end anonymous namespace static std::vector<FlattenedSpelling> @@ -81,22 +94,26 @@ static std::string ReadPCHRecord(StringRef type) { .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)") .Case("Expr *", "ReadExpr(F)") .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") - .Case("std::string", "ReadString(Record, Idx)") + .Case("StringRef", "ReadString(Record, Idx)") .Default("Record[Idx++]"); } +// Get a type that is suitable for storing an object of the specified type. +static StringRef getStorageType(StringRef type) { + return StringSwitch<StringRef>(type) + .Case("StringRef", "std::string") + .Default(type); +} + // Assumes that the way to get the value is SA->getname() static std::string WritePCHRecord(StringRef type, StringRef name) { - return StringSwitch<std::string>(type) - .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + - ", Record);\n") - .Case("TypeSourceInfo *", - "AddTypeSourceInfo(" + std::string(name) + ", Record);\n") + return "Record." + StringSwitch<std::string>(type) + .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + ");\n") + .Case("TypeSourceInfo *", "AddTypeSourceInfo(" + std::string(name) + ");\n") .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") - .Case("IdentifierInfo *", - "AddIdentifierRef(" + std::string(name) + ", Record);\n") - .Case("std::string", "AddString(" + std::string(name) + ", Record);\n") - .Default("Record.push_back(" + std::string(name) + ");\n"); + .Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ");\n") + .Case("StringRef", "AddString(" + std::string(name) + ");\n") + .Default("push_back(" + std::string(name) + ");\n"); } // Normalize attribute name by removing leading and trailing @@ -162,6 +179,7 @@ static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records, } namespace { + class Argument { std::string lowerName, upperName; StringRef attrName; @@ -176,6 +194,11 @@ namespace { lowerName[0] = std::tolower(lowerName[0]); upperName[0] = std::toupper(upperName[0]); } + // Work around MinGW's macro definition of 'interface' to 'struct'. We + // have an attribute argument called 'Interface', so only the lower case + // name conflicts with the macro definition. + if (lowerName == "interface") + lowerName = "interface_"; } virtual ~Argument() = default; @@ -223,8 +246,7 @@ namespace { public: SimpleArgument(const Record &Arg, StringRef Attr, std::string T) - : Argument(Arg, Attr), type(T) - {} + : Argument(Arg, Attr), type(std::move(T)) {} std::string getType() const { return type; } @@ -233,35 +255,45 @@ namespace { OS << " return " << getLowerName() << ";\n"; OS << " }"; } + void writeCloneArgs(raw_ostream &OS) const override { OS << getLowerName(); } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { OS << "A->get" << getUpperName() << "()"; } + void writeCtorInitializers(raw_ostream &OS) const override { OS << getLowerName() << "(" << getUpperName() << ")"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const override { OS << getLowerName() << "()"; } + void writeCtorParameters(raw_ostream &OS) const override { OS << type << " " << getUpperName(); } + void writeDeclarations(raw_ostream &OS) const override { OS << type << " " << getLowerName() << ";"; } + void writePCHReadDecls(raw_ostream &OS) const override { std::string read = ReadPCHRecord(type); OS << " " << type << " " << getLowerName() << " = " << read << ";\n"; } + void writePCHReadArgs(raw_ostream &OS) const override { OS << getLowerName(); } + void writePCHWrite(raw_ostream &OS) const override { OS << " " << WritePCHRecord(type, "SA->get" + std::string(getUpperName()) + "()"); } + void writeValue(raw_ostream &OS) const override { if (type == "FunctionDecl *") { OS << "\" << get" << getUpperName() @@ -274,6 +306,7 @@ namespace { OS << "\" << get" << getUpperName() << "() << \""; } } + void writeDump(raw_ostream &OS) const override { if (type == "FunctionDecl *") { OS << " OS << \" \";\n"; @@ -309,7 +342,12 @@ namespace { SimpleArgument::writeAccessors(OS); OS << "\n\n static const " << getType() << " Default" << getUpperName() - << " = " << Default << ";"; + << " = "; + if (getType() == "bool") + OS << (Default != 0 ? "true" : "false"); + else + OS << Default; + OS << ";"; } }; @@ -337,45 +375,57 @@ namespace { << getLowerName() << "Length);\n"; OS << " }"; } + void writeCloneArgs(raw_ostream &OS) const override { OS << "get" << getUpperName() << "()"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { OS << "A->get" << getUpperName() << "()"; } + void writeCtorBody(raw_ostream &OS) const override { OS << " if (!" << getUpperName() << ".empty())\n"; OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() - << ".data(), " << getLowerName() << "Length);"; + << ".data(), " << getLowerName() << "Length);\n"; } + void writeCtorInitializers(raw_ostream &OS) const override { OS << getLowerName() << "Length(" << getUpperName() << ".size())," << getLowerName() << "(new (Ctx, 1) char[" << getLowerName() << "Length])"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const override { OS << getLowerName() << "Length(0)," << getLowerName() << "(nullptr)"; } + void writeCtorParameters(raw_ostream &OS) const override { OS << "llvm::StringRef " << getUpperName(); } + void writeDeclarations(raw_ostream &OS) const override { OS << "unsigned " << getLowerName() << "Length;\n"; OS << "char *" << getLowerName() << ";"; } + void writePCHReadDecls(raw_ostream &OS) const override { OS << " std::string " << getLowerName() << "= ReadString(Record, Idx);\n"; } + void writePCHReadArgs(raw_ostream &OS) const override { OS << getLowerName(); } + void writePCHWrite(raw_ostream &OS) const override { - OS << " AddString(SA->get" << getUpperName() << "(), Record);\n"; + OS << " Record.AddString(SA->get" << getUpperName() << "());\n"; } + void writeValue(raw_ostream &OS) const override { OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; } + void writeDump(raw_ostream &OS) const override { OS << " OS << \" \\\"\" << SA->get" << getUpperName() << "() << \"\\\"\";\n"; @@ -407,6 +457,7 @@ namespace { OS << " return " << getLowerName() << "Type;\n"; OS << " }"; } + void writeAccessorDefinitions(raw_ostream &OS) const override { OS << "bool " << getAttrName() << "Attr::is" << getUpperName() << "Dependent() const {\n"; @@ -434,16 +485,19 @@ namespace { OS << " return 0; // FIXME\n"; OS << "}\n"; } + void writeCloneArgs(raw_ostream &OS) const override { OS << "is" << getLowerName() << "Expr, is" << getLowerName() << "Expr ? static_cast<void*>(" << getLowerName() << "Expr) : " << getLowerName() << "Type"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { // FIXME: move the definition in Sema::InstantiateAttrs to here. // In the meantime, aligned attributes are cloned. } + void writeCtorBody(raw_ostream &OS) const override { OS << " if (is" << getLowerName() << "Expr)\n"; OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>(" @@ -451,20 +505,25 @@ namespace { OS << " else\n"; OS << " " << getLowerName() << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName() - << ");"; + << ");\n"; } + void writeCtorInitializers(raw_ostream &OS) const override { OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const override { OS << "is" << getLowerName() << "Expr(false)"; } + void writeCtorParameters(raw_ostream &OS) const override { OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName(); } + void writeImplicitCtorArgs(raw_ostream &OS) const override { OS << "Is" << getUpperName() << "Expr, " << getUpperName(); } + void writeDeclarations(raw_ostream &OS) const override { OS << "bool is" << getLowerName() << "Expr;\n"; OS << "union {\n"; @@ -472,9 +531,11 @@ namespace { OS << "TypeSourceInfo *" << getLowerName() << "Type;\n"; OS << "};"; } + void writePCHReadArgs(raw_ostream &OS) const override { OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr"; } + void writePCHReadDecls(raw_ostream &OS) const override { OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n"; OS << " void *" << getLowerName() << "Ptr;\n"; @@ -484,14 +545,16 @@ namespace { OS << " " << getLowerName() << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n"; } + void writePCHWrite(raw_ostream &OS) const override { OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n"; OS << " if (SA->is" << getUpperName() << "Expr())\n"; - OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n"; + OS << " Record.AddStmt(SA->get" << getUpperName() << "Expr());\n"; OS << " else\n"; - OS << " AddTypeSourceInfo(SA->get" << getUpperName() - << "Type(), Record);\n"; + OS << " Record.AddTypeSourceInfo(SA->get" << getUpperName() + << "Type());\n"; } + void writeValue(raw_ostream &OS) const override { OS << "\";\n"; // The aligned attribute argument expression is optional. @@ -500,8 +563,9 @@ namespace { OS << " " << getLowerName() << "Expr->printPretty(OS, nullptr, Policy);\n"; OS << " OS << \""; } - void writeDump(raw_ostream &OS) const override { - } + + void writeDump(raw_ostream &OS) const override {} + void writeDumpChildren(raw_ostream &OS) const override { OS << " if (SA->is" << getUpperName() << "Expr())\n"; OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n"; @@ -509,6 +573,7 @@ namespace { OS << " dumpType(SA->get" << getUpperName() << "Type()->getType());\n"; } + void writeHasChildren(raw_ostream &OS) const override { OS << "SA->is" << getUpperName() << "Expr()"; } @@ -525,10 +590,13 @@ namespace { public: VariadicArgument(const Record &Arg, StringRef Attr, std::string T) - : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"), - ArgSizeName(ArgName + "Size"), RangeName(getLowerName()) {} + : Argument(Arg, Attr), Type(std::move(T)), + ArgName(getLowerName().str() + "_"), ArgSizeName(ArgName + "Size"), + RangeName(getLowerName()) {} - std::string getType() const { return Type; } + const std::string &getType() const { return Type; } + const std::string &getArgName() const { return ArgName; } + const std::string &getArgSizeName() const { return ArgSizeName; } bool isVariadic() const override { return true; } void writeAccessors(raw_ostream &OS) const override { @@ -547,56 +615,87 @@ namespace { << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn << "); }\n"; } + void writeCloneArgs(raw_ostream &OS) const override { OS << ArgName << ", " << ArgSizeName; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { // This isn't elegant, but we have to go through public methods... OS << "A->" << getLowerName() << "_begin(), " << "A->" << getLowerName() << "_size()"; } + void writeCtorBody(raw_ostream &OS) const override { OS << " std::copy(" << getUpperName() << ", " << getUpperName() - << " + " << ArgSizeName << ", " << ArgName << ");"; + << " + " << ArgSizeName << ", " << ArgName << ");\n"; } + void writeCtorInitializers(raw_ostream &OS) const override { OS << ArgSizeName << "(" << getUpperName() << "Size), " << ArgName << "(new (Ctx, 16) " << getType() << "[" << ArgSizeName << "])"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const override { OS << ArgSizeName << "(0), " << ArgName << "(nullptr)"; } + void writeCtorParameters(raw_ostream &OS) const override { OS << getType() << " *" << getUpperName() << ", unsigned " << getUpperName() << "Size"; } + void writeImplicitCtorArgs(raw_ostream &OS) const override { OS << getUpperName() << ", " << getUpperName() << "Size"; } + void writeDeclarations(raw_ostream &OS) const override { OS << " unsigned " << ArgSizeName << ";\n"; OS << " " << getType() << " *" << ArgName << ";"; } + void writePCHReadDecls(raw_ostream &OS) const override { - OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; - OS << " SmallVector<" << Type << ", 4> " << getLowerName() - << ";\n"; - OS << " " << getLowerName() << ".reserve(" << getLowerName() + OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; + OS << " SmallVector<" << getType() << ", 4> " + << getLowerName() << ";\n"; + OS << " " << getLowerName() << ".reserve(" << getLowerName() << "Size);\n"; - OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; - + + // If we can't store the values in the current type (if it's something + // like StringRef), store them in a different type and convert the + // container afterwards. + std::string StorageType = getStorageType(getType()); + std::string StorageName = getLowerName(); + if (StorageType != getType()) { + StorageName += "Storage"; + OS << " SmallVector<" << StorageType << ", 4> " + << StorageName << ";\n"; + OS << " " << StorageName << ".reserve(" << getLowerName() + << "Size);\n"; + } + + OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n"; std::string read = ReadPCHRecord(Type); - OS << " " << getLowerName() << ".push_back(" << read << ");\n"; + OS << " " << StorageName << ".push_back(" << read << ");\n"; + + if (StorageType != getType()) { + OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n"; + OS << " " << getLowerName() << ".push_back(" + << StorageName << "[i]);\n"; + } } + void writePCHReadArgs(raw_ostream &OS) const override { OS << getLowerName() << ".data(), " << getLowerName() << "Size"; } + void writePCHWrite(raw_ostream &OS) const override { OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; OS << " for (auto &Val : SA->" << RangeName << "())\n"; OS << " " << WritePCHRecord(Type, "Val"); } + void writeValue(raw_ostream &OS) const override { OS << "\";\n"; OS << " bool isFirst = true;\n" @@ -607,6 +706,7 @@ namespace { OS << " }\n"; OS << " OS << \""; } + void writeDump(raw_ostream &OS) const override { OS << " for (const auto &Val : SA->" << RangeName << "())\n"; OS << " OS << \" \" << Val;\n"; @@ -649,9 +749,11 @@ namespace { OS << " return " << getLowerName() << ";\n"; OS << " }"; } + void writeCloneArgs(raw_ostream &OS) const override { OS << getLowerName(); } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { OS << "A->get" << getUpperName() << "()"; } @@ -678,17 +780,21 @@ namespace { OS << "private:\n"; OS << " " << type << " " << getLowerName() << ";"; } + void writePCHReadDecls(raw_ostream &OS) const override { OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName() << "(static_cast<" << getAttrName() << "Attr::" << type << ">(Record[Idx++]));\n"; } + void writePCHReadArgs(raw_ostream &OS) const override { OS << getLowerName(); } + void writePCHWrite(raw_ostream &OS) const override { OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; } + void writeValue(raw_ostream &OS) const override { // FIXME: this isn't 100% correct -- some enum arguments require printing // as a string literal, while others require printing as an identifier. @@ -696,6 +802,7 @@ namespace { OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << type << "ToStr(get" << getUpperName() << "()) << \"\\\""; } + void writeDump(raw_ostream &OS) const override { OS << " switch(SA->get" << getUpperName() << "()) {\n"; for (const auto &I : uniques) { @@ -784,6 +891,7 @@ namespace { VariadicArgument::writeDeclarations(OS); } + void writeDump(raw_ostream &OS) const override { OS << " for (" << getAttrName() << "Attr::" << getLowerName() << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" @@ -797,6 +905,7 @@ namespace { OS << " }\n"; OS << " }\n"; } + void writePCHReadDecls(raw_ostream &OS) const override { OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName() @@ -807,6 +916,7 @@ namespace { OS << " " << getLowerName() << ".push_back(" << "static_cast<" << QualifiedTypeName << ">(Record[Idx++]));\n"; } + void writePCHWrite(raw_ostream &OS) const override { OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; OS << " for (" << getAttrName() << "Attr::" << getLowerName() @@ -814,6 +924,7 @@ namespace { << getLowerName() << "_end(); i != e; ++i)\n"; OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)"); } + void writeConversion(raw_ostream &OS) const { OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; OS << type << " &Out) {\n"; @@ -859,37 +970,48 @@ namespace { OS << " " << getLowerName() << " = V;\n"; OS << " }"; } + void writeCloneArgs(raw_ostream &OS) const override { OS << "get" << getUpperName() << "()"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { OS << "A->get" << getUpperName() << "()"; } + void writeCtorInitializers(raw_ostream &OS) const override { OS << getLowerName() << "(" << getUpperName() << ")"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const override { OS << getLowerName() << "()"; } + void writeCtorParameters(raw_ostream &OS) const override { OS << "VersionTuple " << getUpperName(); } + void writeDeclarations(raw_ostream &OS) const override { OS << "VersionTuple " << getLowerName() << ";\n"; } + void writePCHReadDecls(raw_ostream &OS) const override { OS << " VersionTuple " << getLowerName() << "= ReadVersionTuple(Record, Idx);\n"; } + void writePCHReadArgs(raw_ostream &OS) const override { OS << getLowerName(); } + void writePCHWrite(raw_ostream &OS) const override { - OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n"; + OS << " Record.AddVersionTuple(SA->get" << getUpperName() << "());\n"; } + void writeValue(raw_ostream &OS) const override { OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; } + void writeDump(raw_ostream &OS) const override { OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; } @@ -928,6 +1050,7 @@ namespace { void writeDumpChildren(raw_ostream &OS) const override { OS << " dumpStmt(SA->get" << getUpperName() << "());\n"; } + void writeHasChildren(raw_ostream &OS) const override { OS << "true"; } }; @@ -993,8 +1116,21 @@ namespace { class VariadicStringArgument : public VariadicArgument { public: VariadicStringArgument(const Record &Arg, StringRef Attr) - : VariadicArgument(Arg, Attr, "std::string") + : VariadicArgument(Arg, Attr, "StringRef") {} + + void writeCtorBody(raw_ostream &OS) const override { + OS << " for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n" + " ++I) {\n" + " StringRef Ref = " << getUpperName() << "[I];\n" + " if (!Ref.empty()) {\n" + " char *Mem = new (Ctx, 1) char[Ref.size()];\n" + " std::memcpy(Mem, Ref.data(), Ref.size());\n" + " " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n" + " }\n" + " }\n"; + } + void writeValueImpl(raw_ostream &OS) const override { OS << " OS << \"\\\"\" << Val << \"\\\"\";\n"; } @@ -1014,14 +1150,17 @@ namespace { OS << " return " << getLowerName() << ";\n"; OS << " }"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { OS << "A->get" << getUpperName() << "Loc()"; } + void writePCHWrite(raw_ostream &OS) const override { OS << " " << WritePCHRecord( getType(), "SA->get" + std::string(getUpperName()) + "Loc()"); } }; + } // end anonymous namespace static std::unique_ptr<Argument> @@ -1072,9 +1211,9 @@ createArgument(const Record &Arg, StringRef Attr, if (!Ptr) { // Search in reverse order so that the most-derived type is handled first. - ArrayRef<Record*> Bases = Search->getSuperClasses(); - for (const auto *Base : llvm::make_range(Bases.rbegin(), Bases.rend())) { - if ((Ptr = createArgument(Arg, Attr, Base))) + ArrayRef<std::pair<Record*, SMRange>> Bases = Search->getSuperClasses(); + for (const auto &Base : llvm::reverse(Bases)) { + if ((Ptr = createArgument(Arg, Attr, Base.first))) break; } } @@ -1090,6 +1229,7 @@ createArgument(const Record &Arg, StringRef Attr, static void writeAvailabilityValue(raw_ostream &OS) { OS << "\" << getPlatform()->getName();\n" + << " if (getStrict()) OS << \", strict\";\n" << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" @@ -1097,6 +1237,15 @@ static void writeAvailabilityValue(raw_ostream &OS) { << " OS << \""; } +static void writeDeprecatedAttrValue(raw_ostream &OS, std::string &Variety) { + OS << "\\\"\" << getMessage() << \"\\\"\";\n"; + // Only GNU deprecated has an optional fixit argument at the second position. + if (Variety == "GNU") + OS << " if (!getReplacement().empty()) OS << \", \\\"\"" + " << getReplacement() << \"\\\"\";\n"; + OS << " OS << \""; +} + static void writeGetSpellingFunction(Record &R, raw_ostream &OS) { std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); @@ -1210,6 +1359,8 @@ writePrettyPrintFunction(Record &R, OS << "("; if (Spelling == "availability") { writeAvailabilityValue(OS); + } else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") { + writeDeprecatedAttrValue(OS, Variety); } else { unsigned index = 0; for (const auto &arg : Args) { @@ -1303,10 +1454,10 @@ CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings, unsigned Idx = 0; for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) { const FlattenedSpelling &S = *I; - std::string Variety = S.variety(); - std::string Spelling = S.name(); - std::string Namespace = S.nameSpace(); - std::string EnumName = ""; + const std::string &Variety = S.variety(); + const std::string &Spelling = S.name(); + const std::string &Namespace = S.nameSpace(); + std::string EnumName; EnumName += (Variety + "_"); if (!Namespace.empty()) @@ -1381,7 +1532,7 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { if (Args.empty()) continue; - if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument") + if (Args[0]->getSuperClasses().back().first->getName() != "TypeArgument") continue; // All these spellings take a single type argument. @@ -1419,7 +1570,7 @@ static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) static bool isIdentifierArgument(Record *Arg) { return !Arg->getSuperClasses().empty() && - llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName()) + llvm::StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) .Case("IdentifierArgument", true) .Case("EnumArgument", true) .Case("VariadicEnumArgument", true) @@ -1476,13 +1627,13 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { if (!R.getValueAsBit("ASTNode")) continue; - ArrayRef<Record *> Supers = R.getSuperClasses(); + ArrayRef<std::pair<Record *, SMRange>> Supers = R.getSuperClasses(); assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); std::string SuperName; - for (const auto *Super : llvm::make_range(Supers.rbegin(), Supers.rend())) { - const Record &R = *Super; - if (R.getName() != "TargetSpecificAttr" && SuperName.empty()) - SuperName = R.getName(); + for (const auto &Super : llvm::reverse(Supers)) { + const Record *R = Super.first; + if (R->getName() != "TargetSpecificAttr" && SuperName.empty()) + SuperName = R->getName(); } OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; @@ -1506,7 +1657,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { } } - OS << "\npublic:\n"; + OS << "public:\n"; std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); @@ -1576,8 +1727,8 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << " )\n"; OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, " - << R.getValueAsBit("LateParsed") << ", " - << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n"; + << ( R.getValueAsBit("LateParsed") ? "true" : "false" ) << ", " + << ( R.getValueAsBit("DuplicatesAllowedWhileMerging") ? "true" : "false" ) << ")\n"; for (auto const &ai : Args) { OS << " , "; @@ -1594,10 +1745,8 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { for (auto const &ai : Args) { if (!shouldEmitArg(ai)) continue; ai->writeCtorBody(OS); - OS << "\n"; } OS << " }\n\n"; - }; // Emit a constructor that includes all the arguments. @@ -1705,8 +1854,6 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << " return cast<" << R.getName() << "Attr>(this)->" << Method << ";\n"; } - OS << " case attr::NUM_ATTRS:\n"; - OS << " break;\n"; OS << " }\n"; OS << " llvm_unreachable(\"Unexpected attribute kind!\");\n"; OS << "}\n\n"; @@ -1725,20 +1872,10 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { } // end namespace clang -static void EmitAttrList(raw_ostream &OS, StringRef Class, +static void emitAttrList(raw_ostream &OS, StringRef Class, const std::vector<Record*> &AttrList) { - auto i = AttrList.cbegin(), e = AttrList.cend(); - - if (i != e) { - // Move the end iterator back to emit the last attribute. - for(--e; i != e; ++i) { - if (!(*i)->getValueAsBit("ASTNode")) - continue; - - OS << Class << "(" << (*i)->getName() << ")\n"; - } - - OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; + for (auto Cur : AttrList) { + OS << Class << "(" << Cur->getName() << ")\n"; } } @@ -1751,71 +1888,224 @@ static bool AttrHasPragmaSpelling(const Record *R) { }) != Spellings.end(); } -namespace clang { -// Emits the enumeration list for attributes. -void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { - emitSourceFileHeader("List of all attributes that Clang recognizes", OS); +namespace { - OS << "#ifndef LAST_ATTR\n"; - OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; - OS << "#endif\n\n"; + struct AttrClassDescriptor { + const char * const MacroName; + const char * const TableGenName; + }; - OS << "#ifndef INHERITABLE_ATTR\n"; - OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n"; - OS << "#endif\n\n"; +} // end anonymous namespace - OS << "#ifndef LAST_INHERITABLE_ATTR\n"; - OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; - OS << "#endif\n\n"; +static const AttrClassDescriptor AttrClassDescriptors[] = { + { "ATTR", "Attr" }, + { "STMT_ATTR", "StmtAttr" }, + { "INHERITABLE_ATTR", "InheritableAttr" }, + { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" }, + { "PARAMETER_ABI_ATTR", "ParameterABIAttr" } +}; - OS << "#ifndef INHERITABLE_PARAM_ATTR\n"; - OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n"; - OS << "#endif\n\n"; +static void emitDefaultDefine(raw_ostream &OS, StringRef name, + const char *superName) { + OS << "#ifndef " << name << "\n"; + OS << "#define " << name << "(NAME) "; + if (superName) OS << superName << "(NAME)"; + OS << "\n#endif\n\n"; +} - OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n"; - OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)" - " INHERITABLE_PARAM_ATTR(NAME)\n"; - OS << "#endif\n\n"; +namespace { - OS << "#ifndef PRAGMA_SPELLING_ATTR\n"; - OS << "#define PRAGMA_SPELLING_ATTR(NAME)\n"; - OS << "#endif\n\n"; + /// A class of attributes. + struct AttrClass { + const AttrClassDescriptor &Descriptor; + Record *TheRecord; + AttrClass *SuperClass = nullptr; + std::vector<AttrClass*> SubClasses; + std::vector<Record*> Attrs; + + AttrClass(const AttrClassDescriptor &Descriptor, Record *R) + : Descriptor(Descriptor), TheRecord(R) {} + + void emitDefaultDefines(raw_ostream &OS) const { + // Default the macro unless this is a root class (i.e. Attr). + if (SuperClass) { + emitDefaultDefine(OS, Descriptor.MacroName, + SuperClass->Descriptor.MacroName); + } + } - OS << "#ifndef LAST_PRAGMA_SPELLING_ATTR\n"; - OS << "#define LAST_PRAGMA_SPELLING_ATTR(NAME) PRAGMA_SPELLING_ATTR(NAME)\n"; - OS << "#endif\n\n"; + void emitUndefs(raw_ostream &OS) const { + OS << "#undef " << Descriptor.MacroName << "\n"; + } - Record *InhClass = Records.getClass("InheritableAttr"); - Record *InhParamClass = Records.getClass("InheritableParamAttr"); - std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), - NonInhAttrs, InhAttrs, InhParamAttrs, PragmaAttrs; + void emitAttrList(raw_ostream &OS) const { + for (auto SubClass : SubClasses) { + SubClass->emitAttrList(OS); + } + + ::emitAttrList(OS, Descriptor.MacroName, Attrs); + } + + void classifyAttrOnRoot(Record *Attr) { + bool result = classifyAttr(Attr); + assert(result && "failed to classify on root"); (void) result; + } + + void emitAttrRange(raw_ostream &OS) const { + OS << "ATTR_RANGE(" << Descriptor.TableGenName + << ", " << getFirstAttr()->getName() + << ", " << getLastAttr()->getName() << ")\n"; + } + + private: + bool classifyAttr(Record *Attr) { + // Check all the subclasses. + for (auto SubClass : SubClasses) { + if (SubClass->classifyAttr(Attr)) + return true; + } + + // It's not more specific than this class, but it might still belong here. + if (Attr->isSubClassOf(TheRecord)) { + Attrs.push_back(Attr); + return true; + } + + return false; + } + + Record *getFirstAttr() const { + if (!SubClasses.empty()) + return SubClasses.front()->getFirstAttr(); + return Attrs.front(); + } + + Record *getLastAttr() const { + if (!Attrs.empty()) + return Attrs.back(); + return SubClasses.back()->getLastAttr(); + } + }; + + /// The entire hierarchy of attribute classes. + class AttrClassHierarchy { + std::vector<std::unique_ptr<AttrClass>> Classes; + + public: + AttrClassHierarchy(RecordKeeper &Records) { + // Find records for all the classes. + for (auto &Descriptor : AttrClassDescriptors) { + Record *ClassRecord = Records.getClass(Descriptor.TableGenName); + AttrClass *Class = new AttrClass(Descriptor, ClassRecord); + Classes.emplace_back(Class); + } + + // Link up the hierarchy. + for (auto &Class : Classes) { + if (AttrClass *SuperClass = findSuperClass(Class->TheRecord)) { + Class->SuperClass = SuperClass; + SuperClass->SubClasses.push_back(Class.get()); + } + } + +#ifndef NDEBUG + for (auto i = Classes.begin(), e = Classes.end(); i != e; ++i) { + assert((i == Classes.begin()) == ((*i)->SuperClass == nullptr) && + "only the first class should be a root class!"); + } +#endif + } + + void emitDefaultDefines(raw_ostream &OS) const { + for (auto &Class : Classes) { + Class->emitDefaultDefines(OS); + } + } + + void emitUndefs(raw_ostream &OS) const { + for (auto &Class : Classes) { + Class->emitUndefs(OS); + } + } + + void emitAttrLists(raw_ostream &OS) const { + // Just start from the root class. + Classes[0]->emitAttrList(OS); + } + + void emitAttrRanges(raw_ostream &OS) const { + for (auto &Class : Classes) + Class->emitAttrRange(OS); + } + + void classifyAttr(Record *Attr) { + // Add the attribute to the root class. + Classes[0]->classifyAttrOnRoot(Attr); + } + + private: + AttrClass *findClassByRecord(Record *R) const { + for (auto &Class : Classes) { + if (Class->TheRecord == R) + return Class.get(); + } + return nullptr; + } + + AttrClass *findSuperClass(Record *R) const { + // TableGen flattens the superclass list, so we just need to walk it + // in reverse. + auto SuperClasses = R->getSuperClasses(); + for (signed i = 0, e = SuperClasses.size(); i != e; ++i) { + auto SuperClass = findClassByRecord(SuperClasses[e - i - 1].first); + if (SuperClass) return SuperClass; + } + return nullptr; + } + }; + +} // end anonymous namespace + +namespace clang { + +// Emits the enumeration list for attributes. +void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("List of all attributes that Clang recognizes", OS); + + AttrClassHierarchy Hierarchy(Records); + + // Add defaulting macro definitions. + Hierarchy.emitDefaultDefines(OS); + emitDefaultDefine(OS, "PRAGMA_SPELLING_ATTR", nullptr); + + std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); + std::vector<Record *> PragmaAttrs; for (auto *Attr : Attrs) { if (!Attr->getValueAsBit("ASTNode")) continue; + // Add the attribute to the ad-hoc groups. if (AttrHasPragmaSpelling(Attr)) PragmaAttrs.push_back(Attr); - if (Attr->isSubClassOf(InhParamClass)) - InhParamAttrs.push_back(Attr); - else if (Attr->isSubClassOf(InhClass)) - InhAttrs.push_back(Attr); - else - NonInhAttrs.push_back(Attr); + // Place it in the hierarchy. + Hierarchy.classifyAttr(Attr); } - EmitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs); - EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); - EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); - EmitAttrList(OS, "ATTR", NonInhAttrs); + // Emit the main attribute list. + Hierarchy.emitAttrLists(OS); + + // Emit the ad hoc groups. + emitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs); - OS << "#undef LAST_ATTR\n"; - OS << "#undef INHERITABLE_ATTR\n"; - OS << "#undef LAST_INHERITABLE_ATTR\n"; - OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; - OS << "#undef LAST_PRAGMA_ATTR\n"; + // Emit the attribute ranges. + OS << "#ifdef ATTR_RANGE\n"; + Hierarchy.emitAttrRanges(OS); + OS << "#undef ATTR_RANGE\n"; + OS << "#endif\n"; + + Hierarchy.emitUndefs(OS); OS << "#undef PRAGMA_SPELLING_ATTR\n"; - OS << "#undef ATTR\n"; } // Emits the code to read an attribute from a precompiled header. @@ -1828,8 +2118,6 @@ void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { std::vector<std::unique_ptr<Argument>> Args; OS << " switch (Kind) {\n"; - OS << " default:\n"; - OS << " llvm_unreachable(\"Unknown attribute!\");\n"; for (const auto *Attr : Attrs) { const Record &R = *Attr; if (!R.getValueAsBit("ASTNode")) @@ -1869,9 +2157,6 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; OS << " switch (A->getKind()) {\n"; - OS << " default:\n"; - OS << " llvm_unreachable(\"Unknown attribute kind!\");\n"; - OS << " break;\n"; for (const auto *Attr : Attrs) { const Record &R = *Attr; if (!R.getValueAsBit("ASTNode")) @@ -2018,7 +2303,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { for (auto *R : Attrs) { std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R); for (const auto &SI : Spellings) { - std::string Variety = SI.variety(); + const std::string &Variety = SI.variety(); if (Variety == "GNU") GNU.push_back(R); else if (Variety == "Declspec") @@ -2062,11 +2347,7 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Code to translate different attribute spellings " "into internal identifiers", OS); - OS << - " switch (AttrKind) {\n" - " default:\n" - " llvm_unreachable(\"Unknown attribute kind!\");\n" - " break;\n"; + OS << " switch (AttrKind) {\n"; ParsedAttrMap Attrs = getParsedAttrList(Records); for (const auto &I : Attrs) { @@ -2146,9 +2427,7 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { << " if (!A)\n" << " return true;\n" << "\n" - << " switch (A->getKind()) {\n" - << " default:\n" - << " return true;\n"; + << " switch (A->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record &R = *Attr; @@ -2159,7 +2438,8 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { << " return getDerived().Traverse" << R.getName() << "Attr(" << "cast<" << R.getName() << "Attr>(A));\n"; } - OS << " }\n"; // end case + OS << " }\n"; // end switch + OS << " llvm_unreachable(\"bad attribute kind\");\n"; OS << "}\n"; // end function OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; } @@ -2175,9 +2455,7 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " << "Sema &S,\n" << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" - << " switch (At->getKind()) {\n" - << " default:\n" - << " break;\n"; + << " switch (At->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record &R = *Attr; @@ -2375,6 +2653,15 @@ static std::string CalculateDiagnostic(const Record &S) { return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : " "ExpectedVariableOrFunction)"; + case Func | Var | Class | ObjCInterface: + return "(S.getLangOpts().CPlusPlus" + " ? ((S.getLangOpts().ObjC1 || S.getLangOpts().ObjC2)" + " ? ExpectedFunctionVariableClassOrObjCInterface" + " : ExpectedFunctionVariableOrClass)" + " : ((S.getLangOpts().ObjC1 || S.getLangOpts().ObjC2)" + " ? ExpectedFunctionVariableOrObjCInterface" + " : ExpectedVariableOrFunction))"; + case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty"; case ObjCProtocol | ObjCInterface: return "ExpectedObjectiveCInterfaceOrProtocol"; @@ -2671,6 +2958,7 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { SS << ", " << I->second->getValueAsBit("HasCustomParsing"); SS << ", " << I->second->isSubClassOf("TargetSpecificAttr"); SS << ", " << I->second->isSubClassOf("TypeAttr"); + SS << ", " << I->second->isSubClassOf("StmtAttr"); SS << ", " << IsKnownToGCC(*I->second); SS << ", " << GenerateAppertainsTo(*I->second, OS); SS << ", " << GenerateLangOptRequirements(*I->second, OS); @@ -2724,9 +3012,10 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); for (const auto &S : Spellings) { - std::string RawSpelling = S.name(); + const std::string &RawSpelling = S.name(); std::vector<StringMatcher::StringPair> *Matches = nullptr; - std::string Spelling, Variety = S.variety(); + std::string Spelling; + const std::string &Variety = S.variety(); if (Variety == "CXX11") { Matches = &CXX11; Spelling += S.nameSpace(); @@ -2775,11 +3064,7 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Attribute dumper", OS); - OS << - " switch (A->getKind()) {\n" - " default:\n" - " llvm_unreachable(\"Unknown attribute kind!\");\n" - " break;\n"; + OS << " switch (A->getKind()) {\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; for (const auto *Attr : Attrs) { const Record &R = *Attr; diff --git a/gnu/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/gnu/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index efce5219031..bbc2bdb065f 100644 --- a/gnu/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/gnu/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -152,13 +152,12 @@ static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){ } static SMRange findSuperClassRange(const Record *R, StringRef SuperName) { - ArrayRef<Record *> Supers = R->getSuperClasses(); - - for (size_t i = 0, e = Supers.size(); i < e; ++i) - if (Supers[i]->getName() == SuperName) - return R->getSuperClassRanges()[i]; - - return SMRange(); + ArrayRef<std::pair<Record *, SMRange>> Supers = R->getSuperClasses(); + auto I = std::find_if(Supers.begin(), Supers.end(), + [&](const std::pair<Record *, SMRange> &SuperPair) { + return SuperPair.first->getName() == SuperName; + }); + return (I != Supers.end()) ? I->second : SMRange(); } /// \brief Invert the 1-[0/1] mapping of diags to group into a one to many diff --git a/gnu/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp b/gnu/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp index 6e7bc9057fd..b5313a073d1 100644 --- a/gnu/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp +++ b/gnu/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp @@ -40,6 +40,7 @@ #include <map> #include <sstream> #include <string> +#include <utility> #include <vector> using namespace llvm; @@ -146,9 +147,10 @@ public: NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} Type(TypeSpec TS, char CharMod) - : TS(TS), Float(false), Signed(false), Immediate(false), Void(false), - Poly(false), Constant(false), Pointer(false), ScalarForMangling(false), - NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) { + : TS(std::move(TS)), Float(false), Signed(false), Immediate(false), + Void(false), Poly(false), Constant(false), Pointer(false), + ScalarForMangling(false), NoManglingQ(false), Bitwidth(0), + ElementBitwidth(0), NumVectors(0) { applyModifier(CharMod); } @@ -257,7 +259,7 @@ class Variable { public: Variable() : T(Type::getVoid()), N("") {} - Variable(Type T, std::string N) : T(T), N(N) {} + Variable(Type T, std::string N) : T(std::move(T)), N(std::move(N)) {} Type getType() const { return T; } std::string getName() const { return "__" + N; } @@ -1195,12 +1197,12 @@ void Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) { emitNewLine(); for (unsigned K = 0; K < Dest.getType().getNumVectors(); ++K) { - OS << " " << Dest.getName() << ".val[" << utostr(K) << "] = " + OS << " " << Dest.getName() << ".val[" << K << "] = " << "__builtin_shufflevector(" - << Src.getName() << ".val[" << utostr(K) << "], " - << Src.getName() << ".val[" << utostr(K) << "]"; + << Src.getName() << ".val[" << K << "], " + << Src.getName() << ".val[" << K << "]"; for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) - OS << ", " << utostr(J); + OS << ", " << J; OS << ");"; emitNewLine(); } @@ -1208,7 +1210,7 @@ void Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) { OS << " " << Dest.getName() << " = __builtin_shufflevector(" << Src.getName() << ", " << Src.getName(); for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) - OS << ", " << utostr(J); + OS << ", " << J; OS << ");"; emitNewLine(); } @@ -1926,7 +1928,7 @@ void NeonEmitter::createIntrinsic(Record *R, ClassKind CK = ClassNone; if (R->getSuperClasses().size() >= 2) - CK = ClassMap[R->getSuperClasses()[1]]; + CK = ClassMap[R->getSuperClasses()[1].first]; std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs; for (auto TS : TypeSpecs) { diff --git a/gnu/llvm/tools/clang/utils/TableGen/TableGen.cpp b/gnu/llvm/tools/clang/utils/TableGen/TableGen.cpp index 724b0e19586..7ccd7150319 100644 --- a/gnu/llvm/tools/clang/utils/TableGen/TableGen.cpp +++ b/gnu/llvm/tools/clang/utils/TableGen/TableGen.cpp @@ -241,7 +241,7 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) { } int main(int argc, char **argv) { - sys::PrintStackTraceOnErrorSignal(); + sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv); diff --git a/gnu/llvm/tools/clang/utils/analyzer/SATestBuild.py b/gnu/llvm/tools/clang/utils/analyzer/SATestBuild.py index d0503c6389c..ab68518b5ac 100755 --- a/gnu/llvm/tools/clang/utils/analyzer/SATestBuild.py +++ b/gnu/llvm/tools/clang/utils/analyzer/SATestBuild.py @@ -218,11 +218,11 @@ def runScript(ScriptPath, PBuildLogFile, Cwd): try: if Verbose == 1: print " Executing: %s" % (ScriptPath,) - check_call("chmod +x %s" % ScriptPath, cwd = Cwd, + check_call("chmod +x '%s'" % ScriptPath, cwd = Cwd, stderr=PBuildLogFile, stdout=PBuildLogFile, shell=True) - check_call(ScriptPath, cwd = Cwd, stderr=PBuildLogFile, + check_call("'%s'" % ScriptPath, cwd = Cwd, stderr=PBuildLogFile, stdout=PBuildLogFile, shell=True) except: @@ -261,7 +261,7 @@ def applyPatch(Dir, PBuildLogFile): print " Applying patch." try: - check_call("patch -p1 < %s" % (PatchfilePath), + check_call("patch -p1 < '%s'" % (PatchfilePath), cwd = PatchedSourceDirPath, stderr=PBuildLogFile, stdout=PBuildLogFile, @@ -285,8 +285,8 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): # Run scan-build from within the patched source directory. SBCwd = os.path.join(Dir, PatchedSourceDirName) - SBOptions = "--use-analyzer " + Clang + " " - SBOptions += "-plist-html -o " + SBOutputDir + " " + SBOptions = "--use-analyzer '%s' " % Clang + SBOptions += "-plist-html -o '%s' " % SBOutputDir SBOptions += "-enable-checker " + AllCheckers + " " SBOptions += "--keep-empty " # Always use ccc-analyze to ensure that we can locate the failures @@ -376,8 +376,8 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode): raise Exception() # Build and call the analyzer command. - OutputOption = "-o " + os.path.join(PlistPath, FileName) + ".plist " - Command = CmdPrefix + OutputOption + FileName + OutputOption = "-o '%s.plist' " % os.path.join(PlistPath, FileName) + Command = CmdPrefix + OutputOption + ("'%s'" % FileName) LogFile = open(os.path.join(FailPath, FileName + ".stderr.txt"), "w+b") try: if Verbose == 1: @@ -397,23 +397,30 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode): if Failed == False: os.remove(LogFile.name); +def getBuildLogPath(SBOutputDir): + return os.path.join(SBOutputDir, LogFolderName, BuildLogName) + +def removeLogFile(SBOutputDir): + BuildLogPath = getBuildLogPath(SBOutputDir) + # Clean up the log file. + if (os.path.exists(BuildLogPath)) : + RmCommand = "rm '%s'" % BuildLogPath + if Verbose == 1: + print " Executing: %s" % (RmCommand,) + check_call(RmCommand, shell=True) + def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild): TBegin = time.time() - BuildLogPath = os.path.join(SBOutputDir, LogFolderName, BuildLogName) + BuildLogPath = getBuildLogPath(SBOutputDir) print "Log file: %s" % (BuildLogPath,) print "Output directory: %s" %(SBOutputDir, ) - # Clean up the log file. - if (os.path.exists(BuildLogPath)) : - RmCommand = "rm " + BuildLogPath - if Verbose == 1: - print " Executing: %s" % (RmCommand,) - check_call(RmCommand, shell=True) + removeLogFile(SBOutputDir) # Clean up scan build results. if (os.path.exists(SBOutputDir)) : - RmCommand = "rm -r " + SBOutputDir + RmCommand = "rm -r '%s'" % SBOutputDir if Verbose == 1: print " Executing: %s" % (RmCommand,) check_call(RmCommand, shell=True) @@ -585,6 +592,19 @@ def runCmpResults(Dir, Strictness = 0): print "Diagnostic comparison complete (time: %.2f)." % (time.time()-TBegin) return (NumDiffs > 0) +def cleanupReferenceResults(SBOutputDir): + # Delete html, css, and js files from reference results. These can + # include multiple copies of the benchmark source and so get very large. + Extensions = ["html", "css", "js"] + for E in Extensions: + for F in glob.glob("%s/*/*.%s" % (SBOutputDir, E)): + P = os.path.join(SBOutputDir, F) + RmCommand = "rm '%s'" % P + check_call(RmCommand, shell=True) + + # Remove the log file. It leaks absolute path names. + removeLogFile(SBOutputDir) + def updateSVN(Mode, ProjectsMap): try: ProjectsMap.seek(0) @@ -593,9 +613,9 @@ def updateSVN(Mode, ProjectsMap): Path = os.path.join(ProjName, getSBOutputDirName(True)) if Mode == "delete": - Command = "svn delete %s" % (Path,) + Command = "svn delete '%s'" % (Path,) else: - Command = "svn add %s" % (Path,) + Command = "svn add '%s'" % (Path,) if Verbose == 1: print " Executing: %s" % (Command,) @@ -634,6 +654,8 @@ def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Dir=None, Strictne if IsReferenceBuild == False: runCmpResults(Dir, Strictness) + else: + cleanupReferenceResults(SBOutputDir) print "Completed tests for project %s (time: %.2f)." % \ (ID, (time.time()-TBegin)) diff --git a/gnu/llvm/tools/clang/utils/modfuzz.py b/gnu/llvm/tools/clang/utils/modfuzz.py new file mode 100644 index 00000000000..a6aa1f1a257 --- /dev/null +++ b/gnu/llvm/tools/clang/utils/modfuzz.py @@ -0,0 +1,166 @@ +#! /usr/bin/env python + +# To use: +# 1) Update the 'decls' list below with your fuzzing configuration. +# 2) Run with the clang binary as the command-line argument. + +import random +import subprocess +import sys +import os + +clang = sys.argv[1] +none_opts = 0.3 + +class Decl: + def __init__(self, text, depends=[], provides=[], conflicts=[]): + self.text = text + self.depends = depends + self.provides = provides + self.conflicts = conflicts + + def valid(self, model): + for i in self.depends: + if i not in model.decls: + return False + for i in self.conflicts: + if i in model.decls: + return False + return True + + def apply(self, model, name): + for i in self.provides: + model.decls[i] = True + model.source += self.text % {'name': name} + +decls = [ + Decl('struct X { int n; };\n', provides=['X'], conflicts=['X']), + Decl('static_assert(X{.n=1}.n == 1, "");\n', depends=['X']), + Decl('X %(name)s;\n', depends=['X']), +] + +class FS: + def __init__(self): + self.fs = {} + self.prevfs = {} + + def write(self, path, contents): + self.fs[path] = contents + + def done(self): + for f, s in self.fs.items(): + if self.prevfs.get(f) != s: + f = file(f, 'w') + f.write(s) + f.close() + + for f in self.prevfs: + if f not in self.fs: + os.remove(f) + + self.prevfs, self.fs = self.fs, {} + +fs = FS() + +class CodeModel: + def __init__(self): + self.source = '' + self.modules = {} + self.decls = {} + self.i = 0 + + def make_name(self): + self.i += 1 + return 'n' + str(self.i) + + def fails(self): + fs.write('module.modulemap', + ''.join('module %s { header "%s.h" export * }\n' % (m, m) + for m in self.modules.keys())) + + for m, (s, _) in self.modules.items(): + fs.write('%s.h' % m, s) + + fs.write('main.cc', self.source) + fs.done() + + return subprocess.call([clang, '-std=c++11', '-c', '-fmodules', 'main.cc', '-o', '/dev/null']) != 0 + +def generate(): + model = CodeModel() + m = [] + + try: + for d in mutations(model): + d(model) + m.append(d) + if not model.fails(): + return + except KeyboardInterrupt: + print + return True + + sys.stdout.write('\nReducing:\n') + sys.stdout.flush() + + try: + while True: + assert m, 'got a failure with no steps; broken clang binary?' + i = random.choice(range(len(m))) + x = m[0:i] + m[i+1:] + m2 = CodeModel() + for d in x: + d(m2) + if m2.fails(): + m = x + model = m2 + else: + sys.stdout.write('.') + sys.stdout.flush() + except KeyboardInterrupt: + # FIXME: Clean out output directory first. + model.fails() + return model + +def choose(options): + while True: + i = int(random.uniform(0, len(options) + none_opts)) + if i >= len(options): + break + yield options[i] + +def mutations(model): + options = [create_module, add_top_level_decl] + for opt in choose(options): + yield opt(model, options) + +def create_module(model, options): + n = model.make_name() + def go(model): + model.modules[n] = (model.source, model.decls) + (model.source, model.decls) = ('', {}) + options += [lambda model, options: add_import(model, options, n)] + return go + +def add_top_level_decl(model, options): + n = model.make_name() + d = random.choice([decl for decl in decls if decl.valid(model)]) + def go(model): + if not d.valid(model): + return + d.apply(model, n) + return go + +def add_import(model, options, module_name): + def go(model): + if module_name in model.modules: + model.source += '#include "%s.h"\n' % module_name + model.decls.update(model.modules[module_name][1]) + return go + +sys.stdout.write('Finding bug: ') +while True: + if generate(): + break + sys.stdout.write('.') + sys.stdout.flush() diff --git a/gnu/llvm/tools/clang/utils/perf-training/CMakeLists.txt b/gnu/llvm/tools/clang/utils/perf-training/CMakeLists.txt index ccedcf5d516..07d90246107 100644 --- a/gnu/llvm/tools/clang/utils/perf-training/CMakeLists.txt +++ b/gnu/llvm/tools/clang/utils/perf-training/CMakeLists.txt @@ -1,24 +1,28 @@ -if(LLVM_BUILD_INSTRUMENTED) - if (CMAKE_CFG_INTDIR STREQUAL ".") - set(LLVM_BUILD_MODE ".") - else () - set(LLVM_BUILD_MODE "%(build_mode)s") - endif () - string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) +# All test suites added here should be excuded from check-all +set(EXCLUDE_FROM_ALL On) + +if (CMAKE_CFG_INTDIR STREQUAL ".") + set(LLVM_BUILD_MODE ".") +else () + set(LLVM_BUILD_MODE "%(build_mode)s") +endif () + +string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) +if(LLVM_BUILD_INSTRUMENTED) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + ${CMAKE_CURRENT_BINARY_DIR}/pgo-data/lit.site.cfg ) add_lit_testsuite(generate-profraw "Generating clang PGO data" - ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/pgo-data/ DEPENDS clang clear-profraw ) add_custom_target(clear-profraw - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} profraw COMMENT "Clearing old profraw data") if(NOT LLVM_PROFDATA) @@ -34,3 +38,26 @@ if(LLVM_BUILD_INSTRUMENTED) COMMENT "Merging profdata" DEPENDS generate-profraw) endif() + +find_program(DTRACE dtrace) +if(DTRACE) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/order-files.lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/order-files/lit.site.cfg + ) + + add_lit_testsuite(generate-dtrace-logs "Generating clang dtrace data" + ${CMAKE_CURRENT_BINARY_DIR}/order-files/ + ARGS -j 1 + DEPENDS clang clear-dtrace-logs + ) + + add_custom_target(clear-dtrace-logs + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} dtrace + COMMENT "Clearing old dtrace data") + + add_custom_target(generate-order-file + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py gen-order-file --binary $<TARGET_FILE:clang> --output ${CLANG_ORDER_FILE} ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating order file" + DEPENDS generate-dtrace-logs) +endif() diff --git a/gnu/llvm/tools/clang/utils/perf-training/cxx/hello_world.cpp b/gnu/llvm/tools/clang/utils/perf-training/cxx/hello_world.cpp index 66e00d00d26..fc9f6892eb7 100644 --- a/gnu/llvm/tools/clang/utils/perf-training/cxx/hello_world.cpp +++ b/gnu/llvm/tools/clang/utils/perf-training/cxx/hello_world.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cpp -c %s +// RUN: %clang_cpp_skip_driver -Wall -pedantic -c %s #include <iostream> int main(int, char**) { diff --git a/gnu/llvm/tools/clang/utils/perf-training/lit.cfg b/gnu/llvm/tools/clang/utils/perf-training/lit.cfg index af4b43b78b0..85d35514341 100644 --- a/gnu/llvm/tools/clang/utils/perf-training/lit.cfg +++ b/gnu/llvm/tools/clang/utils/perf-training/lit.cfg @@ -26,10 +26,13 @@ config.clang = lit.util.which('clang', config.clang_tools_dir).replace('\\', '/' config.name = 'Clang Perf Training' config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap'] +cc1_wrapper = '%s %s/perf-helper.py cc1' % (config.python_exe, config.test_source_root) + use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") config.test_format = lit.formats.ShTest(use_lit_shell == "0") +config.substitutions.append( ('%clang_cpp_skip_driver', ' %s %s %s ' % (cc1_wrapper, config.clang, sysroot_flags))) config.substitutions.append( ('%clang_cpp', ' %s --driver-mode=cpp %s ' % (config.clang, sysroot_flags))) -config.substitutions.append( ('%clang_cc1', ' %s -cc1 %s ' % (config.clang, sysroot_flags))) +config.substitutions.append( ('%clang_skip_driver', ' %s %s %s ' % (cc1_wrapper, config.clang, sysroot_flags))) config.substitutions.append( ('%clang', ' %s %s ' % (config.clang, sysroot_flags) ) ) config.substitutions.append( ('%test_root', config.test_exec_root ) ) diff --git a/gnu/llvm/tools/clang/utils/perf-training/lit.site.cfg.in b/gnu/llvm/tools/clang/utils/perf-training/lit.site.cfg.in index 9dc380242e5..66683bcd528 100644 --- a/gnu/llvm/tools/clang/utils/perf-training/lit.site.cfg.in +++ b/gnu/llvm/tools/clang/utils/perf-training/lit.site.cfg.in @@ -1,11 +1,12 @@ +@LIT_SITE_CFG_IN_HEADER@ + import sys -## Autogenerated by LLVM/Clang configuration. -# Do not edit! config.clang_tools_dir = "@CLANG_TOOLS_DIR@" config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" config.test_source_root = "@CMAKE_CURRENT_SOURCE_DIR@" config.target_triple = "@TARGET_TRIPLE@" +config.python_exe = "@PYTHON_EXECUTABLE@" # Support substitution of the tools and libs dirs with user parameters. This is # used when we can't determine the tool dir at configuration time. diff --git a/gnu/llvm/tools/clang/utils/perf-training/order-files.lit.cfg b/gnu/llvm/tools/clang/utils/perf-training/order-files.lit.cfg new file mode 100644 index 00000000000..75501f8c629 --- /dev/null +++ b/gnu/llvm/tools/clang/utils/perf-training/order-files.lit.cfg @@ -0,0 +1,41 @@ +# -*- Python -*- + +from lit import Test +import lit.formats +import lit.util +import os + +def getSysrootFlagsOnDarwin(config, lit_config): + # On Darwin, support relocatable SDKs by providing Clang with a + # default system root path. + if 'darwin' in config.target_triple: + try: + out = lit.util.capture(['xcrun', '--show-sdk-path']).strip() + res = 0 + except OSError: + res = -1 + if res == 0 and out: + sdk_path = out + lit_config.note('using SDKROOT: %r' % sdk_path) + return '-isysroot %s' % sdk_path + return '' + +sysroot_flags = getSysrootFlagsOnDarwin(config, lit_config) + +config.clang = os.path.realpath(lit.util.which('clang', config.clang_tools_dir)).replace('\\', '/') + +config.name = 'Clang Perf Training' +config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap'] + +dtrace_wrapper = '%s %s/perf-helper.py dtrace' % (config.python_exe, config.test_source_root) +dtrace_wrapper_cc1 = '%s %s/perf-helper.py dtrace --cc1' % (config.python_exe, config.test_source_root) + +use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") +config.test_format = lit.formats.ShTest(use_lit_shell == "0") +config.substitutions.append( ('%clang_cpp_skip_driver', ' %s %s --driver-mode=cpp %s ' % (dtrace_wrapper_cc1, config.clang, sysroot_flags))) +config.substitutions.append( ('%clang_cpp', ' %s %s --driver-mode=cpp %s ' % (dtrace_wrapper, config.clang, sysroot_flags))) +config.substitutions.append( ('%clang_skip_driver', ' %s %s %s ' % (dtrace_wrapper_cc1, config.clang, sysroot_flags))) +config.substitutions.append( ('%clang', ' %s %s %s ' % (dtrace_wrapper, config.clang, sysroot_flags) ) ) +config.substitutions.append( ('%test_root', config.test_exec_root ) ) + + diff --git a/gnu/llvm/tools/clang/utils/perf-training/order-files.lit.site.cfg.in b/gnu/llvm/tools/clang/utils/perf-training/order-files.lit.site.cfg.in new file mode 100644 index 00000000000..0490a217ad0 --- /dev/null +++ b/gnu/llvm/tools/clang/utils/perf-training/order-files.lit.site.cfg.in @@ -0,0 +1,21 @@ +@LIT_SITE_CFG_IN_HEADER@ + +import sys + +config.clang_tools_dir = "@CLANG_TOOLS_DIR@" +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" +config.test_source_root = "@CMAKE_CURRENT_SOURCE_DIR@" +config.target_triple = "@TARGET_TRIPLE@" +config.python_exe = "@PYTHON_EXECUTABLE@" + +# Support substitution of the tools and libs dirs with user parameters. This is +# used when we can't determine the tool dir at configuration time. +try: + config.clang_tools_dir = config.clang_tools_dir % lit_config.params +except KeyError: + e = sys.exc_info()[1] + key, = e.args + lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) + +# Let the main config do the real work. +lit_config.load_config(config, "@CLANG_SOURCE_DIR@/utils/perf-training/order-files.lit.cfg") diff --git a/gnu/llvm/tools/clang/utils/perf-training/perf-helper.py b/gnu/llvm/tools/clang/utils/perf-training/perf-helper.py index 448801133e0..c7c4bddf895 100644 --- a/gnu/llvm/tools/clang/utils/perf-training/perf-helper.py +++ b/gnu/llvm/tools/clang/utils/perf-training/perf-helper.py @@ -7,36 +7,397 @@ # #===------------------------------------------------------------------------===# +from __future__ import print_function + import sys import os import subprocess +import argparse +import time +import bisect +import shlex +import tempfile + +test_env = { 'PATH' : os.environ['PATH'] } -def findProfrawFiles(path): - profraw_files = [] +def findFilesWithExtension(path, extension): + filenames = [] for root, dirs, files in os.walk(path): for filename in files: - if filename.endswith(".profraw"): - profraw_files.append(os.path.join(root, filename)) - return profraw_files + if filename.endswith(extension): + filenames.append(os.path.join(root, filename)) + return filenames def clean(args): - if len(args) != 1: - print 'Usage: %s clean <path>\n\tRemoves all *.profraw files from <path>.' % __file__ + if len(args) != 2: + print('Usage: %s clean <path> <extension>\n' % __file__ + + '\tRemoves all files with extension from <path>.') return 1 - for profraw in findProfrawFiles(args[0]): - os.remove(profraw) + for filename in findFilesWithExtension(args[0], args[1]): + os.remove(filename) return 0 def merge(args): if len(args) != 3: - print 'Usage: %s clean <llvm-profdata> <output> <path>\n\tMerges all profraw files from path into output.' % __file__ + print('Usage: %s clean <llvm-profdata> <output> <path>\n' % __file__ + + '\tMerges all profraw files from path into output.') return 1 cmd = [args[0], 'merge', '-o', args[1]] - cmd.extend(findProfrawFiles(args[2])) + cmd.extend(findFilesWithExtension(args[2], "profraw")) subprocess.check_call(cmd) return 0 -commands = {'clean' : clean, 'merge' : merge} +def dtrace(args): + parser = argparse.ArgumentParser(prog='perf-helper dtrace', + description='dtrace wrapper for order file generation') + parser.add_argument('--buffer-size', metavar='size', type=int, required=False, + default=1, help='dtrace buffer size in MB (default 1)') + parser.add_argument('--use-oneshot', required=False, action='store_true', + help='Use dtrace\'s oneshot probes') + parser.add_argument('--use-ustack', required=False, action='store_true', + help='Use dtrace\'s ustack to print function names') + parser.add_argument('--cc1', required=False, action='store_true', + help='Execute cc1 directly (don\'t profile the driver)') + parser.add_argument('cmd', nargs='*', help='') + + # Use python's arg parser to handle all leading option arguments, but pass + # everything else through to dtrace + first_cmd = next(arg for arg in args if not arg.startswith("--")) + last_arg_idx = args.index(first_cmd) + + opts = parser.parse_args(args[:last_arg_idx]) + cmd = args[last_arg_idx:] + + if opts.cc1: + cmd = get_cc1_command_for_args(cmd, test_env) + + if opts.use_oneshot: + target = "oneshot$target:::entry" + else: + target = "pid$target:::entry" + predicate = '%s/probemod=="%s"/' % (target, os.path.basename(args[0])) + log_timestamp = 'printf("dtrace-TS: %d\\n", timestamp)' + if opts.use_ustack: + action = 'ustack(1);' + else: + action = 'printf("dtrace-Symbol: %s\\n", probefunc);' + dtrace_script = "%s { %s; %s }" % (predicate, log_timestamp, action) + + dtrace_args = [] + if not os.geteuid() == 0: + print( + 'Script must be run as root, or you must add the following to your sudoers:' + + '%%admin ALL=(ALL) NOPASSWD: /usr/sbin/dtrace') + dtrace_args.append("sudo") + + dtrace_args.extend(( + 'dtrace', '-xevaltime=exec', + '-xbufsize=%dm' % (opts.buffer_size), + '-q', '-n', dtrace_script, + '-c', ' '.join(cmd))) + + if sys.platform == "darwin": + dtrace_args.append('-xmangled') + + start_time = time.time() + + with open("%d.dtrace" % os.getpid(), "w") as f: + subprocess.check_call(dtrace_args, stdout=f, stderr=subprocess.PIPE) + + elapsed = time.time() - start_time + print("... data collection took %.4fs" % elapsed) + + return 0 + +def get_cc1_command_for_args(cmd, env): + # Find the cc1 command used by the compiler. To do this we execute the + # compiler with '-###' to figure out what it wants to do. + cmd = cmd + ['-###'] + cc_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, env=env).strip() + cc_commands = [] + for ln in cc_output.split('\n'): + # Filter out known garbage. + if (ln == 'Using built-in specs.' or + ln.startswith('Configured with:') or + ln.startswith('Target:') or + ln.startswith('Thread model:') or + ln.startswith('InstalledDir:') or + ln.startswith('LLVM Profile Note') or + ' version ' in ln): + continue + cc_commands.append(ln) + + if len(cc_commands) != 1: + print('Fatal error: unable to determine cc1 command: %r' % cc_output) + exit(1) + + cc1_cmd = shlex.split(cc_commands[0]) + if not cc1_cmd: + print('Fatal error: unable to determine cc1 command: %r' % cc_output) + exit(1) + + return cc1_cmd + +def cc1(args): + parser = argparse.ArgumentParser(prog='perf-helper cc1', + description='cc1 wrapper for order file generation') + parser.add_argument('cmd', nargs='*', help='') + + # Use python's arg parser to handle all leading option arguments, but pass + # everything else through to dtrace + first_cmd = next(arg for arg in args if not arg.startswith("--")) + last_arg_idx = args.index(first_cmd) + + opts = parser.parse_args(args[:last_arg_idx]) + cmd = args[last_arg_idx:] + + # clear the profile file env, so that we don't generate profdata + # when capturing the cc1 command + cc1_env = test_env + cc1_env["LLVM_PROFILE_FILE"] = os.devnull + cc1_cmd = get_cc1_command_for_args(cmd, cc1_env) + + subprocess.check_call(cc1_cmd) + return 0 + +def parse_dtrace_symbol_file(path, all_symbols, all_symbols_set, + missing_symbols, opts): + def fix_mangling(symbol): + if sys.platform == "darwin": + if symbol[0] != '_' and symbol != 'start': + symbol = '_' + symbol + return symbol + + def get_symbols_with_prefix(symbol): + start_index = bisect.bisect_left(all_symbols, symbol) + for s in all_symbols[start_index:]: + if not s.startswith(symbol): + break + yield s + + # Extract the list of symbols from the given file, which is assumed to be + # the output of a dtrace run logging either probefunc or ustack(1) and + # nothing else. The dtrace -xdemangle option needs to be used. + # + # This is particular to OS X at the moment, because of the '_' handling. + with open(path) as f: + current_timestamp = None + for ln in f: + # Drop leading and trailing whitespace. + ln = ln.strip() + if not ln.startswith("dtrace-"): + continue + + # If this is a timestamp specifier, extract it. + if ln.startswith("dtrace-TS: "): + _,data = ln.split(': ', 1) + if not data.isdigit(): + print("warning: unrecognized timestamp line %r, ignoring" % ln, + file=sys.stderr) + continue + current_timestamp = int(data) + continue + elif ln.startswith("dtrace-Symbol: "): + + _,ln = ln.split(': ', 1) + if not ln: + continue + + # If there is a '`' in the line, assume it is a ustack(1) entry in + # the form of <modulename>`<modulefunc>, where <modulefunc> is never + # truncated (but does need the mangling patched). + if '`' in ln: + yield (current_timestamp, fix_mangling(ln.split('`',1)[1])) + continue + + # Otherwise, assume this is a probefunc printout. DTrace on OS X + # seems to have a bug where it prints the mangled version of symbols + # which aren't C++ mangled. We just add a '_' to anything but start + # which doesn't already have a '_'. + symbol = fix_mangling(ln) + + # If we don't know all the symbols, or the symbol is one of them, + # just return it. + if not all_symbols_set or symbol in all_symbols_set: + yield (current_timestamp, symbol) + continue + + # Otherwise, we have a symbol name which isn't present in the + # binary. We assume it is truncated, and try to extend it. + + # Get all the symbols with this prefix. + possible_symbols = list(get_symbols_with_prefix(symbol)) + if not possible_symbols: + continue + + # If we found too many possible symbols, ignore this as a prefix. + if len(possible_symbols) > 100: + print( "warning: ignoring symbol %r " % symbol + + "(no match and too many possible suffixes)", file=sys.stderr) + continue + + # Report that we resolved a missing symbol. + if opts.show_missing_symbols and symbol not in missing_symbols: + print("warning: resolved missing symbol %r" % symbol, file=sys.stderr) + missing_symbols.add(symbol) + + # Otherwise, treat all the possible matches as having occurred. This + # is an over-approximation, but it should be ok in practice. + for s in possible_symbols: + yield (current_timestamp, s) + +def uniq(list): + seen = set() + for item in list: + if item not in seen: + yield item + seen.add(item) + +def form_by_call_order(symbol_lists): + # Simply strategy, just return symbols in order of occurrence, even across + # multiple runs. + return uniq(s for symbols in symbol_lists for s in symbols) + +def form_by_call_order_fair(symbol_lists): + # More complicated strategy that tries to respect the call order across all + # of the test cases, instead of giving a huge preference to the first test + # case. + + # First, uniq all the lists. + uniq_lists = [list(uniq(symbols)) for symbols in symbol_lists] + + # Compute the successors for each list. + succs = {} + for symbols in uniq_lists: + for a,b in zip(symbols[:-1], symbols[1:]): + succs[a] = items = succs.get(a, []) + if b not in items: + items.append(b) + + # Emit all the symbols, but make sure to always emit all successors from any + # call list whenever we see a symbol. + # + # There isn't much science here, but this sometimes works better than the + # more naive strategy. Then again, sometimes it doesn't so more research is + # probably needed. + return uniq(s + for symbols in symbol_lists + for node in symbols + for s in ([node] + succs.get(node,[]))) + +def form_by_frequency(symbol_lists): + # Form the order file by just putting the most commonly occurring symbols + # first. This assumes the data files didn't use the oneshot dtrace method. + + counts = {} + for symbols in symbol_lists: + for a in symbols: + counts[a] = counts.get(a,0) + 1 + + by_count = counts.items() + by_count.sort(key = lambda (_,n): -n) + return [s for s,n in by_count] + +def form_by_random(symbol_lists): + # Randomize the symbols. + merged_symbols = uniq(s for symbols in symbol_lists + for s in symbols) + random.shuffle(merged_symbols) + return merged_symbols + +def form_by_alphabetical(symbol_lists): + # Alphabetize the symbols. + merged_symbols = list(set(s for symbols in symbol_lists for s in symbols)) + merged_symbols.sort() + return merged_symbols + +methods = dict((name[len("form_by_"):],value) + for name,value in locals().items() if name.startswith("form_by_")) + +def genOrderFile(args): + parser = argparse.ArgumentParser( + "%prog [options] <dtrace data file directories>]") + parser.add_argument('input', nargs='+', help='') + parser.add_argument("--binary", metavar="PATH", type=str, dest="binary_path", + help="Path to the binary being ordered (for getting all symbols)", + default=None) + parser.add_argument("--output", dest="output_path", + help="path to output order file to write", default=None, required=True, + metavar="PATH") + parser.add_argument("--show-missing-symbols", dest="show_missing_symbols", + help="show symbols which are 'fixed up' to a valid name (requires --binary)", + action="store_true", default=None) + parser.add_argument("--output-unordered-symbols", + dest="output_unordered_symbols_path", + help="write a list of the unordered symbols to PATH (requires --binary)", + default=None, metavar="PATH") + parser.add_argument("--method", dest="method", + help="order file generation method to use", choices=methods.keys(), + default='call_order') + opts = parser.parse_args(args) + + # If the user gave us a binary, get all the symbols in the binary by + # snarfing 'nm' output. + if opts.binary_path is not None: + output = subprocess.check_output(['nm', '-P', opts.binary_path]) + lines = output.split("\n") + all_symbols = [ln.split(' ',1)[0] + for ln in lines + if ln.strip()] + print("found %d symbols in binary" % len(all_symbols)) + all_symbols.sort() + else: + all_symbols = [] + all_symbols_set = set(all_symbols) + + # Compute the list of input files. + input_files = [] + for dirname in opts.input: + input_files.extend(findFilesWithExtension(dirname, "dtrace")) + + # Load all of the input files. + print("loading from %d data files" % len(input_files)) + missing_symbols = set() + timestamped_symbol_lists = [ + list(parse_dtrace_symbol_file(path, all_symbols, all_symbols_set, + missing_symbols, opts)) + for path in input_files] + + # Reorder each symbol list. + symbol_lists = [] + for timestamped_symbols_list in timestamped_symbol_lists: + timestamped_symbols_list.sort() + symbol_lists.append([symbol for _,symbol in timestamped_symbols_list]) + + # Execute the desire order file generation method. + method = methods.get(opts.method) + result = list(method(symbol_lists)) + + # Report to the user on what percentage of symbols are present in the order + # file. + num_ordered_symbols = len(result) + if all_symbols: + print("note: order file contains %d/%d symbols (%.2f%%)" % ( + num_ordered_symbols, len(all_symbols), + 100.*num_ordered_symbols/len(all_symbols)), file=sys.stderr) + + if opts.output_unordered_symbols_path: + ordered_symbols_set = set(result) + with open(opts.output_unordered_symbols_path, 'w') as f: + f.write("\n".join(s for s in all_symbols if s not in ordered_symbols_set)) + + # Write the order file. + with open(opts.output_path, 'w') as f: + f.write("\n".join(result)) + f.write("\n") + + return 0 + +commands = {'clean' : clean, + 'merge' : merge, + 'dtrace' : dtrace, + 'cc1' : cc1, + 'gen-order-file' : genOrderFile} def main(): f = commands[sys.argv[1]] |
