summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-06-15 09:04:53 -0700
committerGitHub <noreply@github.com>2020-06-15 09:04:53 -0700
commit90444f8366255f274993ce4699738d9ab7cf4ee1 (patch)
tree6fa9364535f210698b0ee13894ab956b8dd12c7b /source
parent36a06f1289c9a68a261920ef5d34f075f2a43219 (diff)
Generate IRType for interfaces, and reference them as `operand[0]` in IRWitnessTable values (#1387)
* Generate IRType for interfaces, and use them as the type of IRWitnessTable values. This results the following IR for the included test case: ``` [export("_S3tu010IInterface7Computep1pii")] let %1 : _ = key [export("_ST3tu010IInterface")] [nameHint("IInterface")] interface %IInterface : _(%1); [export("_S3tu04Impl7Computep1pii")] [nameHint("Impl.Compute")] func %Implx5FCompute : Func(Int, Int) { block %2( [nameHint("inVal")] param %inVal : Int): let %3 : Int = mul(%inVal, %inVal) return_val(%3) } [export("_SW3tu04Impl3tu010IInterface")] witness_table %4 : %IInterface { witness_table_entry(%1,%Implx5FCompute) } ``` * Fixes per code review comments. Moved interface type reference in IRWitnessTable from their type to operand[0]. * Fix typo in comment.
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-ast-support-types.h3
-rw-r--r--source/slang/slang-check-decl.cpp2
-rw-r--r--source/slang/slang-emit-c-like.cpp14
-rw-r--r--source/slang/slang-emit-c-like.h2
-rw-r--r--source/slang/slang-emit-cpp.cpp5
-rw-r--r--source/slang/slang-emit-cpp.h2
-rw-r--r--source/slang/slang-emit.cpp3
-rw-r--r--source/slang/slang-ir-insts.h7
-rw-r--r--source/slang/slang-ir-link.cpp15
-rw-r--r--source/slang/slang-ir.cpp82
-rw-r--r--source/slang/slang-lower-to-ir.cpp20
11 files changed, 104 insertions, 51 deletions
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h
index 759930aac..ef6589ca4 100644
--- a/source/slang/slang-ast-support-types.h
+++ b/source/slang/slang-ast-support-types.h
@@ -1285,6 +1285,9 @@ namespace Slang
struct WitnessTable : RefObject
{
RequirementDictionary requirementDictionary;
+
+ // The type that the witness table witnesses conformance to (e.g. an Interface)
+ Type* baseType;
};
typedef Dictionary<unsigned int, NodeBase*> AttributeArgumentValueDict;
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 3aeca23cd..ab22108b9 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -1581,6 +1581,7 @@ namespace Slang
if(!witnessTable)
{
witnessTable = new WitnessTable();
+ witnessTable->baseType = DeclRefType::create(m_astBuilder, interfaceDeclRef);
}
context->mapInterfaceToWitnessTable.Add(interfaceDeclRef, witnessTable);
@@ -2137,6 +2138,7 @@ namespace Slang
// let them define a tag value with the name `__Tag`).
//
RefPtr<WitnessTable> witnessTable = new WitnessTable();
+ witnessTable->baseType = enumConformanceDecl->base.type;
enumConformanceDecl->witnessTable = witnessTable;
Name* tagAssociatedTypeName = getSession()->getNameObj("__Tag");
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 9d23cec43..911928e2a 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -217,8 +217,8 @@ void CLikeSourceEmitter::emitSimpleType(IRType* type)
outNumThreads[i] = decor ? Int(getIntVal(decor->getOperand(i))) : 1;
}
return decor;
-}
-
+}
+
void CLikeSourceEmitter::_emitArrayType(IRArrayType* arrayType, EDeclarator* declarator)
{
EDeclarator arrayDeclarator;
@@ -265,6 +265,12 @@ void CLikeSourceEmitter::_emitType(IRType* type, EDeclarator* declarator)
}
+void CLikeSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable)
+{
+ SLANG_UNUSED(witnessTable);
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "Unimplemented emit: IROpWitnessTable.");
+}
+
void CLikeSourceEmitter::emitTypeImpl(IRType* type, const StringSliceLoc* nameAndLoc)
{
if (nameAndLoc)
@@ -3516,6 +3522,10 @@ void CLikeSourceEmitter::emitGlobalInst(IRInst* inst)
emitStruct(cast<IRStructType>(inst));
break;
+ case kIROp_WitnessTable:
+ emitWitnessTable(cast<IRWitnessTable>(inst));
+ break;
+
default:
// We have an "ordinary" instruction at the global
// scope, and we should therefore emit it using the
diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h
index e1106ea76..2253e7ea8 100644
--- a/source/slang/slang-emit-c-like.h
+++ b/source/slang/slang-emit-c-like.h
@@ -340,6 +340,8 @@ public:
// Again necessary for & prefix intrinsics. May be removable in the future
virtual void emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount) = 0;
+ virtual void emitWitnessTable(IRWitnessTable* witnessTable);
+
virtual void handleCallExprDecorationsImpl(IRInst* funcValue) { SLANG_UNUSED(funcValue); }
virtual bool tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* varType) { SLANG_UNUSED(varDecl); SLANG_UNUSED(varType); return false; }
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index bc82475f4..d7636e5a8 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -1559,6 +1559,11 @@ void CPPSourceEmitter::emitParamTypeImpl(IRType* type, String const& name)
emitType(type, name);
}
+void CPPSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable)
+{
+ SLANG_UNUSED(witnessTable);
+}
+
bool CPPSourceEmitter::tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* varType)
{
SLANG_UNUSED(varDecl);
diff --git a/source/slang/slang-emit-cpp.h b/source/slang/slang-emit-cpp.h
index aeef30804..2f95c8da5 100644
--- a/source/slang/slang-emit-cpp.h
+++ b/source/slang/slang-emit-cpp.h
@@ -75,7 +75,7 @@ protected:
virtual void emitSimpleFuncImpl(IRFunc* func) SLANG_OVERRIDE;
virtual void emitOperandImpl(IRInst* inst, EmitOpInfo const& outerPrec) SLANG_OVERRIDE;
virtual void emitParamTypeImpl(IRType* type, String const& name) SLANG_OVERRIDE;
-
+ virtual void emitWitnessTable(IRWitnessTable* witnessTable) SLANG_OVERRIDE;
virtual bool tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* varType) SLANG_OVERRIDE;
virtual void emitIntrinsicCallExprImpl(IRCall* inst, IRTargetIntrinsicDecoration* targetIntrinsic, EmitOpInfo const& inOuterPrec) SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 3e0d6ae26..2212d5d5a 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -698,6 +698,9 @@ SlangResult emitEntryPointSourceFromIR(
//
// TODO: do we want to emit directly from IR, or translate the
// IR back into AST for emission?
+#if 0
+ dumpIR(compileRequest, irModule, "PRE-EMIT");
+#endif
sourceEmitter->emitModule(irModule);
}
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 0ae05311b..09f78707d 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -1790,7 +1790,10 @@ struct IRBuilder
IRType* valueType);
IRGlobalParam* createGlobalParam(
IRType* valueType);
- IRWitnessTable* createWitnessTable();
+
+ /// Creates an IRWitnessTable value.
+ /// @param baseType: The comformant-to type of this witness.
+ IRWitnessTable* createWitnessTable(IRType* baseType);
IRWitnessTableEntry* createWitnessTableEntry(
IRWitnessTable* witnessTable,
IRInst* requirementKey,
@@ -1800,7 +1803,7 @@ struct IRBuilder
IRStructType* createStructType();
// Create an empty `interface` type.
- IRInterfaceType* createInterfaceType();
+ IRInterfaceType* createInterfaceType(UInt operandCount, IRInst* const* operands);
// Create a global "key" to use for indexing into a `struct` type.
IRStructKey* createStructKey();
diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp
index 904a88d78..3f51aa876 100644
--- a/source/slang/slang-ir-link.cpp
+++ b/source/slang/slang-ir-link.cpp
@@ -567,7 +567,12 @@ IRWitnessTable* cloneWitnessTableImpl(
IRWitnessTable* dstTable = nullptr,
bool registerValue = true)
{
- auto clonedTable = dstTable ? dstTable : builder->createWitnessTable();
+ IRWitnessTable* clonedTable = dstTable;
+ if (!clonedTable)
+ {
+ auto clonedBaseType = cloneType(context, as<IRType>(originalTable->getOperand(0)));
+ clonedTable = builder->createWitnessTable(clonedBaseType);
+ }
cloneSimpleGlobalValueImpl(context, originalTable, originalValues, clonedTable, registerValue);
return clonedTable;
}
@@ -599,7 +604,13 @@ IRInterfaceType* cloneInterfaceTypeImpl(
IRInterfaceType* originalInterface,
IROriginalValuesForClone const& originalValues)
{
- auto clonedInterface = builder->createInterfaceType();
+ auto clonedInterface = builder->createInterfaceType(originalInterface->getOperandCount(), nullptr);
+ for (UInt i = 0; i < originalInterface->getOperandCount(); i++)
+ {
+ auto clonedKey = findClonedValue(context, originalInterface->getOperand(i));
+ SLANG_ASSERT(clonedKey);
+ clonedInterface->setOperand(i, clonedKey);
+ }
cloneSimpleGlobalValueImpl(context, originalInterface, originalValues, clonedInterface);
return clonedInterface;
}
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 136bf322f..4d507de41 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -2770,12 +2770,13 @@ namespace Slang
return inst;
}
- IRWitnessTable* IRBuilder::createWitnessTable()
+ IRWitnessTable* IRBuilder::createWitnessTable(IRType* baseType)
{
IRWitnessTable* witnessTable = createInst<IRWitnessTable>(
this,
kIROp_WitnessTable,
- nullptr);
+ nullptr,
+ baseType);
addGlobalValue(this, witnessTable);
return witnessTable;
}
@@ -2810,12 +2811,14 @@ namespace Slang
return structType;
}
- IRInterfaceType* IRBuilder::createInterfaceType()
+ IRInterfaceType* IRBuilder::createInterfaceType(UInt operandCount, IRInst* const* operands)
{
IRInterfaceType* interfaceType = createInst<IRInterfaceType>(
this,
kIROp_InterfaceType,
- nullptr);
+ nullptr,
+ operandCount,
+ operands);
addGlobalValue(this, interfaceType);
return interfaceType;
}
@@ -4209,6 +4212,42 @@ namespace Slang
dump(context, "}");
}
+ static void dumpInstOperandList(
+ IRDumpContext* context,
+ IRInst* inst)
+ {
+ UInt argCount = inst->getOperandCount();
+
+ if (argCount == 0)
+ return;
+
+ UInt ii = 0;
+
+ // Special case: make printing of `call` a bit
+ // nicer to look at
+ if (inst->op == kIROp_Call && argCount > 0)
+ {
+ dump(context, " ");
+ auto argVal = inst->getOperand(ii++);
+ dumpOperand(context, argVal);
+ }
+
+ bool first = true;
+ dump(context, "(");
+ for (; ii < argCount; ++ii)
+ {
+ if (!first)
+ dump(context, ", ");
+
+ auto argVal = inst->getOperand(ii);
+
+ dumpOperand(context, argVal);
+
+ first = false;
+ }
+
+ dump(context, ")");
+ }
void dumpIRWitnessTableEntry(
IRDumpContext* context,
@@ -4234,6 +4273,8 @@ namespace Slang
dumpInstTypeClause(context, inst->getFullType());
+ dumpInstOperandList(context, inst);
+
if (!inst->getFirstChild())
{
// Empty.
@@ -4321,38 +4362,7 @@ namespace Slang
dump(context, opInfo.name);
- UInt argCount = inst->getOperandCount();
-
- if(argCount == 0)
- return;
-
- UInt ii = 0;
-
- // Special case: make printing of `call` a bit
- // nicer to look at
- if (inst->op == kIROp_Call && argCount > 0)
- {
- dump(context, " ");
- auto argVal = inst->getOperand(ii++);
- dumpOperand(context, argVal);
- }
-
- bool first = true;
- dump(context, "(");
- for (; ii < argCount; ++ii)
- {
- if (!first)
- dump(context, ", ");
-
- auto argVal = inst->getOperand(ii);
-
- dumpOperand(context, argVal);
-
- first = false;
- }
-
- dump(context, ")");
-
+ dumpInstOperandList(context, inst);
}
static void dumpInstBody(
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index a1089b537..42f53ef22 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -1105,7 +1105,8 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower
UNREACHABLE_RETURN(LoweredValInfo());
}
- auto irWitnessTable = getBuilder()->createWitnessTable();
+ auto irWitnessTableBaseType = lowerType(context, supDeclRefType);
+ auto irWitnessTable = getBuilder()->createWitnessTable(irWitnessTableBaseType);
// Now we will iterate over the requirements (members) of the
// interface and try to synthesize an appropriate value for each.
@@ -4524,7 +4525,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
if(!mapASTToIRWitnessTable.TryGetValue(astReqWitnessTable, irSatisfyingWitnessTable))
{
// Need to construct a sub-witness-table
- irSatisfyingWitnessTable = subBuilder->createWitnessTable();
+ auto irWitnessTableBaseType = lowerType(subContext, astReqWitnessTable->baseType);
+ irSatisfyingWitnessTable = subBuilder->createWitnessTable(irWitnessTableBaseType);
// Recursively lower the sub-table.
lowerWitnessTable(
@@ -4637,10 +4639,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// and we need those parameters to lower as references to
// the parameters of our IR-level generic.
//
- lowerType(subContext, superType);
+ auto irWitnessTableBaseType = lowerType(subContext, superType);
// Create the IR-level witness table
- auto irWitnessTable = subBuilder->createWitnessTable();
+ auto irWitnessTable = subBuilder->createWitnessTable(irWitnessTableBaseType);
addLinkageDecoration(context, irWitnessTable, inheritanceDecl, mangledName.getUnownedSlice());
// Register the value now, rather than later, to avoid any possible infinite recursion.
@@ -5243,9 +5245,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// a witness table for the interface type's conformance
// to its own interface.
//
+ List<IRStructKey*> requirementKeys;
for (auto requirementDecl : decl->members)
{
- getInterfaceRequirementKey(requirementDecl);
+ requirementKeys.add(getInterfaceRequirementKey(requirementDecl));
// As a special case, any type constraints placed
// on an associated type will *also* need to be turned
@@ -5254,7 +5257,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
{
for (auto constraintDecl : associatedTypeDecl->getMembersOfType<TypeConstraintDecl>())
{
- getInterfaceRequirementKey(constraintDecl);
+ requirementKeys.add(getInterfaceRequirementKey(constraintDecl));
}
}
}
@@ -5267,11 +5270,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// Emit any generics that should wrap the actual type.
emitOuterGenerics(subContext, decl, decl);
- IRInterfaceType* irInterface = subBuilder->createInterfaceType();
+ IRInterfaceType* irInterface = subBuilder->createInterfaceType(
+ requirementKeys.getCount(),
+ reinterpret_cast<IRInst**>(requirementKeys.getBuffer()));
addNameHint(context, irInterface, decl);
addLinkageDecoration(context, irInterface, decl);
subBuilder->setInsertInto(irInterface);
-
// TODO: are there any interface members that should be
// nested inside the interface type itself?