Files
RedBear-OS/local/recipes/dev/libclc/source/llvm/lib/MC/DXContainerPSVInfo.cpp
T
vasilito cb424d7448 build: static patch-sanity linter (shift-left the malformed-patch class)
verify-patch-sanity.py validates every active recipe .patch has internally-
consistent hunk line counts — catching the 'malformed patch at line N' failure
at commit/CI/preflight time instead of hours into a cook. This cycle hit that
class three times (qtwaylandscanner, sddm, xwayland), each only discovered when
cookbook tried to apply the patch.

Running it across the repo found 29 latent malformed patches (validated against
GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22').
They were harmless only because they sit in vendored recipes (baked, not re-
applied) — but would fail on any version-bump re-derivation. --fix recounts the
hunk headers (body untouched) and repaired all 29.

Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test
(test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats
(empty placeholders, bare-@@ git hunks).
2026-08-01 05:13:02 +03:00

236 lines
8.8 KiB
C++

//===- llvm/MC/DXContainerPSVInfo.cpp - DXContainer PSVInfo -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/MC/DXContainerPSVInfo.h"
#include "llvm/BinaryFormat/DXContainer.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::mcdxbc;
using namespace llvm::dxbc::PSV;
static constexpr size_t npos = StringRef::npos;
static size_t FindSequence(ArrayRef<uint32_t> Buffer,
ArrayRef<uint32_t> Sequence) {
if (Buffer.size() < Sequence.size())
return npos;
for (size_t Idx = 0; Idx <= Buffer.size() - Sequence.size(); ++Idx) {
if (0 == memcmp(static_cast<const void *>(&Buffer[Idx]),
static_cast<const void *>(Sequence.begin()),
Sequence.size() * sizeof(uint32_t)))
return Idx;
}
return npos;
}
static void
ProcessElementList(StringTableBuilder &StrTabBuilder,
SmallVectorImpl<uint32_t> &IndexBuffer,
SmallVectorImpl<v0::SignatureElement> &FinalElements,
SmallVectorImpl<StringRef> &SemanticNames,
ArrayRef<PSVSignatureElement> Elements) {
for (const auto &El : Elements) {
// Put the name in the string table and the name list.
StrTabBuilder.add(El.Name);
SemanticNames.push_back(El.Name);
v0::SignatureElement FinalElement;
memset(&FinalElement, 0, sizeof(v0::SignatureElement));
FinalElement.Rows = static_cast<uint8_t>(El.Indices.size());
FinalElement.StartRow = El.StartRow;
FinalElement.Cols = El.Cols;
FinalElement.StartCol = El.StartCol;
FinalElement.Allocated = El.Allocated;
FinalElement.Kind = El.Kind;
FinalElement.Type = El.Type;
FinalElement.Mode = El.Mode;
FinalElement.DynamicMask = El.DynamicMask;
FinalElement.Stream = El.Stream;
size_t Idx = FindSequence(IndexBuffer, El.Indices);
if (Idx == npos) {
FinalElement.IndicesOffset = static_cast<uint32_t>(IndexBuffer.size());
llvm::append_range(IndexBuffer, El.Indices);
} else
FinalElement.IndicesOffset = static_cast<uint32_t>(Idx);
FinalElements.push_back(FinalElement);
}
}
void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
assert(IsFinalized && "finalize must be called before write");
uint32_t InfoSize;
uint32_t BindingSize;
switch (Version) {
case 0:
InfoSize = sizeof(dxbc::PSV::v0::RuntimeInfo);
BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
break;
case 1:
InfoSize = sizeof(dxbc::PSV::v1::RuntimeInfo);
BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
break;
case 2:
InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo);
BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
break;
case 3:
default:
InfoSize = sizeof(dxbc::PSV::v3::RuntimeInfo);
BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
}
// Write the size of the info.
support::endian::write(OS, InfoSize, llvm::endianness::little);
// Write the info itself.
OS.write(reinterpret_cast<const char *>(&BaseData), InfoSize);
uint32_t ResourceCount = static_cast<uint32_t>(Resources.size());
support::endian::write(OS, ResourceCount, llvm::endianness::little);
if (ResourceCount > 0)
support::endian::write(OS, BindingSize, llvm::endianness::little);
for (const auto &Res : Resources)
OS.write(reinterpret_cast<const char *>(&Res), BindingSize);
// PSV Version 0 stops after the resource list.
if (Version == 0)
return;
support::endian::write(OS,
static_cast<uint32_t>(DXConStrTabBuilder.getSize()),
llvm::endianness::little);
// Write the string table.
DXConStrTabBuilder.write(OS);
// Write the index table size, then table.
support::endian::write(OS, static_cast<uint32_t>(IndexBuffer.size()),
llvm::endianness::little);
for (auto I : IndexBuffer)
support::endian::write(OS, I, llvm::endianness::little);
if (SignatureElements.size() > 0) {
// write the size of the signature elements.
support::endian::write(OS,
static_cast<uint32_t>(sizeof(v0::SignatureElement)),
llvm::endianness::little);
// write the signature elements.
OS.write(reinterpret_cast<const char *>(&SignatureElements[0]),
SignatureElements.size() * sizeof(v0::SignatureElement));
}
for (const auto &MaskVector : OutputVectorMasks)
support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
llvm::endianness::little);
support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOrPrimMasks),
llvm::endianness::little);
for (const auto &MaskVector : InputOutputMap)
support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
llvm::endianness::little);
support::endian::write_array(OS, ArrayRef<uint32_t>(InputPatchMap),
llvm::endianness::little);
support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOutputMap),
llvm::endianness::little);
}
void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
IsFinalized = true;
BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size());
BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size());
BaseData.SigPatchOrPrimElements =
static_cast<uint32_t>(PatchOrPrimElements.size());
SmallVector<StringRef, 32> SemanticNames;
// Build a string table and set associated offsets to be written when
// write() is called
ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
SemanticNames, InputElements);
ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
SemanticNames, OutputElements);
ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
SemanticNames, PatchOrPrimElements);
DXConStrTabBuilder.add(EntryName);
DXConStrTabBuilder.finalize();
for (auto ElAndName : zip(SignatureElements, SemanticNames)) {
llvm::dxbc::PSV::v0::SignatureElement &El = std::get<0>(ElAndName);
StringRef Name = std::get<1>(ElAndName);
El.NameOffset = static_cast<uint32_t>(DXConStrTabBuilder.getOffset(Name));
if (sys::IsBigEndianHost)
El.swapBytes();
}
BaseData.EntryNameOffset =
static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));
if (!sys::IsBigEndianHost)
return;
BaseData.swapBytes();
BaseData.swapBytes(Stage);
for (auto &Res : Resources)
Res.swapBytes();
}
void Signature::write(raw_ostream &OS) {
SmallVector<dxbc::ProgramSignatureElement> SigParams;
SigParams.reserve(Params.size());
StringTableBuilder StrTabBuilder((StringTableBuilder::DWARF));
// Name offsets are from the start of the part. Pre-calculate the offset to
// the start of the string table so that it can be added to the table offset.
uint32_t TableStart = sizeof(dxbc::ProgramSignatureHeader) +
(sizeof(dxbc::ProgramSignatureElement) * Params.size());
for (const auto &P : Params) {
// zero out the data
dxbc::ProgramSignatureElement FinalElement;
memset(&FinalElement, 0, sizeof(dxbc::ProgramSignatureElement));
FinalElement.Stream = P.Stream;
FinalElement.NameOffset =
static_cast<uint32_t>(StrTabBuilder.add(P.Name)) + TableStart;
FinalElement.Index = P.Index;
FinalElement.SystemValue = P.SystemValue;
FinalElement.CompType = P.CompType;
FinalElement.Register = P.Register;
FinalElement.Mask = P.Mask;
FinalElement.ExclusiveMask = P.ExclusiveMask;
FinalElement.MinPrecision = P.MinPrecision;
SigParams.push_back(FinalElement);
}
StrTabBuilder.finalizeInOrder();
stable_sort(SigParams, [&](const dxbc::ProgramSignatureElement &L,
const dxbc::ProgramSignatureElement R) {
return std::tie(L.Stream, L.Register, L.NameOffset) <
std::tie(R.Stream, R.Register, R.NameOffset);
});
if (sys::IsBigEndianHost)
for (auto &El : SigParams)
El.swapBytes();
dxbc::ProgramSignatureHeader Header = {static_cast<uint32_t>(Params.size()),
sizeof(dxbc::ProgramSignatureHeader)};
if (sys::IsBigEndianHost)
Header.swapBytes();
OS.write(reinterpret_cast<const char *>(&Header),
sizeof(dxbc::ProgramSignatureHeader));
OS.write(reinterpret_cast<const char *>(SigParams.data()),
sizeof(dxbc::ProgramSignatureElement) * SigParams.size());
StrTabBuilder.write(OS);
}