Skip to content

Commit 5758d16

Browse files
authored
IR pass to generate witness table wrappers. (shader-slang#1443)
* Refactor lower-generics pass into separate subpasses. * IR pass to generate witness table wrappers. * Re-generate vs project files. * Fix x86 build error.
1 parent e9d5ecb commit 5758d16

8 files changed

+274
-152
lines changed

source/slang/slang-emit-cpp.cpp

+26-141
Original file line numberDiff line numberDiff line change
@@ -1467,24 +1467,6 @@ UnownedStringSlice CPPSourceEmitter::_getFuncName(const HLSLIntrinsic* specOp)
14671467
return m_slicePool.getSlice(handle);
14681468
}
14691469

1470-
UnownedStringSlice CPPSourceEmitter::_getWitnessTableWrapperFuncName(IRFunc* func)
1471-
{
1472-
StringSlicePool::Handle handle = StringSlicePool::kNullHandle;
1473-
if (m_witnessTableWrapperFuncNameMap.TryGetValue(func, handle))
1474-
{
1475-
return m_slicePool.getSlice(handle);
1476-
}
1477-
1478-
StringBuilder builder;
1479-
builder << getName(func) << "_wtwrapper";
1480-
1481-
handle = m_slicePool.add(builder);
1482-
m_witnessTableWrapperFuncNameMap.Add(func, handle);
1483-
1484-
SLANG_ASSERT(handle != StringSlicePool::kNullHandle);
1485-
return m_slicePool.getSlice(handle);
1486-
}
1487-
14881470
SlangResult CPPSourceEmitter::calcFuncName(const HLSLIntrinsic* specOp, StringBuilder& outBuilder)
14891471
{
14901472
typedef HLSLIntrinsic::Op Op;
@@ -1629,122 +1611,6 @@ void CPPSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable)
16291611
pendingWitnessTableDefinitions.add(witnessTable);
16301612
}
16311613

