llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-directx Author: None (joaosaffran) <details> <summary>Changes</summary> Closes: https://github.com/orgs/llvm/projects/4/views/22?sliceBy%5Bvalue%5D=joaosaffran&pane=issue&itemId=97332852&issue=llvm%7Cllvm-project%7C126635 --- Patch is 45.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138315.diff 13 Files Affected: - (modified) llvm/include/llvm/BinaryFormat/DXContainer.h (+35) - (modified) llvm/include/llvm/BinaryFormat/DXContainerConstants.def (+24-1) - (modified) llvm/include/llvm/MC/DXContainerRootSignature.h (+27-5) - (modified) llvm/include/llvm/Object/DXContainer.h (+66-3) - (modified) llvm/include/llvm/ObjectYAML/DXContainerYAML.h (+99) - (modified) llvm/lib/MC/DXContainerRootSignature.cpp (+72-6) - (modified) llvm/lib/ObjectYAML/DXContainerEmitter.cpp (+27) - (modified) llvm/lib/ObjectYAML/DXContainerYAML.cpp (+81) - (added) llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.0.yaml (+57) - (added) llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.1.yaml (+59) - (modified) llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml (+53-30) - (modified) llvm/unittests/Object/DXContainerTest.cpp (+107) - (modified) llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp (+113) ``````````diff diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index 3dbcfa82f3d7c..a441fa3a36886 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -163,6 +163,11 @@ enum class RootDescriptorFlag : uint32_t { #include "DXContainerConstants.def" }; +#define DESCRIPTOR_RANGE_FLAG(Num, Val) Val = 1ull << Num, +enum class DescriptorRangeFlag : uint32_t { +#include "DXContainerConstants.def" +}; + #define ROOT_PARAMETER(Val, Enum) Enum = Val, enum class RootParameterType : uint32_t { #include "DXContainerConstants.def" @@ -170,6 +175,13 @@ enum class RootParameterType : uint32_t { ArrayRef<EnumEntry<RootParameterType>> getRootParameterTypes(); +#define DESCRIPTOR_RANGE(Val, Enum) Enum = Val, +enum class DescriptorRangeType : uint32_t { +#include "DXContainerConstants.def" +}; + +ArrayRef<EnumEntry<DescriptorRangeType>> getDescriptorRangeTypes(); + #define ROOT_PARAMETER(Val, Enum) \ case Val: \ return true; @@ -595,6 +607,21 @@ struct RootDescriptor { sys::swapByteOrder(RegisterSpace); } }; + +struct DescriptorRange { + uint32_t RangeType; + uint32_t NumDescriptors; + uint32_t BaseShaderRegister; + uint32_t RegisterSpace; + int32_t OffsetInDescriptorsFromTableStart; + void swapBytes() { + sys::swapByteOrder(RangeType); + sys::swapByteOrder(NumDescriptors); + sys::swapByteOrder(BaseShaderRegister); + sys::swapByteOrder(RegisterSpace); + sys::swapByteOrder(OffsetInDescriptorsFromTableStart); + } +}; } // namespace v0 namespace v1 { @@ -605,6 +632,14 @@ struct RootDescriptor : public v0::RootDescriptor { sys::swapByteOrder(Flags); } }; + +struct DescriptorRange : public v0::DescriptorRange { + uint32_t Flags; + void swapBytes() { + v0::DescriptorRange::swapBytes(); + sys::swapByteOrder(Flags); + } +}; } // namespace v1 } // namespace RST0 // following dx12 naming diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def index bd9bd760547dc..5fe7e7c321a33 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def +++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def @@ -73,7 +73,7 @@ ROOT_ELEMENT_FLAG(11, SamplerHeapDirectlyIndexed) #endif // ROOT_ELEMENT_FLAG -// ROOT_ELEMENT_FLAG(bit offset for the flag, name). +// ROOT_DESCRIPTOR_FLAG(bit offset for the flag, name). #ifdef ROOT_DESCRIPTOR_FLAG ROOT_DESCRIPTOR_FLAG(0, NONE) @@ -84,8 +84,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC) #endif // ROOT_DESCRIPTOR_FLAG +// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name). +#ifdef DESCRIPTOR_RANGE_FLAG + +DESCRIPTOR_RANGE_FLAG(0, NONE) +DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE) +DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE) +DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE) +DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC) +DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS) +#undef DESCRIPTOR_RANGE_FLAG +#endif // DESCRIPTOR_RANGE_FLAG + #ifdef ROOT_PARAMETER +ROOT_PARAMETER(0, DescriptorTable) ROOT_PARAMETER(1, Constants32Bit) ROOT_PARAMETER(2, CBV) ROOT_PARAMETER(3, SRV) @@ -93,6 +106,16 @@ ROOT_PARAMETER(4, UAV) #undef ROOT_PARAMETER #endif // ROOT_PARAMETER + +#ifdef DESCRIPTOR_RANGE + +DESCRIPTOR_RANGE(0, SRV) +DESCRIPTOR_RANGE(1, UAV) +DESCRIPTOR_RANGE(2, CBV) +DESCRIPTOR_RANGE(3, Sampler) +#undef DESCRIPTOR_RANGE +#endif // DESCRIPTOR_RANGE + #ifdef SHADER_VISIBILITY SHADER_VISIBILITY(0, All) diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h index c8af613a57094..3f5960a6de2f9 100644 --- a/llvm/include/llvm/MC/DXContainerRootSignature.h +++ b/llvm/include/llvm/MC/DXContainerRootSignature.h @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLForwardCompat.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/DXContainer.h" #include <cstddef> #include <cstdint> @@ -28,17 +29,30 @@ struct RootParameterInfo { RootParameterInfo(dxbc::RootParameterHeader H, size_t L) : Header(H), Location(L) {} }; +using DescriptorRanges = std::variant<dxbc::RST0::v0::DescriptorRange, + dxbc::RST0::v1::DescriptorRange>; +struct DescriptorTable { + SmallVector<DescriptorRanges> Ranges; + + SmallVector<DescriptorRanges>::const_iterator begin() const { + return Ranges.begin(); + } + SmallVector<DescriptorRanges>::const_iterator end() const { + return Ranges.end(); + } +}; using RootDescriptor = std::variant<dxbc::RST0::v0::RootDescriptor, dxbc::RST0::v1::RootDescriptor>; -using ParametersView = std::variant<const dxbc::RootConstants *, - const dxbc::RST0::v0::RootDescriptor *, - const dxbc::RST0::v1::RootDescriptor *>; + +using ParametersView = std::variant< + const dxbc::RootConstants *, const dxbc::RST0::v0::RootDescriptor *, + const dxbc::RST0::v1::RootDescriptor *, const DescriptorTable *>; struct RootParametersContainer { SmallVector<RootParameterInfo> ParametersInfo; - SmallVector<dxbc::RootConstants> Constants; SmallVector<RootDescriptor> Descriptors; + SmallVector<DescriptorTable> Tables; void addInfo(dxbc::RootParameterHeader H, size_t L) { ParametersInfo.push_back(RootParameterInfo(H, L)); @@ -61,13 +75,18 @@ struct RootParametersContainer { Descriptors.push_back(D); } + void addParameter(dxbc::RootParameterHeader H, DescriptorTable D) { + addInfo(H, Tables.size()); + Tables.push_back(D); + } + std::optional<ParametersView> getParameter(const RootParameterInfo *H) const { switch (H->Header.ParameterType) { case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): return &Constants[H->Location]; case llvm::to_underlying(dxbc::RootParameterType::CBV): case llvm::to_underlying(dxbc::RootParameterType::SRV): - case llvm::to_underlying(dxbc::RootParameterType::UAV): + case llvm::to_underlying(dxbc::RootParameterType::UAV): { const RootDescriptor &VersionedParam = Descriptors[H->Location]; if (std::holds_alternative<dxbc::RST0::v0::RootDescriptor>( VersionedParam)) { @@ -75,6 +94,9 @@ struct RootParametersContainer { } return &std::get<dxbc::RST0::v1::RootDescriptor>(VersionedParam); } + case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): + return &Tables[H->Location]; + } return std::nullopt; } diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index e359d85f08bec..c6c22213d7de8 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -19,11 +19,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Object/Error.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/TargetParser/Triple.h" -#include <array> -#include <cstddef> #include <variant> namespace llvm { @@ -39,6 +39,7 @@ template <typename T> std::enable_if_t<std::is_class<T>::value, void> swapBytes(T &value) { value.swapBytes(); } + } // namespace detail // This class provides a view into the underlying resource array. The Resource @@ -121,8 +122,10 @@ namespace DirectX { struct RootParameterView { const dxbc::RootParameterHeader &Header; StringRef ParamData; + uint32_t Version; + RootParameterView(uint32_t V, const dxbc::RootParameterHeader &H, StringRef P) - : Header(H), ParamData(P) {} + : Header(H), ParamData(P), Version(V) {} template <typename T, typename VersionT = T> Expected<T> readParameter() { assert(sizeof(VersionT) <= sizeof(T) && @@ -169,6 +172,55 @@ struct RootDescriptorView : RootParameterView { return readParameter<dxbc::RST0::v1::RootDescriptor>(); } }; +template <typename T> struct DescriptorTable { + uint32_t NumRanges; + uint32_t RangesOffset; + ViewArray<T> Ranges; + + typename ViewArray<T>::iterator begin() const { return Ranges.begin(); } + + typename ViewArray<T>::iterator end() const { return Ranges.end(); } +}; +template <typename T> struct TemplateTypeToVersion { + // Default version + static constexpr uint32_t Value = -1; +}; + +template <> struct TemplateTypeToVersion<dxbc::RST0::v0::DescriptorRange> { + static constexpr uint32_t Value = 1; +}; + +template <> struct TemplateTypeToVersion<dxbc::RST0::v1::DescriptorRange> { + static constexpr uint32_t Value = 2; +}; + +template <typename T> struct DescriptorTableView : RootParameterView { + using TemplateType = T; + + static bool classof(const RootParameterView *V) { + return (V->Header.ParameterType == + llvm::to_underlying(dxbc::RootParameterType::DescriptorTable)) && + (V->Version == TemplateTypeToVersion<T>::Value); + } + + // Define a type alias to access the template parameter from inside classof + llvm::Expected<DescriptorTable<T>> read() { + const char *Current = ParamData.begin(); + DescriptorTable<T> Table; + + Table.NumRanges = + support::endian::read<uint32_t, llvm::endianness::little>(Current); + Current += sizeof(uint32_t); + + Table.RangesOffset = + support::endian::read<uint32_t, llvm::endianness::little>(Current); + Current += sizeof(uint32_t); + + Table.Ranges.Data = + ParamData.substr(2 * sizeof(uint32_t), Table.NumRanges * sizeof(T)); + return Table; + } +}; static Error parseFailed(const Twine &Msg) { return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed); @@ -221,6 +273,17 @@ class RootSignature { else DataSize = sizeof(dxbc::RST0::v1::RootDescriptor); break; + case dxbc::RootParameterType::DescriptorTable: + uint32_t NumRanges = + support::endian::read<uint32_t, llvm::endianness::little>( + PartData.begin() + Header.ParameterOffset); + if (Version == 1) + DataSize = sizeof(dxbc::RST0::v0::DescriptorRange) * NumRanges + + 2 * sizeof(uint32_t); + else + DataSize = sizeof(dxbc::RST0::v1::DescriptorRange) * NumRanges + + 2 * sizeof(uint32_t); + break; } size_t EndOfSectionByte = getNumStaticSamplers() == 0 ? PartData.size() diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h index 8bb9da7884bed..9cf0f8df1debf 100644 --- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h +++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h @@ -15,6 +15,8 @@ #ifndef LLVM_OBJECTYAML_DXCONTAINERYAML_H #define LLVM_OBJECTYAML_DXCONTAINERYAML_H +#include "llvm/ADT/STLForwardCompat.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Object/DXContainer.h" @@ -91,6 +93,25 @@ struct RootDescriptorYaml { #include "llvm/BinaryFormat/DXContainerConstants.def" }; +struct DescriptorRangeYaml { + uint32_t RangeType; + uint32_t NumDescriptors; + uint32_t BaseShaderRegister; + uint32_t RegisterSpace; + int32_t OffsetInDescriptorsFromTableStart; + + uint32_t getEncodedFlags() const; + +#define DESCRIPTOR_RANGE_FLAG(Num, Val) bool Val = false; +#include "llvm/BinaryFormat/DXContainerConstants.def" +}; + +struct DescriptorTableYaml { + uint32_t NumRanges; + uint32_t RangesOffset; + SmallVector<DescriptorRangeYaml> Ranges; +}; + struct RootParameterYamlDesc { uint32_t Type; uint32_t Visibility; @@ -107,13 +128,82 @@ struct RootParameterYamlDesc { case llvm::to_underlying(dxbc::RootParameterType::UAV): Descriptor = RootDescriptorYaml(); break; + case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): + Table = DescriptorTableYaml(); + break; + } + } + + ~RootParameterYamlDesc() { + switch (Type) { + + case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): + Constants.~RootConstantsYaml(); + break; + case llvm::to_underlying(dxbc::RootParameterType::CBV): + case llvm::to_underlying(dxbc::RootParameterType::SRV): + case llvm::to_underlying(dxbc::RootParameterType::UAV): + Descriptor.~RootDescriptorYaml(); + break; + case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): + Table.~DescriptorTableYaml(); + break; } } + RootParameterYamlDesc(const RootParameterYamlDesc &Other) + : Type(Other.Type), Visibility(Other.Visibility), Offset(Other.Offset) { + // Initialize the appropriate union member based on Type + switch (Type) { + case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): + // Placement new to construct the union member + new (&Constants) RootConstantsYaml(Other.Constants); + break; + case llvm::to_underlying(dxbc::RootParameterType::CBV): + case llvm::to_underlying(dxbc::RootParameterType::SRV): + case llvm::to_underlying(dxbc::RootParameterType::UAV): + new (&Descriptor) RootDescriptorYaml(Other.Descriptor); + break; + case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): + new (&Table) DescriptorTableYaml(Other.Table); + break; + } + } + + RootParameterYamlDesc &operator=(const RootParameterYamlDesc &Other) { + if (this != &Other) { + // First, destroy the current union member + this->~RootParameterYamlDesc(); + + // Copy the basic members + Type = Other.Type; + Visibility = Other.Visibility; + Offset = Other.Offset; + + // Initialize the new union member based on the Type from 'other' + switch (Type) { + case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): + new (&Constants) RootConstantsYaml(Other.Constants); + break; + case llvm::to_underlying(dxbc::RootParameterType::CBV): + case llvm::to_underlying(dxbc::RootParameterType::SRV): + case llvm::to_underlying(dxbc::RootParameterType::UAV): + new (&Descriptor) RootDescriptorYaml(Other.Descriptor); + break; + case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): + new (&Table) DescriptorTableYaml(Other.Table); + break; + } + } + return *this; + } + + // ToDo: Fix this (Already have a follow up PR with it) union { RootConstantsYaml Constants; RootDescriptorYaml Descriptor; }; + DescriptorTableYaml Table; }; struct RootSignatureYamlDesc { @@ -244,6 +334,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureElement) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::PSVInfo::MaskVector) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureParameter) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::RootParameterYamlDesc) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::DescriptorRangeYaml) LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::SemanticKind) LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::ComponentType) LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::InterpolationMode) @@ -328,6 +419,14 @@ template <> struct MappingTraits<llvm::DXContainerYAML::RootDescriptorYaml> { static void mapping(IO &IO, llvm::DXContainerYAML::RootDescriptorYaml &D); }; +template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorTableYaml> { + static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorTableYaml &D); +}; + +template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorRangeYaml> { + static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorRangeYaml &D); +}; + } // namespace yaml } // namespace llvm diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp index 641c2f5fa1b1b..4c725969e63cf 100644 --- a/llvm/lib/MC/DXContainerRootSignature.cpp +++ b/llvm/lib/MC/DXContainerRootSignature.cpp @@ -10,11 +10,43 @@ #include "llvm/ADT/SmallString.h" #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Support/EndianStream.h" +#include <cstdint> #include <variant> using namespace llvm; using namespace llvm::mcdxbc; +class SizeCalculatorVisitor { +public: + SizeCalculatorVisitor(uint32_t Version, size_t &SizeRef) + : Size(SizeRef), Version(Version) {} + + void operator()(const dxbc::RootConstants *Value) const { + Size += sizeof(dxbc::RootConstants); + } + + void operator()(const dxbc::RST0::v0::RootDescriptor *Value) const { + Size += sizeof(dxbc::RST0::v0::RootDescriptor); + } + + void operator()(const dxbc::RST0::v1::RootDescriptor *Value) const { + Size += sizeof(dxbc::RST0::v1::RootDescriptor); + } + + void operator()(const DescriptorTable *Value) const { + if (Version == 1) + Size += + sizeof(dxbc::RST0::v0::DescriptorRange) * Value->Ranges.size() + 8; + else + Size += + sizeof(dxbc::RST0::v1::DescriptorRange) * Value->Ranges.size() + 8; + } + +private: + size_t &Size; + uint32_t Version; +}; + static uint32_t writePlaceholder(raw_svector_ostream &Stream) { const uint32_t DummyValue = std::numeric_limits<uint32_t>::max(); uint32_t Offset = Stream.tell(); @@ -38,12 +70,8 @@ size_t RootSignatureDesc::getSize() const { std::optional<ParametersView> P = ParametersContainer.getParameter(&I); if (!P) continue; - std::visit( - [&Size](auto &Value) -> void { - using T = std::decay_t<decltype(*Value)>; - Size += sizeof(T); - }, - *P); + + std::visit(SizeCalculatorVisitor(Version, Size), *P); } return Size; @@ -106,6 +134,44 @@ void RootSignatureDesc::write(raw_ostream &OS) const { support::endian::write(BOS, Descriptor->RegisterSpace, llvm::endianness::little); support::endian::write(BOS, Descriptor->Flags, llvm::endianness::little); + } else if (std::holds_alternative<const DescriptorTable *>(P.value())) { + auto *Table = std::get<const DescriptorTable *>(P.value()); + + support::endian::write(BOS, (uint32_t)Table->Ranges.size(), + llvm::endianness::little); + rewriteOffsetToCurrentByte(BOS, writePlaceholder(BOS)); + for (const auto &R : *Table) { + if (std::holds_alternative<dxbc::RST0::v0::DescriptorRange>(R)) { + auto Range = std::get<dxbc::RST0::v0::DescriptorRange>(R); + + support::endian::write(BOS, Range.RangeType, + llvm::endianness::little); + support::endian::write(BOS, Range.NumDescriptors, + llvm::endianness::little); + support::endian::write(BOS, Range.BaseShaderRegister, + llvm::endianness::little); + support::endian::write(BOS, Range.RegisterSpace, + llvm::endianness::little); + support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart, + llvm::endianness::little); + } else { + if (std::holds_alternative<dxbc::RST0::v1::DescriptorRange>(R)) { + auto Range = std::get<dxbc::RST0::v1::DescriptorRange>(R); + + support::endian::write(BOS, Range.RangeType, + llvm::endianness::little); + support::endian::write(BOS, Range.NumDescriptors, + llvm::endianness::little); + support::endian::write(BOS, Range.BaseShaderRegister, + llvm::endianness::little); + support::endian::write(BOS, Range.RegisterSpace, + llvm::endianness::little); + support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart, + llvm::endianness::little); + support::endian::write(BOS, Range.Flags, llvm::endianness::little); + } + } + } } } assert(Storage.size() == getSize()); diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp index b8ea1b048edfe..6336a42c8e4ae 100644 --- a/llv... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/138315 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits