[Visualizer]

llvm::SmallVector<*,*>{
	preview (
		#if ((($T1*)$e.EndX - ($T1*)$e.BeginX) == 0) ( "empty" )
		#else (
			#(
				"[",
				($T1*)$e.EndX - ($T1*)$e.BeginX,
				"](",
				#array(
					expr: (($T1*)$e.BeginX)[$i],
					size: ($T1*)$e.EndX - ($T1*)$e.BeginX
				),
				")"
			)
		)
	)

	children (
		#(
			#([size] : ($T1*)$e.EndX - ($T1*)$e.BeginX),
			#([capacity] : ($T1*)$e.CapacityX - ($T1*)$e.BeginX),
			#array(
				expr: (($T1*)$e.BeginX)[$i],
				size: ($T1*)$e.EndX - ($T1*)$e.BeginX
			)
		)
	)
}

llvm::SmallVectorImpl<*>{
	preview (
		#if ((($T1*)$e.EndX - ($T1*)$e.BeginX) == 0) ( "empty" )
		#else (
			#(
				"[",
				($T1*)$e.EndX - ($T1*)$e.BeginX,
				"](",
				#array(
					expr: (($T1*)$e.BeginX)[$i],
					size: ($T1*)$e.EndX - ($T1*)$e.BeginX
				),
				")"
			)
		)
	)

	children (
		#(
			#([size] : ($T1*)$e.EndX - ($T1*)$e.BeginX),
			#([capacity] : ($T1*)$e.CapacityX - ($T1*)$e.BeginX),
			#array(
				expr: (($T1*)$e.BeginX)[$i],
				size: ($T1*)$e.EndX - ($T1*)$e.BeginX
			)
		)
	)
}

llvm::SmallString<*>{
	preview ([$e.BeginX,s])
	stringview ([$e.BeginX,sb])
}

llvm::StringRef{
	preview ([$e.Data,s])
	stringview ([$e.Data,sb])

	children (
		#(
			#([size] : $e.Length),
			#array(expr: $e.Data[$i], size: $e.Length)
		)
	)
}

clang::Token{
	preview((clang::tok::TokenKind)(int)$e.Kind)
}

llvm::PointerIntPair<*,*,*,*>{
	preview (
		#(
			($T1*)($e.Value & $e.PointerBitMask),
			" [",
			($T3)(($e.Value >> $e.IntShift) & $e.IntMask),
			"]"
		)
	)
	
	children (
		#(
			#([raw members] : [$e,!]),
			#([ptr] : ($T1*)($e.Value & $e.PointerBitMask)),
			#([int] : ($T3)($e.Value >> $e.IntShift) & $e.IntMask)
		)
	)
}

llvm::PointerUnion<*,*>{
	preview (
		#if ((($e.Val.Value >> $e.Val.IntShift) & $e.Val.IntMask) == 0) ( "PT1" )
		#else ( "PT2" )
	)
	
	children (
		#(
			#([raw members] : [$e,!]),
			#if ((($e.Val.Value >> $e.Val.IntShift) & $e.Val.IntMask) == 0) (
				#([ptr] : ($T1)($e.Val.Value & $e.Val.PointerBitMask))
			) #else (
				#([ptr] : ($T2)($e.Val.Value & $e.Val.PointerBitMask))
			)
		)
	)
}

llvm::PointerUnion3<*,*,*>{
	preview (
		#if (($e.Val.Val.Value & 0x2) == 2) ( "PT2" )
		#elif (($e.Val.Val.Value & 0x1) == 1) ( "PT3" )
		#else ( "PT1" )
	)
	
	children (
		#(
			#if (($e.Val.Val.Value & 0x2) == 2) (
				#([ptr] : ($T2)(($e.Val.Val.Value >> 2) << 2))
			) #elif (($e.Val.Val.Value & 0x1) == 1) (
				#([ptr] : ($T3)(($e.Val.Val.Value >> 2) << 2))
			) #else (
				#([ptr] : ($T1)(($e.Val.Val.Value >> 2) << 2))
			)
		)
	)
}