1632-
void CPPSourceEmitter::_emitWitnessTableWrappers()
1633-
{
1634-
for (auto witnessTable : pendingWitnessTableDefinitions)
1635-
{
1636-
auto interfaceType = cast<IRInterfaceType>(witnessTable->getOperand(0));
1637-
for (auto child : witnessTable->getChildren())
1638-
{
1639-
if (auto entry = as<IRWitnessTableEntry>(child))
1640-
{
1641-
if (auto funcVal = as<IRFunc>(entry->getSatisfyingVal()))
1642-
{
1643-
IRInst* requirementVal = nullptr;
1644-
for (UInt i = 0; i < interfaceType->getOperandCount(); i++)
1645-
{
1646-
if (auto reqEntry = as<IRInterfaceRequirementEntry>(interfaceType->getOperand(i)))
1647-
{
1648-
if (reqEntry->getRequirementKey() == entry->getRequirementKey())
1649-
{
1650-
requirementVal = reqEntry->getRequirementVal();
1651-
break;
1652-
}
1653-
}
1654-
}
1655-
SLANG_ASSERT(requirementVal != nullptr);
1656-
IRFuncType* requirementFuncType = cast<IRFuncType>(requirementVal);
1657-
emitType(funcVal->getResultType());
1658-
m_writer->emit(" ");
1659-
m_writer->emit(_getWitnessTableWrapperFuncName(funcVal));
1660-
m_writer->emit("(");
1661-
// Emit parameter list.
1662-
{
1663-
bool isFirst = true;
1664-
SLANG_ASSERT(funcVal->getParamCount() == requirementFuncType->getParamCount());
1665-
auto pp = funcVal->getParams().begin();
1666-
for (UInt i = 0; i < requirementFuncType->getParamCount(); ++i, ++pp)
1667-
{
1668-
auto paramType = requirementFuncType->getParamType(i);
1669-
1670-
if (as<IRTypeType>(paramType))
1671-
continue;
1672-
1673-
if (isFirst)
1674-
isFirst = false;
1675-
else
1676-
m_writer->emit(",");
1677-
emitParamType(paramType, getName(*pp));
1678-
}
1679-
}
1680-
m_writer->emit(")\n{\n");
1681-
m_writer->indent();
1682-
m_writer->emit("return ");
1683-
m_writer->emit(getName(funcVal));
1684-
m_writer->emit("(");
1685-
// Emit argument list.
1686-
{
1687-
bool isFirst = true;
1688-
UInt paramIndex = 0;
1689-
for (auto defParamIter = funcVal->getParams().begin();
1690-
defParamIter!=funcVal->getParams().end();
1691-
++defParamIter, ++paramIndex)
1692-
{
1693-
auto param = *defParamIter;
1694-
auto reqParamType = requirementFuncType->getParamType(paramIndex);
1695-
if (as<IRTypeType>(param->getFullType()))
1696-
continue;
1697-
1698-
if (isFirst)
1699-
isFirst = false;
1700-
else
1701-
m_writer->emit(", ");
1702-
1703-
// If the implementation expects a concrete type
1704-
// (either in the form of a pointer for `out`/`inout` parameters,
1705-
// or in the form a a value for `in` parameters, while
1706-
// the interface exposes a raw pointer type (void*),
1707-
// we need to cast the raw pointer type to the appropriate
1708-
// concerete type. (void*->Concrete* / void*->Concrete&).
1709-
if (reqParamType->op == kIROp_RawPointerType &&
1710-
param->getDataType()->op != kIROp_RawPointerType)
1711-
{
1712-
if (as<IRPtrTypeBase>(param->getFullType()))
1713-
{
1714-
// The implementation function expects a pointer to the
1715-
// concrete type. This is the case for inout/out parameters.
1716-
m_writer->emit("static_cast<");
1717-
emitType(param->getFullType());
1718-
m_writer->emit(">(");
1719-
m_writer->emit(getName(param));
1720-
m_writer->emit(")");
1721-
}
1722-
else
1723-
{
1724-
// The implementation function expects just a value of the
1725-
// concrete type. We need to insert a dereference in this case.
1726-
m_writer->emit("*static_cast<");
1727-
emitType(param->getFullType());
1728-
m_writer->emit("*>(");
1729-
m_writer->emit(getName(param));
1730-
m_writer->emit(")");
1731-
}
1732-
}
1733-
else
1734-
{
1735-
m_writer->emit(getName(param));
1736-
}
1737-
}
1738-
}
1739-
m_writer->emit(");\n");
1740-
m_writer->dedent();
1741-
m_writer->emit("}\n");
1742-
}
1743-
}
1744-
}
1745-
}
1746-
}
1747-
17481614
void CPPSourceEmitter::_emitWitnessTableDefinitions()
17491615
{
17501616
for (auto witnessTable : pendingWitnessTableDefinitions)
@@ -1767,7 +1633,7 @@ void CPPSourceEmitter::_emitWitnessTableDefinitions()
17671633
else
17681634
isFirstEntry = false;
17691635

1770-
m_writer->emit(_getWitnessTableWrapperFuncName(funcVal));
1636+
m_writer->emit(getName(funcVal));
17711637
}
17721638
else if (auto witnessTableVal = as<IRWitnessTable>(entry->getSatisfyingVal()))
17731639
{
@@ -1778,9 +1644,18 @@ void CPPSourceEmitter::_emitWitnessTableDefinitions()
17781644
m_writer->emit("&");
17791645
m_writer->emit(getName(witnessTableVal));
17801646
}
1647+
else if (entry->getSatisfyingVal() &&
1648+
isPointerOfType(entry->getSatisfyingVal()->getDataType(), kIROp_RTTIType))
1649+
{
1650+
if (!isFirstEntry)
1651+
m_writer->emit(",\n");
1652+
else
1653+
isFirstEntry = false;
1654+
emitInstExpr(entry->getSatisfyingVal(), getInfo(EmitOp::General));
1655+
}
17811656
else
17821657
{
1783-
// TODO: handle other witness table entry types.
1658+
SLANG_UNEXPECTED("unknown witnesstable entry type");
17841659
}
17851660
}
17861661
m_writer->dedent();
@@ -1857,6 +1732,12 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition(
18571732
m_writer->emit(getName(entry->getRequirementKey()));
18581733
m_writer->emit(";\n");
18591734
}
1735+
else if (isPointerOfType(entry->getRequirementVal(), kIROp_RTTIType))
1736+
{
1737+
m_writer->emit("TypeInfo* ");
1738+
m_writer->emit(getName(entry->getRequirementKey()));
1739+
m_writer->emit(";\n");
1740+
}
18601741
}
18611742
m_writer->dedent();
18621743
m_writer->emit("};\n");
@@ -2336,6 +2217,15 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut
23362217
m_writer->emit("->typeSize)");
23372218
return true;
23382219
}
2220+
case kIROp_BitCast:
2221+
{
2222+
m_writer->emit("((");
2223+
emitType(inst->getDataType());
2224+
m_writer->emit(")(");
2225+
emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
2226+
m_writer->emit("))");
2227+
return true;
2228+
}
23392229
}
23402230
}
23412231

