summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-emit-cpp.cpp157
-rw-r--r--source/slang/slang-emit-cpp.h33
-rw-r--r--source/slang/slang-ir-type-set.cpp229
-rw-r--r--source/slang/slang-ir-type-set.h84
-rw-r--r--source/slang/slang.vcxproj2
-rw-r--r--source/slang/slang.vcxproj.filters6
6 files changed, 344 insertions, 167 deletions
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index e7f11fc92..46eeee5bd 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -265,13 +265,13 @@ void CPPSourceEmitter::emitTypeDefinition(IRType* inType)
return;
}
- IRType* type = _cloneType(inType);
+ IRType* type = m_typeSet.getType(inType);
if (m_typeEmittedMap.TryGetValue(type))
{
return;
}
- if (type->getModule() != m_uniqueModule)
+ if (!m_typeSet.isOwned(type))
{
// If defined in a different module, we assume they are emitted already. (Assumed to
// be a nominal type)
@@ -322,7 +322,7 @@ void CPPSourceEmitter::emitTypeDefinition(IRType* inType)
const auto rowCount = int(GetIntVal(matType->getRowCount()));
const auto colCount = int(GetIntVal(matType->getColumnCount()));
- IRType* vecType = _getVecType(matType->getElementType(), colCount);
+ IRType* vecType = m_typeSet.addVectorType(matType->getElementType(), colCount);
emitTypeDefinition(vecType);
UnownedStringSlice typeName = _getTypeName(type);
@@ -373,7 +373,7 @@ void CPPSourceEmitter::emitTypeDefinition(IRType* inType)
UnownedStringSlice CPPSourceEmitter::_getTypeName(IRType* inType)
{
- IRType* type = _cloneType(inType);
+ IRType* type = m_typeSet.getType(inType);
StringSlicePool::Handle handle = StringSlicePool::kNullHandle;
if (m_typeNameMap.TryGetValue(type, handle))
@@ -390,7 +390,7 @@ UnownedStringSlice CPPSourceEmitter::_getTypeName(IRType* inType)
const auto colCount = int(GetIntVal(matType->getColumnCount()));
// Make sure the vector type the matrix is built on is added
- useType(_getVecType(elementType, colCount));
+ useType(m_typeSet.addVectorType(elementType, colCount));
}
StringBuilder builder;
@@ -631,115 +631,6 @@ void CPPSourceEmitter::useType(IRType* type)
_getTypeName(type);
}
-IRInst* CPPSourceEmitter::_clone(IRInst* inst)
-{
- if (inst == nullptr)
- {
- return nullptr;
- }
-
- IRModule* module = inst->getModule();
- // All inst's must belong to a module
- SLANG_ASSERT(module);
-
- // If it's in this module then we don't need to clone
- if (module == m_uniqueModule)
- {
- return inst;
- }
-
- if (IRInst*const* newInstPtr = m_cloneMap.TryGetValue(inst))
- {
- return *newInstPtr;
- }
-
- if (isNominalOp(inst->op))
- {
- // TODO(JS)
- // This is arguably problematic - I'm adding an instruction from another module to the map, to be it's self.
- // I did have code which created a copy of the nominal instruction and name hint, but because nominality means
- // 'same address' other code would generate a different name for that instruction (say as compared to being a member in
- // the original instruction)
- //
- // Because I use findOrAddInst which doesn't hoist instructions, the hoisting doesn't rely on parenting, that would
- // break.
-
- // If nominal, we just use the original inst
- m_cloneMap.Add(inst, inst);
- return inst;
- }
-
- // It would be nice if I could use ir-clone.cpp to do this -> but it doesn't clone
- // operands. We wouldn't want to clone decorations, and it can't clone IRConstant(!) so
- // it's no use
-
- IRInst* clone = nullptr;
- switch (inst->op)
- {
- case kIROp_IntLit:
- {
- auto intLit = static_cast<IRConstant*>(inst);
- IRType* cloneType = _cloneType(intLit->getDataType());
- clone = m_irBuilder.getIntValue(cloneType, intLit->value.intVal);
- break;
- }
- case kIROp_StringLit:
- {
- auto stringLit = static_cast<IRStringLit*>(inst);
- clone = m_irBuilder.getStringValue(stringLit->getStringSlice());
- break;
- }
- default:
- {
- if (IRBasicType::isaImpl(inst->op))
- {
- clone = m_irBuilder.getType(inst->op);
- }
- else
- {
- IRType* irType = dynamicCast<IRType>(inst);
- if (irType)
- {
- auto cloneType = _cloneType(inst->getFullType());
- Index operandCount = Index(inst->getOperandCount());
-
- List<IRInst*> cloneOperands;
- cloneOperands.setCount(operandCount);
-
- for (Index i = 0; i < operandCount; ++i)
- {
- cloneOperands[i] = _clone(inst->getOperand(i));
- }
-
- //clone = m_irBuilder.findOrEmitHoistableInst(cloneType, inst->op, operandCount, cloneOperands.getBuffer());
-
- UInt operandCounts[1] = { UInt(operandCount) };
- IRInst*const* listOperands[1] = { cloneOperands.getBuffer() };
-
- clone = m_irBuilder.findOrAddInst(cloneType, inst->op, 1, operandCounts, listOperands);
- }
- else
- {
- // This cloning style only works on insts that are not unique
- auto cloneType = _cloneType(inst->getFullType());
-
- Index operandCount = Index(inst->getOperandCount());
- clone = m_irBuilder.emitIntrinsicInst(cloneType, inst->op, operandCount, nullptr);
- for (Index i = 0; i < operandCount; ++i)
- {
- auto cloneOperand = _clone(inst->getOperand(i));
- clone->getOperands()[i].init(clone, cloneOperand);
- }
- }
- }
- break;
- }
- }
-
- m_cloneMap.Add(inst, clone);
- return clone;
-}
-
static IRBasicType* _getElementType(IRType* type)
{
switch (type->op)
@@ -1102,10 +993,13 @@ void CPPSourceEmitter::_emitCrossDefinition(const UnownedStringSlice& funcName,
UnownedStringSlice CPPSourceEmitter::_getAndEmitSpecializedOperationDefinition(IntrinsicOp op, IRType*const* argTypes, Int argCount, IRType* retType)
{
+ // Use the type sets builder...
+ IRBuilder& builder = m_typeSet.getBuilder();
+
SpecializedIntrinsic specOp;
specOp.op = op;
specOp.returnType = retType;
- specOp.signatureType = m_irBuilder.getFuncType(argCount, argTypes, m_irBuilder.getVoidType());
+ specOp.signatureType = builder.getFuncType(argCount, argTypes, builder.getVoidType());
emitSpecializedOperationDefinition(specOp);
return _getFuncName(specOp);
@@ -1443,12 +1337,6 @@ void CPPSourceEmitter::emitSpecializedOperationDefinition(const SpecializedIntri
SLANG_ASSERT(!"Unhandled");
}
-IRType* CPPSourceEmitter::_getVecType(IRType* elementType, int elementCount)
-{
- elementType = _cloneType(elementType);
- return m_irBuilder.getVectorType(elementType, m_irBuilder.getIntValue(m_irBuilder.getIntType(), elementCount));
-}
-
CPPSourceEmitter::SpecializedIntrinsic CPPSourceEmitter::getSpecializedOperation(IntrinsicOp op, IRType*const* inArgTypes, int argTypesCount, IRType* retType)
{
SpecializedIntrinsic specOp;
@@ -1459,11 +1347,14 @@ CPPSourceEmitter::SpecializedIntrinsic CPPSourceEmitter::getSpecializedOperation
for (int i = 0; i < argTypesCount; ++i)
{
- argTypes[i] = _cloneType(inArgTypes[i]->getCanonicalType());
+ argTypes[i] = m_typeSet.getType(inArgTypes[i]->getCanonicalType());
}
- specOp.returnType = _cloneType(retType);
- specOp.signatureType = m_irBuilder.getFuncType(argTypes, m_irBuilder.getBasicType(BaseType::Void));
+ specOp.returnType = m_typeSet.getType(retType);
+
+ // Use the typesets builder
+ IRBuilder& builder = m_typeSet.getBuilder();
+ specOp.signatureType = builder.getFuncType(argTypes, builder.getBasicType(BaseType::Void));
return specOp;
}
@@ -1786,21 +1677,12 @@ void CPPSourceEmitter::emitOperationCall(IntrinsicOp op, IRInst* inst, IRUse* op
CPPSourceEmitter::CPPSourceEmitter(const Desc& desc):
Super(desc),
- m_slicePool(StringSlicePool::Style::Default)
+ m_slicePool(StringSlicePool::Style::Default),
+ m_typeSet(desc.compileRequest->getSession())
{
m_semanticUsedFlags = 0;
//m_semanticUsedFlags = SemanticUsedFlag::GroupID | SemanticUsedFlag::GroupThreadID | SemanticUsedFlag::DispatchThreadID;
- m_sharedIRBuilder.module = nullptr;
- m_sharedIRBuilder.session = desc.compileRequest->getSession();
-
- m_irBuilder.sharedBuilder = &m_sharedIRBuilder;
-
- m_uniqueModule = m_irBuilder.createModule();
- m_sharedIRBuilder.module = m_uniqueModule;
-
- m_irBuilder.setInsertInto(m_irBuilder.getModule()->getModuleInst());
-
// Add all the operations with names (not ops like -, / etc) to the lookup map
for (int i = 0; i < SLANG_COUNT_OF(s_operationInfos); ++i)
{
@@ -2028,13 +1910,12 @@ void CPPSourceEmitter::emitSimpleValueImpl(IRInst* inst)
void CPPSourceEmitter::emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount)
{
- emitSimpleType(_getVecType(elementType, int(elementCount)));
+ emitSimpleType(m_typeSet.addVectorType(elementType, int(elementCount)));
}
void CPPSourceEmitter::emitSimpleTypeImpl(IRType* inType)
{
-
- UnownedStringSlice slice = _getTypeName(_cloneType(inType));
+ UnownedStringSlice slice = _getTypeName(m_typeSet.getType(inType));
m_writer->emit(slice);
}
diff --git a/source/slang/slang-emit-cpp.h b/source/slang/slang-emit-cpp.h
index fdc283574..ffe4a1544 100644
--- a/source/slang/slang-emit-cpp.h
+++ b/source/slang/slang-emit-cpp.h
@@ -5,6 +5,8 @@
#include "slang-emit-c-like.h"
#include "slang-ir-clone.h"
+#include "slang-ir-type-set.h"
+
#include "../core/slang-string-slice-pool.h"
namespace Slang
@@ -254,11 +256,6 @@ protected:
static TypeDimension _getTypeDimension(IRType* type, bool vecSwap);
static void _emitAccess(const UnownedStringSlice& name, const TypeDimension& dimension, int row, int col, SourceWriter* writer);
- IRType* _getVecType(IRType* elementType, int elementCount);
-
- IRInst* _clone(IRInst* inst);
- IRType* _cloneType(IRType* type) { return (IRType*)_clone((IRInst*)type); }
-
StringSlicePool::Handle _calcScalarFuncName(IntrinsicOp op, IRBasicType* type);
UnownedStringSlice _getScalarFuncName(IntrinsicOp operation, IRBasicType* scalarType);
@@ -282,30 +279,8 @@ protected:
Dictionary<SpecializedIntrinsic, StringSlicePool::Handle> m_intrinsicNameMap;
Dictionary<IRType*, StringSlicePool::Handle> m_typeNameMap;
- /* This is used so as to try and use slangs type system to uniquely identify types and specializations on intrinsic.
- That we want to have a pointer to a type be unique, and slang supports this through the m_sharedIRBuilder. BUT for this to
- work all work on the module must use the same sharedIRBuilder, and that appears to not be the case in terms
- of other passes.
- Even if it was the case when we may want to add types as part of emitting, we can't use the previously used
- shared builder, so again we end up with pointers to the same things not being the same thing.
-
- To work around this we clone types we want to use as keys into the 'unique module'.
- This is not necessary for all types though - as we assume nominal types *must* have unique pointers (that is the
- definition of nominal).
-
- This could be handled in other ways (for example not testing equality on pointer equality). Anyway for now this
- works, but probably needs to be handled in a better way. The better way may involve having guarantees about equality
- enabled in other code generation and making de-duping possible in emit code.
-
- Note that one pro for this approach is that it does not alter the source module. That as it stands it's not necessary
- for the source module to be immutable, because it is created for emitting and then discarded.
- */
- RefPtr<IRModule> m_uniqueModule;
- SharedIRBuilder m_sharedIRBuilder;
- IRBuilder m_irBuilder;
-
- Dictionary<IRInst*, IRInst*> m_cloneMap;
-
+ IRTypeSet m_typeSet;
+
Dictionary<IRType*, bool> m_typeEmittedMap;
Dictionary<SpecializedIntrinsic, bool> m_intrinsicEmittedMap;
diff --git a/source/slang/slang-ir-type-set.cpp b/source/slang/slang-ir-type-set.cpp
new file mode 100644
index 000000000..7beeaced4
--- /dev/null
+++ b/source/slang/slang-ir-type-set.cpp
@@ -0,0 +1,229 @@
+// slang-ir-type-set.cpp
+#include "slang-ir-type-set.h"
+
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+
+namespace Slang
+{
+
+IRTypeSet::IRTypeSet(Session* session)
+{
+ m_sharedBuilder.module = nullptr;
+ m_sharedBuilder.session = session;
+
+ m_builder.sharedBuilder = &m_sharedBuilder;
+
+ m_module = m_builder.createModule();
+
+ m_sharedBuilder.module = m_module;
+
+ m_builder.setInsertInto(m_module->getModuleInst());
+}
+
+IRTypeSet::~IRTypeSet()
+{
+ List<IRType*> types;
+ getTypes(types);
+
+ for (auto type : types)
+ {
+ // We need to destroy references to instructions in other modules
+ if (type->getModule() == m_module)
+ {
+ // We want to remove arguments because an argument *could* be an instruction in another module,
+ // and we don't want to those modules insts to have uses, in this module which is being destroyed
+ type->removeArguments();
+ }
+ }
+}
+
+IRInst* IRTypeSet::cloneInst(IRInst* inst)
+{
+ if (inst == nullptr)
+ {
+ return nullptr;
+ }
+
+ // See if it's already cloned
+ if (IRInst*const* newInstPtr = m_cloneMap.TryGetValue(inst))
+ {
+ return *newInstPtr;
+ }
+
+ IRModule* module = inst->getModule();
+ // All inst's must belong to a module
+ SLANG_ASSERT(module);
+
+ // If it's in this module then we don't need to clone
+ if (module == m_module)
+ {
+ return inst;
+ }
+
+ if (isNominalOp(inst->op))
+ {
+ // We can clone without any definition, and add the linkage
+
+ // TODO(JS)
+ // This is arguably problematic - I'm adding an instruction from another module to the map, to be it's self.
+ // I did have code which created a copy of the nominal instruction and name hint, but because nominality means
+ // 'same address' other code would generate a different name for that instruction (say as compared to being a member in
+ // the original instruction)
+ //
+ // Because I use findOrAddInst which doesn't hoist instructions, the hoisting doesn't rely on parenting, that would
+ // break.
+
+ // If nominal, we just use the original inst
+ m_cloneMap.Add(inst, inst);
+ return inst;
+ }
+
+ // It would be nice if I could use ir-clone.cpp to do this -> but it doesn't clone
+ // operands. We wouldn't want to clone decorations, and it can't clone IRConstant(!) so
+ // it's no use
+
+ IRInst* clone = nullptr;
+ switch (inst->op)
+ {
+ case kIROp_IntLit:
+ {
+ auto intLit = static_cast<IRConstant*>(inst);
+ IRType* clonedType = cloneType(intLit->getDataType());
+ clone = m_builder.getIntValue(clonedType, intLit->value.intVal);
+ break;
+ }
+ case kIROp_StringLit:
+ {
+ auto stringLit = static_cast<IRStringLit*>(inst);
+ clone = m_builder.getStringValue(stringLit->getStringSlice());
+ break;
+ }
+ default:
+ {
+ if (IRBasicType::isaImpl(inst->op))
+ {
+ clone = m_builder.getType(inst->op);
+ }
+ else
+ {
+ IRType* irType = dynamicCast<IRType>(inst);
+ if (irType)
+ {
+ auto clonedType = cloneType(inst->getFullType());
+ Index operandCount = Index(inst->getOperandCount());
+
+ List<IRInst*> cloneOperands;
+ cloneOperands.setCount(operandCount);
+
+ for (Index i = 0; i < operandCount; ++i)
+ {
+ cloneOperands[i] = cloneInst(inst->getOperand(i));
+ }
+
+ //clone = m_irBuilder.findOrEmitHoistableInst(cloneType, inst->op, operandCount, cloneOperands.getBuffer());
+
+ UInt operandCounts[1] = { UInt(operandCount) };
+ IRInst*const* listOperands[1] = { cloneOperands.getBuffer() };
+
+ clone = m_builder.findOrAddInst(clonedType, inst->op, 1, operandCounts, listOperands);
+ }
+ else
+ {
+ // This cloning style only works on insts that are not unique
+ auto clonedType = cloneType(inst->getFullType());
+
+ Index operandCount = Index(inst->getOperandCount());
+ clone = m_builder.emitIntrinsicInst(clonedType, inst->op, operandCount, nullptr);
+ for (Index i = 0; i < operandCount; ++i)
+ {
+ auto cloneOperand = cloneInst(inst->getOperand(i));
+ clone->getOperands()[i].init(clone, cloneOperand);
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ m_cloneMap.Add(inst, clone);
+ return clone;
+}
+
+IRType* IRTypeSet::add(IRType* irType)
+{
+ if (irType->getModule() == m_module)
+ {
+ return irType;
+ }
+ // We need to clone the type
+ return cloneType(irType);
+}
+
+void IRTypeSet::getTypes(List<IRType*>& outTypes) const
+{
+ outTypes.clear();
+ for (auto inst : m_module->getModuleInst()->getChildren())
+ {
+ if (IRType* type = as<IRType>(inst))
+ {
+ outTypes.add(type);
+ }
+ }
+}
+
+void IRTypeSet::getTypes(Kind kind, List<IRType*>& outTypes) const
+{
+ outTypes.clear();
+
+ for (auto inst : m_module->getModuleInst()->getChildren())
+ {
+ IRType* type = nullptr;
+
+ switch (kind)
+ {
+ case Kind::Scalar:
+ {
+ type = as<IRBasicType>(inst);
+ break;
+ }
+ case Kind::Vector:
+ {
+ type = as<IRVectorType>(inst);
+ break;
+ }
+ case Kind::Matrix:
+ {
+ type = as<IRMatrixType>(inst);
+ break;
+ }
+ default: break;
+ }
+
+ if (type)
+ {
+ outTypes.add(type);
+ }
+ }
+}
+
+IRType* IRTypeSet::addVectorType(IRType* inElementType, int colsCount)
+{
+ IRType* elementType = cloneType(inElementType);
+ return m_builder.getVectorType(elementType, m_builder.getIntValue(m_builder.getIntType(), colsCount));
+}
+
+void IRTypeSet::addVectorForMatrixTypes()
+{
+ // Make a copy so we can alter m_types dictionary
+ List<IRType*> types;
+ getTypes(Kind::Matrix, types);
+ for (IRType* type : types)
+ {
+ SLANG_ASSERT(as<IRMatrixType>(type));
+ IRMatrixType* matType = static_cast<IRMatrixType*>(type);
+ m_builder.getVectorType(matType->getElementType(), matType->getColumnCount());
+ }
+}
+
+}
diff --git a/source/slang/slang-ir-type-set.h b/source/slang/slang-ir-type-set.h
new file mode 100644
index 000000000..016513258
--- /dev/null
+++ b/source/slang/slang-ir-type-set.h
@@ -0,0 +1,84 @@
+// slang-ir-type-set.h
+#pragma once
+
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+
+#include "../core/slang-string-slice-pool.h"
+
+namespace Slang
+{
+
+/*
+NOTE! This type set is only designed to work for emitting code to determine unique types. It is envisaged in the
+future that it will not be needed because types will be made unique within a module, and thus the pointer to a type
+will uniquely identify the type.
+
+The other reason this type exists, is to allow an IRModule for emit to be immutable. That is not currently possible
+within emit code because it may be necessary in order to emit to be able to create other types that needed (for example
+vector types required for a matrix type implementation).
+
+This is used so as to try and use slangs type system to uniquely identify types and specializations on intrinsic.
+That we want to have a pointer to a type be unique, and slang supports this through the m_sharedIRBuilder. BUT for this to
+work all work on the module must use the same sharedIRBuilder, and that appears to not be the case in terms
+of other passes.
+Even if it was the case when we may want to add types as part of emitting, we can't use the previously used
+shared builder, so again we end up with pointers to the same things not being the same thing.
+
+To work around this we clone types we want to use as keys into the 'unique module'.
+This is not necessary for all types though - as we assume nominal types *must* have unique pointers (that is the
+definition of nominal).
+
+This could be handled in other ways (for example not testing equality on pointer equality). Anyway for now this
+works, but probably needs to be handled in a better way. The better way may involve having guarantees about equality
+enabled in other code generation and making de-duping possible in emit code.
+
+Note that one pro for this approach is that it does not alter the source module. That as it stands it's not necessary
+for the source module to be immutable, because it is created for emitting and then discarded.
+ */
+class IRTypeSet
+{
+public:
+ enum class Kind
+ {
+ Scalar,
+ Vector,
+ Matrix,
+ CountOf,
+ };
+
+ IRType* add(IRType* type);
+ IRType* addVectorType(IRType* elementType, int colsCount);
+
+ void addVectorForMatrixTypes();
+
+ void getTypes(List<IRType*>& outTypes) const;
+ void getTypes(Kind kind, List<IRType*>& outTypes) const;
+
+ IRType* getType(IRType* type) { return cloneType(type); }
+
+ IRType* cloneType(IRType* type) { return (IRType*)cloneInst((IRInst*)type); }
+ IRInst* cloneInst(IRInst* inst);
+
+ /// Returns true if the type belongs and is created on the module owned by the set
+ bool isOwned(IRType* type) { return type->getModule() == m_module; }
+
+ IRBuilder& getBuilder() { return m_builder; }
+ IRModule* getModule() const { return m_module; }
+
+ IRTypeSet(Session* session);
+ ~IRTypeSet();
+
+protected:
+
+ // Maps insts from source modules into m_module.
+ // NOTE! That nominal types are not cloned, as they are identified by pointer. They are just
+ Dictionary<IRInst*, IRInst*> m_cloneMap;
+
+ // Can find all types by traversing the types in the m_module
+ SharedIRBuilder m_sharedBuilder;
+ IRBuilder m_builder;
+ RefPtr<IRModule> m_module;
+};
+
+} // namespace Slang
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index e120e006f..df34de00c 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -230,6 +230,7 @@
<ClInclude Include="slang-ir-ssa.h" />
<ClInclude Include="slang-ir-string-hash.h" />
<ClInclude Include="slang-ir-strip.h" />
+ <ClInclude Include="slang-ir-type-set.h" />
<ClInclude Include="slang-ir-union.h" />
<ClInclude Include="slang-ir-validate.h" />
<ClInclude Include="slang-ir.h" />
@@ -310,6 +311,7 @@
<ClCompile Include="slang-ir-ssa.cpp" />
<ClCompile Include="slang-ir-string-hash.cpp" />
<ClCompile Include="slang-ir-strip.cpp" />
+ <ClCompile Include="slang-ir-type-set.cpp" />
<ClCompile Include="slang-ir-union.cpp" />
<ClCompile Include="slang-ir-validate.cpp" />
<ClCompile Include="slang-ir.cpp" />
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index 1c619a3d5..6c3626a3b 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -141,6 +141,9 @@
<ClInclude Include="slang-ir-strip.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-ir-type-set.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-ir-union.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -377,6 +380,9 @@
<ClCompile Include="slang-ir-strip.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-ir-type-set.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-ir-union.cpp">
<Filter>Source Files</Filter>
</ClCompile>