@@ -488,6 +488,16 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S
488
488
out << " >" ;
489
489
return SLANG_OK;
490
490
}
491
+ case kIROp_WitnessTableType :
492
+ {
493
+ // A witness table typed value translates to a pointer to the
494
+ // struct of function pointers corresponding to the interface type.
495
+ auto witnessTableType = static_cast <IRWitnessTableType*>(type);
496
+ auto baseType = cast<IRType>(witnessTableType->getOperand (0 ));
497
+ emitType (baseType);
498
+ out << " *" ;
499
+ return SLANG_OK;
500
+ }
491
501
default :
492
502
{
493
503
if (isNominalOp (type->op ))
@@ -1561,7 +1571,117 @@ void CPPSourceEmitter::emitParamTypeImpl(IRType* type, String const& name)
1561
1571
1562
1572
void CPPSourceEmitter::emitWitnessTable (IRWitnessTable* witnessTable)
1563
1573
{
1564
- SLANG_UNUSED (witnessTable);
1574
+ auto interfaceType = cast<IRInterfaceType>(witnessTable->getOperand (0 ));
1575
+ auto witnessTableItems = witnessTable->getChildren ();
1576
+ List<IRWitnessTableEntry*> sortedWitnessTableEntries = getSortedWitnessTableEntries (witnessTable);
1577
+ _maybeEmitWitnessTableTypeDefinition (interfaceType, sortedWitnessTableEntries);
1578
+
1579
+ // Define a global variable for the witness table.
1580
+ m_writer->emit (" extern " );
1581
+ emitSimpleType (interfaceType);
1582
+ m_writer->emit (" " );
1583
+ m_writer->emit (getName (witnessTable));
1584
+ m_writer->emit (" ;\n " );
1585
+
1586
+ // The actual definition of this witness table global variable
1587
+ // is deferred until the entire `Context` class is emitted, so
1588
+ // that the member functions are available for reference.
1589
+ // The witness table definition emission logic is defined in the
1590
+ // `_emitWitnessTableDefinitions` function.
1591
+ pendingWitnessTableDefinitions.add (witnessTable);
1592
+ }
1593
+
1594
+ void CPPSourceEmitter::_emitWitnessTableDefinitions ()
1595
+ {
1596
+ for (auto witnessTable : pendingWitnessTableDefinitions)
1597
+ {
1598
+ auto interfaceType = cast<IRInterfaceType>(witnessTable->getOperand (0 ));
1599
+ List<IRWitnessTableEntry*> sortedWitnessTableEntries = getSortedWitnessTableEntries (witnessTable);
1600
+ emitSimpleType (interfaceType);
1601
+ m_writer->emit (" " );
1602
+ m_writer->emit (getName (witnessTable));
1603
+ m_writer->emit (" = {\n " );
1604
+ m_writer->indent ();
1605
+ bool isFirstEntry = true ;
1606
+ for (Index i = 0 ; i < sortedWitnessTableEntries.getCount (); i++)
1607
+ {
1608
+ auto entry = sortedWitnessTableEntries[i];
1609
+ if (auto funcVal = as<IRFunc>(entry->satisfyingVal .get ()))
1610
+ {
1611
+ if (!isFirstEntry)
1612
+ m_writer->emit (" ,\n " );
1613
+ else
1614
+ isFirstEntry = false ;
1615
+ m_writer->emit (" &Context::" );
1616
+ m_writer->emit (getName (funcVal));
1617
+ }
1618
+ else
1619
+ {
1620
+ // TODO: handle other witness table entry types.
1621
+ }
1622
+ }
1623
+ m_writer->dedent ();
1624
+ m_writer->emit (" \n };\n " );
1625
+ }
1626
+ }
1627
+
1628
+ void CPPSourceEmitter::emitInterface (IRInterfaceType* interfaceType)
1629
+ {
1630
+ // The current IRInterfaceType defintion does not contain
1631
+ // sufficient info for emitting a witness table struct by itself
1632
+ // Instead, it defines the order of entries in a witness table.
1633
+ // Therefore, we emit a forward declaration here, and actual definition
1634
+ // for the witness table type during emitWitnessTable.
1635
+ SLANG_UNUSED (interfaceType);
1636
+ m_writer->emit (" struct " );
1637
+ emitSimpleType (interfaceType);
1638
+ m_writer->emit (" ;\n " );
1639
+ }
1640
+
1641
+ // / Emits witness table type definition given a sorted list of witness tables
1642
+ // / acoording to the order defined by `interfaceType`.
1643
+ // /
1644
+ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition (
1645
+ IRInterfaceType* interfaceType,
1646
+ const List<IRWitnessTableEntry*>& sortedWitnessTableEntries)
1647
+ {
1648
+ m_writer->emit (" struct " );
1649
+ emitSimpleType (interfaceType);
1650
+ m_writer->emit (" \n {\n " );
1651
+ m_writer->indent ();
1652
+ bool isFirstEntry = true ;
1653
+ for (Index i = 0 ; i < sortedWitnessTableEntries.getCount (); i++)
1654
+ {
1655
+ auto entry = sortedWitnessTableEntries[i];
1656
+ if (auto funcVal = as<IRFunc>(entry->satisfyingVal .get ()))
1657
+ {
1658
+ if (!isFirstEntry)
1659
+ m_writer->emit (" ,\n " );
1660
+ else
1661
+ isFirstEntry = false ;
1662
+ emitType (funcVal->getResultType ());
1663
+ m_writer->emit (" (Context::*" );
1664
+ m_writer->emit (getName (entry->requirementKey .get ()));
1665
+ m_writer->emit (" )" );
1666
+ m_writer->emit (" (" );
1667
+ bool isFirstParam = true ;
1668
+ for (auto param : funcVal->getParams ())
1669
+ {
1670
+ if (!isFirstParam)
1671
+ m_writer->emit (" , " );
1672
+ else
1673
+ isFirstParam = false ;
1674
+ emitParamType (param->getFullType (), getName (param));
1675
+ }
1676
+ m_writer->emit (" );\n " );
1677
+ }
1678
+ else
1679
+ {
1680
+ // TODO: handle other witness table entry types.
1681
+ }
1682
+ }
1683
+ m_writer->dedent ();
1684
+ m_writer->emit (" \n };\n " );
1565
1685
}
1566
1686
1567
1687
bool CPPSourceEmitter::tryEmitGlobalParamImpl (IRGlobalParam* varDecl, IRType* varType)
@@ -1673,6 +1793,12 @@ void CPPSourceEmitter::emitSimpleFuncImpl(IRFunc* func)
1673
1793
auto firstParam = func->getFirstParam ();
1674
1794
for (auto pp = firstParam; pp; pp = pp->getNextParam ())
1675
1795
{
1796
+ // Ingore TypeType-typed parameters for now.
1797
+ // In the future we will pass around runtime type info
1798
+ // for TypeType parameters.
1799
+ if (as<IRTypeType>(pp->getFullType ()))
1800
+ continue ;
1801
+
1676
1802
if (pp != firstParam)
1677
1803
m_writer->emit (" , " );
1678
1804
@@ -1950,9 +2076,32 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut
1950
2076
// Does this function declare any requirements.
1951
2077
handleCallExprDecorationsImpl (funcValue);
1952
2078
2079
+ if (funcValue->op == kIROp_lookup_interface_method )
2080
+ {
2081
+ m_writer->emit (" (this->*(" );
2082
+ emitOperand (funcValue, EmitOpInfo ());
2083
+ m_writer->emit (" ))" );
2084
+ _emitCallArgList (as<IRCall>(inst));
2085
+ return true ;
2086
+ }
2087
+
1953
2088
// try doing automatically
1954
2089
return _tryEmitInstExprAsIntrinsic (inst, inOuterPrec);
1955
2090
}
2091
+ case kIROp_lookup_interface_method :
2092
+ {
2093
+ emitInstExpr (inst->getOperand (0 ), inOuterPrec);
2094
+ m_writer->emit (" ->" );
2095
+ m_writer->emit (getName (inst->getOperand (1 )));
2096
+ return true ;
2097
+ }
2098
+ case kIROp_WitnessTable :
2099
+ {
2100
+ m_writer->emit (" (&" );
2101
+ m_writer->emit (getName (inst));
2102
+ m_writer->emit (" )" );
2103
+ return true ;
2104
+ }
1956
2105
}
1957
2106
}
1958
2107
@@ -2513,6 +2662,9 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module)
2513
2662
m_writer->emit (" };\n\n " );
2514
2663
}
2515
2664
2665
+ // Emit all witness table definitions.
2666
+ _emitWitnessTableDefinitions ();
2667
+
2516
2668
// Finally we need to output dll entry points
2517
2669
2518
2670
for (auto action : actions)
0 commit comments