@@ -2668,11 +2558,6 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module)
26682558
emitGlobalInst(action.inst);
26692559
}
26702560
}
2671-
2672-
// Emit wrapper functions for each witness table entry.
2673-
// These wrapper functions takes an abstract type parameter (void*)
2674-
// in the place of `this` parameter.
2675-
_emitWitnessTableWrappers();
26762561
}
26772562

26782563
// Emit all witness table definitions.

source/slang/slang-emit-cpp.h

-11
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,6 @@ class CPPSourceEmitter: public CLikeSourceEmitter
106106

107107
UnownedStringSlice _getFuncName(const HLSLIntrinsic* specOp);
108108

109-
// Returns a StringSlice representing the mangled name of a witness table
110-
// wrapper function.
111-
UnownedStringSlice _getWitnessTableWrapperFuncName(IRFunc* func);
112-
113109
UnownedStringSlice _getTypeName(IRType* type);
114110

115111
SlangResult _calcCPPTextureTypeName(IRTextureTypeBase* texType, StringBuilder& outName);
@@ -127,19 +123,12 @@ class CPPSourceEmitter: public CLikeSourceEmitter
127123
// of all the witness table objects in `pendingWitnessTableDefinitions`.
128124
void _emitWitnessTableDefinitions();
129125

130-
// Emit wrapper functions that are referenced in witness tables.
131-
// Wrapper functions wraps the actual member function, and takes a `void*`
132-
// as the `this` parameter instead of the actual object type, so that
133-
// their signature is agnostic to the object type.
134-
void _emitWitnessTableWrappers();
135-
136126
HLSLIntrinsic* _addIntrinsic(HLSLIntrinsic::Op op, IRType* returnType, IRType*const* argTypes, Index argTypeCount);
137127

138128
static bool _isVariable(IROp op);
139129

140130
Dictionary<IRType*, StringSlicePool::Handle> m_typeNameMap;
141131
Dictionary<const HLSLIntrinsic*, StringSlicePool::Handle> m_intrinsicNameMap;
142-
Dictionary<IRFunc*, StringSlicePool::Handle> m_witnessTableWrapperFuncNameMap;
143132

144133

145134
IRTypeSet m_typeSet;

source/slang/slang-ir-lower-generic-function.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ namespace Slang
212212
{
213213
entry->setRequirementVal(lowerGenericFuncType(&builder, genericFuncType));
214214
}
215+
else if (entry->getRequirementVal()->op == kIROp_AssociatedType)
216+
{
217+
entry->setRequirementVal(builder.getPtrType(builder.getRTTIType()));
218+
}
215219
}
216220
}
217221

source/slang/slang-ir-lower-generics.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "slang-ir-lower-generic-function.h"
66
#include "slang-ir-lower-generic-call.h"
77
#include "slang-ir-lower-generic-var.h"
8+
#include "slang-ir-witness-table-wrapper.h"
89

910
namespace Slang
1011
{
@@ -16,5 +17,6 @@ namespace Slang
1617
lowerGenericFunctions(&sharedContext);
1718
lowerGenericCalls(&sharedContext);
1819
lowerGenericVar(&sharedContext);
20+
generateWitnessTableWrapperFunctions(&sharedContext);
1921
}
2022
} // namespace Slang

0 commit comments

Comments
 (0)