llvm::PointerUnion4<*,*,*,*>{
	preview (
		#if (($e.Val.Val.Value & 0x3) == 3) ( "PT4" )
		#elif (($e.Val.Val.Value & 0x2) == 2) ( "PT2" )
		#elif (($e.Val.Val.Value & 0x1) == 1) ( "PT3" )
		#else ( "PT1" )
	)
	
	children (
		#(
			#if (($e.Val.Val.Value & 0x3) == 3) (
				#([ptr] : ($T4)(($e.Val.Val.Value >> 2) << 2))
			) #elif (($e.Val.Val.Value & 0x2) == 2) (
				#([ptr] : ($T2)(($e.Val.Val.Value >> 2) << 2))
			) #elif (($e.Val.Val.Value & 0x1) == 1) (
				#([ptr] : ($T3)(($e.Val.Val.Value >> 2) << 2))
			) #else (
				#([ptr] : ($T1)(($e.Val.Val.Value >> 2) << 2))
			)
		)
	)
}

llvm::IntrusiveRefCntPtr<*>{
	preview (
		#if ($e.Obj == 0) ( "empty" )
		#else (
			#(
				"[RefCnt=", $e.Obj->ref_cnt,
				", ",
				"Obj=", $e.Obj,
				"]"
			)
		)
	)

	children (
		#if ($e.Obj == 0) ( #array(expr: 0, size: 0) )
		#else (
			#(
				#(RefCnt : $e.Obj->ref_cnt),
				#(Obj : $e.Obj)
			)
		)
	)
}

llvm::OwningPtr<*>{
	preview (
		#if ($e.Ptr == 0) ( "empty" )
		#else ( $e.Ptr )
	)

	children (
		#if ($e.Ptr == 0) ( #array(expr: 0, size: 0) )
		#else ( #(Ptr : $e.Ptr) )
	)	
}

llvm::SmallPtrSet<*,*>{
	preview (
		#(
			#if (($e.CurArray) == ($e.SmallArray)) ( "[Small Mode] " )
			#else ( "[Big Mode] " ),
			"NumElements=", $e.NumElements,
			" CurArraySize=", $e.CurArraySize
		)
	)

	children (
		#(
			#([raw members] : [$c,!]),
			#(NumElements : $e.NumElements),
			#(CurArraySize : $e.CurArraySize),
			#array(
				expr: $e.CurArray[$i],
				size: $e.CurArraySize + 1
			) : ($T1*)&$e
		)
	)
}

llvm::DenseMap<*,*,*>{
	preview (
		#if ($e.NumEntries == 0) ( "empty" )
		#else (
			#(
				"[NumEntries=", $e.NumEntries,
				" NumBuckets=", $e.NumBuckets,
				"]"
			)
		)
	)

	children (
		#if ($e.NumEntries == 0) ( #array(expr: 0, size: 0) )
		#else (
			#(
				#([raw members] : [$c,!]),
				#(NumEntries : $e.NumEntries),
				#(NumBuckets : $e.NumBuckets),
				#array(
					expr: $e.Buckets[$i],
					size: $e.NumBuckets
				)
			)
		)
	)
}

llvm::StringMap<*,*>{
	preview (
		#(
			"[NumBuckets=", $e.NumBuckets,
			" ItemSize=", $e.ItemSize,
			"]"
		)
	)

	children (
		#(
			#([raw members] : [$c,!]),
			#(NumBuckets : $e.NumBuckets),
			#(ItemSize : $e.ItemSize),
			#array(
				expr: $e.TheTable[$i],
				size: $e.NumBuckets,
			) : (llvm::StringMapEntry<$T1>*)&$e
		)
	)
}

llvm::StringMapEntry<*>{
	preview (
		#if ($e.StrLen == 0) ( "empty" )
		#else (	#(Entry : $e.second) )
	)

	children (
		#if ($e.StrLen == 0) ( "empty" )
		#else ( #(Entry : $e.second) )	
	)
}

