Fix Windows Clang SPIR-V serialization with typed operands

This commit is contained in:
nmzik
2026-09-12 13:08:23 +02:00
parent 3a27f8a76a
commit 1208d22547
17 changed files with 1204 additions and 1084 deletions
@@ -15,8 +15,8 @@ static void AppendInstructionWords(std::vector<uint32_t>& section, const uint32_
if (words_num == 0) {
return;
}
const auto opcode = words[0];
const auto word_count = static_cast<uint32_t>(words_num);
const uint32_t opcode = words[0];
const auto word_count = static_cast<uint32_t>(words_num);
section.push_back((word_count << spv::WordCountShift) | opcode);
section.insert(section.end(), words + 1, words + words_num);
}
@@ -38,7 +38,7 @@ void Builder::RequireVersion(uint32_t version) {
void Builder::RequireCapability(spv::Capability capability) {
if (m_required_capabilities.insert(capability).second) {
AppendInstruction(m_capabilities, spv::OpCapability, {static_cast<uint32_t>(capability)});
AppendInstruction(m_capabilities, spv::OpCapability, capability);
}
}
@@ -62,38 +62,25 @@ uint32_t Builder::Import(const char* name) {
return id;
}
uint32_t Builder::Type(spv::Op opcode, std::initializer_list<uint32_t> operands) {
return Type(opcode, std::vector<uint32_t>(operands));
}
uint32_t Builder::Type(spv::Op opcode, const std::vector<uint32_t>& operands) {
std::vector<uint32_t> key;
key.reserve(operands.size() + 2u);
key.push_back(opcode);
key.push_back(static_cast<uint32_t>(operands.size()));
key.insert(key.end(), operands.begin(), operands.end());
uint32_t Builder::DeclareType(spv::Op opcode, std::vector<uint32_t> key) {
if (const auto it = m_declaration_ids.find(key); it != m_declaration_ids.end()) {
return it->second;
}
const auto id = AllocateId();
AppendInstruction(m_declarations, opcode, id, std::span<const uint32_t>(key).subspan(2));
m_declaration_ids.emplace(std::move(key), id);
std::vector<uint32_t> words {static_cast<uint32_t>(opcode), id};
words.insert(words.end(), operands.begin(), operands.end());
AppendInstructionWords(m_declarations, words.data(), words.size());
return id;
}
uint32_t Builder::DecoratedType(spv::Op opcode, std::initializer_list<uint32_t> operands,
std::initializer_list<TypeAnnotation> annotations) {
uint32_t Builder::DeclareDecoratedType(spv::Op opcode, std::vector<uint32_t> key,
std::initializer_list<TypeAnnotation> annotations) {
if (annotations.size() == 0) {
return Type(opcode, operands);
return DeclareType(opcode, std::move(key));
}
std::vector<uint32_t> key {static_cast<uint32_t>(opcode),
static_cast<uint32_t>(operands.size())};
key.insert(key.end(), operands.begin(), operands.end());
const auto operand_count = key[1];
key.push_back(static_cast<uint32_t>(annotations.size()));
for (const auto& annotation: annotations) {
key.push_back(annotation.opcode);
AppendOperand(key, annotation.opcode);
key.push_back(static_cast<uint32_t>(annotation.operands.size()));
key.insert(key.end(), annotation.operands.begin(), annotation.operands.end());
}
@@ -101,37 +88,23 @@ uint32_t Builder::DecoratedType(spv::Op opcode, std::initializer_list<uint32_t>
return it->second;
}
const auto id = AllocateId();
AppendInstruction(m_declarations, opcode, id,
std::span<const uint32_t>(key).subspan(2, operand_count));
m_declaration_ids.emplace(std::move(key), id);
std::vector<uint32_t> words {static_cast<uint32_t>(opcode), id};
words.insert(words.end(), operands.begin(), operands.end());
AppendInstructionWords(m_declarations, words.data(), words.size());
for (const auto& annotation: annotations) {
words = {static_cast<uint32_t>(annotation.opcode), id};
words.insert(words.end(), annotation.operands.begin(), annotation.operands.end());
AppendInstructionWords(m_annotations, words.data(), words.size());
AppendInstruction(m_annotations, annotation.opcode, id, annotation.operands);
}
return id;
}
uint32_t Builder::Constant(spv::Op opcode, uint32_t type,
std::initializer_list<uint32_t> operands) {
return Constant(opcode, type, std::vector<uint32_t>(operands));
}
uint32_t Builder::Constant(spv::Op opcode, uint32_t type, const std::vector<uint32_t>& operands) {
std::vector<uint32_t> key;
key.reserve(operands.size() + 2u);
key.push_back(opcode);
key.push_back(type);
key.insert(key.end(), operands.begin(), operands.end());
uint32_t Builder::DeclareConstant(spv::Op opcode, std::vector<uint32_t> key) {
if (const auto it = m_declaration_ids.find(key); it != m_declaration_ids.end()) {
return it->second;
}
const auto id = AllocateId();
AppendInstruction(m_declarations, opcode, key[1], id,
std::span<const uint32_t>(key).subspan(2));
m_declaration_ids.emplace(std::move(key), id);
std::vector<uint32_t> words {static_cast<uint32_t>(opcode), type, id};
words.insert(words.end(), operands.begin(), operands.end());
AppendInstructionWords(m_declarations, words.data(), words.size());
return id;
}
@@ -143,8 +116,7 @@ uint32_t Builder::DefineGlobalVariable(uint32_t pointer_type, spv::StorageClass
void Builder::DefineGlobalVariable(uint32_t id, uint32_t pointer_type,
spv::StorageClass storage_class) {
AppendInstruction(m_declarations, spv::OpVariable,
{pointer_type, id, static_cast<uint32_t>(storage_class)});
AppendInstruction(m_declarations, spv::OpVariable, pointer_type, id, storage_class);
}
void Builder::AppendString(std::vector<uint32_t>& words, const char* text) {
@@ -163,27 +135,14 @@ void Builder::AppendString(std::vector<uint32_t>& words, const char* text) {
}
}
void Builder::AppendInstruction(std::vector<uint32_t>& section, spv::Op opcode,
const std::vector<uint32_t>& operands) {
const uint32_t word_count = static_cast<uint32_t>(operands.size() + 1u);
section.push_back((word_count << spv::WordCountShift) | opcode);
section.insert(section.end(), operands.begin(), operands.end());
}
void Builder::AppendInstruction(std::vector<uint32_t>& section, spv::Op opcode,
std::initializer_list<uint32_t> operands) {
const uint32_t word_count = static_cast<uint32_t>(operands.size() + 1u);
section.push_back((word_count << spv::WordCountShift) | opcode);
section.insert(section.end(), operands.begin(), operands.end());
}
void Builder::AddMemoryModel(std::initializer_list<uint32_t> operands) {
AppendInstruction(m_memory_model, spv::OpMemoryModel, operands);
void Builder::AddMemoryModel(spv::AddressingModel addressing_model, spv::MemoryModel memory_model) {
AppendInstruction(m_memory_model, spv::OpMemoryModel, addressing_model, memory_model);
}
void Builder::AddEntryPoint(spv::ExecutionModel execution_model, uint32_t entry_point,
const char* name, const std::vector<uint32_t>& interfaces) {
std::vector<uint32_t> operands = {static_cast<uint32_t>(execution_model), entry_point};
std::vector<uint32_t> operands;
AppendOperands(operands, execution_model, entry_point);
AppendString(operands, name);
operands.insert(operands.end(), interfaces.begin(), interfaces.end());
if (m_version >= 0x00010400u) {
@@ -201,25 +160,13 @@ void Builder::AddEntryPoint(spv::ExecutionModel execution_model, uint32_t entry_
AppendInstruction(m_entry_points, spv::OpEntryPoint, operands);
}
void Builder::AddExecutionMode(std::initializer_list<uint32_t> operands) {
AppendInstruction(m_execution_modes, spv::OpExecutionMode, operands);
}
void Builder::AddName(uint32_t target, const char* name) {
std::vector<uint32_t> operands = {target};
AppendString(operands, name);
AppendInstruction(m_debug, spv::OpName, operands);
}
void Builder::AddAnnotation(std::initializer_list<uint32_t> words) {
AppendInstructionWords(m_annotations, words.begin(), words.size());
}
void Builder::AddFunction(std::initializer_list<uint32_t> words) {
AppendInstructionWords(m_functions, words.begin(), words.size());
}
void Builder::AddFunction(const std::vector<uint32_t>& words) {
void Builder::AddFunction(std::span<const uint32_t> words) {
AppendInstructionWords(m_functions, words.data(), words.size());
}