clang::DirectoryEntry|clang::FileEntry|clang::PragmaHandler{
	preview ( [$e.Name,s] )
	children (
		#(
			#([raw members] : [$c,!]),
			#(Name : [$e.Name,s])
		)
	)
}

clang::DeclarationName{
	preview (
		; enum values from clang::DeclarationName::StoredNameKind
		#if ($e.Ptr == 0) (
			"empty"
		) #elif (($e.Ptr & $e.PtrMask) == $e.StoredIdentifier) (
			#else ( #("Identifier, ", (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask)) )
		) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCZeroArgSelector) (
			#("ZeroArgSelector, ", (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask))
		) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCOneArgSelector) (
			#("OneArgSelector, ", (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask))
		) #elif (($e.Ptr & $e.PtrMask) == $e.StoredDeclarationNameExtra) (
			#switch (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs)
			#case 0 ( ;DeclarationNameExtra::CXXConstructor
				#("CXXConstructorName, ", (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask))
			)
			#case 1 ( ;DeclarationNameExtra::CXXDestructor
				#("CXXDestructorName, ", (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask))
			)
			#case 2 ( ;DeclarationNameExtra::CXXConversionFunction
				#("CXXConversionFunctionName, ", (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask))
			)
			#case 46 ( ;DeclarationNameExtra::CXXLiteralOperator
				#("CXXLiteralOperatorName, ", (clang::CXXLiteralOperatorIdName*)($e.Ptr & ~$e.PtrMask))
			)
			#case 47 ( ;DeclarationNameExtra::CXXUsingDirective
				#("CXXUsingDirective")	;TODO What to add here?
			)
			#default (
				#if (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs < 47) (
					#("CXXOperatorName, ", (clang::CXXOperatorIdName*)($e.Ptr & ~$e.PtrMask))
				) #else (
					#("ObjCMultiArgSelector, ", (clang::MultiKeywordSelector*)($e.Ptr & ~$e.PtrMask))
				)
			)
		)
	)

	children (
		#(
			; enum values from clang::DeclarationName::StoredNameKind
			#if ($e.Ptr == 0) (
				#array( expr: 0, size: 0 )
			) #else (
				#(
					#([raw members] : [$e.Ptr,!]),
					if (($e.Ptr & $e.PtrMask) == $e.StoredIdentifier) (
						#(Ptr : (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask))
					) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCZeroArgSelector) (
						#(Ptr : (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask))
					) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCOneArgSelector) (
						#(Ptr : (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask))
					) #elif (($e.Ptr & $e.PtrMask) == $e.StoredDeclarationNameExtra) (
						#switch (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs)
						#case 0 ( ;DeclarationNameExtra::CXXConstructor
							#(Ptr : (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask))
						)
						#case 1 ( ;DeclarationNameExtra::CXXDestructor
							#(Ptr : (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask))
						)
						#case 2 ( ;DeclarationNameExtra::CXXConversionFunction
							#(Ptr : (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask))
						)
						#case 46 ( ;DeclarationNameExtra::CXXLiteralOperator
							#(Ptr : (clang::CXXLiteralOperatorIdName*)($e.Ptr & ~$e.PtrMask))
						)
						#case 47 ( ;DeclarationNameExtra::CXXUsingDirective
							#(Ptr : $e.Ptr)	;TODO What to add here?
						)
						#default (
							#if (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs < 47) (
								#(Ptr : (CXXOperatorIdName*)($e.Ptr & ~$e.PtrMask))
							) #else (
								#(Ptr : (clang::MultiKeywordSelector*)($e.Ptr & ~$e.PtrMask))
							)
						)
					)
				)
			)
		)
	)
}

clang::DeclSpec{
	preview (
		#(
			"[",
			(clang::DeclSpec::SCS)$e.StorageClassSpec,
			", ",
			(clang::TypeSpecifierType)$e.TypeSpecType,
			"]"
		)
	)
}

llvm::Triple{
	preview ( $e.Data )
}